Прецизно ограничаващо поле за глифове в PDF?

Опитвам се да изчисля точното ограничаващо поле на всеки текстов глиф във векторен PDF файл.

Това включва следене на CTM, чертане/позициониране на PDF инструкции и т.н., но също така и изчисляване на границите на всеки конкретен глиф в „пространството на глифове“ (използвайки информацията от GLYF таблиците във вградените шрифтове).

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

Моето специфично приложение е извличане на музикалната семантика от векторен PDF файл с ноти. Като такова, едно хубаво ограничение е, че мога да предположа, че глифовете не са начертани заедно в един и същ оператор Tj/TJ. Всеки глиф се рисува независимо.

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

Тук има много движещи се части и открих, че е доста трудно да се отстранят грешки. И така, ето с какво ще се радвам да ми помогнете:

  1. Този примерен PDF файл, който създадох има 10 глифа. Какво е позиционирането на ограничителната кутия на „основната истина“ за тези 10 глифа в пространството на устройството? Текущият ми код създава следното, но е неправилно. Знам, че е неправилно, защото казва, че първият глиф ("&") хоризонтално пресича втория ("˙"), което можете да видите, че не е вярно, когато преглеждате PDF в PDF четец.
'&'      ( 57.2799755477664, 600.7092061684704,  86.7452642315424, 677.1570718099680)
'\u02d9' ( 82.0030393188000, 633.6851606704608,  96.3090818379936, 644.6969866323168)
'\u0153' (144.7841941848000, 623.9630080194528, 158.6735558539200, 634.5581702962656)
'\u0153' (181.6778111184000, 619.0027260546528, 195.5671727875200, 629.5978883314656)
'w'      (226.1671727148000, 611.3638918288608, 245.0765465300448, 622.3161944071392)
'w'      (320.1063822180000, 631.2050196880608, 339.0157560332448, 642.1573222663392)
'\u0153' (414.0455917212000, 641.3239948962528, 427.9349533903200, 651.9191571730656)
'\u0153' (450.9392086548000, 636.3637129314528, 464.8285703239200, 646.9588752082656)
'\u0153' (487.9878407856000, 631.4034309666528, 501.8772024547200, 641.9985932434656)
'\u0153' (524.8814577192000, 628.9232899842528, 538.7708193883200, 639.5184522610656)
  1. Как изчислихте тези позиции? (Осъзнавам, че има много въпроси, като се има предвид сложността на PDF.) Би било от голяма полза да имам упътване и съм сигурен, че ще помогне на други в бъдеще.

  2. Има ли готов инструмент, който прави това?


person Adrian Holovaty    schedule 04.05.2015    source източник
comment
Опасявам се, че A описанието в PDF спецификацията вече е доста добро. Може да искате да зададете конкретни въпроси или да споделите своя (подреден) код за анализ, вместо да чакате някой да преформулира спецификацията. И B вашите начални позиции не изглеждат твърде далеч (разликите може да се дължат на различна целева координатна система или избрана начална точка), но правоъгълниците, които обхващате от тях, изглеждат много странни.   -  person mkl    schedule 04.05.2015


Отговори (2)


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

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

Има общо три категории шрифтове в PDF:

  1. Шрифтове с PostScript контури
  2. Шрифтове с TrueType контури
  3. Дефинирани от потребителя шрифтове.

Можете да използвате FreeType за изобразяване на глифове от шрифтове с очертания на PostScript и TrueType (можете също така да го накарате да върне пътя, ако предпочитате да го използвате).

Дефинирани от потребителя (тип 3) шрифтове, които трябва да третирате като поредица от PDF операции, мащабирани от текстовата матрица. Така че трябва да го направите сами.

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

Възможно е във вашия случай да имате работен процес, който ограничава видовете шрифтове, които можете да видите, така че може да не се нуждаете от пълно внедряване на всичко това. Например виждам, че използвате CIDFonts с очертания TrueType, но CIDToGIDMap е /Identity, което намалява обхвата на проблема.

За допълнителна сложност ще трябва да обмислите какво представлява „ограничаващата кутия“ на вашия глиф. Смятате ли, че авансовата ширина и левият страничен лагер са част от ограничителната кутия, или само зоните, отбелязани?

Не забравяйте, че PDF може да указва различни ширини за глифове от тези, дефинирани във шрифта, и двата ви шрифта включват /W масиви, които променят ширините, дефинирани във шрифта.

Ако смятате, че лявата страна и предната ширина са част от глифа, но имате /Widths масив със стойност, по-малка от предната ширина, може да изглежда, че два глифа ще се „сблъскат“, но всъщност все още има бяло пространство между тях. Всичко, което /Widths направи, е да намали бялото пространство от ширината на напредъка, така че глифовете да са по-близо един до друг, отколкото обикновено.

Имах бърз удар с това, използвайки MuPDF, което даде отговорите:

