iTextSharp و نمایش صحیح تاریخ در متنی راست به چپ
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: دو دقیقه


خروجی PDF زیر را در نظر بگیرید:

مشکلی را در آن مشاهده می‌کنید؟ اصل آن یا صحیح آن باید به شکل زیر باشد:


و این وارونه نمایش دادن‌ها، دقیقا مشکلی است که حین کار با iTextSharp برای نمایش متنی مثلا به همراه یک تاریخ شمسی وجود دارد. البته این مشکل هم اساسا به خود استاندارد یونیکد برمی‌گردد که یک سری کاراکتر را «کاراکتر ضعیف» معرفی کرده؛ برای مثال کاراکتر اسلش بکار رفته در یک تاریخ هم از این دست است. بنابراین PDF تولیدی توسط iTextSharp از دید استاندارد یونیکد مشکلی ندارد، زیرا یک «نویسه ضعیف» مثل اسلش نمی‌تواند جهت را تغییر دهد؛ مگر اینکه از یک «نویسه قوی» برای دستکاری آن استفاده شود. برای مثال این نویسه‌ها قوی هستند:

U+202A:   LEFT-TO-RIGHT EMBEDDING (LRE) 
U+202B:   RIGHT-TO-LEFT EMBEDDING (RLE)
U+202D:   LEFT-TO-RIGHT OVERRIDE (LRO)
U+202E:   RIGHT-TO-LEFT OVERRIDE (RLO)
U+202C:   POP DIRECTIONAL FORMATTING (PDF)

برای رسیدن به تصویر صحیح نمایش داده شده در بالا، متد FixWeakCharacters زیر را تهیه کرده‌ام که حداقل با iTextSharp جواب می‌ده:

