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

HotPDF TextOut в Delphi: Размер, стил, ротация и разстояние

Всяка видима последователност от знаци в HotPDF документ пристига чрез едно извикване: TextOut(X, Y, angle, Text). Примерът Hello World го използва в най-чистия му вид, шрифт зададен веднъж и четири аргумента оставени на разумни стойности по подразбиране. След тази първа страница същите четири аргумента носят цялата тежест на оформлението. Третият аргумент завърта текста. Шрифтът, зададен точно преди това, определя размера и стила. И двойката X, Y, измерена от ъгъла на страницата в пунктове, е единственото нещо, което стои между чист отчет и текст, който се припокрива, изрязва или се измества с един ред по-надолу на нечий чужд принтер. Тук TextOut си изработва прехраната и където стойностите по подразбиране престават да бъдат достатъчни

Сигнатурата си струва да се фиксира в ума преди всичко останало: X и Y са Single в пунктове, angle е Extended в градуси, а Text е WideString, така че Unicode преминава без отделно извикване. Второ претоварване приема PWORD плюс дължина, за случаите когато вече държите кодове на глифове, но за обикновени низове формата WideString е тази, към която посягате

Размерът и стилът идват от SetFont, а не от TextOut

TextOut няма параметър за размер. Размерът, дебелината, наклонът, всичко това живее в извикването SetFont, което предшества текста, и остава в сила, докато следващият SetFont не го замени. Това е единственият факт, който обяснява по-голямата част от объркването в първия ден: ред излиза получер, защото три извиквания по-рано нещо е задало [fsBold] и нищо не го е изчистило

Pdf.CurrentPage.SetFont('Times New Roman', [], 24);
Pdf.CurrentPage.TextOut(72, 740, 0, 'Quarterly Report');        // 24pt regular

Pdf.CurrentPage.SetFont('Times New Roman', [fsBold], 12);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Revenue');                 // 12pt bold

Pdf.CurrentPage.SetFont('Times New Roman', [fsItalic], 11);
Pdf.CurrentPage.TextOut(72, 694, 0, 'figures in thousands');    // 11pt italic

Pdf.CurrentPage.SetFont('Courier New', [fsBold, fsItalic], 10);
Pdf.CurrentPage.TextOut(72, 676, 0, '  +18.4% YoY');            // styles combine

Вторият аргумент е набор TFontStyles, така че [fsBold, fsItalic] е получер курсив, а [] е обикновен. Размерът е в пунктове, същата единица като координатите, което прави вертикалното разстояние лесно за обмисляне: 12-пунктов ред иска грубо 14 до 16 пункта вертикална стъпка, за да диша, така че намаляването на Y с 14 на ред е разумно начално разстояние между редовете. Няма автоматично преминаване на нов ред. Вие сами изчислявате всяка базова линия, което е досадно за абзац, но точно за формуляр, където всяко поле се намира на фиксирана координата

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

HotPDF TextOut страница, показваща Arial, Times New Roman и Courier New, изобразени с обикновен, получер и курсивен стил в няколко набора от знаци

Аргументът за ъгъл се върти около котвата

Третият аргумент е този, който повечето код оставя на нула завинаги. Подайте ненулева стойност и текстът се завърта обратно на часовниковата стрелка около собствената си (X, Y) котва, долната лява част на текста, с толкова градуса. Самата котва не се движи, така че същата координата, която е поставила хоризонтален етикет, поставя неговия завъртян близнак; само посоката, в която маршируват глифовете, се променя

Pdf.CurrentPage.SetFont('Arial', [fsBold], 11);

// A vertical axis label down the left margin: 90 degrees reads bottom-to-top.
Pdf.CurrentPage.TextOut(40, 300, 90, 'Units sold');

// A diagonal DRAFT watermark across the page body.
Pdf.CurrentPage.SetFont('Arial', [fsBold], 60);
Pdf.CurrentPage.TextOut(150, 250, 45, 'DRAFT');

// Column headers tilted 60 degrees so long labels fit a narrow table.
Pdf.CurrentPage.SetFont('Arial', [], 9);
Pdf.CurrentPage.TextOut(120, 600, 60, 'Q1 actual');
Pdf.CurrentPage.TextOut(160, 600, 60, 'Q2 actual');

Деветдесет градуса е често срещаният случай, етикет, вървящ нагоре отстрани на диаграма или заглавие на гръбче. Четиридесет и пет градуса се справят с наклонени заглавки на колони, трикът, който позволява широк етикет да седи над тясна колона, без да се прехвърля в съседите си. Завъртането не променя начина, по който се интерпретира котвата, което спъва хората: текст на 90 градуса все още започва от (X, Y) и расте нагоре оттам, така че за да центрирате завъртян етикет, коригирате котвата, а не ъгъла. Когато няколко завъртени текста споделят базова линия, дайте им еднакво Y и стъпка X, точно както бихте направили стъпка Y за подредени хоризонтални редове