<span bbox="39.21884 163.68216 42.53509 163.99687" font="PlantinMTStd-Regular" size="11.935925">
<char bbox="39.21884 163.68216 42.53509 163.99687" x="39.21884" y="163.99687" c=" "/>

<span bbox="57.200607 163.69899 73.08967 165.2394" font="OpusStd" size="19.841537">
<char bbox="57.200607 163.69899 73.08967 165.2394" x="57.200607" y="165.2394" c="&amp;"/>

<char bbox="82.003044 151.29828 90.63545 152.83868" x="82.003044" y="152.83868" c="&#x2d9;"/>

<char bbox="144.7842 161.21884 153.1744 162.75925" x="144.7842" y="162.75925" c="&#x153;"/>

<char bbox="181.67781 166.17912 190.06801 167.71953" x="181.67781" y="167.71953" c="&#x153;"/>

<char bbox="226.16718 173.61955 236.8826 175.15996" x="226.16718" y="175.15996" c="w"/>

<char bbox="320.10638 153.77843 330.8218 155.31883" x="320.10638" y="155.31883" c="w"/>

<char bbox="414.0456 143.85785 422.4358 145.39825" x="414.0456" y="145.39825" c="&#x153;"/>

<char bbox="450.9392 148.81815 459.3294 150.35855" x="450.9392" y="150.35855" c="&#x153;"/>

<char bbox="487.98785 153.77843 496.37805 155.31883" x="487.98785" y="155.31883" c="&#x153;"/>

<char bbox="524.8815 156.25856 533.27167 157.79897" x="524.8815" y="157.79897" c="&#x153;"/>

И за пълнота, ето същата информация от Ghostscript, използвайки txtwrite устройство с -dTextFormat=0:

<page>
<span bbox="39 164 43 164" font="PlantinMTStd-Regular" size="11.9357">
<char bbox="39 164 39 164" c=" "/>
</span>
<span bbox="57 165 73 165" font="OpusStd" size="19.8411">
<char bbox="57 165 57 165" c="&amp;"/>
</span>
<span bbox="82 153 91 153" font="OpusStd" size="19.8411">
<char bbox="82 153 82 153" c="&#x2d9;"/>
</span>
<span bbox="145 163 153 163" font="OpusStd" size="19.8411">
<char bbox="145 163 145 163" c="&#x153;"/>
</span>
<span bbox="182 168 190 168" font="OpusStd" size="19.8411">
<char bbox="182 168 182 168" c="&#x153;"/>
</span>
<span bbox="226 175 237 175" font="OpusStd" size="19.8411">
<char bbox="226 175 226 175" c="w"/>
</span>
<span bbox="320 155 331 155" font="OpusStd" size="19.8411">
<char bbox="320 155 320 155" c="w"/>
</span>
<span bbox="414 145 422 145" font="OpusStd" size="19.8411">
<char bbox="414 145 414 145" c="&#x153;"/>
</span>
<span bbox="451 150 459 150" font="OpusStd" size="19.8411">
<char bbox="451 150 451 150" c="&#x153;"/>
</span>
<span bbox="488 155 496 155" font="OpusStd" size="19.8411">
<char bbox="488 155 488 155" c="&#x153;"/>
</span>
<span bbox="525 158 533 158" font="OpusStd" size="19.8411">
<char bbox="525 158 525 158" c="&#x153;"/>
</span>
</page>

Изглежда обаче, че там има грешка, urx стойността е неправилна в char bbox, но е правилна в span bbox.

person KenS    schedule 04.05.2015
comment
ще трябва да обмислите какво представлява "ограничаващата кутия" - благодаря, че посочихте това. Току-що редактирах въпроса, за да изясня. - person Adrian Holovaty; 04.05.2015

Може също да искате да разгледате това хранилище на Adobe GitHub:

Поддиректорията afdko съдържа много инструменти за команден ред, които могат да бъдат полезни за тестване, проверка и конвертиране на файлове с шрифтове. Използвах инструмента tx от това хранилище, за да отпечатам малко информация за файла с шрифтове, извлечен с mutool extract от вашия PDF образец:

$ mutool extract pdf_example.pdf

 extracting font QNAAAA+PlantinMTStd-Regular-0013.ttf
 extracting font QSAAAA+OpusStd-0018.ttf

Тогава:

$  tx -mtx  QSAAAA+OpusStd-0018.ttf 

 tx: --- QSAAAA+OpusStd-0018.ttf
 tx: (ttr) cmap table missing
 ### glyph[tag] {gname,enc,width,{left,bottom,right,top}}
 glyph[0] {.notdef,-,0,{0,0,0,0}}
 glyph[1] {g1,-,1640,{4,-1313,1489,2540}}
 glyph[2] {g2,-,891,{0,-276,721,279}}
 glyph[3] {g3,-,866,{0,-266,700,268}}
 glyph[4] {g4,-,1106,{0,-276,953,276}}

Може би това или някой от другите 28 инструмента на командния ред в това репо също може да ви бъде полезен...

person Kurt Pfeifle    schedule 04.05.2015