مقاله فنی

متن عمودی ژاپنی و چینی در PDF با Delphi

PDFlibPas متن ژاپنی و چینی را پایین صفحه رسم می‌کند. SetVerticalWritingMode نوشتار عمودی را روشن می‌کند، سپس فراخوانی‌های معمولی DrawText به‌سمت پایین اجرا می‌شوند، و GetVerticalWritingMode حالت فعلی را گزارش می‌دهد. قبل از وجود این، تنظیم متن به‌صورت عمودی یعنی قرار دادن هر نویسه به‌صورت دستی و امید به اینکه فاصله‌گذاری درست به‌نظر برسد

نوشتار عمودی متن افقی چرخیده ۹۰ درجه نیست. نویسه‌ها عمودی می‌مانند، advance به‌جای افقی به‌سمت پایین اجرا می‌شود، و تعدادی از نویسه‌ها کاملاً شکل خود را تغییر می‌دهند — که همان بخشی است که سندی که طبیعی خوانده می‌شود را از سندی که یک خواننده ژاپنی فوراً به‌عنوان ماشینی‌ساخته تشخیص می‌دهد جدا می‌کند

درون PDF چه تغییر می‌کند

متنی که این‌طور رسم می‌شود از طریق یک فونت Type0 در حالت نوشتار عمودی با متریک‌های عمودی خود فونت عبور می‌کند. این در دو جهت اهمیت دارد. یک خواننده هر نویسه را به‌اندازه فاصله‌ای که طراحش در نظر گرفته advance می‌کند به‌جای یک گام یکنواخت، پس ستون ریتمی دارد که typeface برایش کشیده شده. و کپی‌کردن متن بیرون نویسه‌های اصلی را برمی‌گرداند، چون run عمودی هنوز متن واقعی با یک نگاشت مناسب است به‌جای یک دنباله از گلیف‌های موقعیت‌داده‌شده

فونتی که هیچ متریک عمودی خودش را حمل نمی‌کند یک em در هر نویسه advance می‌کند، که همان چیزی است یک خواننده با پیش‌فرض انجام می‌داد. آن fallback ارزش دانستن دارد چون همان تفاوتی است که می‌بینید وقتی یک سند با یک فونت CJK مناسب درست رندر می‌شود و با یک فونت لاتین که اتفاقاً مقداری kana دارد از نظر ماشینی فاصله‌دار به‌نظر می‌رسد

var
  Lib: TPDFlib;
  H: Double;
begin
  Lib := TPDFlib.Create;
  try
    Lib.SetOrigin(1);
    Lib.AddTrueTypeFont('MS Mincho', 1);      // 1 = embed the face
    Lib.SetTextSize(12);
    Lib.SetVerticalWritingMode(1);            // ordinary DrawText now runs down
    H := Lib.GetVerticalTextHeight('MS Mincho', 12, '第三章 保守点検');
    Lib.DrawText(480, 72, '第三章 保守点検');
    Lib.SetVerticalWritingMode(0);            // back to horizontal
    Lib.DrawText(72, 72 + H, 'Chapter 3');
    Lib.SaveToFile('manual-ja.pdf');
  finally
    Lib.Free;
  end;
end;

چرا کروشه‌ها در متن عمودی اشتباه به‌نظر می‌رسند؟

چون یک کروشه دو فرم دارد و فقط یکی در یک ستون جای می‌گیرد. کروشه‌ها، علامت مصوت بلند و kanaهای کوچک وقتی متن پایین صفحه اجرا می‌شود متفاوت رسم می‌شوند — یک پرانتز برای نشستن در امتداد ستون چرخیده به‌جای آنکه سرتاسر آن دراز بکشد، و علامت مصوت بلند به یک خط عمودی تبدیل می‌شود. فرم‌های افقی را در یک ستون عمودی رسم کنید و هر یک روی پهلو دراز می‌کشد

PDFlibPas فرم‌ها را از ویژگی عمودی خود فونت می‌گیرد، پس هر فونت آنچه طراحش کشیده را فراهم می‌کند به‌جای یک جانشینی از روی نویسه حدس زده‌شده. آن تمایز برای درستی اهمیت دارد: یک جدول جانشینی حدسی برای موارد معمولی درست است و برای فونت‌هایی که یک نویسه را متفاوت پردازش می‌کنند اشتباه، و فونتی که هیچ فرم عمودی نام‌گذاری نمی‌کند دقیقاً همان‌طور که قبلاً بود رسم می‌شود به‌جای آنکه از جدولی عبور کند که هرگز درخواست نکرده

