bdflib.c 69 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436
  1. /*
  2. * Copyright 2000 Computing Research Labs, New Mexico State University
  3. * Copyright 2001, 2002 Francesco Zappa Nardelli
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a
  6. * copy of this software and associated documentation files (the "Software"),
  7. * to deal in the Software without restriction, including without limitation
  8. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. * and/or sell copies of the Software, and to permit persons to whom the
  10. * Software is furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY
  19. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
  20. * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
  21. * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. /*************************************************************************/
  24. /* */
  25. /* This file is based on bdf.c,v 1.22 2000/03/16 20:08:50 */
  26. /* */
  27. /* taken from Mark Leisher's xmbdfed package */
  28. /* */
  29. /*************************************************************************/
  30. #include <ft2build.h>
  31. #include FT_FREETYPE_H
  32. #include FT_INTERNAL_DEBUG_H
  33. #include FT_INTERNAL_STREAM_H
  34. #include FT_INTERNAL_OBJECTS_H
  35. #include "bdf.h"
  36. #include "bdferror.h"
  37. /*************************************************************************/
  38. /* */
  39. /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
  40. /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
  41. /* messages during execution. */
  42. /* */
  43. #undef FT_COMPONENT
  44. #define FT_COMPONENT trace_bdflib
  45. /*************************************************************************/
  46. /* */
  47. /* Default BDF font options. */
  48. /* */
  49. /*************************************************************************/
  50. static const bdf_options_t _bdf_opts =
  51. {
  52. 1, /* Correct metrics. */
  53. 1, /* Preserve unencoded glyphs. */
  54. 0, /* Preserve comments. */
  55. BDF_PROPORTIONAL /* Default spacing. */
  56. };
  57. /*************************************************************************/
  58. /* */
  59. /* Builtin BDF font properties. */
  60. /* */
  61. /*************************************************************************/
  62. /* List of most properties that might appear in a font. Doesn't include */
  63. /* the RAW_* and AXIS_* properties in X11R6 polymorphic fonts. */
  64. static const bdf_property_t _bdf_properties[] =
  65. {
  66. { (char *)"ADD_STYLE_NAME", BDF_ATOM, 1, { 0 } },
  67. { (char *)"AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } },
  68. { (char *)"AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } },
  69. { (char *)"AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } },
  70. { (char *)"CAP_HEIGHT", BDF_INTEGER, 1, { 0 } },
  71. { (char *)"CHARSET_COLLECTIONS", BDF_ATOM, 1, { 0 } },
  72. { (char *)"CHARSET_ENCODING", BDF_ATOM, 1, { 0 } },
  73. { (char *)"CHARSET_REGISTRY", BDF_ATOM, 1, { 0 } },
  74. { (char *)"COMMENT", BDF_ATOM, 1, { 0 } },
  75. { (char *)"COPYRIGHT", BDF_ATOM, 1, { 0 } },
  76. { (char *)"DEFAULT_CHAR", BDF_CARDINAL, 1, { 0 } },
  77. { (char *)"DESTINATION", BDF_CARDINAL, 1, { 0 } },
  78. { (char *)"DEVICE_FONT_NAME", BDF_ATOM, 1, { 0 } },
  79. { (char *)"END_SPACE", BDF_INTEGER, 1, { 0 } },
  80. { (char *)"FACE_NAME", BDF_ATOM, 1, { 0 } },
  81. { (char *)"FAMILY_NAME", BDF_ATOM, 1, { 0 } },
  82. { (char *)"FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } },
  83. { (char *)"FONT", BDF_ATOM, 1, { 0 } },
  84. { (char *)"FONTNAME_REGISTRY", BDF_ATOM, 1, { 0 } },
  85. { (char *)"FONT_ASCENT", BDF_INTEGER, 1, { 0 } },
  86. { (char *)"FONT_DESCENT", BDF_INTEGER, 1, { 0 } },
  87. { (char *)"FOUNDRY", BDF_ATOM, 1, { 0 } },
  88. { (char *)"FULL_NAME", BDF_ATOM, 1, { 0 } },
  89. { (char *)"ITALIC_ANGLE", BDF_INTEGER, 1, { 0 } },
  90. { (char *)"MAX_SPACE", BDF_INTEGER, 1, { 0 } },
  91. { (char *)"MIN_SPACE", BDF_INTEGER, 1, { 0 } },
  92. { (char *)"NORM_SPACE", BDF_INTEGER, 1, { 0 } },
  93. { (char *)"NOTICE", BDF_ATOM, 1, { 0 } },
  94. { (char *)"PIXEL_SIZE", BDF_INTEGER, 1, { 0 } },
  95. { (char *)"POINT_SIZE", BDF_INTEGER, 1, { 0 } },
  96. { (char *)"QUAD_WIDTH", BDF_INTEGER, 1, { 0 } },
  97. { (char *)"RAW_ASCENT", BDF_INTEGER, 1, { 0 } },
  98. { (char *)"RAW_AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } },
  99. { (char *)"RAW_AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } },
  100. { (char *)"RAW_AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } },
  101. { (char *)"RAW_CAP_HEIGHT", BDF_INTEGER, 1, { 0 } },
  102. { (char *)"RAW_DESCENT", BDF_INTEGER, 1, { 0 } },
  103. { (char *)"RAW_END_SPACE", BDF_INTEGER, 1, { 0 } },
  104. { (char *)"RAW_FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } },
  105. { (char *)"RAW_MAX_SPACE", BDF_INTEGER, 1, { 0 } },
  106. { (char *)"RAW_MIN_SPACE", BDF_INTEGER, 1, { 0 } },
  107. { (char *)"RAW_NORM_SPACE", BDF_INTEGER, 1, { 0 } },
  108. { (char *)"RAW_PIXEL_SIZE", BDF_INTEGER, 1, { 0 } },
  109. { (char *)"RAW_POINT_SIZE", BDF_INTEGER, 1, { 0 } },
  110. { (char *)"RAW_PIXELSIZE", BDF_INTEGER, 1, { 0 } },
  111. { (char *)"RAW_POINTSIZE", BDF_INTEGER, 1, { 0 } },
  112. { (char *)"RAW_QUAD_WIDTH", BDF_INTEGER, 1, { 0 } },
  113. { (char *)"RAW_SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } },
  114. { (char *)"RAW_STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } },
  115. { (char *)"RAW_STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } },
  116. { (char *)"RAW_SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
  117. { (char *)"RAW_SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } },
  118. { (char *)"RAW_SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
  119. { (char *)"RAW_SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
  120. { (char *)"RAW_SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } },
  121. { (char *)"RAW_SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
  122. { (char *)"RAW_UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } },
  123. { (char *)"RAW_UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } },
  124. { (char *)"RAW_X_HEIGHT", BDF_INTEGER, 1, { 0 } },
  125. { (char *)"RELATIVE_SETWIDTH", BDF_CARDINAL, 1, { 0 } },
  126. { (char *)"RELATIVE_WEIGHT", BDF_CARDINAL, 1, { 0 } },
  127. { (char *)"RESOLUTION", BDF_INTEGER, 1, { 0 } },
  128. { (char *)"RESOLUTION_X", BDF_CARDINAL, 1, { 0 } },
  129. { (char *)"RESOLUTION_Y", BDF_CARDINAL, 1, { 0 } },
  130. { (char *)"SETWIDTH_NAME", BDF_ATOM, 1, { 0 } },
  131. { (char *)"SLANT", BDF_ATOM, 1, { 0 } },
  132. { (char *)"SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } },
  133. { (char *)"SPACING", BDF_ATOM, 1, { 0 } },
  134. { (char *)"STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } },
  135. { (char *)"STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } },
  136. { (char *)"SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
  137. { (char *)"SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } },
  138. { (char *)"SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
  139. { (char *)"SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },
  140. { (char *)"SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } },
  141. { (char *)"SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } },
  142. { (char *)"UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } },
  143. { (char *)"UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } },
  144. { (char *)"WEIGHT", BDF_CARDINAL, 1, { 0 } },
  145. { (char *)"WEIGHT_NAME", BDF_ATOM, 1, { 0 } },
  146. { (char *)"X_HEIGHT", BDF_INTEGER, 1, { 0 } },
  147. { (char *)"_MULE_BASELINE_OFFSET", BDF_INTEGER, 1, { 0 } },
  148. { (char *)"_MULE_RELATIVE_COMPOSE", BDF_INTEGER, 1, { 0 } },
  149. };
  150. static unsigned long
  151. _num_bdf_properties = sizeof ( _bdf_properties ) /
  152. sizeof ( _bdf_properties[0] );
  153. /*************************************************************************/
  154. /* */
  155. /* Hash table utilities for the properties. */
  156. /* */
  157. /*************************************************************************/
  158. /* XXX: Replace this with FreeType's hash functions */
  159. #define INITIAL_HT_SIZE 241
  160. typedef void
  161. (*hash_free_func)( hashnode node );
  162. static hashnode*
  163. hash_bucket( char* key,
  164. hashtable* ht )
  165. {
  166. char* kp = key;
  167. unsigned long res = 0;
  168. hashnode* bp = ht->table, *ndp;
  169. /* Mocklisp hash function. */
  170. while ( *kp )
  171. res = ( res << 5 ) - res + *kp++;
  172. ndp = bp + ( res % ht->size );
  173. while ( *ndp )
  174. {
  175. kp = (*ndp)->key;
  176. if ( kp[0] == key[0] && ft_strcmp( kp, key ) == 0 )
  177. break;
  178. ndp--;
  179. if ( ndp < bp )
  180. ndp = bp + ( ht->size - 1 );
  181. }
  182. return ndp;
  183. }
  184. static FT_Error
  185. hash_rehash( hashtable* ht,
  186. FT_Memory memory )
  187. {
  188. hashnode* obp = ht->table, *bp, *nbp;
  189. int i, sz = ht->size;
  190. FT_Error error = BDF_Err_Ok;
  191. ht->size <<= 1;
  192. ht->limit = ht->size / 3;
  193. if ( FT_NEW_ARRAY( ht->table, ht->size ) )
  194. goto Exit;
  195. FT_MEM_ZERO( ht->table, sizeof ( hashnode ) * ht->size );
  196. for ( i = 0, bp = obp; i < sz; i++, bp++ )
  197. {
  198. if ( *bp )
  199. {
  200. nbp = hash_bucket( (*bp)->key, ht );
  201. *nbp = *bp;
  202. }
  203. }
  204. FT_FREE( obp );
  205. Exit:
  206. return error;
  207. }
  208. static FT_Error
  209. hash_init( hashtable* ht,
  210. FT_Memory memory )
  211. {
  212. int sz = INITIAL_HT_SIZE;
  213. FT_Error error = BDF_Err_Ok;
  214. ht->size = sz;
  215. ht->limit = sz / 3;
  216. ht->used = 0;
  217. if ( FT_NEW_ARRAY( ht->table, sz ) )
  218. goto Exit;
  219. FT_MEM_ZERO( ht->table, sizeof ( hashnode ) * sz );
  220. Exit:
  221. return error;
  222. }
  223. static void
  224. hash_free( hashtable* ht,
  225. FT_Memory memory )
  226. {
  227. if ( ht != 0 )
  228. {
  229. int i, sz = ht->size;
  230. hashnode* bp = ht->table;
  231. for ( i = 0; i < sz; i++, bp++ )
  232. FT_FREE( *bp );
  233. FT_FREE( ht->table );
  234. }
  235. }
  236. static FT_Error
  237. hash_insert( char* key,
  238. void* data,
  239. hashtable* ht,
  240. FT_Memory memory )
  241. {
  242. hashnode nn, *bp = hash_bucket( key, ht );
  243. FT_Error error = BDF_Err_Ok;
  244. nn = *bp;
  245. if ( !nn )
  246. {
  247. if ( FT_NEW( nn ) )
  248. goto Exit;
  249. *bp = nn;
  250. nn->key = key;
  251. nn->data = data;
  252. if ( ht->used >= ht->limit )
  253. {
  254. error = hash_rehash( ht, memory );
  255. if ( error )
  256. goto Exit;
  257. }
  258. ht->used++;
  259. }
  260. else
  261. nn->data = data;
  262. Exit:
  263. return error;
  264. }
  265. static hashnode
  266. hash_lookup( char* key,
  267. hashtable* ht )
  268. {
  269. hashnode *np = hash_bucket( key, ht );
  270. return *np;
  271. }
  272. /*************************************************************************/
  273. /* */
  274. /* Utility types and functions. */
  275. /* */
  276. /*************************************************************************/
  277. /* Function type for parsing lines of a BDF font. */
  278. typedef FT_Error
  279. (*_bdf_line_func_t)( char* line,
  280. unsigned long linelen,
  281. unsigned long lineno,
  282. void* call_data,
  283. void* client_data );
  284. /* List structure for splitting lines into fields. */
  285. typedef struct _bdf_list_t_
  286. {
  287. char** field;
  288. unsigned long size;
  289. unsigned long used;
  290. } _bdf_list_t;
  291. /* Structure used while loading BDF fonts. */
  292. typedef struct _bdf_parse_t_
  293. {
  294. unsigned long flags;
  295. unsigned long cnt;
  296. unsigned long row;
  297. short minlb;
  298. short maxlb;
  299. short maxrb;
  300. short maxas;
  301. short maxds;
  302. short rbearing;
  303. char* glyph_name;
  304. long glyph_enc;
  305. bdf_font_t* font;
  306. bdf_options_t* opts;
  307. unsigned long have[2048];
  308. _bdf_list_t list;
  309. FT_Memory memory;
  310. } _bdf_parse_t;
  311. #define setsbit( m, cc ) ( m[(cc) >> 3] |= (FT_Byte)( 1 << ( (cc) & 7 ) ) )
  312. #define sbitset( m, cc ) ( m[(cc) >> 3] & ( 1 << ( (cc) & 7 ) ) )
  313. /* An empty string for empty fields. */
  314. static char empty[1] = { 0 }; /* XXX eliminate this */
  315. /* Assume the line is NULL-terminated and that the `list' parameter */
  316. /* was initialized the first time it was used. */
  317. static FT_Error
  318. _bdf_split( char* separators,
  319. char* line,
  320. unsigned long linelen,
  321. _bdf_list_t* list,
  322. FT_Memory memory )
  323. {
  324. int mult, final_empty;
  325. char *sp, *ep, *end;
  326. char seps[32];
  327. FT_Error error = BDF_Err_Ok;
  328. /* Initialize the list. */
  329. list->used = 0;
  330. /* If the line is empty, then simply return. */
  331. if ( linelen == 0 || line[0] == 0 )
  332. goto Exit;
  333. /* In the original code, if the `separators' parameter is NULL or */
  334. /* empty, the list is split into individual bytes. We don't need */
  335. /* this, so an error is signaled. */
  336. if ( separators == 0 || *separators == 0 )
  337. {
  338. error = BDF_Err_Invalid_Argument;
  339. goto Exit;
  340. }
  341. /* Prepare the separator bitmap. */
  342. FT_MEM_ZERO( seps, 32 );
  343. /* If the very last character of the separator string is a plus, then */
  344. /* set the `mult' flag to indicate that multiple separators should be */
  345. /* collapsed into one. */
  346. for ( mult = 0, sp = separators; sp && *sp; sp++ )
  347. {
  348. if ( *sp == '+' && *( sp + 1 ) == 0 )
  349. mult = 1;
  350. else
  351. setsbit( seps, *sp );
  352. }
  353. /* Break the line up into fields. */
  354. for ( final_empty = 0, sp = ep = line, end = sp + linelen;
  355. sp < end && *sp; )
  356. {
  357. /* Collect everything that is not a separator. */
  358. for ( ; *ep && !sbitset( seps, *ep ); ep++ )
  359. ;
  360. /* Resize the list if necessary. */
  361. if ( list->used == list->size )
  362. {
  363. if ( list->size == 0 )
  364. {
  365. if ( FT_NEW_ARRAY( list->field, 5 ) )
  366. goto Exit;
  367. }
  368. else
  369. {
  370. if ( FT_RENEW_ARRAY ( list->field ,
  371. list->size,
  372. list->size + 5 ) )
  373. goto Exit;
  374. }
  375. list->size += 5;
  376. }
  377. /* Assign the field appropriately. */
  378. list->field[list->used++] = ( ep > sp ) ? sp : empty;
  379. sp = ep;
  380. if ( mult )
  381. {
  382. /* If multiple separators should be collapsed, do it now by */
  383. /* setting all the separator characters to 0. */
  384. for ( ; *ep && sbitset( seps, *ep ); ep++ )
  385. *ep = 0;
  386. }
  387. else if ( *ep != 0 )
  388. /* Don't collapse multiple separators by making them 0, so just */
  389. /* make the one encountered 0. */
  390. *ep++ = 0;
  391. final_empty = ( ep > sp && *ep == 0 );
  392. sp = ep;
  393. }
  394. /* Finally, NULL-terminate the list. */
  395. if ( list->used + final_empty + 1 >= list->size )
  396. {
  397. if ( list->used == list->size )
  398. {
  399. if ( list->size == 0 )
  400. {
  401. if ( FT_NEW_ARRAY( list->field, 5 ) )
  402. goto Exit;
  403. }
  404. else
  405. {
  406. if ( FT_RENEW_ARRAY( list->field,
  407. list->size,
  408. list->size + 5 ) )
  409. goto Exit;
  410. }
  411. list->size += 5;
  412. }
  413. }
  414. if ( final_empty )
  415. list->field[list->used++] = empty;
  416. if ( list->used == list->size )
  417. {
  418. if ( list->size == 0 )
  419. {
  420. if ( FT_NEW_ARRAY( list->field, 5 ) )
  421. goto Exit;
  422. }
  423. else
  424. {
  425. if ( FT_RENEW_ARRAY( list->field,
  426. list->size,
  427. list->size + 5 ) )
  428. goto Exit;
  429. }
  430. list->size += 5;
  431. }
  432. list->field[list->used] = 0;
  433. Exit:
  434. return error;
  435. }
  436. static void
  437. _bdf_shift( unsigned long n,
  438. _bdf_list_t* list )
  439. {
  440. unsigned long i, u;
  441. if ( list == 0 || list->used == 0 || n == 0 )
  442. return;
  443. if ( n >= list->used )
  444. {
  445. list->used = 0;
  446. return;
  447. }
  448. for ( u = n, i = 0; u < list->used; i++, u++ )
  449. list->field[i] = list->field[u];
  450. list->used -= n;
  451. }
  452. static char *
  453. _bdf_join( int c,
  454. unsigned long* len,
  455. _bdf_list_t* list )
  456. {
  457. unsigned long i, j;
  458. char *fp, *dp;
  459. if ( list == 0 || list->used == 0 )
  460. return 0;
  461. *len = 0;
  462. dp = list->field[0];
  463. for ( i = j = 0; i < list->used; i++ )
  464. {
  465. fp = list->field[i];
  466. while ( *fp )
  467. dp[j++] = *fp++;
  468. if ( i + 1 < list->used )
  469. dp[j++] = (char)c;
  470. }
  471. dp[j] = 0;
  472. *len = j;
  473. return dp;
  474. }
  475. /* High speed file reader that passes each line to a callback. */
  476. static FT_Error
  477. bdf_internal_readstream( FT_Stream stream,
  478. char* buffer,
  479. int count,
  480. int *read_bytes )
  481. {
  482. int rbytes;
  483. unsigned long pos = stream->pos;
  484. FT_Error error = BDF_Err_Ok;
  485. if ( pos > stream->size )
  486. {
  487. FT_ERROR(( "bdf_internal_readstream:" ));
  488. FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
  489. pos, stream->size ));
  490. error = BDF_Err_Invalid_Stream_Operation;
  491. goto Exit;
  492. }
  493. if ( stream->read )
  494. rbytes = stream->read( stream, pos,
  495. (unsigned char *)buffer, count );
  496. else
  497. {
  498. rbytes = stream->size - pos;
  499. if ( rbytes > count )
  500. rbytes = count;
  501. FT_MEM_COPY( buffer, stream->base + pos, rbytes );
  502. }
  503. stream->pos = pos + rbytes;
  504. *read_bytes = rbytes;
  505. Exit:
  506. return error;
  507. }
  508. static FT_Error
  509. _bdf_readstream( FT_Stream stream,
  510. _bdf_line_func_t callback,
  511. void* client_data,
  512. unsigned long *lno )
  513. {
  514. _bdf_line_func_t cb;
  515. unsigned long lineno;
  516. int n, res, done, refill, bytes, hold;
  517. char *ls, *le, *pp, *pe, *hp;
  518. char *buf = 0;
  519. FT_Memory memory = stream->memory;
  520. FT_Error error = BDF_Err_Ok;
  521. if ( callback == 0 )
  522. {
  523. error = BDF_Err_Invalid_Argument;
  524. goto Exit;
  525. }
  526. if ( FT_NEW_ARRAY( buf, 65536L ) )
  527. goto Exit;
  528. cb = callback;
  529. lineno = 1;
  530. buf[0] = 0;
  531. res = done = 0;
  532. pp = ls = le = buf;
  533. bytes = 65536L;
  534. while ( !done )
  535. {
  536. error = bdf_internal_readstream( stream, pp, bytes, &n );
  537. if ( error )
  538. goto Exit;
  539. if ( n == 0 )
  540. break;
  541. /* Determine the new end of the buffer pages. */
  542. pe = pp + n;
  543. for ( refill = 0; done == 0 && refill == 0; )
  544. {
  545. while ( le < pe && *le != '\n' && *le != '\r' )
  546. le++;
  547. if ( le == pe )
  548. {
  549. /* Hit the end of the last page in the buffer. Need to find */
  550. /* out how many pages to shift and how many pages need to be */
  551. /* read in. Adjust the line start and end pointers down to */
  552. /* point to the right places in the pages. */
  553. pp = buf + ( ( ( ls - buf ) >> 13 ) << 13 );
  554. n = pp - buf;
  555. ls -= n;
  556. le -= n;
  557. n = pe - pp;
  558. FT_MEM_COPY( buf, pp, n );
  559. pp = buf + n;
  560. bytes = 65536L - n;
  561. refill = 1;
  562. }
  563. else
  564. {
  565. /* Temporarily NULL-terminate the line. */
  566. hp = le;
  567. hold = *le;
  568. *le = 0;
  569. /* XXX: Use encoding independent value for 0x1a */
  570. if ( *ls != '#' && *ls != 0x1a &&
  571. le > ls &&
  572. ( error = (*cb)( ls, le - ls, lineno, (void *)&cb,
  573. client_data ) ) != BDF_Err_Ok )
  574. done = 1;
  575. else
  576. {
  577. ls = ++le;
  578. /* Handle the case of DOS crlf sequences. */
  579. if ( le < pe && hold == '\n' && *le =='\r' )
  580. ls = ++le;
  581. }
  582. /* Increment the line number. */
  583. lineno++;
  584. /* Restore the character at the end of the line. */
  585. *hp = (char)hold;
  586. }
  587. }
  588. }
  589. *lno = lineno;
  590. Exit:
  591. FT_FREE( buf );
  592. return error;
  593. }
  594. /* XXX: make this work with EBCDIC also */
  595. static const unsigned char a2i[128] =
  596. {
  597. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  598. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  599. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  600. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  601. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00,
  602. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00,
  603. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  604. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  605. 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  606. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  607. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  608. };
  609. static const unsigned char odigits[32] =
  610. {
  611. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  612. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  613. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  614. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  615. };
  616. static const unsigned char ddigits[32] =
  617. {
  618. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
  619. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  620. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  621. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  622. };
  623. static const unsigned char hdigits[32] =
  624. {
  625. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
  626. 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
  627. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  628. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  629. };
  630. #define isdigok( m, d ) (m[(d) >> 3] & ( 1 << ( (d) & 7 ) ) )
  631. /* Routine to convert an ASCII string into an unsigned long integer. */
  632. static unsigned long
  633. _bdf_atoul( char* s,
  634. char** end,
  635. int base )
  636. {
  637. unsigned long v;
  638. const unsigned char* dmap;
  639. if ( s == 0 || *s == 0 )
  640. return 0;
  641. /* Make sure the radix is something recognizable. Default to 10. */
  642. switch ( base )
  643. {
  644. case 8:
  645. dmap = odigits;
  646. break;
  647. case 16:
  648. dmap = hdigits;
  649. break;
  650. default:
  651. base = 10;
  652. dmap = ddigits;
  653. break;
  654. }
  655. /* Check for the special hex prefix. */
  656. if ( *s == '0' &&
  657. ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
  658. {
  659. base = 16;
  660. dmap = hdigits;
  661. s += 2;
  662. }
  663. for ( v = 0; isdigok( dmap, *s ); s++ )
  664. v = v * base + a2i[(int)*s];
  665. if ( end != 0 )
  666. *end = s;
  667. return v;
  668. }
  669. /* Routine to convert an ASCII string into an signed long integer. */
  670. static long
  671. _bdf_atol( char* s,
  672. char** end,
  673. int base )
  674. {
  675. long v, neg;
  676. const unsigned char* dmap;
  677. if ( s == 0 || *s == 0 )
  678. return 0;
  679. /* Make sure the radix is something recognizable. Default to 10. */
  680. switch ( base )
  681. {
  682. case 8:
  683. dmap = odigits;
  684. break;
  685. case 16:
  686. dmap = hdigits;
  687. break;
  688. default:
  689. base = 10;
  690. dmap = ddigits;
  691. break;
  692. }
  693. /* Check for a minus sign. */
  694. neg = 0;
  695. if ( *s == '-' )
  696. {
  697. s++;
  698. neg = 1;
  699. }
  700. /* Check for the special hex prefix. */
  701. if ( *s == '0' &&
  702. ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
  703. {
  704. base = 16;
  705. dmap = hdigits;
  706. s += 2;
  707. }
  708. for ( v = 0; isdigok( dmap, *s ); s++ )
  709. v = v * base + a2i[(int)*s];
  710. if ( end != 0 )
  711. *end = s;
  712. return ( !neg ) ? v : -v;
  713. }
  714. /* Routine to convert an ASCII string into an signed short integer. */
  715. static short
  716. _bdf_atos( char* s,
  717. char** end,
  718. int base )
  719. {
  720. short v, neg;
  721. const unsigned char* dmap;
  722. if ( s == 0 || *s == 0 )
  723. return 0;
  724. /* Make sure the radix is something recognizable. Default to 10. */
  725. switch ( base )
  726. {
  727. case 8:
  728. dmap = odigits;
  729. break;
  730. case 16:
  731. dmap = hdigits;
  732. break;
  733. default:
  734. base = 10;
  735. dmap = ddigits;
  736. break;
  737. }
  738. /* Check for a minus. */
  739. neg = 0;
  740. if ( *s == '-' )
  741. {
  742. s++;
  743. neg = 1;
  744. }
  745. /* Check for the special hex prefix. */
  746. if ( *s == '0' &&
  747. ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
  748. {
  749. base = 16;
  750. dmap = hdigits;
  751. s += 2;
  752. }
  753. for ( v = 0; isdigok( dmap, *s ); s++ )
  754. v = (short)( v * base + a2i[(int)*s] );
  755. if ( end != 0 )
  756. *end = s;
  757. return (short)( ( !neg ) ? v : -v );
  758. }
  759. /* Routine to compare two glyphs by encoding so they can be sorted. */
  760. static int
  761. by_encoding( const void* a,
  762. const void* b )
  763. {
  764. bdf_glyph_t *c1, *c2;
  765. c1 = (bdf_glyph_t *)a;
  766. c2 = (bdf_glyph_t *)b;
  767. if ( c1->encoding < c2->encoding )
  768. return -1;
  769. else if ( c1->encoding > c2->encoding )
  770. return 1;
  771. return 0;
  772. }
  773. static FT_Error
  774. bdf_create_property( char* name,
  775. int format,
  776. bdf_font_t* font )
  777. {
  778. unsigned long n;
  779. bdf_property_t* p;
  780. FT_Memory memory = font->memory;
  781. FT_Error error = BDF_Err_Ok;
  782. /* First check to see if the property has */
  783. /* already been added or not. If it has, then */
  784. /* simply ignore it. */
  785. if ( hash_lookup( name, &(font->proptbl) ) )
  786. goto Exit;
  787. if ( font->nuser_props == 0 )
  788. {
  789. if ( FT_NEW_ARRAY( font->user_props, 1 ) )
  790. goto Exit;
  791. }
  792. else
  793. {
  794. if ( FT_RENEW_ARRAY( font->user_props,
  795. font->nuser_props,
  796. font->nuser_props + 1 ) )
  797. goto Exit;
  798. }
  799. p = font->user_props + font->nuser_props;
  800. FT_MEM_ZERO( p, sizeof ( bdf_property_t ) );
  801. n = (unsigned long)( ft_strlen( name ) + 1 );
  802. if ( FT_NEW_ARRAY( p->name, n ) )
  803. goto Exit;
  804. FT_MEM_COPY( (char *)p->name, name, n );
  805. p->format = format;
  806. p->builtin = 0;
  807. n = _num_bdf_properties + font->nuser_props;
  808. error = hash_insert( p->name, (void *)n, &(font->proptbl), memory );
  809. if ( error )
  810. goto Exit;
  811. font->nuser_props++;
  812. Exit:
  813. return error;
  814. }
  815. FT_LOCAL_DEF( bdf_property_t * )
  816. bdf_get_property( char* name,
  817. bdf_font_t* font )
  818. {
  819. hashnode hn;
  820. unsigned long propid;
  821. if ( name == 0 || *name == 0 )
  822. return 0;
  823. if ( ( hn = hash_lookup( name, &(font->proptbl) ) ) == 0 )
  824. return 0;
  825. propid = (unsigned long)hn->data;
  826. if ( propid >= _num_bdf_properties )
  827. return font->user_props + ( propid - _num_bdf_properties );
  828. return (bdf_property_t*)_bdf_properties + propid;
  829. }
  830. /*************************************************************************/
  831. /* */
  832. /* BDF font file parsing flags and functions. */
  833. /* */
  834. /*************************************************************************/
  835. /* Parse flags. */
  836. #define _BDF_START 0x0001
  837. #define _BDF_FONT_NAME 0x0002
  838. #define _BDF_SIZE 0x0004
  839. #define _BDF_FONT_BBX 0x0008
  840. #define _BDF_PROPS 0x0010
  841. #define _BDF_GLYPHS 0x0020
  842. #define _BDF_GLYPH 0x0040
  843. #define _BDF_ENCODING 0x0080
  844. #define _BDF_SWIDTH 0x0100
  845. #define _BDF_DWIDTH 0x0200
  846. #define _BDF_BBX 0x0400
  847. #define _BDF_BITMAP 0x0800
  848. #define _BDF_SWIDTH_ADJ 0x1000
  849. #define _BDF_GLYPH_BITS ( _BDF_GLYPH | \
  850. _BDF_ENCODING | \
  851. _BDF_SWIDTH | \
  852. _BDF_DWIDTH | \
  853. _BDF_BBX | \
  854. _BDF_BITMAP )
  855. #define _BDF_GLYPH_WIDTH_CHECK 0x40000000L
  856. #define _BDF_GLYPH_HEIGHT_CHECK 0x80000000L
  857. /* Auto correction messages. */
  858. #define ACMSG1 "FONT_ASCENT property missing. " \
  859. "Added \"FONT_ASCENT %hd\".\n"
  860. #define ACMSG2 "FONT_DESCENT property missing. " \
  861. "Added \"FONT_DESCENT %hd\".\n"
  862. #define ACMSG3 "Font width != actual width. Old: %hd New: %hd.\n"
  863. #define ACMSG4 "Font left bearing != actual left bearing. " \
  864. "Old: %hd New: %hd.\n"
  865. #define ACMSG5 "Font ascent != actual ascent. Old: %hd New: %hd.\n"
  866. #define ACMSG6 "Font descent != actual descent. Old: %hd New: %hd.\n"
  867. #define ACMSG7 "Font height != actual height. Old: %hd New: %hd.\n"
  868. #define ACMSG8 "Glyph scalable width (SWIDTH) adjustments made.\n"
  869. #define ACMSG9 "SWIDTH field missing at line %ld. Set automatically.\n"
  870. #define ACMSG10 "DWIDTH field missing at line %ld. Set to glyph width.\n"
  871. #define ACMSG11 "SIZE bits per pixel field adjusted to %hd.\n"
  872. #define ACMSG12 "Duplicate encoding %ld (%s) changed to unencoded.\n"
  873. #define ACMSG13 "Glyph %ld extra rows removed.\n"
  874. #define ACMSG14 "Glyph %ld extra columns removed.\n"
  875. #define ACMSG15 "Incorrect glyph count: %ld indicated but %ld found.\n"
  876. /* Error messages. */
  877. #define ERRMSG1 "[line %ld] Missing \"%s\" line.\n"
  878. #define ERRMSG2 "[line %ld] Font header corrupted or missing fields.\n"
  879. #define ERRMSG3 "[line %ld] Font glyphs corrupted or missing fields.\n"
  880. static FT_Error
  881. _bdf_add_comment( bdf_font_t* font,
  882. char* comment,
  883. unsigned long len )
  884. {
  885. char* cp;
  886. FT_Memory memory = font->memory;
  887. FT_Error error = BDF_Err_Ok;
  888. if ( font->comments_len == 0 )
  889. {
  890. if ( FT_NEW_ARRAY( font->comments, len + 1 ) )
  891. goto Exit;
  892. }
  893. else
  894. {
  895. if ( FT_RENEW_ARRAY( font->comments,
  896. font->comments_len,
  897. font->comments_len + len + 1 ) )
  898. goto Exit;
  899. }
  900. cp = font->comments + font->comments_len;
  901. FT_MEM_COPY( cp, comment, len );
  902. cp += len;
  903. *cp++ = '\n';
  904. font->comments_len += len + 1;
  905. Exit:
  906. return error;
  907. }
  908. /* Set the spacing from the font name if it exists, or set it to the */
  909. /* default specified in the options. */
  910. static FT_Error
  911. _bdf_set_default_spacing( bdf_font_t* font,
  912. bdf_options_t* opts )
  913. {
  914. unsigned long len;
  915. char name[128];
  916. _bdf_list_t list;
  917. FT_Memory memory;
  918. FT_Error error = BDF_Err_Ok;
  919. if ( font == 0 || font->name == 0 || font->name[0] == 0 )
  920. {
  921. error = BDF_Err_Invalid_Argument;
  922. goto Exit;
  923. }
  924. memory = font->memory;
  925. font->spacing = opts->font_spacing;
  926. len = (unsigned long)( ft_strlen( font->name ) + 1 );
  927. FT_MEM_COPY( name, font->name, len );
  928. list.size = list.used = 0;
  929. error = _bdf_split( (char *)"-", name, len, &list, memory );
  930. if ( error )
  931. goto Exit;
  932. if ( list.used == 15 )
  933. {
  934. switch ( list.field[11][0] )
  935. {
  936. case 'C':
  937. case 'c':
  938. font->spacing = BDF_CHARCELL;
  939. break;
  940. case 'M':
  941. case 'm':
  942. font->spacing = BDF_MONOWIDTH;
  943. break;
  944. case 'P':
  945. case 'p':
  946. font->spacing = BDF_PROPORTIONAL;
  947. break;
  948. }
  949. }
  950. FT_FREE( list.field );
  951. Exit:
  952. return error;
  953. }
  954. /* Determine whether the property is an atom or not. If it is, then */
  955. /* clean it up so the double quotes are removed if they exist. */
  956. static int
  957. _bdf_is_atom( char* line,
  958. unsigned long linelen,
  959. char** name,
  960. char** value,
  961. bdf_font_t* font )
  962. {
  963. int hold;
  964. char *sp, *ep;
  965. bdf_property_t* p;
  966. *name = sp = ep = line;
  967. while ( *ep && *ep != ' ' && *ep != '\t' )
  968. ep++;
  969. hold = -1;
  970. if ( *ep )
  971. {
  972. hold = *ep;
  973. *ep = 0;
  974. }
  975. p = bdf_get_property( sp, font );
  976. /* Restore the character that was saved before any return can happen. */
  977. if ( hold != -1 )
  978. *ep = (char)hold;
  979. /* If the property exists and is not an atom, just return here. */
  980. if ( p && p->format != BDF_ATOM )
  981. return 0;
  982. /* The property is an atom. Trim all leading and trailing whitespace */
  983. /* and double quotes for the atom value. */
  984. sp = ep;
  985. ep = line + linelen;
  986. /* Trim the leading whitespace if it exists. */
  987. *sp++ = 0;
  988. while ( *sp &&
  989. ( *sp == ' ' || *sp == '\t' ) )
  990. sp++;
  991. /* Trim the leading double quote if it exists. */
  992. if ( *sp == '"' )
  993. sp++;
  994. *value = sp;
  995. /* Trim the trailing whitespace if it exists. */
  996. while ( ep > sp &&
  997. ( *( ep - 1 ) == ' ' || *( ep - 1 ) == '\t' ) )
  998. *--ep = 0;
  999. /* Trim the trailing double quote if it exists. */
  1000. if ( ep > sp && *( ep - 1 ) == '"' )
  1001. *--ep = 0;
  1002. return 1;
  1003. }
  1004. static FT_Error
  1005. _bdf_add_property( bdf_font_t* font,
  1006. char* name,
  1007. char* value )
  1008. {
  1009. unsigned long propid;
  1010. hashnode hn;
  1011. int len;
  1012. bdf_property_t *prop, *fp;
  1013. FT_Memory memory = font->memory;
  1014. FT_Error error = BDF_Err_Ok;
  1015. /* First, check to see if the property already exists in the font. */
  1016. if ( ( hn = hash_lookup( name, (hashtable *)font->internal ) ) != 0 )
  1017. {
  1018. /* The property already exists in the font, so simply replace */
  1019. /* the value of the property with the current value. */
  1020. fp = font->props + (unsigned long)hn->data;
  1021. switch ( fp->format )
  1022. {
  1023. case BDF_ATOM:
  1024. /* Delete the current atom if it exists. */
  1025. FT_FREE( fp->value.atom );
  1026. if ( value == 0 )
  1027. len = 1;
  1028. else
  1029. len = ft_strlen( value ) + 1;
  1030. if ( len > 1 )
  1031. {
  1032. if ( FT_NEW_ARRAY( fp->value.atom, len ) )
  1033. goto Exit;
  1034. FT_MEM_COPY( fp->value.atom, value, len );
  1035. }
  1036. else
  1037. fp->value.atom = 0;
  1038. break;
  1039. case BDF_INTEGER:
  1040. fp->value.int32 = _bdf_atol( value, 0, 10 );
  1041. break;
  1042. case BDF_CARDINAL:
  1043. fp->value.card32 = _bdf_atoul( value, 0, 10 );
  1044. break;
  1045. default:
  1046. ;
  1047. }
  1048. goto Exit;
  1049. }
  1050. /* See whether this property type exists yet or not. */
  1051. /* If not, create it. */
  1052. hn = hash_lookup( name, &(font->proptbl) );
  1053. if ( hn == 0 )
  1054. {
  1055. error = bdf_create_property( name, BDF_ATOM, font );
  1056. if ( error )
  1057. goto Exit;
  1058. hn = hash_lookup( name, &(font->proptbl) );
  1059. }
  1060. /* Allocate another property if this is overflow. */
  1061. if ( font->props_used == font->props_size )
  1062. {
  1063. if ( font->props_size == 0 )
  1064. {
  1065. if ( FT_NEW_ARRAY( font->props, 1 ) )
  1066. goto Exit;
  1067. }
  1068. else
  1069. {
  1070. if ( FT_RENEW_ARRAY( font->props,
  1071. font->props_size,
  1072. font->props_size + 1 ) )
  1073. goto Exit;
  1074. }
  1075. fp = font->props + font->props_size;
  1076. FT_MEM_ZERO( fp, sizeof ( bdf_property_t ) );
  1077. font->props_size++;
  1078. }
  1079. propid = (unsigned long)hn->data;
  1080. if ( propid >= _num_bdf_properties )
  1081. prop = font->user_props + ( propid - _num_bdf_properties );
  1082. else
  1083. prop = (bdf_property_t*)_bdf_properties + propid;
  1084. fp = font->props + font->props_used;
  1085. fp->name = prop->name;
  1086. fp->format = prop->format;
  1087. fp->builtin = prop->builtin;
  1088. switch ( prop->format )
  1089. {
  1090. case BDF_ATOM:
  1091. if ( value == 0 )
  1092. len = 1;
  1093. else
  1094. len = ft_strlen( value ) + 1;
  1095. if ( len > 1 )
  1096. {
  1097. if ( FT_NEW_ARRAY( fp->value.atom, len ) )
  1098. goto Exit;
  1099. FT_MEM_COPY( fp->value.atom, value, len );
  1100. }
  1101. else
  1102. fp->value.atom = 0;
  1103. break;
  1104. case BDF_INTEGER:
  1105. fp->value.int32 = _bdf_atol( value, 0, 10 );
  1106. break;
  1107. case BDF_CARDINAL:
  1108. fp->value.card32 = _bdf_atoul( value, 0, 10 );
  1109. break;
  1110. }
  1111. /* If the property happens to be a comment, then it doesn't need */
  1112. /* to be added to the internal hash table. */
  1113. if ( ft_memcmp( name, "COMMENT", 7 ) != 0 ) {
  1114. /* Add the property to the font property table. */
  1115. error = hash_insert( fp->name,
  1116. (void *)font->props_used,
  1117. (hashtable *)font->internal,
  1118. memory );
  1119. if ( error )
  1120. goto Exit;
  1121. }
  1122. font->props_used++;
  1123. /* Some special cases need to be handled here. The DEFAULT_CHAR */
  1124. /* property needs to be located if it exists in the property list, the */
  1125. /* FONT_ASCENT and FONT_DESCENT need to be assigned if they are */
  1126. /* present, and the SPACING property should override the default */
  1127. /* spacing. */
  1128. if ( ft_memcmp( name, "DEFAULT_CHAR", 12 ) == 0 )
  1129. font->default_glyph = fp->value.int32;
  1130. else if ( ft_memcmp( name, "FONT_ASCENT", 11 ) == 0 )
  1131. font->font_ascent = fp->value.int32;
  1132. else if ( ft_memcmp( name, "FONT_DESCENT", 12 ) == 0 )
  1133. font->font_descent = fp->value.int32;
  1134. else if ( ft_memcmp( name, "SPACING", 7 ) == 0 )
  1135. {
  1136. if ( fp->value.atom[0] == 'p' || fp->value.atom[0] == 'P' )
  1137. font->spacing = BDF_PROPORTIONAL;
  1138. else if ( fp->value.atom[0] == 'm' || fp->value.atom[0] == 'M' )
  1139. font->spacing = BDF_MONOWIDTH;
  1140. else if ( fp->value.atom[0] == 'c' || fp->value.atom[0] == 'C' )
  1141. font->spacing = BDF_CHARCELL;
  1142. }
  1143. Exit:
  1144. return error;
  1145. }
  1146. static const unsigned char nibble_mask[8] =
  1147. {
  1148. 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE
  1149. };
  1150. /* Actually parse the glyph info and bitmaps. */
  1151. static FT_Error
  1152. _bdf_parse_glyphs( char* line,
  1153. unsigned long linelen,
  1154. unsigned long lineno,
  1155. void* call_data,
  1156. void* client_data )
  1157. {
  1158. int c, mask_index;
  1159. char* s;
  1160. unsigned char* bp;
  1161. unsigned long i, slen, nibbles;
  1162. _bdf_line_func_t* next;
  1163. _bdf_parse_t* p;
  1164. bdf_glyph_t* glyph;
  1165. bdf_font_t* font;
  1166. FT_Memory memory;
  1167. FT_Error error = BDF_Err_Ok;
  1168. FT_UNUSED( lineno ); /* only used in debug mode */
  1169. next = (_bdf_line_func_t *)call_data;
  1170. p = (_bdf_parse_t *) client_data;
  1171. font = p->font;
  1172. memory = font->memory;
  1173. /* Check for a comment. */
  1174. if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )
  1175. {
  1176. linelen -= 7;
  1177. s = line + 7;
  1178. if ( *s != 0 )
  1179. {
  1180. s++;
  1181. linelen--;
  1182. }
  1183. error = _bdf_add_comment( p->font, s, linelen );
  1184. goto Exit;
  1185. }
  1186. /* The very first thing expected is the number of glyphs. */
  1187. if ( !( p->flags & _BDF_GLYPHS ) )
  1188. {
  1189. if ( ft_memcmp( line, "CHARS", 5 ) != 0 )
  1190. {
  1191. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "CHARS" ));
  1192. error = BDF_Err_Missing_Chars_Field;
  1193. goto Exit;
  1194. }
  1195. error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
  1196. if ( error )
  1197. goto Exit;
  1198. p->cnt = font->glyphs_size = _bdf_atoul( p->list.field[1], 0, 10 );
  1199. /* Make sure the number of glyphs is non-zero. */
  1200. if ( p->cnt == 0 )
  1201. font->glyphs_size = 64;
  1202. if ( FT_NEW_ARRAY( font->glyphs, font->glyphs_size ) )
  1203. goto Exit;
  1204. p->flags |= _BDF_GLYPHS;
  1205. goto Exit;
  1206. }
  1207. /* Check for the ENDFONT field. */
  1208. if ( ft_memcmp( line, "ENDFONT", 7 ) == 0 )
  1209. {
  1210. /* Sort the glyphs by encoding. */
  1211. ft_qsort( (char *)font->glyphs,
  1212. font->glyphs_used,
  1213. sizeof ( bdf_glyph_t ),
  1214. by_encoding );
  1215. p->flags &= ~_BDF_START;
  1216. goto Exit;
  1217. }
  1218. /* Check for the ENDCHAR field. */
  1219. if ( ft_memcmp( line, "ENDCHAR", 7 ) == 0 )
  1220. {
  1221. p->glyph_enc = 0;
  1222. p->flags &= ~_BDF_GLYPH_BITS;
  1223. goto Exit;
  1224. }
  1225. /* Check to see whether a glyph is being scanned but should be */
  1226. /* ignored because it is an unencoded glyph. */
  1227. if ( ( p->flags & _BDF_GLYPH ) &&
  1228. p->glyph_enc == -1 &&
  1229. p->opts->keep_unencoded == 0 )
  1230. goto Exit;
  1231. /* Check for the STARTCHAR field. */
  1232. if ( ft_memcmp( line, "STARTCHAR", 9 ) == 0 )
  1233. {
  1234. /* Set the character name in the parse info first until the */
  1235. /* encoding can be checked for an unencoded character. */
  1236. FT_FREE( p->glyph_name );
  1237. error = _bdf_split( (char *)" +", line, linelen, &p->list,memory );
  1238. if ( error )
  1239. goto Exit;
  1240. _bdf_shift( 1, &p->list );
  1241. s = _bdf_join( ' ', &slen, &p->list );
  1242. if ( FT_NEW_ARRAY( p->glyph_name, slen + 1 ) )
  1243. goto Exit;
  1244. FT_MEM_COPY( p->glyph_name, s, slen + 1 );
  1245. p->flags |= _BDF_GLYPH;
  1246. goto Exit;
  1247. }
  1248. /* Check for the ENCODING field. */
  1249. if ( ft_memcmp( line, "ENCODING", 8 ) == 0 )
  1250. {
  1251. if ( !( p->flags & _BDF_GLYPH ) )
  1252. {
  1253. /* Missing STARTCHAR field. */
  1254. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "STARTCHAR" ));
  1255. error = BDF_Err_Missing_Startchar_Field;
  1256. goto Exit;
  1257. }
  1258. error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
  1259. if ( error )
  1260. goto Exit;
  1261. p->glyph_enc = _bdf_atol( p->list.field[1], 0, 10 );
  1262. /* Check to see whether this encoding has already been encountered. */
  1263. /* If it has then change it to unencoded so it gets added if */
  1264. /* indicated. */
  1265. if ( p->glyph_enc >= 0 )
  1266. {
  1267. if ( _bdf_glyph_modified( p->have, p->glyph_enc ) )
  1268. {
  1269. /* Emit a message saying a glyph has been moved to the */
  1270. /* unencoded area. */
  1271. FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG12,
  1272. p->glyph_enc, p->glyph_name ));
  1273. p->glyph_enc = -1;
  1274. font->modified = 1;
  1275. }
  1276. else
  1277. _bdf_set_glyph_modified( p->have, p->glyph_enc );
  1278. }
  1279. if ( p->glyph_enc >= 0 )
  1280. {
  1281. /* Make sure there are enough glyphs allocated in case the */
  1282. /* number of characters happen to be wrong. */
  1283. if ( font->glyphs_used == font->glyphs_size )
  1284. {
  1285. if ( FT_RENEW_ARRAY( font->glyphs,
  1286. font->glyphs_size,
  1287. font->glyphs_size + 64 ) )
  1288. goto Exit;
  1289. FT_MEM_ZERO( font->glyphs + font->glyphs_size,
  1290. sizeof ( bdf_glyph_t ) * 64 ); /* FZ inutile */
  1291. font->glyphs_size += 64;
  1292. }
  1293. glyph = font->glyphs + font->glyphs_used++;
  1294. glyph->name = p->glyph_name;
  1295. glyph->encoding = p->glyph_enc;
  1296. /* Reset the initial glyph info. */
  1297. p->glyph_name = 0;
  1298. }
  1299. else
  1300. {
  1301. /* Unencoded glyph. Check to see whether it should */
  1302. /* be added or not. */
  1303. if ( p->opts->keep_unencoded != 0 )
  1304. {
  1305. /* Allocate the next unencoded glyph. */
  1306. if ( font->unencoded_used == font->unencoded_size )
  1307. {
  1308. if ( font->unencoded_size == 0 )
  1309. {
  1310. if ( FT_NEW_ARRAY( font->unencoded, 4 ) )
  1311. goto Exit;
  1312. }
  1313. else
  1314. {
  1315. if ( FT_RENEW_ARRAY( font->unencoded ,
  1316. font->unencoded_size,
  1317. font->unencoded_size + 4 ) )
  1318. goto Exit;
  1319. }
  1320. font->unencoded_size += 4;
  1321. }
  1322. glyph = font->unencoded + font->unencoded_used;
  1323. glyph->name = p->glyph_name;
  1324. glyph->encoding = font->unencoded_used++;
  1325. }
  1326. else
  1327. /* Free up the glyph name if the unencoded shouldn't be */
  1328. /* kept. */
  1329. FT_FREE( p->glyph_name );
  1330. p->glyph_name = 0;
  1331. }
  1332. /* Clear the flags that might be added when width and height are */
  1333. /* checked for consistency. */
  1334. p->flags &= ~( _BDF_GLYPH_WIDTH_CHECK | _BDF_GLYPH_HEIGHT_CHECK );
  1335. p->flags |= _BDF_ENCODING;
  1336. goto Exit;
  1337. }
  1338. /* Point at the glyph being constructed. */
  1339. if ( p->glyph_enc == -1 )
  1340. glyph = font->unencoded + ( font->unencoded_used - 1 );
  1341. else
  1342. glyph = font->glyphs + ( font->glyphs_used - 1 );
  1343. /* Check to see whether a bitmap is being constructed. */
  1344. if ( p->flags & _BDF_BITMAP )
  1345. {
  1346. /* If there are more rows than are specified in the glyph metrics, */
  1347. /* ignore the remaining lines. */
  1348. if ( p->row >= (unsigned long)glyph->bbx.height )
  1349. {
  1350. if ( !( p->flags & _BDF_GLYPH_HEIGHT_CHECK ) )
  1351. {
  1352. FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG13, glyph->encoding ));
  1353. p->flags |= _BDF_GLYPH_HEIGHT_CHECK;
  1354. font->modified = 1;
  1355. }
  1356. goto Exit;
  1357. }
  1358. /* Only collect the number of nibbles indicated by the glyph */
  1359. /* metrics. If there are more columns, they are simply ignored. */
  1360. nibbles = glyph->bpr << 1;
  1361. bp = glyph->bitmap + p->row * glyph->bpr;
  1362. for ( i = 0, *bp = 0; i < nibbles; i++ )
  1363. {
  1364. c = line[i];
  1365. *bp = (FT_Byte)( ( *bp << 4 ) + a2i[c] );
  1366. if ( i + 1 < nibbles && ( i & 1 ) )
  1367. *++bp = 0;
  1368. }
  1369. /* Remove possible garbage at the right. */
  1370. mask_index = ( glyph->bbx.width * p->font->bpp ) & 7;
  1371. *bp &= nibble_mask[mask_index];
  1372. /* If any line has extra columns, indicate they have been removed. */
  1373. if ( ( line[nibbles] == '0' || a2i[(int)line[nibbles]] != 0 ) &&
  1374. !( p->flags & _BDF_GLYPH_WIDTH_CHECK ) )
  1375. {
  1376. FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG14, glyph->encoding ));
  1377. p->flags |= _BDF_GLYPH_WIDTH_CHECK;
  1378. font->modified = 1;
  1379. }
  1380. p->row++;
  1381. goto Exit;
  1382. }
  1383. /* Expect the SWIDTH (scalable width) field next. */
  1384. if ( ft_memcmp( line, "SWIDTH", 6 ) == 0 )
  1385. {
  1386. if ( !( p->flags & _BDF_ENCODING ) )
  1387. {
  1388. /* Missing ENCODING field. */
  1389. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "ENCODING" ));
  1390. error = BDF_Err_Missing_Encoding_Field;
  1391. goto Exit;
  1392. }
  1393. error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
  1394. if ( error )
  1395. goto Exit;
  1396. glyph->swidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 );
  1397. p->flags |= _BDF_SWIDTH;
  1398. goto Exit;
  1399. }
  1400. /* Expect the DWIDTH (scalable width) field next. */
  1401. if ( ft_memcmp( line, "DWIDTH", 6 ) == 0 )
  1402. {
  1403. error = _bdf_split( (char *)" +", line, linelen, &p->list,memory );
  1404. if ( error )
  1405. goto Exit;
  1406. glyph->dwidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 );
  1407. if ( !( p->flags & _BDF_SWIDTH ) )
  1408. {
  1409. /* Missing SWIDTH field. Emit an auto correction message and set */
  1410. /* the scalable width from the device width. */
  1411. FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG9, lineno ));
  1412. glyph->swidth = (unsigned short)FT_MulDiv(
  1413. glyph->dwidth, 72000L,
  1414. (FT_Long)( font->point_size *
  1415. font->resolution_x ) );
  1416. }
  1417. p->flags |= _BDF_DWIDTH;
  1418. goto Exit;
  1419. }
  1420. /* Expect the BBX field next. */
  1421. if ( ft_memcmp( line, "BBX", 3 ) == 0 )
  1422. {
  1423. error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
  1424. if ( error )
  1425. goto Exit;
  1426. glyph->bbx.width = _bdf_atos( p->list.field[1], 0, 10 );
  1427. glyph->bbx.height = _bdf_atos( p->list.field[2], 0, 10 );
  1428. glyph->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 );
  1429. glyph->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 );
  1430. /* Generate the ascent and descent of the character. */
  1431. glyph->bbx.ascent = (short)( glyph->bbx.height + glyph->bbx.y_offset );
  1432. glyph->bbx.descent = (short)( -glyph->bbx.y_offset );
  1433. /* Determine the overall font bounding box as the characters are */
  1434. /* loaded so corrections can be done later if indicated. */
  1435. p->maxas = (short)MAX( glyph->bbx.ascent, p->maxas );
  1436. p->maxds = (short)MAX( glyph->bbx.descent, p->maxds );
  1437. p->rbearing = (short)( glyph->bbx.width + glyph->bbx.x_offset );
  1438. p->maxrb = (short)MAX( p->rbearing, p->maxrb );
  1439. p->minlb = (short)MIN( glyph->bbx.x_offset, p->minlb );
  1440. p->maxlb = (short)MAX( glyph->bbx.x_offset, p->maxlb );
  1441. if ( !( p->flags & _BDF_DWIDTH ) )
  1442. {
  1443. /* Missing DWIDTH field. Emit an auto correction message and set */
  1444. /* the device width to the glyph width. */
  1445. FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG10, lineno ));
  1446. glyph->dwidth = glyph->bbx.width;
  1447. }
  1448. /* If the BDF_CORRECT_METRICS flag is set, then adjust the SWIDTH */
  1449. /* value if necessary. */
  1450. if ( p->opts->correct_metrics != 0 )
  1451. {
  1452. /* Determine the point size of the glyph. */
  1453. unsigned short sw = (unsigned short)FT_MulDiv(
  1454. glyph->dwidth, 72000L,
  1455. (FT_Long)( font->point_size *
  1456. font->resolution_x ) );
  1457. if ( sw != glyph->swidth )
  1458. {
  1459. glyph->swidth = sw;
  1460. if ( p->glyph_enc == -1 )
  1461. _bdf_set_glyph_modified( font->umod,
  1462. font->unencoded_used - 1 );
  1463. else
  1464. _bdf_set_glyph_modified( font->nmod, glyph->encoding );
  1465. p->flags |= _BDF_SWIDTH_ADJ;
  1466. font->modified = 1;
  1467. }
  1468. }
  1469. p->flags |= _BDF_BBX;
  1470. goto Exit;
  1471. }
  1472. /* And finally, gather up the bitmap. */
  1473. if ( ft_memcmp( line, "BITMAP", 6 ) == 0 )
  1474. {
  1475. if ( !( p->flags & _BDF_BBX ) )
  1476. {
  1477. /* Missing BBX field. */
  1478. FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "BBX" ));
  1479. error = BDF_Err_Missing_Bbx_Field;
  1480. goto Exit;
  1481. }
  1482. /* Allocate enough space for the bitmap. */
  1483. glyph->bpr = ( glyph->bbx.width * p->font->bpp + 7 ) >> 3;
  1484. glyph->bytes = (unsigned short)( glyph->bpr * glyph->bbx.height );
  1485. if ( FT_NEW_ARRAY( glyph->bitmap, glyph->bytes ) )
  1486. goto Exit;
  1487. p->row = 0;
  1488. p->flags |= _BDF_BITMAP;
  1489. goto Exit;
  1490. }
  1491. error = BDF_Err_Invalid_File_Format;
  1492. Exit:
  1493. return error;
  1494. }
  1495. /* Load the font properties. */
  1496. static FT_Error
  1497. _bdf_parse_properties( char* line,
  1498. unsigned long linelen,
  1499. unsigned long lineno,
  1500. void* call_data,
  1501. void* client_data )
  1502. {
  1503. unsigned long vlen;
  1504. _bdf_line_func_t* next;
  1505. _bdf_parse_t* p;
  1506. char* name;
  1507. char* value;
  1508. char nbuf[128];
  1509. FT_Memory memory;
  1510. FT_Error error = BDF_Err_Ok;
  1511. FT_UNUSED( lineno );
  1512. next = (_bdf_line_func_t *)call_data;
  1513. p = (_bdf_parse_t *) client_data;
  1514. memory = p->font->memory;
  1515. /* Check for the end of the properties. */
  1516. if ( ft_memcmp( line, "ENDPROPERTIES", 13 ) == 0 )
  1517. {
  1518. /* If the FONT_ASCENT or FONT_DESCENT properties have not been */
  1519. /* encountered yet, then make sure they are added as properties and */
  1520. /* make sure they are set from the font bounding box info. */
  1521. /* */
  1522. /* This is *always* done regardless of the options, because X11 */
  1523. /* requires these two fields to compile fonts. */
  1524. if ( bdf_get_font_property( p->font, (char *)"FONT_ASCENT" ) == 0 )
  1525. {
  1526. p->font->font_ascent = p->font->bbx.ascent;
  1527. ft_sprintf( nbuf, "%hd", p->font->bbx.ascent );
  1528. error = _bdf_add_property( p->font, (char *)"FONT_ASCENT", nbuf );
  1529. if ( error )
  1530. goto Exit;
  1531. FT_TRACE2(( "_bdf_parse_properties: " ACMSG1, p->font->bbx.ascent ));
  1532. p->font->modified = 1;
  1533. }
  1534. if ( bdf_get_font_property( p->font, (char *)"FONT_DESCENT" ) == 0 )
  1535. {
  1536. p->font->font_descent = p->font->bbx.descent;
  1537. ft_sprintf( nbuf, "%hd", p->font->bbx.descent );
  1538. error = _bdf_add_property( p->font, (char *)"FONT_DESCENT", nbuf );
  1539. if ( error )
  1540. goto Exit;
  1541. FT_TRACE2(( "_bdf_parse_properties: " ACMSG2, p->font->bbx.descent ));
  1542. p->font->modified = 1;
  1543. }
  1544. p->flags &= ~_BDF_PROPS;
  1545. *next = _bdf_parse_glyphs;
  1546. goto Exit;
  1547. }
  1548. /* Ignore the _XFREE86_GLYPH_RANGES properties. */
  1549. if ( ft_memcmp( line, "_XFREE86_GLYPH_RANGES", 21 ) == 0 )
  1550. goto Exit;
  1551. /* Handle COMMENT fields and properties in a special way to preserve */
  1552. /* the spacing. */
  1553. if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )
  1554. {
  1555. name = value = line;
  1556. value += 7;
  1557. if ( *value )
  1558. *value++ = 0;
  1559. error = _bdf_add_property( p->font, name, value );
  1560. if ( error )
  1561. goto Exit;
  1562. }
  1563. else if ( _bdf_is_atom( line, linelen, &name, &value, p->font ) )
  1564. {
  1565. error = _bdf_add_property( p->font, name, value );
  1566. if ( error )
  1567. goto Exit;
  1568. }
  1569. else
  1570. {
  1571. error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
  1572. if ( error )
  1573. goto Exit;
  1574. name = p->list.field[0];
  1575. _bdf_shift( 1, &p->list );
  1576. value = _bdf_join( ' ', &vlen, &p->list );
  1577. error = _bdf_add_property( p->font, name, value );
  1578. if ( error )
  1579. goto Exit;
  1580. }
  1581. Exit:
  1582. return error;
  1583. }
  1584. /* Load the font header. */
  1585. static FT_Error
  1586. _bdf_parse_start( char* line,
  1587. unsigned long linelen,
  1588. unsigned long lineno,
  1589. void* call_data,
  1590. void* client_data )
  1591. {
  1592. unsigned long slen;
  1593. _bdf_line_func_t* next;
  1594. _bdf_parse_t* p;
  1595. bdf_font_t* font;
  1596. char *s;
  1597. FT_Memory memory = NULL;
  1598. FT_Error error = BDF_Err_Ok;
  1599. FT_UNUSED( lineno ); /* only used in debug mode */
  1600. next = (_bdf_line_func_t *)call_data;
  1601. p = (_bdf_parse_t *) client_data;
  1602. if ( p->font )
  1603. memory = p->font->memory;
  1604. /* Check for a comment. This is done to handle those fonts that have */
  1605. /* comments before the STARTFONT line for some reason. */
  1606. if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )
  1607. {
  1608. if ( p->opts->keep_comments != 0 && p->font != 0 )
  1609. {
  1610. linelen -= 7;
  1611. s = line + 7;
  1612. if ( *s != 0 )
  1613. {
  1614. s++;
  1615. linelen--;
  1616. }
  1617. error = _bdf_add_comment( p->font, s, linelen );
  1618. if ( error )
  1619. goto Exit;
  1620. /* here font is not defined! */
  1621. }
  1622. goto Exit;
  1623. }
  1624. if ( !( p->flags & _BDF_START ) )
  1625. {
  1626. memory = p->memory;
  1627. if ( ft_memcmp( line, "STARTFONT", 9 ) != 0 )
  1628. {
  1629. /* No STARTFONT field is a good indication of a problem. */
  1630. error = BDF_Err_Missing_Startfont_Field;
  1631. goto Exit;
  1632. }
  1633. p->flags = _BDF_START;
  1634. font = p->font = 0;
  1635. if ( FT_NEW( font ) )
  1636. goto Exit;
  1637. p->font = font;
  1638. font->memory = p->memory;
  1639. p->memory = 0;
  1640. { /* setup */
  1641. unsigned long i;
  1642. bdf_property_t* prop;
  1643. error = hash_init( &(font->proptbl), memory );
  1644. if ( error )
  1645. goto Exit;
  1646. for ( i = 0, prop = (bdf_property_t*)_bdf_properties;
  1647. i < _num_bdf_properties; i++, prop++ )
  1648. {
  1649. error = hash_insert( prop->name, (void *)i,
  1650. &(font->proptbl), memory );
  1651. if ( error )
  1652. goto Exit;
  1653. }
  1654. }
  1655. if ( FT_ALLOC( p->font->internal, sizeof ( hashtable ) ) )
  1656. goto Exit;
  1657. error = hash_init( (hashtable *)p->font->internal,memory );
  1658. if ( error )
  1659. goto Exit;
  1660. p->font->spacing = p->opts->font_spacing;
  1661. p->font->default_glyph = -1;
  1662. goto Exit;
  1663. }
  1664. /* Check for the start of the properties. */
  1665. if ( ft_memcmp( line, "STARTPROPERTIES", 15 ) == 0 )
  1666. {
  1667. error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
  1668. if ( error )
  1669. goto Exit;
  1670. p->cnt = p->font->props_size = _bdf_atoul( p->list.field[1], 0, 10 );
  1671. if ( FT_NEW_ARRAY( p->font->props, p->cnt ) )
  1672. goto Exit;
  1673. p->flags |= _BDF_PROPS;
  1674. *next = _bdf_parse_properties;
  1675. goto Exit;
  1676. }
  1677. /* Check for the FONTBOUNDINGBOX field. */
  1678. if ( ft_memcmp( line, "FONTBOUNDINGBOX", 15 ) == 0 )
  1679. {
  1680. if ( !(p->flags & _BDF_SIZE ) )
  1681. {
  1682. /* Missing the SIZE field. */
  1683. FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "SIZE" ));
  1684. error = BDF_Err_Missing_Size_Field;
  1685. goto Exit;
  1686. }
  1687. error = _bdf_split( (char *)" +", line, linelen, &p->list , memory );
  1688. if ( error )
  1689. goto Exit;
  1690. p->font->bbx.width = _bdf_atos( p->list.field[1], 0, 10 );
  1691. p->font->bbx.height = _bdf_atos( p->list.field[2], 0, 10 );
  1692. p->font->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 );
  1693. p->font->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 );
  1694. p->font->bbx.ascent = (short)( p->font->bbx.height +
  1695. p->font->bbx.y_offset );
  1696. p->font->bbx.descent = (short)( -p->font->bbx.y_offset );
  1697. p->flags |= _BDF_FONT_BBX;
  1698. goto Exit;
  1699. }
  1700. /* The next thing to check for is the FONT field. */
  1701. if ( ft_memcmp( line, "FONT", 4 ) == 0 )
  1702. {
  1703. error = _bdf_split( (char *)" +", line, linelen, &p->list , memory );
  1704. if ( error )
  1705. goto Exit;
  1706. _bdf_shift( 1, &p->list );
  1707. s = _bdf_join( ' ', &slen, &p->list );
  1708. if ( FT_NEW_ARRAY( p->font->name, slen + 1 ) )
  1709. goto Exit;
  1710. FT_MEM_COPY( p->font->name, s, slen + 1 );
  1711. /* If the font name is an XLFD name, set the spacing to the one in */
  1712. /* the font name. If there is no spacing fall back on the default. */
  1713. error = _bdf_set_default_spacing( p->font, p->opts );
  1714. if ( error )
  1715. goto Exit;
  1716. p->flags |= _BDF_FONT_NAME;
  1717. goto Exit;
  1718. }
  1719. /* Check for the SIZE field. */
  1720. if ( ft_memcmp( line, "SIZE", 4 ) == 0 )
  1721. {
  1722. if ( !( p->flags & _BDF_FONT_NAME ) )
  1723. {
  1724. /* Missing the FONT field. */
  1725. FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONT" ));
  1726. error = BDF_Err_Missing_Font_Field;
  1727. goto Exit;
  1728. }
  1729. error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
  1730. if ( error )
  1731. goto Exit;
  1732. p->font->point_size = _bdf_atoul( p->list.field[1], 0, 10 );
  1733. p->font->resolution_x = _bdf_atoul( p->list.field[2], 0, 10 );
  1734. p->font->resolution_y = _bdf_atoul( p->list.field[3], 0, 10 );
  1735. /* Check for the bits per pixel field. */
  1736. if ( p->list.used == 5 )
  1737. {
  1738. unsigned short bitcount, i, shift;
  1739. p->font->bpp = (unsigned short)_bdf_atos( p->list.field[4], 0, 10 );
  1740. /* Only values 1, 2, 4, 8 are allowed. */
  1741. shift = p->font->bpp;
  1742. bitcount = 0;
  1743. for ( i = 0; shift > 0; i++ )
  1744. {
  1745. if ( shift & 1 )
  1746. bitcount = i;
  1747. shift >>= 1;
  1748. }
  1749. shift = (short)( ( bitcount > 3 ) ? 8 : ( 1 << bitcount ) );
  1750. if ( p->font->bpp > shift || p->font->bpp != shift )
  1751. {
  1752. /* select next higher value */
  1753. p->font->bpp = (unsigned short)( shift << 1 );
  1754. FT_TRACE2(( "_bdf_parse_start: " ACMSG11, p->font->bpp ));
  1755. }
  1756. }
  1757. else
  1758. p->font->bpp = 1;
  1759. p->flags |= _BDF_SIZE;
  1760. goto Exit;
  1761. }
  1762. error = BDF_Err_Invalid_File_Format;
  1763. Exit:
  1764. return error;
  1765. }
  1766. /*************************************************************************/
  1767. /* */
  1768. /* API. */
  1769. /* */
  1770. /*************************************************************************/
  1771. FT_LOCAL_DEF( FT_Error )
  1772. bdf_load_font( FT_Stream stream,
  1773. FT_Memory extmemory,
  1774. bdf_options_t* opts,
  1775. bdf_font_t* *font )
  1776. {
  1777. unsigned long lineno;
  1778. _bdf_parse_t *p;
  1779. FT_Memory memory = extmemory;
  1780. FT_Error error = BDF_Err_Ok;
  1781. if ( FT_ALLOC( p, sizeof ( _bdf_parse_t ) ) )
  1782. goto Exit;
  1783. memory = NULL;
  1784. p->opts = (bdf_options_t*)( ( opts != 0 ) ? opts : &_bdf_opts );
  1785. p->minlb = 32767;
  1786. p->memory = extmemory; /* only during font creation */
  1787. error = _bdf_readstream( stream, _bdf_parse_start,
  1788. (void *)p, &lineno );
  1789. if ( error )
  1790. goto Exit;
  1791. if ( p->font != 0 )
  1792. {
  1793. /* If the font is not proportional, set the font's monowidth */
  1794. /* field to the width of the font bounding box. */
  1795. memory = p->font->memory;
  1796. if ( p->font->spacing != BDF_PROPORTIONAL )
  1797. p->font->monowidth = p->font->bbx.width;
  1798. /* If the number of glyphs loaded is not that of the original count, */
  1799. /* indicate the difference. */
  1800. if ( p->cnt != p->font->glyphs_used + p->font->unencoded_used )
  1801. {
  1802. FT_TRACE2(( "bdf_load_font: " ACMSG15, p->cnt,
  1803. p->font->glyphs_used + p->font->unencoded_used ));
  1804. p->font->modified = 1;
  1805. }
  1806. /* Once the font has been loaded, adjust the overall font metrics if */
  1807. /* necessary. */
  1808. if ( p->opts->correct_metrics != 0 &&
  1809. ( p->font->glyphs_used > 0 || p->font->unencoded_used > 0 ) )
  1810. {
  1811. if ( p->maxrb - p->minlb != p->font->bbx.width )
  1812. {
  1813. FT_TRACE2(( "bdf_load_font: " ACMSG3,
  1814. p->font->bbx.width, p->maxrb - p->minlb ));
  1815. p->font->bbx.width = (unsigned short)( p->maxrb - p->minlb );
  1816. p->font->modified = 1;
  1817. }
  1818. if ( p->font->bbx.x_offset != p->minlb )
  1819. {
  1820. FT_TRACE2(( "bdf_load_font: " ACMSG4,
  1821. p->font->bbx.x_offset, p->minlb ));
  1822. p->font->bbx.x_offset = p->minlb;
  1823. p->font->modified = 1;
  1824. }
  1825. if ( p->font->bbx.ascent != p->maxas )
  1826. {
  1827. FT_TRACE2(( "bdf_load_font: " ACMSG5,
  1828. p->font->bbx.ascent, p->maxas ));
  1829. p->font->bbx.ascent = p->maxas;
  1830. p->font->modified = 1;
  1831. }
  1832. if ( p->font->bbx.descent != p->maxds )
  1833. {
  1834. FT_TRACE2(( "bdf_load_font: " ACMSG6,
  1835. p->font->bbx.descent, p->maxds ));
  1836. p->font->bbx.descent = p->maxds;
  1837. p->font->bbx.y_offset = (short)( -p->maxds );
  1838. p->font->modified = 1;
  1839. }
  1840. if ( p->maxas + p->maxds != p->font->bbx.height )
  1841. {
  1842. FT_TRACE2(( "bdf_load_font: " ACMSG7,
  1843. p->font->bbx.height, p->maxas + p->maxds ));
  1844. p->font->bbx.height = (unsigned short)( p->maxas + p->maxds );
  1845. }
  1846. if ( p->flags & _BDF_SWIDTH_ADJ )
  1847. FT_TRACE2(( "bdf_load_font: " ACMSG8 ));
  1848. }
  1849. }
  1850. if ( p->flags & _BDF_START )
  1851. {
  1852. {
  1853. /* The ENDFONT field was never reached or did not exist. */
  1854. if ( !( p->flags & _BDF_GLYPHS ) )
  1855. /* Error happened while parsing header. */
  1856. FT_ERROR(( "bdf_load_font: " ERRMSG2, lineno ));
  1857. else
  1858. /* Error happened when parsing glyphs. */
  1859. FT_ERROR(( "bdf_load_font: " ERRMSG3, lineno ));
  1860. }
  1861. }
  1862. /* Free up the list used during the parsing. */
  1863. if ( memory != NULL )
  1864. FT_FREE( p->list.field );
  1865. if ( p->font != 0 )
  1866. {
  1867. /* Make sure the comments are NULL terminated if they exist. */
  1868. memory = p->font->memory;
  1869. if ( p->font->comments_len > 0 ) {
  1870. if ( FT_RENEW_ARRAY( p->font->comments,
  1871. p->font->comments_len,
  1872. p->font->comments_len + 1 ) )
  1873. goto Exit;
  1874. p->font->comments[p->font->comments_len] = 0;
  1875. }
  1876. }
  1877. else if ( error == BDF_Err_Ok )
  1878. error = BDF_Err_Invalid_File_Format;
  1879. *font = p->font;
  1880. Exit:
  1881. if ( p )
  1882. {
  1883. memory = extmemory;
  1884. FT_FREE( p );
  1885. }
  1886. return error;
  1887. }
  1888. FT_LOCAL_DEF( void )
  1889. bdf_free_font( bdf_font_t* font )
  1890. {
  1891. bdf_property_t* prop;
  1892. unsigned long i;
  1893. bdf_glyph_t* glyphs;
  1894. FT_Memory memory;
  1895. if ( font == 0 )
  1896. return;
  1897. memory = font->memory;
  1898. FT_FREE( font->name );
  1899. /* Free up the internal hash table of property names. */
  1900. if ( font->internal )
  1901. {
  1902. hash_free( (hashtable *)font->internal, memory );
  1903. FT_FREE( font->internal );
  1904. }
  1905. /* Free up the comment info. */
  1906. FT_FREE( font->comments );
  1907. /* Free up the properties. */
  1908. for ( i = 0; i < font->props_size; i++ )
  1909. {
  1910. if ( font->props[i].format == BDF_ATOM )
  1911. FT_FREE( font->props[i].value.atom );
  1912. }
  1913. FT_FREE( font->props );
  1914. /* Free up the character info. */
  1915. for ( i = 0, glyphs = font->glyphs;
  1916. i < font->glyphs_used; i++, glyphs++ )
  1917. {
  1918. FT_FREE( glyphs->name );
  1919. FT_FREE( glyphs->bitmap );
  1920. }
  1921. for ( i = 0, glyphs = font->unencoded; i < font->unencoded_used;
  1922. i++, glyphs++ )
  1923. {
  1924. FT_FREE( glyphs->name );
  1925. FT_FREE( glyphs->bitmap );
  1926. }
  1927. FT_FREE( font->glyphs );
  1928. FT_FREE( font->unencoded );
  1929. /* Free up the overflow storage if it was used. */
  1930. for ( i = 0, glyphs = font->overflow.glyphs;
  1931. i < font->overflow.glyphs_used; i++, glyphs++ )
  1932. {
  1933. FT_FREE( glyphs->name );
  1934. FT_FREE( glyphs->bitmap );
  1935. }
  1936. FT_FREE( font->overflow.glyphs );
  1937. /* bdf_cleanup */
  1938. hash_free( &(font->proptbl), memory );
  1939. /* Free up the user defined properties. */
  1940. for (prop = font->user_props, i = 0;
  1941. i < font->nuser_props; i++, prop++ )
  1942. {
  1943. FT_FREE( prop->name );
  1944. if ( prop->format == BDF_ATOM )
  1945. FT_FREE( prop->value.atom );
  1946. }
  1947. FT_FREE( font->user_props );
  1948. /* FREE( font ); */ /* XXX Fixme */
  1949. }
  1950. FT_LOCAL_DEF( bdf_property_t * )
  1951. bdf_get_font_property( bdf_font_t* font,
  1952. char* name )
  1953. {
  1954. hashnode hn;
  1955. if ( font == 0 || font->props_size == 0 || name == 0 || *name == 0 )
  1956. return 0;
  1957. hn = hash_lookup( name, (hashtable *)font->internal );
  1958. return hn ? ( font->props + (unsigned long)hn->data ) : 0;
  1959. }
  1960. /* END */