ttload.c 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849
  1. /***************************************************************************/
  2. /* */
  3. /* ttload.c */
  4. /* */
  5. /* Load the basic TrueType tables, i.e., tables that can be either in */
  6. /* TTF or OTF fonts (body). */
  7. /* */
  8. /* Copyright 1996-2001, 2002 by */
  9. /* David Turner, Robert Wilhelm, and Werner Lemberg. */
  10. /* */
  11. /* This file is part of the FreeType project, and may only be used, */
  12. /* modified, and distributed under the terms of the FreeType project */
  13. /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
  14. /* this file you indicate that you have read the license and */
  15. /* understand and accept it fully. */
  16. /* */
  17. /***************************************************************************/
  18. #include <ft2build.h>
  19. #include FT_INTERNAL_DEBUG_H
  20. #include FT_INTERNAL_STREAM_H
  21. #include FT_TRUETYPE_TAGS_H
  22. #include "ttload.h"
  23. #include "ttcmap.h"
  24. #include "sferrors.h"
  25. /*************************************************************************/
  26. /* */
  27. /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
  28. /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
  29. /* messages during execution. */
  30. /* */
  31. #undef FT_COMPONENT
  32. #define FT_COMPONENT trace_ttload
  33. /*************************************************************************/
  34. /* */
  35. /* <Function> */
  36. /* tt_face_lookup_table */
  37. /* */
  38. /* <Description> */
  39. /* Looks for a TrueType table by name. */
  40. /* */
  41. /* <Input> */
  42. /* face :: A face object handle. */
  43. /* */
  44. /* tag :: The searched tag. */
  45. /* */
  46. /* <Return> */
  47. /* A pointer to the table directory entry. 0 if not found. */
  48. /* */
  49. FT_LOCAL_DEF( TT_Table )
  50. tt_face_lookup_table( TT_Face face,
  51. FT_ULong tag )
  52. {
  53. TT_Table entry;
  54. TT_Table limit;
  55. FT_TRACE3(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ",
  56. face,
  57. (FT_Char)( tag >> 24 ),
  58. (FT_Char)( tag >> 16 ),
  59. (FT_Char)( tag >> 8 ),
  60. (FT_Char)( tag ) ));
  61. entry = face->dir_tables;
  62. limit = entry + face->num_tables;
  63. for ( ; entry < limit; entry++ )
  64. {
  65. /* For compatibility with Windows, we consider 0-length */
  66. /* tables the same as missing tables. */
  67. if ( entry->Tag == tag && entry->Length != 0 )
  68. {
  69. FT_TRACE3(( "found table.\n" ));
  70. return entry;
  71. }
  72. }
  73. FT_TRACE3(( "could not find table!\n" ));
  74. return 0;
  75. }
  76. /*************************************************************************/
  77. /* */
  78. /* <Function> */
  79. /* tt_face_goto_table */
  80. /* */
  81. /* <Description> */
  82. /* Looks for a TrueType table by name, then seek a stream to it. */
  83. /* */
  84. /* <Input> */
  85. /* face :: A face object handle. */
  86. /* */
  87. /* tag :: The searched tag. */
  88. /* */
  89. /* stream :: The stream to seek when the table is found. */
  90. /* */
  91. /* <Output> */
  92. /* length :: The length of the table if found, undefined otherwise. */
  93. /* */
  94. /* <Return> */
  95. /* FreeType error code. 0 means success. */
  96. /* */
  97. FT_LOCAL_DEF( FT_Error )
  98. tt_face_goto_table( TT_Face face,
  99. FT_ULong tag,
  100. FT_Stream stream,
  101. FT_ULong* length )
  102. {
  103. TT_Table table;
  104. FT_Error error;
  105. table = tt_face_lookup_table( face, tag );
  106. if ( table )
  107. {
  108. if ( length )
  109. *length = table->Length;
  110. if ( FT_STREAM_SEEK( table->Offset ) )
  111. goto Exit;
  112. }
  113. else
  114. error = SFNT_Err_Table_Missing;
  115. Exit:
  116. return error;
  117. }
  118. /* In theory, we should check the values of `search_range', */
  119. /* `entry_selector', and `range_shift' to detect non-SFNT based files */
  120. /* whose header might also start with 0x100000L (yes, these exist). */
  121. /* */
  122. /* Very unfortunately, many TrueType fonts don't have these fields */
  123. /* set correctly and we must ignore them to support them. An alternative */
  124. /* way to check the font file is thus to: */
  125. /* */
  126. /* - check that `num_tables' is valid */
  127. /* - look for a "head" table, check its size, and parse it to */
  128. /* see if its "magic" field is correctly set */
  129. /* */
  130. /* When checking directory entries, ignore the tables `glyx' and `locx' */
  131. /* which are hacked-out versions of `glyf' and `loca' in some PostScript */
  132. /* Type 42 fonts, and will generally be invalid. */
  133. /* */
  134. static FT_Error
  135. sfnt_dir_check( FT_Stream stream,
  136. FT_ULong offset,
  137. FT_UInt num_tables )
  138. {
  139. FT_Error error;
  140. FT_UInt nn, has_head = 0;
  141. const FT_ULong glyx_tag = FT_MAKE_TAG( 'g', 'l', 'y', 'x' );
  142. const FT_ULong locx_tag = FT_MAKE_TAG( 'l', 'o', 'c', 'x' );
  143. static const FT_Frame_Field sfnt_dir_entry_fields[] =
  144. {
  145. #undef FT_STRUCTURE
  146. #define FT_STRUCTURE TT_TableRec
  147. FT_FRAME_START( 16 ),
  148. FT_FRAME_ULONG( Tag ),
  149. FT_FRAME_ULONG( CheckSum ),
  150. FT_FRAME_ULONG( Offset ),
  151. FT_FRAME_ULONG( Length ),
  152. FT_FRAME_END
  153. };
  154. /* if 'num_tables' is 0, read the table count from the file */
  155. if ( num_tables == 0 )
  156. {
  157. FT_ULong format_tag;
  158. if ( FT_STREAM_SEEK( offset ) ||
  159. FT_READ_ULONG ( format_tag ) ||
  160. FT_READ_USHORT( num_tables ) ||
  161. FT_STREAM_SKIP( 6 ) )
  162. goto Bad_Format;
  163. if ( offset + 12 + num_tables*16 > stream->size )
  164. goto Bad_Format;
  165. }
  166. else if ( FT_STREAM_SEEK( offset + 12 ) )
  167. goto Bad_Format;
  168. for ( nn = 0; nn < num_tables; nn++ )
  169. {
  170. TT_TableRec table;
  171. if ( FT_STREAM_READ_FIELDS( sfnt_dir_entry_fields, &table ) )
  172. goto Bad_Format;
  173. if ( table.Offset + table.Length > stream->size &&
  174. table.Tag != glyx_tag && table.Tag != locx_tag )
  175. goto Bad_Format;
  176. if ( table.Tag == TTAG_head )
  177. {
  178. FT_UInt32 magic;
  179. has_head = 1;
  180. if ( table.Length != 0x36 ||
  181. FT_STREAM_SEEK( table.Offset + 12 ) ||
  182. FT_READ_ULONG( magic ) ||
  183. magic != 0x5F0F3CF5UL )
  184. goto Bad_Format;
  185. if ( FT_STREAM_SEEK( offset + 28 + 16*nn ) )
  186. goto Bad_Format;
  187. }
  188. }
  189. if ( has_head == 0 )
  190. goto Bad_Format;
  191. Exit:
  192. return error;
  193. Bad_Format:
  194. error = FT_Err_Unknown_File_Format;
  195. goto Exit;
  196. }
  197. /*************************************************************************/
  198. /* */
  199. /* <Function> */
  200. /* tt_face_load_sfnt_header */
  201. /* */
  202. /* <Description> */
  203. /* Loads the header of a SFNT font file. Supports collections. */
  204. /* */
  205. /* <Input> */
  206. /* face :: A handle to the target face object. */
  207. /* */
  208. /* stream :: The input stream. */
  209. /* */
  210. /* face_index :: If the font is a collection, the number of the font */
  211. /* in the collection, ignored otherwise. */
  212. /* */
  213. /* <Output> */
  214. /* sfnt :: The SFNT header. */
  215. /* */
  216. /* <Return> */
  217. /* FreeType error code. 0 means success. */
  218. /* */
  219. /* <Note> */
  220. /* The stream cursor must be at the font file's origin. */
  221. /* */
  222. /* This function recognizes fonts embedded in a `TrueType collection' */
  223. /* */
  224. /* The header will be checked whether it is valid by looking at the */
  225. /* values of `search_range', `entry_selector', and `range_shift'. */
  226. /* */
  227. FT_LOCAL_DEF( FT_Error )
  228. tt_face_load_sfnt_header( TT_Face face,
  229. FT_Stream stream,
  230. FT_Long face_index,
  231. SFNT_Header sfnt )
  232. {
  233. FT_Error error;
  234. FT_ULong format_tag, offset;
  235. FT_Memory memory = stream->memory;
  236. static const FT_Frame_Field sfnt_header_fields[] =
  237. {
  238. #undef FT_STRUCTURE
  239. #define FT_STRUCTURE SFNT_HeaderRec
  240. FT_FRAME_START( 8 ),
  241. FT_FRAME_USHORT( num_tables ),
  242. FT_FRAME_USHORT( search_range ),
  243. FT_FRAME_USHORT( entry_selector ),
  244. FT_FRAME_USHORT( range_shift ),
  245. FT_FRAME_END
  246. };
  247. static const FT_Frame_Field ttc_header_fields[] =
  248. {
  249. #undef FT_STRUCTURE
  250. #define FT_STRUCTURE TTC_HeaderRec
  251. FT_FRAME_START( 8 ),
  252. FT_FRAME_LONG( version ),
  253. FT_FRAME_LONG( count ),
  254. FT_FRAME_END
  255. };
  256. FT_TRACE2(( "tt_face_load_sfnt_header: %08p, %ld\n",
  257. face, face_index ));
  258. face->ttc_header.tag = 0;
  259. face->ttc_header.version = 0;
  260. face->ttc_header.count = 0;
  261. face->num_tables = 0;
  262. /* first of all, read the first 4 bytes. If it is `ttcf', then the */
  263. /* file is a TrueType collection, otherwise it can be any other */
  264. /* kind of font. */
  265. /* */
  266. offset = FT_STREAM_POS();
  267. if ( FT_READ_ULONG( format_tag ) )
  268. goto Exit;
  269. if ( format_tag == TTAG_ttcf )
  270. {
  271. FT_Int n;
  272. FT_TRACE3(( "tt_face_load_sfnt_header: file is a collection\n" ));
  273. /* It is a TrueType collection, i.e. a file containing several */
  274. /* font files. Read the font directory now */
  275. if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
  276. goto Exit;
  277. /* now read the offsets of each font in the file */
  278. if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ||
  279. FT_FRAME_ENTER( face->ttc_header.count * 4L ) )
  280. goto Exit;
  281. for ( n = 0; n < face->ttc_header.count; n++ )
  282. face->ttc_header.offsets[n] = FT_GET_ULONG();
  283. FT_FRAME_EXIT();
  284. /* check face index */
  285. if ( face_index >= face->ttc_header.count )
  286. {
  287. error = SFNT_Err_Bad_Argument;
  288. goto Exit;
  289. }
  290. /* seek to the appropriate TrueType file, then read tag */
  291. offset = face->ttc_header.offsets[face_index];
  292. if ( FT_STREAM_SEEK( offset ) ||
  293. FT_READ_LONG( format_tag ) )
  294. goto Exit;
  295. }
  296. /* the format tag was read, now check the rest of the header */
  297. sfnt->format_tag = format_tag;
  298. sfnt->offset = offset;
  299. if ( FT_STREAM_READ_FIELDS( sfnt_header_fields, sfnt ) )
  300. goto Exit;
  301. /* now check the sfnt directory */
  302. error = sfnt_dir_check( stream, offset, sfnt->num_tables );
  303. if ( error )
  304. {
  305. FT_TRACE2(( "tt_face_load_sfnt_header: file is not SFNT!\n" ));
  306. error = SFNT_Err_Unknown_File_Format;
  307. }
  308. Exit:
  309. return error;
  310. }
  311. /*************************************************************************/
  312. /* */
  313. /* <Function> */
  314. /* tt_face_load_directory */
  315. /* */
  316. /* <Description> */
  317. /* Loads the table directory into a face object. */
  318. /* */
  319. /* <InOut> */
  320. /* face :: A handle to the target face object. */
  321. /* */
  322. /* <Input> */
  323. /* stream :: The input stream. */
  324. /* */
  325. /* sfnt :: The SFNT directory header. */
  326. /* */
  327. /* <Return> */
  328. /* FreeType error code. 0 means success. */
  329. /* */
  330. /* <Note> */
  331. /* The stream cursor must be at the font file's origin. */
  332. /* */
  333. FT_LOCAL_DEF( FT_Error )
  334. tt_face_load_directory( TT_Face face,
  335. FT_Stream stream,
  336. SFNT_Header sfnt )
  337. {
  338. FT_Error error;
  339. FT_Memory memory = stream->memory;
  340. TT_TableRec *entry, *limit;
  341. FT_TRACE2(( "tt_face_load_directory: %08p\n", face ));
  342. FT_TRACE2(( "-- Tables count: %12u\n", sfnt->num_tables ));
  343. FT_TRACE2(( "-- Format version: %08lx\n", sfnt->format_tag ));
  344. face->num_tables = sfnt->num_tables;
  345. if ( FT_NEW_ARRAY( face->dir_tables, face->num_tables ) )
  346. goto Exit;
  347. if ( FT_STREAM_SEEK( sfnt->offset + 12 ) ||
  348. FT_FRAME_ENTER( face->num_tables * 16L ) )
  349. goto Exit;
  350. entry = face->dir_tables;
  351. limit = entry + face->num_tables;
  352. for ( ; entry < limit; entry++ )
  353. { /* loop through the tables and get all entries */
  354. entry->Tag = FT_GET_TAG4();
  355. entry->CheckSum = FT_GET_ULONG();
  356. entry->Offset = FT_GET_LONG();
  357. entry->Length = FT_GET_LONG();
  358. FT_TRACE2(( " %c%c%c%c - %08lx - %08lx\n",
  359. (FT_Char)( entry->Tag >> 24 ),
  360. (FT_Char)( entry->Tag >> 16 ),
  361. (FT_Char)( entry->Tag >> 8 ),
  362. (FT_Char)( entry->Tag ),
  363. entry->Offset,
  364. entry->Length ));
  365. }
  366. FT_FRAME_EXIT();
  367. FT_TRACE2(( "Directory loaded\n\n" ));
  368. Exit:
  369. return error;
  370. }
  371. /*************************************************************************/
  372. /* */
  373. /* <Function> */
  374. /* tt_face_load_any */
  375. /* */
  376. /* <Description> */
  377. /* Loads any font table into client memory. */
  378. /* */
  379. /* <Input> */
  380. /* face :: The face object to look for. */
  381. /* */
  382. /* tag :: The tag of table to load. Use the value 0 if you want */
  383. /* to access the whole font file, else set this parameter */
  384. /* to a valid TrueType table tag that you can forge with */
  385. /* the MAKE_TT_TAG macro. */
  386. /* */
  387. /* offset :: The starting offset in the table (or the file if */
  388. /* tag == 0). */
  389. /* */
  390. /* length :: The address of the decision variable: */
  391. /* */
  392. /* If length == NULL: */
  393. /* Loads the whole table. Returns an error if */
  394. /* `offset' == 0! */
  395. /* */
  396. /* If *length == 0: */
  397. /* Exits immediately; returning the length of the given */
  398. /* table or of the font file, depending on the value of */
  399. /* `tag'. */
  400. /* */
  401. /* If *length != 0: */
  402. /* Loads the next `length' bytes of table or font, */
  403. /* starting at offset `offset' (in table or font too). */
  404. /* */
  405. /* <Output> */
  406. /* buffer :: The address of target buffer. */
  407. /* */
  408. /* <Return> */
  409. /* FreeType error code. 0 means success. */
  410. /* */
  411. FT_LOCAL_DEF( FT_Error )
  412. tt_face_load_any( TT_Face face,
  413. FT_ULong tag,
  414. FT_Long offset,
  415. FT_Byte* buffer,
  416. FT_ULong* length )
  417. {
  418. FT_Error error;
  419. FT_Stream stream;
  420. TT_Table table;
  421. FT_ULong size;
  422. if ( tag != 0 )
  423. {
  424. /* look for tag in font directory */
  425. table = tt_face_lookup_table( face, tag );
  426. if ( !table )
  427. {
  428. error = SFNT_Err_Table_Missing;
  429. goto Exit;
  430. }
  431. offset += table->Offset;
  432. size = table->Length;
  433. }
  434. else
  435. /* tag == 0 -- the user wants to access the font file directly */
  436. size = face->root.stream->size;
  437. if ( length && *length == 0 )
  438. {
  439. *length = size;
  440. return SFNT_Err_Ok;
  441. }
  442. if ( length )
  443. size = *length;
  444. stream = face->root.stream;
  445. /* the `if' is syntactic sugar for picky compilers */
  446. if ( FT_STREAM_READ_AT( offset, buffer, size ) )
  447. goto Exit;
  448. Exit:
  449. return error;
  450. }
  451. /*************************************************************************/
  452. /* */
  453. /* <Function> */
  454. /* tt_face_load_generic_header */
  455. /* */
  456. /* <Description> */
  457. /* Loads the TrueType table `head' or `bhed'. */
  458. /* */
  459. /* <Input> */
  460. /* face :: A handle to the target face object. */
  461. /* */
  462. /* stream :: The input stream. */
  463. /* */
  464. /* <Return> */
  465. /* FreeType error code. 0 means success. */
  466. /* */
  467. static FT_Error
  468. tt_face_load_generic_header( TT_Face face,
  469. FT_Stream stream,
  470. FT_ULong tag )
  471. {
  472. FT_Error error;
  473. TT_Header* header;
  474. static const FT_Frame_Field header_fields[] =
  475. {
  476. #undef FT_STRUCTURE
  477. #define FT_STRUCTURE TT_Header
  478. FT_FRAME_START( 54 ),
  479. FT_FRAME_ULONG ( Table_Version ),
  480. FT_FRAME_ULONG ( Font_Revision ),
  481. FT_FRAME_LONG ( CheckSum_Adjust ),
  482. FT_FRAME_LONG ( Magic_Number ),
  483. FT_FRAME_USHORT( Flags ),
  484. FT_FRAME_USHORT( Units_Per_EM ),
  485. FT_FRAME_LONG ( Created[0] ),
  486. FT_FRAME_LONG ( Created[1] ),
  487. FT_FRAME_LONG ( Modified[0] ),
  488. FT_FRAME_LONG ( Modified[1] ),
  489. FT_FRAME_SHORT ( xMin ),
  490. FT_FRAME_SHORT ( yMin ),
  491. FT_FRAME_SHORT ( xMax ),
  492. FT_FRAME_SHORT ( yMax ),
  493. FT_FRAME_USHORT( Mac_Style ),
  494. FT_FRAME_USHORT( Lowest_Rec_PPEM ),
  495. FT_FRAME_SHORT ( Font_Direction ),
  496. FT_FRAME_SHORT ( Index_To_Loc_Format ),
  497. FT_FRAME_SHORT ( Glyph_Data_Format ),
  498. FT_FRAME_END
  499. };
  500. FT_TRACE2(( "tt_face_load_generic_header: "
  501. "%08p, looking up font table `%c%c%c%c'.\n",
  502. face,
  503. (FT_Char)( tag >> 24 ),
  504. (FT_Char)( tag >> 16 ),
  505. (FT_Char)( tag >> 8 ),
  506. (FT_Char)( tag ) ));
  507. error = face->goto_table( face, tag, stream, 0 );
  508. if ( error )
  509. {
  510. FT_TRACE2(( "tt_face_load_generic_header: Font table is missing!\n" ));
  511. goto Exit;
  512. }
  513. header = &face->header;
  514. if ( FT_STREAM_READ_FIELDS( header_fields, header ) )
  515. goto Exit;
  516. FT_TRACE2(( " Units per EM: %8u\n", header->Units_Per_EM ));
  517. FT_TRACE2(( " IndexToLoc: %8d\n", header->Index_To_Loc_Format ));
  518. FT_TRACE2(( "tt_face_load_generic_header: Font table loaded.\n" ));
  519. Exit:
  520. return error;
  521. }
  522. FT_LOCAL_DEF( FT_Error )
  523. tt_face_load_header( TT_Face face,
  524. FT_Stream stream )
  525. {
  526. return tt_face_load_generic_header( face, stream, TTAG_head );
  527. }
  528. #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
  529. FT_LOCAL_DEF( FT_Error )
  530. tt_face_load_bitmap_header( TT_Face face,
  531. FT_Stream stream )
  532. {
  533. return tt_face_load_generic_header( face, stream, TTAG_bhed );
  534. }
  535. #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
  536. /*************************************************************************/
  537. /* */
  538. /* <Function> */
  539. /* tt_face_load_max_profile */
  540. /* */
  541. /* <Description> */
  542. /* Loads the maximum profile into a face object. */
  543. /* */
  544. /* <Input> */
  545. /* face :: A handle to the target face object. */
  546. /* */
  547. /* stream :: The input stream. */
  548. /* */
  549. /* <Return> */
  550. /* FreeType error code. 0 means success. */
  551. /* */
  552. FT_LOCAL_DEF( FT_Error )
  553. tt_face_load_max_profile( TT_Face face,
  554. FT_Stream stream )
  555. {
  556. FT_Error error;
  557. TT_MaxProfile* maxProfile = &face->max_profile;
  558. const FT_Frame_Field maxp_fields[] =
  559. {
  560. #undef FT_STRUCTURE
  561. #define FT_STRUCTURE TT_MaxProfile
  562. FT_FRAME_START( 6 ),
  563. FT_FRAME_LONG ( version ),
  564. FT_FRAME_USHORT( numGlyphs ),
  565. FT_FRAME_END
  566. };
  567. const FT_Frame_Field maxp_fields_extra[] =
  568. {
  569. FT_FRAME_START( 26 ),
  570. FT_FRAME_USHORT( maxPoints ),
  571. FT_FRAME_USHORT( maxContours ),
  572. FT_FRAME_USHORT( maxCompositePoints ),
  573. FT_FRAME_USHORT( maxCompositeContours ),
  574. FT_FRAME_USHORT( maxZones ),
  575. FT_FRAME_USHORT( maxTwilightPoints ),
  576. FT_FRAME_USHORT( maxStorage ),
  577. FT_FRAME_USHORT( maxFunctionDefs ),
  578. FT_FRAME_USHORT( maxInstructionDefs ),
  579. FT_FRAME_USHORT( maxStackElements ),
  580. FT_FRAME_USHORT( maxSizeOfInstructions ),
  581. FT_FRAME_USHORT( maxComponentElements ),
  582. FT_FRAME_USHORT( maxComponentDepth ),
  583. FT_FRAME_END
  584. };
  585. FT_TRACE2(( "Load_TT_MaxProfile: %08p\n", face ));
  586. error = face->goto_table( face, TTAG_maxp, stream, 0 );
  587. if ( error )
  588. goto Exit;
  589. if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) )
  590. goto Exit;
  591. maxProfile->maxPoints = 0;
  592. maxProfile->maxContours = 0;
  593. maxProfile->maxCompositePoints = 0;
  594. maxProfile->maxCompositeContours = 0;
  595. maxProfile->maxZones = 0;
  596. maxProfile->maxTwilightPoints = 0;
  597. maxProfile->maxStorage = 0;
  598. maxProfile->maxFunctionDefs = 0;
  599. maxProfile->maxInstructionDefs = 0;
  600. maxProfile->maxStackElements = 0;
  601. maxProfile->maxSizeOfInstructions = 0;
  602. maxProfile->maxComponentElements = 0;
  603. maxProfile->maxComponentDepth = 0;
  604. if ( maxProfile->version >= 0x10000L )
  605. {
  606. if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) )
  607. goto Exit;
  608. /* XXX: an adjustment that is necessary to load certain */
  609. /* broken fonts like `Keystrokes MT' :-( */
  610. /* */
  611. /* We allocate 64 function entries by default when */
  612. /* the maxFunctionDefs field is null. */
  613. if ( maxProfile->maxFunctionDefs == 0 )
  614. maxProfile->maxFunctionDefs = 64;
  615. face->root.num_glyphs = maxProfile->numGlyphs;
  616. face->root.internal->max_points =
  617. (FT_UShort)MAX( maxProfile->maxCompositePoints,
  618. maxProfile->maxPoints );
  619. face->root.internal->max_contours =
  620. (FT_Short)MAX( maxProfile->maxCompositeContours,
  621. maxProfile->maxContours );
  622. face->max_components = (FT_ULong)maxProfile->maxComponentElements +
  623. maxProfile->maxComponentDepth;
  624. /* XXX: some fonts have maxComponents set to 0; we will */
  625. /* then use 16 of them by default. */
  626. if ( face->max_components == 0 )
  627. face->max_components = 16;
  628. /* We also increase maxPoints and maxContours in order to support */
  629. /* some broken fonts. */
  630. face->root.internal->max_points += (FT_UShort)8;
  631. face->root.internal->max_contours += (FT_Short) 4;
  632. }
  633. FT_TRACE2(( "MAXP loaded.\n" ));
  634. Exit:
  635. return error;
  636. }
  637. /*************************************************************************/
  638. /* */
  639. /* <Function> */
  640. /* tt_face_load_metrics */
  641. /* */
  642. /* <Description> */
  643. /* Loads the horizontal or vertical metrics table into a face object. */
  644. /* */
  645. /* <Input> */
  646. /* face :: A handle to the target face object. */
  647. /* */
  648. /* stream :: The input stream. */
  649. /* */
  650. /* vertical :: A boolean flag. If set, load vertical metrics. */
  651. /* */
  652. /* <Return> */
  653. /* FreeType error code. 0 means success. */
  654. /* */
  655. static FT_Error
  656. tt_face_load_metrics( TT_Face face,
  657. FT_Stream stream,
  658. FT_Bool vertical )
  659. {
  660. FT_Error error;
  661. FT_Memory memory = stream->memory;
  662. FT_ULong table_len;
  663. FT_Long num_shorts, num_longs, num_shorts_checked;
  664. TT_LongMetrics * longs;
  665. TT_ShortMetrics** shorts;
  666. FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical"
  667. : "Horizontal",
  668. face ));
  669. if ( vertical )
  670. {
  671. /* The table is optional, quit silently if it wasn't found */
  672. /* */
  673. /* XXX: Some fonts have a valid vertical header with a non-null */
  674. /* `number_of_VMetrics' fields, but no corresponding `vmtx' */
  675. /* table to get the metrics from (e.g. mingliu). */
  676. /* */
  677. /* For safety, we set the field to 0! */
  678. /* */
  679. error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
  680. if ( error )
  681. {
  682. /* Set number_Of_VMetrics to 0! */
  683. FT_TRACE2(( " no vertical header in file.\n" ));
  684. face->vertical.number_Of_VMetrics = 0;
  685. error = SFNT_Err_Ok;
  686. goto Exit;
  687. }
  688. num_longs = face->vertical.number_Of_VMetrics;
  689. longs = (TT_LongMetrics *)&face->vertical.long_metrics;
  690. shorts = (TT_ShortMetrics**)&face->vertical.short_metrics;
  691. }
  692. else
  693. {
  694. error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
  695. if ( error )
  696. {
  697. FT_ERROR(( " no horizontal metrics in file!\n" ));
  698. error = SFNT_Err_Hmtx_Table_Missing;
  699. goto Exit;
  700. }
  701. num_longs = face->horizontal.number_Of_HMetrics;
  702. longs = (TT_LongMetrics *)&face->horizontal.long_metrics;
  703. shorts = (TT_ShortMetrics**)&face->horizontal.short_metrics;
  704. }
  705. /* never trust derived values */
  706. num_shorts = face->max_profile.numGlyphs - num_longs;
  707. num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
  708. if ( num_shorts < 0 )
  709. {
  710. FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n",
  711. vertical ? "Vertical"
  712. : "Horizontal" ));
  713. error = vertical ? SFNT_Err_Invalid_Vert_Metrics
  714. : SFNT_Err_Invalid_Horiz_Metrics;
  715. goto Exit;
  716. }
  717. if ( FT_NEW_ARRAY( *longs, num_longs ) ||
  718. FT_NEW_ARRAY( *shorts, num_shorts ) )
  719. goto Exit;
  720. if ( FT_FRAME_ENTER( table_len ) )
  721. goto Exit;
  722. {
  723. TT_LongMetrics cur = *longs;
  724. TT_LongMetrics limit = cur + num_longs;
  725. for ( ; cur < limit; cur++ )
  726. {
  727. cur->advance = FT_GET_USHORT();
  728. cur->bearing = FT_GET_SHORT();
  729. }
  730. }
  731. /* do we have an inconsistent number of metric values? */
  732. {
  733. TT_ShortMetrics* cur = *shorts;
  734. TT_ShortMetrics* limit = cur + MIN( num_shorts, num_shorts_checked );
  735. for ( ; cur < limit; cur++ )
  736. *cur = FT_GET_SHORT();
  737. /* we fill up the missing left side bearings with the */
  738. /* last valid value. Since this will occur for buggy CJK */
  739. /* fonts usually only, nothing serious will happen */
  740. if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
  741. {
  742. FT_Short val = (*shorts)[num_shorts_checked - 1];
  743. limit = *shorts + num_shorts;
  744. for ( ; cur < limit; cur++ )
  745. *cur = val;
  746. }
  747. }
  748. FT_FRAME_EXIT();
  749. FT_TRACE2(( "loaded\n" ));
  750. Exit:
  751. return error;
  752. }
  753. /*************************************************************************/
  754. /* */
  755. /* <Function> */
  756. /* tt_face_load_metrics_header */
  757. /* */
  758. /* <Description> */
  759. /* Loads the horizontal or vertical header in a face object. */
  760. /* */
  761. /* <Input> */
  762. /* face :: A handle to the target face object. */
  763. /* */
  764. /* stream :: The input stream. */
  765. /* */
  766. /* vertical :: A boolean flag. If set, load vertical metrics. */
  767. /* */
  768. /* <Return> */
  769. /* FreeType error code. 0 means success. */
  770. /* */
  771. FT_LOCAL_DEF( FT_Error )
  772. tt_face_load_metrics_header( TT_Face face,
  773. FT_Stream stream,
  774. FT_Bool vertical )
  775. {
  776. FT_Error error;
  777. TT_HoriHeader* header;
  778. const FT_Frame_Field metrics_header_fields[] =
  779. {
  780. #undef FT_STRUCTURE
  781. #define FT_STRUCTURE TT_HoriHeader
  782. FT_FRAME_START( 36 ),
  783. FT_FRAME_ULONG ( Version ),
  784. FT_FRAME_SHORT ( Ascender ),
  785. FT_FRAME_SHORT ( Descender ),
  786. FT_FRAME_SHORT ( Line_Gap ),
  787. FT_FRAME_USHORT( advance_Width_Max ),
  788. FT_FRAME_SHORT ( min_Left_Side_Bearing ),
  789. FT_FRAME_SHORT ( min_Right_Side_Bearing ),
  790. FT_FRAME_SHORT ( xMax_Extent ),
  791. FT_FRAME_SHORT ( caret_Slope_Rise ),
  792. FT_FRAME_SHORT ( caret_Slope_Run ),
  793. FT_FRAME_SHORT ( caret_Offset ),
  794. FT_FRAME_SHORT ( Reserved[0] ),
  795. FT_FRAME_SHORT ( Reserved[1] ),
  796. FT_FRAME_SHORT ( Reserved[2] ),
  797. FT_FRAME_SHORT ( Reserved[3] ),
  798. FT_FRAME_SHORT ( metric_Data_Format ),
  799. FT_FRAME_USHORT( number_Of_HMetrics ),
  800. FT_FRAME_END
  801. };
  802. FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " ));
  803. if ( vertical )
  804. {
  805. face->vertical_info = 0;
  806. /* The vertical header table is optional, so return quietly if */
  807. /* we don't find it. */
  808. error = face->goto_table( face, TTAG_vhea, stream, 0 );
  809. if ( error )
  810. {
  811. error = SFNT_Err_Ok;
  812. goto Exit;
  813. }
  814. face->vertical_info = 1;
  815. header = (TT_HoriHeader*)&face->vertical;
  816. }
  817. else
  818. {
  819. /* The horizontal header is mandatory; return an error if we */
  820. /* don't find it. */
  821. error = face->goto_table( face, TTAG_hhea, stream, 0 );
  822. if ( error )
  823. {
  824. error = SFNT_Err_Horiz_Header_Missing;
  825. goto Exit;
  826. }
  827. header = &face->horizontal;
  828. }
  829. if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )
  830. goto Exit;
  831. header->long_metrics = NULL;
  832. header->short_metrics = NULL;
  833. FT_TRACE2(( "loaded\n" ));
  834. /* Now try to load the corresponding metrics */
  835. error = tt_face_load_metrics( face, stream, vertical );
  836. Exit:
  837. return error;
  838. }
  839. /*************************************************************************/
  840. /* */
  841. /* <Function> */
  842. /* tt_face_load_names */
  843. /* */
  844. /* <Description> */
  845. /* Loads the name records. */
  846. /* */
  847. /* <Input> */
  848. /* face :: A handle to the target face object. */
  849. /* */
  850. /* stream :: The input stream. */
  851. /* */
  852. /* <Return> */
  853. /* FreeType error code. 0 means success. */
  854. /* */
  855. FT_LOCAL_DEF( FT_Error )
  856. tt_face_load_names( TT_Face face,
  857. FT_Stream stream )
  858. {
  859. FT_Error error;
  860. FT_Memory memory = stream->memory;
  861. FT_ULong table_pos, table_len;
  862. FT_ULong storage_start, storage_limit;
  863. FT_UInt count;
  864. TT_NameTable table;
  865. static const FT_Frame_Field name_table_fields[] =
  866. {
  867. #undef FT_STRUCTURE
  868. #define FT_STRUCTURE TT_NameTableRec
  869. FT_FRAME_START( 6 ),
  870. FT_FRAME_USHORT( format ),
  871. FT_FRAME_USHORT( numNameRecords ),
  872. FT_FRAME_USHORT( storageOffset ),
  873. FT_FRAME_END
  874. };
  875. static const FT_Frame_Field name_record_fields[] =
  876. {
  877. #undef FT_STRUCTURE
  878. #define FT_STRUCTURE TT_NameEntryRec
  879. /* no FT_FRAME_START */
  880. FT_FRAME_USHORT( platformID ),
  881. FT_FRAME_USHORT( encodingID ),
  882. FT_FRAME_USHORT( languageID ),
  883. FT_FRAME_USHORT( nameID ),
  884. FT_FRAME_USHORT( stringLength ),
  885. FT_FRAME_USHORT( stringOffset ),
  886. FT_FRAME_END
  887. };
  888. table = &face->name_table;
  889. table->stream = stream;
  890. FT_TRACE2(( "Names " ));
  891. error = face->goto_table( face, TTAG_name, stream, &table_len );
  892. if ( error )
  893. {
  894. /* The name table is required so indicate failure. */
  895. FT_TRACE2(( "is missing!\n" ));
  896. error = SFNT_Err_Name_Table_Missing;
  897. goto Exit;
  898. }
  899. table_pos = FT_STREAM_POS();
  900. if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) )
  901. goto Exit;
  902. /* Some popular asian fonts have an invalid `storageOffset' value */
  903. /* (it should be at least "6 + 12*num_names"). However, the string */
  904. /* offsets, computed as "storageOffset + entry->stringOffset", are */
  905. /* valid pointers within the name table... */
  906. /* */
  907. /* We thus can't check `storageOffset' right now. */
  908. /* */
  909. storage_start = table_pos + 6 + 12*table->numNameRecords;
  910. storage_limit = table_pos + table_len;
  911. if ( storage_start > storage_limit )
  912. {
  913. FT_ERROR(( "tt_face_load_names: invalid `name' table\n" ));
  914. error = SFNT_Err_Name_Table_Missing;
  915. goto Exit;
  916. }
  917. /* Allocate the array of name records. */
  918. count = table->numNameRecords;
  919. table->numNameRecords = 0;
  920. if ( FT_NEW_ARRAY( table->names, count ) ||
  921. FT_FRAME_ENTER( count * 12 ) )
  922. goto Exit;
  923. /* Load the name records and determine how much storage is needed */
  924. /* to hold the strings themselves. */
  925. {
  926. TT_NameEntryRec* entry = table->names;
  927. for ( ; count > 0; count-- )
  928. {
  929. if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) )
  930. continue;
  931. /* check that the name is not empty */
  932. if ( entry->stringLength == 0 )
  933. continue;
  934. /* check that the name string is within the table */
  935. entry->stringOffset += table_pos + table->storageOffset;
  936. if ( entry->stringOffset < storage_start ||
  937. entry->stringOffset + entry->stringLength > storage_limit )
  938. {
  939. /* invalid entry - ignore it */
  940. entry->stringOffset = 0;
  941. entry->stringLength = 0;
  942. continue;
  943. }
  944. entry++;
  945. }
  946. table->numNameRecords = (FT_UInt)( entry - table->names );
  947. }
  948. FT_FRAME_EXIT();
  949. FT_TRACE2(( "loaded\n" ));
  950. /* everything went well, update face->num_names */
  951. face->num_names = (FT_UShort) table->numNameRecords;
  952. Exit:
  953. return error;
  954. }
  955. /*************************************************************************/
  956. /* */
  957. /* <Function> */
  958. /* tt_face_free_names */
  959. /* */
  960. /* <Description> */
  961. /* Frees the name records. */
  962. /* */
  963. /* <Input> */
  964. /* face :: A handle to the target face object. */
  965. /* */
  966. FT_LOCAL_DEF( void )
  967. tt_face_free_names( TT_Face face )
  968. {
  969. FT_Memory memory = face->root.driver->root.memory;
  970. TT_NameTable table = &face->name_table;
  971. TT_NameEntry entry = table->names;
  972. FT_UInt count = table->numNameRecords;
  973. for ( ; count > 0; count--, entry++ )
  974. {
  975. FT_FREE( entry->string );
  976. entry->stringLength = 0;
  977. }
  978. /* free strings table */
  979. FT_FREE( table->names );
  980. table->numNameRecords = 0;
  981. table->format = 0;
  982. table->storageOffset = 0;
  983. }
  984. /*************************************************************************/
  985. /* */
  986. /* <Function> */
  987. /* tt_face_load_cmap */
  988. /* */
  989. /* <Description> */
  990. /* Loads the cmap directory in a face object. The cmaps itselves are */
  991. /* loaded on demand in the `ttcmap.c' module. */
  992. /* */
  993. /* <Input> */
  994. /* face :: A handle to the target face object. */
  995. /* */
  996. /* stream :: A handle to the input stream. */
  997. /* */
  998. /* <Return> */
  999. /* FreeType error code. 0 means success. */
  1000. /* */
  1001. FT_LOCAL_DEF( FT_Error )
  1002. tt_face_load_cmap( TT_Face face,
  1003. FT_Stream stream )
  1004. {
  1005. FT_Error error;
  1006. error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size );
  1007. if ( error )
  1008. {
  1009. FT_TRACE2(( "No `cmap' table in font !\n" ));
  1010. error = SFNT_Err_CMap_Table_Missing;
  1011. goto Exit;
  1012. }
  1013. if ( !FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) )
  1014. FT_TRACE2(( "`cmap' table loaded\n" ));
  1015. else
  1016. {
  1017. FT_ERROR(( "`cmap' table is too short!\n" ));
  1018. face->cmap_size = 0;
  1019. }
  1020. Exit:
  1021. return error;
  1022. }
  1023. /*************************************************************************/
  1024. /* */
  1025. /* <Function> */
  1026. /* tt_face_load_os2 */
  1027. /* */
  1028. /* <Description> */
  1029. /* Loads the OS2 table. */
  1030. /* */
  1031. /* <Input> */
  1032. /* face :: A handle to the target face object. */
  1033. /* */
  1034. /* stream :: A handle to the input stream. */
  1035. /* */
  1036. /* <Return> */
  1037. /* FreeType error code. 0 means success. */
  1038. /* */
  1039. FT_LOCAL_DEF( FT_Error )
  1040. tt_face_load_os2( TT_Face face,
  1041. FT_Stream stream )
  1042. {
  1043. FT_Error error;
  1044. TT_OS2* os2;
  1045. const FT_Frame_Field os2_fields[] =
  1046. {
  1047. #undef FT_STRUCTURE
  1048. #define FT_STRUCTURE TT_OS2
  1049. FT_FRAME_START( 78 ),
  1050. FT_FRAME_USHORT( version ),
  1051. FT_FRAME_SHORT ( xAvgCharWidth ),
  1052. FT_FRAME_USHORT( usWeightClass ),
  1053. FT_FRAME_USHORT( usWidthClass ),
  1054. FT_FRAME_SHORT ( fsType ),
  1055. FT_FRAME_SHORT ( ySubscriptXSize ),
  1056. FT_FRAME_SHORT ( ySubscriptYSize ),
  1057. FT_FRAME_SHORT ( ySubscriptXOffset ),
  1058. FT_FRAME_SHORT ( ySubscriptYOffset ),
  1059. FT_FRAME_SHORT ( ySuperscriptXSize ),
  1060. FT_FRAME_SHORT ( ySuperscriptYSize ),
  1061. FT_FRAME_SHORT ( ySuperscriptXOffset ),
  1062. FT_FRAME_SHORT ( ySuperscriptYOffset ),
  1063. FT_FRAME_SHORT ( yStrikeoutSize ),
  1064. FT_FRAME_SHORT ( yStrikeoutPosition ),
  1065. FT_FRAME_SHORT ( sFamilyClass ),
  1066. FT_FRAME_BYTE ( panose[0] ),
  1067. FT_FRAME_BYTE ( panose[1] ),
  1068. FT_FRAME_BYTE ( panose[2] ),
  1069. FT_FRAME_BYTE ( panose[3] ),
  1070. FT_FRAME_BYTE ( panose[4] ),
  1071. FT_FRAME_BYTE ( panose[5] ),
  1072. FT_FRAME_BYTE ( panose[6] ),
  1073. FT_FRAME_BYTE ( panose[7] ),
  1074. FT_FRAME_BYTE ( panose[8] ),
  1075. FT_FRAME_BYTE ( panose[9] ),
  1076. FT_FRAME_ULONG ( ulUnicodeRange1 ),
  1077. FT_FRAME_ULONG ( ulUnicodeRange2 ),
  1078. FT_FRAME_ULONG ( ulUnicodeRange3 ),
  1079. FT_FRAME_ULONG ( ulUnicodeRange4 ),
  1080. FT_FRAME_BYTE ( achVendID[0] ),
  1081. FT_FRAME_BYTE ( achVendID[1] ),
  1082. FT_FRAME_BYTE ( achVendID[2] ),
  1083. FT_FRAME_BYTE ( achVendID[3] ),
  1084. FT_FRAME_USHORT( fsSelection ),
  1085. FT_FRAME_USHORT( usFirstCharIndex ),
  1086. FT_FRAME_USHORT( usLastCharIndex ),
  1087. FT_FRAME_SHORT ( sTypoAscender ),
  1088. FT_FRAME_SHORT ( sTypoDescender ),
  1089. FT_FRAME_SHORT ( sTypoLineGap ),
  1090. FT_FRAME_USHORT( usWinAscent ),
  1091. FT_FRAME_USHORT( usWinDescent ),
  1092. FT_FRAME_END
  1093. };
  1094. const FT_Frame_Field os2_fields_extra[] =
  1095. {
  1096. FT_FRAME_START( 8 ),
  1097. FT_FRAME_ULONG( ulCodePageRange1 ),
  1098. FT_FRAME_ULONG( ulCodePageRange2 ),
  1099. FT_FRAME_END
  1100. };
  1101. const FT_Frame_Field os2_fields_extra2[] =
  1102. {
  1103. FT_FRAME_START( 10 ),
  1104. FT_FRAME_SHORT ( sxHeight ),
  1105. FT_FRAME_SHORT ( sCapHeight ),
  1106. FT_FRAME_USHORT( usDefaultChar ),
  1107. FT_FRAME_USHORT( usBreakChar ),
  1108. FT_FRAME_USHORT( usMaxContext ),
  1109. FT_FRAME_END
  1110. };
  1111. FT_TRACE2(( "OS/2 Table " ));
  1112. /* We now support old Mac fonts where the OS/2 table doesn't */
  1113. /* exist. Simply put, we set the `version' field to 0xFFFF */
  1114. /* and test this value each time we need to access the table. */
  1115. error = face->goto_table( face, TTAG_OS2, stream, 0 );
  1116. if ( error )
  1117. {
  1118. FT_TRACE2(( "is missing!\n" ));
  1119. face->os2.version = 0xFFFFU;
  1120. error = SFNT_Err_Ok;
  1121. goto Exit;
  1122. }
  1123. os2 = &face->os2;
  1124. if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) )
  1125. goto Exit;
  1126. os2->ulCodePageRange1 = 0;
  1127. os2->ulCodePageRange2 = 0;
  1128. os2->sxHeight = 0;
  1129. os2->sCapHeight = 0;
  1130. os2->usDefaultChar = 0;
  1131. os2->usBreakChar = 0;
  1132. os2->usMaxContext = 0;
  1133. if ( os2->version >= 0x0001 )
  1134. {
  1135. /* only version 1 tables */
  1136. if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) )
  1137. goto Exit;
  1138. if ( os2->version >= 0x0002 )
  1139. {
  1140. /* only version 2 tables */
  1141. if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) )
  1142. goto Exit;
  1143. }
  1144. }
  1145. FT_TRACE2(( "loaded\n" ));
  1146. Exit:
  1147. return error;
  1148. }
  1149. /*************************************************************************/
  1150. /* */
  1151. /* <Function> */
  1152. /* tt_face_load_postscript */
  1153. /* */
  1154. /* <Description> */
  1155. /* Loads the Postscript table. */
  1156. /* */
  1157. /* <Input> */
  1158. /* face :: A handle to the target face object. */
  1159. /* */
  1160. /* stream :: A handle to the input stream. */
  1161. /* */
  1162. /* <Return> */
  1163. /* FreeType error code. 0 means success. */
  1164. /* */
  1165. FT_LOCAL_DEF( FT_Error )
  1166. tt_face_load_postscript( TT_Face face,
  1167. FT_Stream stream )
  1168. {
  1169. FT_Error error;
  1170. TT_Postscript* post = &face->postscript;
  1171. static const FT_Frame_Field post_fields[] =
  1172. {
  1173. #undef FT_STRUCTURE
  1174. #define FT_STRUCTURE TT_Postscript
  1175. FT_FRAME_START( 32 ),
  1176. FT_FRAME_ULONG( FormatType ),
  1177. FT_FRAME_ULONG( italicAngle ),
  1178. FT_FRAME_SHORT( underlinePosition ),
  1179. FT_FRAME_SHORT( underlineThickness ),
  1180. FT_FRAME_ULONG( isFixedPitch ),
  1181. FT_FRAME_ULONG( minMemType42 ),
  1182. FT_FRAME_ULONG( maxMemType42 ),
  1183. FT_FRAME_ULONG( minMemType1 ),
  1184. FT_FRAME_ULONG( maxMemType1 ),
  1185. FT_FRAME_END
  1186. };
  1187. FT_TRACE2(( "PostScript " ));
  1188. error = face->goto_table( face, TTAG_post, stream, 0 );
  1189. if ( error )
  1190. return SFNT_Err_Post_Table_Missing;
  1191. if ( FT_STREAM_READ_FIELDS( post_fields, post ) )
  1192. return error;
  1193. /* we don't load the glyph names, we do that in another */
  1194. /* module (ttpost). */
  1195. FT_TRACE2(( "loaded\n" ));
  1196. return SFNT_Err_Ok;
  1197. }
  1198. /*************************************************************************/
  1199. /* */
  1200. /* <Function> */
  1201. /* tt_face_load_pclt */
  1202. /* */
  1203. /* <Description> */
  1204. /* Loads the PCL 5 Table. */
  1205. /* */
  1206. /* <Input> */
  1207. /* face :: A handle to the target face object. */
  1208. /* */
  1209. /* stream :: A handle to the input stream. */
  1210. /* */
  1211. /* <Return> */
  1212. /* FreeType error code. 0 means success. */
  1213. /* */
  1214. FT_LOCAL_DEF( FT_Error )
  1215. tt_face_load_pclt( TT_Face face,
  1216. FT_Stream stream )
  1217. {
  1218. static const FT_Frame_Field pclt_fields[] =
  1219. {
  1220. #undef FT_STRUCTURE
  1221. #define FT_STRUCTURE TT_PCLT
  1222. FT_FRAME_START( 54 ),
  1223. FT_FRAME_ULONG ( Version ),
  1224. FT_FRAME_ULONG ( FontNumber ),
  1225. FT_FRAME_USHORT( Pitch ),
  1226. FT_FRAME_USHORT( xHeight ),
  1227. FT_FRAME_USHORT( Style ),
  1228. FT_FRAME_USHORT( TypeFamily ),
  1229. FT_FRAME_USHORT( CapHeight ),
  1230. FT_FRAME_BYTES ( TypeFace, 16 ),
  1231. FT_FRAME_BYTES ( CharacterComplement, 8 ),
  1232. FT_FRAME_BYTES ( FileName, 6 ),
  1233. FT_FRAME_CHAR ( StrokeWeight ),
  1234. FT_FRAME_CHAR ( WidthType ),
  1235. FT_FRAME_BYTE ( SerifStyle ),
  1236. FT_FRAME_BYTE ( Reserved ),
  1237. FT_FRAME_END
  1238. };
  1239. FT_Error error;
  1240. TT_PCLT* pclt = &face->pclt;
  1241. FT_TRACE2(( "PCLT " ));
  1242. /* optional table */
  1243. error = face->goto_table( face, TTAG_PCLT, stream, 0 );
  1244. if ( error )
  1245. {
  1246. FT_TRACE2(( "missing (optional)\n" ));
  1247. pclt->Version = 0;
  1248. return SFNT_Err_Ok;
  1249. }
  1250. if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) )
  1251. goto Exit;
  1252. FT_TRACE2(( "loaded\n" ));
  1253. Exit:
  1254. return error;
  1255. }
  1256. /*************************************************************************/
  1257. /* */
  1258. /* <Function> */
  1259. /* tt_face_load_gasp */
  1260. /* */
  1261. /* <Description> */
  1262. /* Loads the `gasp' table into a face object. */
  1263. /* */
  1264. /* <Input> */
  1265. /* face :: A handle to the target face object. */
  1266. /* */
  1267. /* stream :: The input stream. */
  1268. /* */
  1269. /* <Return> */
  1270. /* FreeType error code. 0 means success. */
  1271. /* */
  1272. FT_LOCAL_DEF( FT_Error )
  1273. tt_face_load_gasp( TT_Face face,
  1274. FT_Stream stream )
  1275. {
  1276. FT_Error error;
  1277. FT_Memory memory = stream->memory;
  1278. FT_UInt j,num_ranges;
  1279. TT_GaspRange gaspranges;
  1280. FT_TRACE2(( "tt_face_load_gasp: %08p\n", face ));
  1281. /* the gasp table is optional */
  1282. error = face->goto_table( face, TTAG_gasp, stream, 0 );
  1283. if ( error )
  1284. return SFNT_Err_Ok;
  1285. if ( FT_FRAME_ENTER( 4L ) )
  1286. goto Exit;
  1287. face->gasp.version = FT_GET_USHORT();
  1288. face->gasp.numRanges = FT_GET_USHORT();
  1289. FT_FRAME_EXIT();
  1290. num_ranges = face->gasp.numRanges;
  1291. FT_TRACE3(( "number of ranges = %d\n", num_ranges ));
  1292. if ( FT_NEW_ARRAY( gaspranges, num_ranges ) ||
  1293. FT_FRAME_ENTER( num_ranges * 4L ) )
  1294. goto Exit;
  1295. face->gasp.gaspRanges = gaspranges;
  1296. for ( j = 0; j < num_ranges; j++ )
  1297. {
  1298. gaspranges[j].maxPPEM = FT_GET_USHORT();
  1299. gaspranges[j].gaspFlag = FT_GET_USHORT();
  1300. FT_TRACE3(( " [max:%d flag:%d]",
  1301. gaspranges[j].maxPPEM,
  1302. gaspranges[j].gaspFlag ));
  1303. }
  1304. FT_TRACE3(( "\n" ));
  1305. FT_FRAME_EXIT();
  1306. FT_TRACE2(( "GASP loaded\n" ));
  1307. Exit:
  1308. return error;
  1309. }
  1310. FT_CALLBACK_DEF( int )
  1311. tt_kern_pair_compare( const void* a,
  1312. const void* b );
  1313. /*************************************************************************/
  1314. /* */
  1315. /* <Function> */
  1316. /* tt_face_load_kern */
  1317. /* */
  1318. /* <Description> */
  1319. /* Loads the first kerning table with format 0 in the font. Only */
  1320. /* accepts the first horizontal kerning table. Developers should use */
  1321. /* the `ftxkern' extension to access other kerning tables in the font */
  1322. /* file, if they really want to. */
  1323. /* */
  1324. /* <Input> */
  1325. /* face :: A handle to the target face object. */
  1326. /* */
  1327. /* stream :: The input stream. */
  1328. /* */
  1329. /* <Return> */
  1330. /* FreeType error code. 0 means success. */
  1331. /* */
  1332. FT_LOCAL_DEF( FT_Error )
  1333. tt_face_load_kern( TT_Face face,
  1334. FT_Stream stream )
  1335. {
  1336. FT_Error error;
  1337. FT_Memory memory = stream->memory;
  1338. FT_UInt n, num_tables;
  1339. /* the kern table is optional; exit silently if it is missing */
  1340. error = face->goto_table( face, TTAG_kern, stream, 0 );
  1341. if ( error )
  1342. return SFNT_Err_Ok;
  1343. if ( FT_FRAME_ENTER( 4L ) )
  1344. goto Exit;
  1345. (void)FT_GET_USHORT(); /* version */
  1346. num_tables = FT_GET_USHORT();
  1347. FT_FRAME_EXIT();
  1348. for ( n = 0; n < num_tables; n++ )
  1349. {
  1350. FT_UInt coverage;
  1351. FT_UInt length;
  1352. if ( FT_FRAME_ENTER( 6L ) )
  1353. goto Exit;
  1354. (void)FT_GET_USHORT(); /* version */
  1355. length = FT_GET_USHORT() - 6; /* substract header length */
  1356. coverage = FT_GET_USHORT();
  1357. FT_FRAME_EXIT();
  1358. if ( coverage == 0x0001 )
  1359. {
  1360. FT_UInt num_pairs;
  1361. TT_Kern0_Pair pair;
  1362. TT_Kern0_Pair limit;
  1363. /* found a horizontal format 0 kerning table! */
  1364. if ( FT_FRAME_ENTER( 8L ) )
  1365. goto Exit;
  1366. num_pairs = FT_GET_USHORT();
  1367. /* skip the rest */
  1368. FT_FRAME_EXIT();
  1369. /* allocate array of kerning pairs */
  1370. if ( FT_NEW_ARRAY( face->kern_pairs, num_pairs ) ||
  1371. FT_FRAME_ENTER( 6L * num_pairs ) )
  1372. goto Exit;
  1373. pair = face->kern_pairs;
  1374. limit = pair + num_pairs;
  1375. for ( ; pair < limit; pair++ )
  1376. {
  1377. pair->left = FT_GET_USHORT();
  1378. pair->right = FT_GET_USHORT();
  1379. pair->value = FT_GET_USHORT();
  1380. }
  1381. FT_FRAME_EXIT();
  1382. face->num_kern_pairs = num_pairs;
  1383. face->kern_table_index = n;
  1384. /* ensure that the kerning pair table is sorted (yes, some */
  1385. /* fonts have unsorted tables!) */
  1386. {
  1387. FT_UInt i;
  1388. TT_Kern0_Pair pair0;
  1389. pair0 = face->kern_pairs;
  1390. for ( i = 1; i < num_pairs; i++, pair0++ )
  1391. {
  1392. if ( tt_kern_pair_compare( pair0, pair0 + 1 ) != -1 )
  1393. {
  1394. ft_qsort( (void*)face->kern_pairs, (int)num_pairs,
  1395. sizeof ( TT_Kern0_PairRec ), tt_kern_pair_compare );
  1396. break;
  1397. }
  1398. }
  1399. }
  1400. goto Exit;
  1401. }
  1402. if ( FT_STREAM_SKIP( length ) )
  1403. goto Exit;
  1404. }
  1405. /* no kern table found -- doesn't matter */
  1406. face->kern_table_index = -1;
  1407. face->num_kern_pairs = 0;
  1408. face->kern_pairs = NULL;
  1409. Exit:
  1410. return error;
  1411. }
  1412. #undef TT_KERN_INDEX
  1413. #define TT_KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 )
  1414. FT_CALLBACK_DEF( int )
  1415. tt_kern_pair_compare( const void* a,
  1416. const void* b )
  1417. {
  1418. TT_Kern0_Pair pair1 = (TT_Kern0_Pair)a;
  1419. TT_Kern0_Pair pair2 = (TT_Kern0_Pair)b;
  1420. FT_ULong index1 = TT_KERN_INDEX( pair1->left, pair1->right );
  1421. FT_ULong index2 = TT_KERN_INDEX( pair2->left, pair2->right );
  1422. return ( index1 < index2 ? -1 :
  1423. ( index1 > index2 ? 1 : 0 ));
  1424. }
  1425. #undef TT_KERN_INDEX
  1426. /*************************************************************************/
  1427. /* */
  1428. /* <Function> */
  1429. /* tt_face_load_hdmx */
  1430. /* */
  1431. /* <Description> */
  1432. /* Loads the horizontal device metrics table. */
  1433. /* */
  1434. /* <Input> */
  1435. /* face :: A handle to the target face object. */
  1436. /* */
  1437. /* stream :: A handle to the input stream. */
  1438. /* */
  1439. /* <Return> */
  1440. /* FreeType error code. 0 means success. */
  1441. /* */
  1442. FT_LOCAL_DEF( FT_Error )
  1443. tt_face_load_hdmx( TT_Face face,
  1444. FT_Stream stream )
  1445. {
  1446. FT_Error error;
  1447. FT_Memory memory = stream->memory;
  1448. TT_Hdmx hdmx = &face->hdmx;
  1449. FT_Long num_glyphs;
  1450. FT_Long record_size;
  1451. hdmx->version = 0;
  1452. hdmx->num_records = 0;
  1453. hdmx->records = 0;
  1454. /* this table is optional */
  1455. error = face->goto_table( face, TTAG_hdmx, stream, 0 );
  1456. if ( error )
  1457. return SFNT_Err_Ok;
  1458. if ( FT_FRAME_ENTER( 8L ) )
  1459. goto Exit;
  1460. hdmx->version = FT_GET_USHORT();
  1461. hdmx->num_records = FT_GET_SHORT();
  1462. record_size = FT_GET_LONG();
  1463. FT_FRAME_EXIT();
  1464. /* Only recognize format 0 */
  1465. if ( hdmx->version != 0 )
  1466. goto Exit;
  1467. if ( FT_NEW_ARRAY( hdmx->records, hdmx->num_records ) )
  1468. goto Exit;
  1469. num_glyphs = face->root.num_glyphs;
  1470. record_size -= num_glyphs + 2;
  1471. {
  1472. TT_HdmxEntry cur = hdmx->records;
  1473. TT_HdmxEntry limit = cur + hdmx->num_records;
  1474. for ( ; cur < limit; cur++ )
  1475. {
  1476. /* read record */
  1477. if ( FT_READ_BYTE( cur->ppem ) ||
  1478. FT_READ_BYTE( cur->max_width ) )
  1479. goto Exit;
  1480. if ( FT_ALLOC( cur->widths, num_glyphs ) ||
  1481. FT_STREAM_READ( cur->widths, num_glyphs ) )
  1482. goto Exit;
  1483. /* skip padding bytes */
  1484. if ( record_size > 0 && FT_STREAM_SKIP( record_size ) )
  1485. goto Exit;
  1486. }
  1487. }
  1488. Exit:
  1489. return error;
  1490. }
  1491. /*************************************************************************/
  1492. /* */
  1493. /* <Function> */
  1494. /* tt_face_free_hdmx */
  1495. /* */
  1496. /* <Description> */
  1497. /* Frees the horizontal device metrics table. */
  1498. /* */
  1499. /* <Input> */
  1500. /* face :: A handle to the target face object. */
  1501. /* */
  1502. FT_LOCAL_DEF( void )
  1503. tt_face_free_hdmx( TT_Face face )
  1504. {
  1505. if ( face )
  1506. {
  1507. FT_Int n;
  1508. FT_Memory memory = face->root.driver->root.memory;
  1509. for ( n = 0; n < face->hdmx.num_records; n++ )
  1510. FT_FREE( face->hdmx.records[n].widths );
  1511. FT_FREE( face->hdmx.records );
  1512. face->hdmx.num_records = 0;
  1513. }
  1514. }
  1515. /* END */