Техническа статия

Вертикален японски и китайски текст в PDF с Delphi

PDFlibPas чертае японски и китайски текст надолу по страницата. SetVerticalWritingMode включва вертикално писане, обикновените извиквания на DrawText след това текат надолу, а GetVerticalWritingMode отчита текущото състояние. Преди това да съществува, нареждането на текст вертикално означаваше да поставите всеки символ ръчно и да се надявате разстоянията да изглеждат правилни

Вертикалното писане не е хоризонтален текст, завъртян на деветдесет градуса. Символите остават изправени, движението се извършва надолу вместо настрани, а редица символи променят изцяло формата си — което е частта, която отделя документ, четящ се естествено, от такъв, който японски читател веднага разпознава като машинно създаден

Какво се променя вътре в PDF

Текстът, начертан по този начин, минава през Type0 шрифт във вертикален режим на писане, носещ собствените вертикални метрики на шрифта. Това има значение в две посоки. Четецът придвижда всеки символ с разстоянието, което неговият дизайнер е предвидил, а не с еднаква стъпка, така че колоната има ритъма, за който шрифтът е бил нарисуван. И копирането на текста връща оригиналните символи, защото вертикалното преживяване все още е истински текст с правилно съпоставяне, а не последователност от позиционирани глифове

Шрифт, който не носи собствени вертикални метрики, придвижва с един em на символ, което е точно това, което четецът би направил с подразбирането. Този резерв си струва да се знае, защото е разликата, която ще видите, когато документ се рендерира правилно с настоящ CJK шрифт и изглежда механично разположен с латински шрифт, който случайно съдържа някои кана

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;

Защо скобите изглеждат грешно във вертикален текст?

Защото една скоба има две форми и само една от тях принадлежи на колона. Скобите, знакът за дълга гласна и малките кана се чертаят различно, когато текстът тече надолу по страницата — една кръгла скоба се завърта, за да седи по дължината на колоната, вместо да лежи напречно, а знакът за дълга гласна става вертикална черта. Начертайте хоризонталните форми във вертикална колона и всяка от тях лежи на една страна

PDFlibPas взима формите от собствената вертикална характеристика на шрифта, така че всеки шрифт доставя това, което неговият дизайнер е нарисувал, а не заместване, отгатнато от символа. Това разграничение има значение за правилността: таблица с отгатнати замествания е правилна за често срещаните случаи и грешна за шрифтовете, които третират символ различно, а шрифт, който не назовава вертикални форми, се чертае точно както преди, вместо да бъде принуждаван през таблица, за която никога не е питал

GetVerticalTextHeight измерва формите, които реално ще бъдат начертани, така че колона, чиито символи променят форма, все още се измерва правилно. Измерването на хоризонталните форми и чертането на вертикалните е класическият източник на колони, които преливат от своята кутия с няколко символа

Чертане на едно преживяване без промяна на режима

DrawVerticalText чертае едно преживяване вертикално, приема позицията, името на шрифта, размера и текста, и оставя режима на писане на мира. Използвайте го за вертикалното изключение вътре в хоризонтален документ — етикет на гръб, печат, една колона с имена — където превключването на глобален режим на всички и от всички около всяко извикване е повече състояние, отколкото задачата заслужава

Хоризонталните и вертикалните форми на един шрифт се пазят отделно вътрешно, така че една страница може да носи и двете без едната да смущава другата. Това е точно това, което прави смесена страница практична: японска книжна страница с вертикален основен текст и хоризонтални колонтитули, или китайско удостоверение с вертикално заглавие над хоризонтални детайлни редове

// 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 наведнъж, без никакви промени на формата. Ако вертикалният текст изглежда фино грешен, прегледайте шрифта, преди да преглеждате кода

Вграждането следва обичайните правила и обичайните разходи. Пълен CJK шрифт е голям, така че подмножаването не е по желание за документи, които отиват някъде — записките за оптимизация на размера на PDF файл и подмножаване на шрифтове разглеждат какво да се очаква, а ръководството за вграждане на липсващи шрифтове в съществуващ PDF разглежда случая на поправка, при който вертикален документ пристига без шрифтовете си

Къде вертикалният текст все още се нуждае от решение за оформление от вас

Ред на колоните. Японският вертикален текст тече отдясно наляво по колони, така че двуколонна страница започва от десния ръб, и никоя настройка на режим на писане не може да го изведе от текста. Същото се отнася за реда на страниците в документ, който се чете отдясно наляво като цяло, и за това къде седят фуригана, бележките под линия и надписите на фигурите

Това, което библиотеката гарантира, е, че всяко преживяване е наредено правилно: правилни форми, правилни придвижвания, извлекаем текст. Къде отиват преживяванията на страницата е проблем за оформление, а за документи, сглобени от данни, ръководството за търсене на текст и изброяване на елементи на страница е полезно за последваща проверка, че това, което е попаднало на страницата, е това, което сте имали предвид

PDFlibPas е нативна Pascal PDF библиотека за Delphi, C++Builder и Lazarus, а вертикално CJK писане е част от API за чертане, а не добавка — вижте страницата на продукта PDFlibPas за списъка с функции за текст и шрифтове