Поставяне на координати без гадаене

Координатите са частта, която оцелява при преглед или тихо се проваля. HotPDF измерва от долния ляв ъгъл на страницата, Y расте нагоре, в пунктове по 72 на инч. Страница US Letter е 612 на 792 пункта; A4 е 595 на 842. Поле от един инч отгоре на Letter следователно поставя първата ви базова линия близо до Y = 792 минус 72 минус размера на шрифта, а не на някакво малко число близо до върха. Всеки, пристигащ от екранни координати, където Y расте надолу от нула, записва първия ред извън долния ръб и прекарва десет минути в чудене къде е отишъл

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

const
  LeftMargin = 72;        // 1 inch in
  TopBaseline = 720;       // first line, ~1 inch down on Letter
  Leading = 16;            // vertical step between lines
var
  Y: Single;
  Line: string;
begin
  Pdf.CurrentPage.SetFont('Arial', [], 11);
  Y := TopBaseline;
  for Line in ReportLines do
  begin
    Pdf.CurrentPage.TextOut(LeftMargin, Y, 0, Line);
    Y := Y - Leading;
    if Y < 72 then            // bottom margin reached
    begin
      Pdf.AddPage;
      Pdf.CurrentPage.SetFont('Arial', [], 11);  // font resets on a new page
      Y := TopBaseline;
    end;
  end;
end;

Предпазителят за прекъсване на страница е редът, който всеки забравя пръв, и който удря полето най-силно. Няма потоково оформление под TextOut. Намалете под долното поле и текстът продължава да се чертае в улея, извън страницата, в нищото, без предупреждение. Така че сами следите Y, извиквате AddPage, когато пресече пода, и нулирате базовата линия. SetFont след AddPage не е опционален пълнеж: текущият шрифт не оцелява след прекъсване на страницата и първият текст на новата страница излиза в шрифта по подразбиране на зрителя, ако го пропуснете

Разстояние между знаците и думите за напасване и подравняване

Понякога низът е правилен, но с грешна ширина: заглавка, която трябва да обхване фиксирана линия, код, който трябва да се чете с по-въздушни цифри, колона, която се нуждае нейните стойности да бъдат побутнати, за да се подравнят. PDF носи два оператора за текстово състояние за това, разстояние между знаците (Tc, допълнително пространство, добавено след всеки глиф) и разстояние между думите (Tw, допълнително пространство, добавено при всеки знак за интервал), и двете са изразени в немащабирани единици на текстовото пространство, ефективно пунктове при текущия размер на шрифта. Те са състояние, а не аргументи за TextOut, така че ги задавате, чертаете и ги задавате обратно

// Letter-space a short heading so it stretches across a rule.
Pdf.CurrentPage.SetCharacterSpacing(4);
Pdf.CurrentPage.SetFont('Arial', [fsBold], 14);
Pdf.CurrentPage.TextOut(72, 740, 0, 'S U M M A R Y');
Pdf.CurrentPage.SetCharacterSpacing(0);   // reset before normal body text

// Open up the gaps between words on a single wide line.
Pdf.CurrentPage.SetWordSpacing(6);
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Name        Department        Extension');
Pdf.CurrentPage.SetWordSpacing(0);

Разстоянието между думите действа само върху знака за интервал (код 32), което има следствие, което си струва да се знае: то не прави нищо в CJK текст, който няма ASCII интервали, и взаимодейства странно с текст, кодиран като индекси на глифове, а не като байтове. За табличен изход на латиница това е евтиният начин за разширяване на празнините без пренаписване на низа. Разстоянието между знаците е по-добрият инструмент за заглавие, което трябва да достигне целева ширина, тъй като разпределя корекцията равномерно върху всеки глиф, вместо да я обединява в интервалите

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

HotPDF TextOut страница, сравняваща хоризонтално мащабиране на текст, разстояние между знаците, разстояние между думите и режими на изобразяване със запълване срещу очертание

Проверка на изхода там, където всъщност се чупи

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

Ако все още не сте написали нито една страница, започнете с примера за Hello World на HotPDF, който настройва документа, шрифта и координатната система отдолу-наляво, от която зависи всичко по-горе. Извикванията TextOut, SetFont и за разстояние, показани тук, са част от HotPDF Component за Delphi и C++Builder