using System;
using System.Diagnostics;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace RleTests
{
class Program
{
const char RightToLeftEmbedding = (char)0x202B;
const char PopDirectionalFormatting = (char)0x202C;

static string FixWeakCharacters(string data)
{
if (string.IsNullOrWhiteSpace(data)) return string.Empty;
var weakCharacters = new[] { @"\", "/", "+", "-", "=", ";", "$" };
foreach (var weakCharacter in weakCharacters)
{
data = data.Replace(weakCharacter, RightToLeftEmbedding + weakCharacter + PopDirectionalFormatting);
}
return data;
}

static void Main(string[] args)
{
using (var pdfDoc = new Document(PageSize.A4))
{
PdfWriter.GetInstance(pdfDoc, new FileStream("Test.pdf", FileMode.Create));
pdfDoc.Open();

FontFactory.Register("c:\\windows\\fonts\\Arial.ttf");
Font tahoma = FontFactory.GetFont("Arial", BaseFont.IDENTITY_H);

var table1 = new PdfPTable(1);
table1.WidthPercentage = 100;

var pdfCell = new PdfPCell
{
RunDirection = PdfWriter.RUN_DIRECTION_RTL,
Border = 0,
Phrase = new Phrase(FixWeakCharacters(
"تاریخ: " + "1390/11/18" + Environment.NewLine +
"شماره پروژه: " + "1/2/3/4/56" + Environment.NewLine +
"اسلش: " + " 12/A/13 " + Environment.NewLine +
"بک اسلش: " + " 12\\13\\14 " + Environment.NewLine +
"مساوی و جمع: " + " 2+3=5 " + Environment.NewLine +
"سمی کولون: " + " 2=1+1; " + Environment.NewLine +
"دلار: " + "12$" + Environment.NewLine +
"کاما: " + "12,34,67" + Environment.NewLine +
"نقطه: " + "12.34" + Environment.NewLine +
"پرانتز: " + "متن (ساده)"
),
tahoma)
};

table1.AddCell(pdfCell);
pdfDoc.Add(table1);

}

Process.Start("Test.pdf");
}
}
}

از این نوع مشکلات حین کار با HTML هم هست؛ وارونه نمایش داده شدن تاریخ فارسی در بین یک متن راست به چپ. البته در آنجا راه حل زیر هم توصیه شده (بدون نیاز به دستکاری نویسه‌ها):

<span dir="ltr" style="display:inline">1390/11/19</span>

  • #
    ‫۱۲ سال و ۸ ماه قبل، پنجشنبه ۲۰ بهمن ۱۳۹۰، ساعت ۰۰:۴۶
    ممنون. جناب نصیری.
    آقای حاجلو هم مطلبه بسیار مفیدی در همین موضوع دارند.
    http://hajloo.wordpress.com/2009/03/02/persian-text-problem-in-ltr-forms/
  • #
    ‫۱۲ سال و ۸ ماه قبل، یکشنبه ۲۳ بهمن ۱۳۹۰، ساعت ۰۲:۴۹
    برای جدا سازی اجزای تاریخ شمسی، ماه ، روز و سال نباید از / استفاده کرد در unicode برای این کار از Unicode Character 'ARABIC DATE SEPARATOR' (U+060D) استفاده کنید برای دیدن جزییات بیشتر
    http://www.fileformat.info/info/unicode/char/60d/index.htm
  • #
    ‫۱۲ سال و ۸ ماه قبل، یکشنبه ۲۳ بهمن ۱۳۹۰، ساعت ۰۳:۳۰
    شاید در زبان عربی اینطور باشه. حتما می‌دونید که نحوه نمایش و نویسه‌های اعداد 4 و 6 عربی و فارسی یکی نیست. ک و ی عربی و فارسی هم یکی نیست. حتی ممیز فارسی هم شیوه خاص خودش را دارد و کلا بحث من اینجا در مورد نحوه متداول ورود اطلاعات در زبان فارسی است؛ در مورد هزاران هزار سطر موجود. ضمن اینکه اگر به مثال دقت کرده باشید یک شماره پروژه‌ای هم این وسط هست که الگویی شبیه به تاریخ ندارد؛ به علاوه یک سری نویسه ضعیف دیگر مثل مساوی و جمع و منها و غیره. به علاوه بحث من در مورد کتابخانه تولید PDF ذکر شده است و راه حلی که با آن جواب بدهد.
    راه حل بالایی که من مطرح کردم در نمایش هیچ تغییری ایجاد نمی‌کنه. این حرف بکارگرفته شده، نامرئی هستند. PDF هم یک لایه Presentation است. بنابراین زمانیکه اطلاعاتی را درست نمایش می‌دهد، یعنی هدف اصلی خودش را برآورده کرده.
  • #
    ‫۱۲ سال و ۷ ماه قبل، دوشنبه ۸ اسفند ۱۳۹۰، ساعت ۱۸:۵۹
    سلام، می خواستم اگر ممکن باشه من رو راهنمایی کنید، من می خوام با استفاده از itextsharp محتوای یک فایل پی دی اف رو به صورت txt ذخیره کنم، با زبانهای چپ به راست خیلی آسون هست ولی در زبان راست به چپ، کلمات از اخر به اول نوشته می شن مثلا کلمه ارزیابی به صورت "یبایزرا" خوانده می شه، ممنون می شم من رو راهنمایی بکنید.
            private static string ParsPDFToString()
            {
                PdfReader reader = new PdfReader("c:/2v.pdf");
                PdfReaderContentParser parser = new PdfReaderContentParser(reader);
                StringBuilder sb = new StringBuilder();
                Console.WriteLine("reader.NumberOfPages : " + reader.NumberOfPages.ToString());
                Console.ReadKey();
                for (int i = 1; i <= reader.NumberOfPages; i++)
                {
                    ITextExtractionStrategy strategy = parser.ProcessContent(
                      i , new SimpleTextExtractionStrategy()
                    );
                    sb.Append(strategy.GetResultantText());
                }
                return sb.ToString();
            }
  • #
    ‫۱۲ سال و ۷ ماه قبل، دوشنبه ۸ اسفند ۱۳۹۰، ساعت ۲۳:۳۶
    بستگی داره نرم افزار تولید PDF از چه روشی استفاده کرده باشه. بعضی‌ها از چرخاندن حروف استفاده می‌کنند و این روش بسیار متداولی هست. یعنی مشکل از iTextSharp نیست. در اصل به همین ترتیب حروف ذخیره شدن. الگوریتم اولیه به همین صورت بوده.
  • #
    ‫۱۲ سال و ۷ ماه قبل، سه‌شنبه ۹ اسفند ۱۳۹۰، ساعت ۱۵:۵۹
    دو مورد تکمیلی:
    - کار این چرخاندن‌ها توسط دو کلاس ArabicLigaturizer و BidiLine در iTextSharp انجام می‌شود. سورس کتابخانه را دریافت و این دو کلاس را مطالعه کنید (ضمن اینکه PDF های فارسی هم وجود دارند که اصلا با این الگویتم‌ها تهیه نشده‌اند و خلاصه راه سختی را پیش رو دارید).iTextSharp انجمنی نداره ولی یک mailing list فعال داره: https://lists.sourceforge.net/lists/listinfo/itext-questions