GetVerticalTextHeight فرم‌هایی را که واقعاً رسم می‌شوند اندازه‌گیری می‌کند، پس ستونی که نویسه‌هایش تغییر شکل می‌دهند هنوز درست اندازه‌گیری می‌شود. اندازه‌گیری فرم‌های افقی و رسم فرم‌های عمودی منبع کلاسیک ستون‌هایی است که چند نویسه از جعبه‌شان بیرون می‌زنند

رسم یک run بدون تغییر حالت

DrawVerticalText یک run واحد را عمودی رسم می‌کند، موقعیت، نام فونت، اندازه و متن را می‌گیرد، و حالت نوشتار را دست‌نخورده می‌گذارد. از آن برای استثنای عمودی درون یک سند افقی استفاده کنید — یک برچسب روی جلد، یک مهر، یک ستون واحد از نام‌ها — جایی که روشن و خاموش کردن یک حالت سراسری دور هر فراخوانی، حالت بیشتری است از آنچه کار لایق آن است

فرم‌های افقی و عمودی یک فونت درونی جدا نگه‌داشته می‌شوند، پس یک صفحه می‌تواند هر دو را بدون اینکه یکی دیگری را مختل کند حمل کند. این همان چیزی است که یک صفحه مختلط را عملی می‌کند: یک صفحه کتاب ژاپنی با متن بدنه عمودی و سرصفحه‌های روان افقی، یا یک گواهی چینی با یک عنوان عمودی روی خطوط جزئیات افقی

// One vertical run inside an otherwise horizontal page
Lib.DrawVerticalText(520, 96, 'MS Mincho', 14, '保守点検記録');
// The horizontal text around it is unaffected
Lib.DrawText(72, 96, 'Maintenance inspection record');

درست‌کردن فونت قبل از هر چیز دیگر

نوشتار عمودی کاملاً به فونت وابسته است. یک فونت CJK با متریک عمودی مناسب و یک ویژگی عمودی خروجی درست بدون کار اضافی تولید می‌کند؛ فونتی بدون آن‌ها نویسه‌های عمودی تولید می‌کند که یک em در هر مرحله advance می‌کنند و هیچ تغییر شکلی ندارند. اگر متن عمودی به‌طور ظریفی اشتباه به‌نظر می‌رسد، قبل از کد فونت را بررسی کنید

جاسازی از قواعد معمول و هزینه‌های معمول پیروی می‌کند. یک فونت کامل CJK بزرگ است، پس زیرمجموعه‌سازی برای اسنادی که به هر جایی می‌روند اختیاری نیست — یادداشت‌های بهینه‌سازی اندازه فایل PDF و زیرمجموعه‌سازی فونت پوشش می‌دهند چه انتظاری داشته باشید، و مرور جاسازی فونت‌های مفقود در یک PDF موجود مورد تعمیر را پوشش می‌دهد که یک سند عمودی بدون فونت‌هایش می‌رسد

جایی که متن عمودی هنوز به یک تصمیم چیدمان از شما نیاز دارد

ترتیب ستون. متن عمودی ژاپنی به‌ترتیب ستون از راست به چپ اجرا می‌شود، پس یک صفحه دوستونه از لبه راست شروع می‌شود، و هیچ تنظیم حالت نوشتار نمی‌تواند آن را از متن استنتاج کند. همان مورد برای ترتیب صفحه در سندی که به‌عنوان کل از راست به چپ خوانده می‌شود صدق می‌کند، و برای جایی که furigana، پاورقی‌ها و عنوان‌های figure می‌نشینند

آنچه کتابخانه تضمین می‌کند این است که هر run درست تنظیم شده: فرم‌های درست، advanceهای درست، متن قابل استخراج. جایی که runها روی صفحه می‌روند یک مسئله چیدمان است، و برای اسنادی از داده اسمبل می‌شوند مرور جستجوی متن و شمارش عنصر صفحه برای تأیید بعداً اینکه آنچه روی صفحه نشسته همان چیزی است که در نظر داشتید مفید است

PDFlibPas یک کتابخانه PDF بومی Pascal برای Delphi، C++Builder و Lazarus است، و نوشتار عمودی CJK بخشی از API رسم است به‌جای یک add-on — صفحه محصول PDFlibPas را برای لیست ویژگی‌های متن و فونت ببینید