ReactOS  0.4.14-dev-358-gbef841c
pcfread.c
Go to the documentation of this file.
1 /* pcfread.c
2 
3  FreeType font driver for pcf fonts
4 
5  Copyright 2000-2010, 2012-2014 by
6  Francesco Zappa Nardelli
7 
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14 
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 THE SOFTWARE.
25 */
26 
27 
28 #include <ft2build.h>
29 
30 #include FT_INTERNAL_DEBUG_H
31 #include FT_INTERNAL_STREAM_H
32 #include FT_INTERNAL_OBJECTS_H
33 
34 #include "pcf.h"
35 #include "pcfread.h"
36 
37 #include "pcferror.h"
38 
39 
40  /*************************************************************************/
41  /* */
42  /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
43  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
44  /* messages during execution. */
45  /* */
46 #undef FT_COMPONENT
47 #define FT_COMPONENT trace_pcfread
48 
49 
50 #ifdef FT_DEBUG_LEVEL_TRACE
51  static const char* const tableNames[] =
52  {
53  "properties",
54  "accelerators",
55  "metrics",
56  "bitmaps",
57  "ink metrics",
58  "encodings",
59  "swidths",
60  "glyph names",
61  "BDF accelerators"
62  };
63 #endif
64 
65 
66  static
68  {
69 #undef FT_STRUCTURE
70 #define FT_STRUCTURE PCF_TocRec
71 
72  FT_FRAME_START( 8 ),
76  };
77 
78 
79  static
81  {
82 #undef FT_STRUCTURE
83 #define FT_STRUCTURE PCF_TableRec
84 
85  FT_FRAME_START( 16 ),
88  FT_FRAME_ULONG_LE( size ), /* rounded up to a multiple of 4 */
91  };
92 
93 
94  static FT_Error
96  PCF_Face face )
97  {
99  PCF_Toc toc = &face->toc;
101 
102  FT_Memory memory = FT_FACE( face )->memory;
103  FT_UInt n;
104 
105  FT_ULong size;
106 
107 
108  if ( FT_STREAM_SEEK( 0 ) ||
110  return FT_THROW( Cannot_Open_Resource );
111 
112  if ( toc->version != PCF_FILE_VERSION ||
113  toc->count == 0 )
114  return FT_THROW( Invalid_File_Format );
115 
116  if ( stream->size < 16 )
117  return FT_THROW( Invalid_File_Format );
118 
119  /* we need 16 bytes per TOC entry, */
120  /* and there can be most 9 tables */
121  if ( toc->count > ( stream->size >> 4 ) ||
122  toc->count > 9 )
123  {
124  FT_TRACE0(( "pcf_read_TOC: adjusting number of tables"
125  " (from %d to %d)\n",
126  toc->count,
127  FT_MIN( stream->size >> 4, 9 ) ));
128  toc->count = FT_MIN( stream->size >> 4, 9 );
129  }
130 
131  if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) )
132  return error;
133 
134  tables = face->toc.tables;
135  for ( n = 0; n < toc->count; n++ )
136  {
138  goto Exit;
139  tables++;
140  }
141 
142  /* Sort tables and check for overlaps. Because they are almost */
143  /* always ordered already, an in-place bubble sort with simultaneous */
144  /* boundary checking seems appropriate. */
145  tables = face->toc.tables;
146 
147  for ( n = 0; n < toc->count - 1; n++ )
148  {
149  FT_UInt i, have_change;
150 
151 
152  have_change = 0;
153 
154  for ( i = 0; i < toc->count - 1 - n; i++ )
155  {
156  PCF_TableRec tmp;
157 
158 
159  if ( tables[i].offset > tables[i + 1].offset )
160  {
161  tmp = tables[i];
162  tables[i] = tables[i + 1];
163  tables[i + 1] = tmp;
164 
165  have_change = 1;
166  }
167 
168  if ( ( tables[i].size > tables[i + 1].offset ) ||
169  ( tables[i].offset > tables[i + 1].offset - tables[i].size ) )
170  {
171  error = FT_THROW( Invalid_Offset );
172  goto Exit;
173  }
174  }
175 
176  if ( !have_change )
177  break;
178  }
179 
180  /*
181  * We now check whether the `size' and `offset' values are reasonable:
182  * `offset' + `size' must not exceed the stream size.
183  *
184  * Note, however, that X11's `pcfWriteFont' routine (used by the
185  * `bdftopcf' program to create PDF font files) has two special
186  * features.
187  *
188  * - It always assigns the accelerator table a size of 100 bytes in the
189  * TOC, regardless of its real size, which can vary between 34 and 72
190  * bytes.
191  *
192  * - Due to the way the routine is designed, it ships out the last font
193  * table with its real size, ignoring the TOC's size value. Since
194  * the TOC size values are always rounded up to a multiple of 4, the
195  * difference can be up to three bytes for all tables except the
196  * accelerator table, for which the difference can be as large as 66
197  * bytes.
198  *
199  */
200 
201  tables = face->toc.tables;
202  size = stream->size;
203 
204  for ( n = 0; n < toc->count - 1; n++ )
205  {
206  /* we need two checks to avoid overflow */
207  if ( ( tables->size > size ) ||
208  ( tables->offset > size - tables->size ) )
209  {
210  error = FT_THROW( Invalid_Table );
211  goto Exit;
212  }
213  tables++;
214  }
215 
216  /* only check `tables->offset' for last table element ... */
217  if ( ( tables->offset > size ) )
218  {
219  error = FT_THROW( Invalid_Table );
220  goto Exit;
221  }
222  /* ... and adjust `tables->size' to the real value if necessary */
223  if ( tables->size > size - tables->offset )
224  tables->size = size - tables->offset;
225 
226 #ifdef FT_DEBUG_LEVEL_TRACE
227 
228  {
229  FT_UInt i, j;
230  const char* name = "?";
231 
232 
233  FT_TRACE4(( "pcf_read_TOC:\n" ));
234 
235  FT_TRACE4(( " number of tables: %ld\n", face->toc.count ));
236 
237  tables = face->toc.tables;
238  for ( i = 0; i < toc->count; i++ )
239  {
240  for ( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] );
241  j++ )
242  if ( tables[i].type == (FT_UInt)( 1 << j ) )
243  name = tableNames[j];
244 
245  FT_TRACE4(( " %d: type=%s, format=0x%X,"
246  " size=%ld (0x%lX), offset=%ld (0x%lX)\n",
247  i, name,
248  tables[i].format,
249  tables[i].size, tables[i].size,
250  tables[i].offset, tables[i].offset ));
251  }
252  }
253 
254 #endif
255 
256  return FT_Err_Ok;
257 
258  Exit:
259  FT_FREE( face->toc.tables );
260  return error;
261  }
262 
263 
264 #define PCF_METRIC_SIZE 12
265 
266  static
268  {
269 #undef FT_STRUCTURE
270 #define FT_STRUCTURE PCF_MetricRec
271 
273  FT_FRAME_SHORT_LE( leftSideBearing ),
274  FT_FRAME_SHORT_LE( rightSideBearing ),
275  FT_FRAME_SHORT_LE( characterWidth ),
276  FT_FRAME_SHORT_LE( ascent ),
277  FT_FRAME_SHORT_LE( descent ),
278  FT_FRAME_SHORT_LE( attributes ),
280  };
281 
282 
283  static
285  {
286 #undef FT_STRUCTURE
287 #define FT_STRUCTURE PCF_MetricRec
288 
290  FT_FRAME_SHORT( leftSideBearing ),
291  FT_FRAME_SHORT( rightSideBearing ),
292  FT_FRAME_SHORT( characterWidth ),
293  FT_FRAME_SHORT( ascent ),
294  FT_FRAME_SHORT( descent ),
295  FT_FRAME_SHORT( attributes ),
297  };
298 
299 
300 #define PCF_COMPRESSED_METRIC_SIZE 5
301 
302  static
304  {
305 #undef FT_STRUCTURE
306 #define FT_STRUCTURE PCF_Compressed_MetricRec
307 
309  FT_FRAME_BYTE( leftSideBearing ),
310  FT_FRAME_BYTE( rightSideBearing ),
311  FT_FRAME_BYTE( characterWidth ),
312  FT_FRAME_BYTE( ascent ),
313  FT_FRAME_BYTE( descent ),
315  };
316 
317 
318  static FT_Error
321  PCF_Metric metric )
322  {
324 
325 
327  {
328  const FT_Frame_Field* fields;
329 
330 
331  /* parsing normal metrics */
332  fields = ( PCF_BYTE_ORDER( format ) == MSBFirst )
335 
336  /* the following sets `error' but doesn't return in case of failure */
337  (void)FT_STREAM_READ_FIELDS( fields, metric );
338  }
339  else
340  {
342 
343 
344  /* parsing compressed metrics */
346  goto Exit;
347 
348  metric->leftSideBearing = (FT_Short)( compr.leftSideBearing - 0x80 );
349  metric->rightSideBearing = (FT_Short)( compr.rightSideBearing - 0x80 );
350  metric->characterWidth = (FT_Short)( compr.characterWidth - 0x80 );
351  metric->ascent = (FT_Short)( compr.ascent - 0x80 );
352  metric->descent = (FT_Short)( compr.descent - 0x80 );
353  metric->attributes = 0;
354  }
355 
356  FT_TRACE5(( " width=%d,"
357  " lsb=%d, rsb=%d,"
358  " ascent=%d, descent=%d,"
359  " attributes=%d\n",
360  metric->characterWidth,
361  metric->leftSideBearing,
362  metric->rightSideBearing,
363  metric->ascent,
364  metric->descent,
365  metric->attributes ));
366 
367  Exit:
368  return error;
369  }
370 
371 
372  static FT_Error
375  FT_ULong ntables, /* same as PCF_Toc->count */
376  FT_ULong type,
377  FT_ULong *aformat,
378  FT_ULong *asize )
379  {
380  FT_Error error = FT_ERR( Invalid_File_Format );
381  FT_ULong i;
382 
383 
384  for ( i = 0; i < ntables; i++ )
385  if ( tables[i].type == type )
386  {
387  if ( stream->pos > tables[i].offset )
388  {
389  error = FT_THROW( Invalid_Stream_Skip );
390  goto Fail;
391  }
392 
393  if ( FT_STREAM_SKIP( tables[i].offset - stream->pos ) )
394  {
395  error = FT_THROW( Invalid_Stream_Skip );
396  goto Fail;
397  }
398 
399  *asize = tables[i].size;
400  *aformat = tables[i].format;
401 
402  return FT_Err_Ok;
403  }
404 
405  Fail:
406  *asize = 0;
407  return error;
408  }
409 
410 
411  static FT_Bool
413  FT_ULong ntables, /* same as PCF_Toc->count */
414  FT_ULong type )
415  {
416  FT_ULong i;
417 
418 
419  for ( i = 0; i < ntables; i++ )
420  if ( tables[i].type == type )
421  return TRUE;
422 
423  return FALSE;
424  }
425 
426 
427 #define PCF_PROPERTY_SIZE 9
428 
429  static
431  {
432 #undef FT_STRUCTURE
433 #define FT_STRUCTURE PCF_ParsePropertyRec
434 
437  FT_FRAME_BYTE ( isString ),
440  };
441 
442 
443  static
445  {
446 #undef FT_STRUCTURE
447 #define FT_STRUCTURE PCF_ParsePropertyRec
448 
450  FT_FRAME_LONG( name ),
451  FT_FRAME_BYTE( isString ),
452  FT_FRAME_LONG( value ),
454  };
455 
456 
459  const FT_String* prop )
460  {
461  PCF_Property properties = face->properties;
462  FT_Bool found = 0;
463  int i;
464 
465 
466  for ( i = 0; i < face->nprops && !found; i++ )
467  {
468  if ( !ft_strcmp( properties[i].name, prop ) )
469  found = 1;
470  }
471 
472  if ( found )
473  return properties + i - 1;
474  else
475  return NULL;
476  }
477 
478 
479  static FT_Error
481  PCF_Face face )
482  {
484  PCF_Property properties = NULL;
485  FT_ULong nprops, orig_nprops, i;
487  FT_Error error;
488  FT_Memory memory = FT_FACE( face )->memory;
489  FT_ULong string_size;
491 
492 
494  face->toc.tables,
495  face->toc.count,
497  &format,
498  &size );
499  if ( error )
500  goto Bail;
501 
502  if ( FT_READ_ULONG_LE( format ) )
503  goto Bail;
504 
505  FT_TRACE4(( "pcf_get_properties:\n"
506  " format: 0x%lX (%s)\n",
507  format,
508  PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB" ));
509 
511  goto Bail;
512 
513  if ( PCF_BYTE_ORDER( format ) == MSBFirst )
514  (void)FT_READ_ULONG( orig_nprops );
515  else
516  (void)FT_READ_ULONG_LE( orig_nprops );
517  if ( error )
518  goto Bail;
519 
520  FT_TRACE4(( " number of properties: %ld\n", orig_nprops ));
521 
522  /* rough estimate */
523  if ( orig_nprops > size / PCF_PROPERTY_SIZE )
524  {
525  error = FT_THROW( Invalid_Table );
526  goto Bail;
527  }
528 
529  /* as a heuristic limit to avoid excessive allocation in */
530  /* gzip bombs (i.e., very small, invalid input data that */
531  /* pretends to expand to an insanely large file) we only */
532  /* load the first 256 properties */
533  if ( orig_nprops > 256 )
534  {
535  FT_TRACE0(( "pcf_get_properties:"
536  " only loading first 256 properties\n" ));
537  nprops = 256;
538  }
539  else
540  nprops = orig_nprops;
541 
542  face->nprops = (int)nprops;
543 
544  if ( FT_NEW_ARRAY( props, nprops ) )
545  goto Bail;
546 
547  for ( i = 0; i < nprops; i++ )
548  {
549  if ( PCF_BYTE_ORDER( format ) == MSBFirst )
550  {
552  goto Bail;
553  }
554  else
555  {
557  goto Bail;
558  }
559  }
560 
561  /* this skip will only work if we really have an extremely large */
562  /* number of properties; it will fail for fake data, avoiding an */
563  /* unnecessarily large allocation later on */
564  if ( FT_STREAM_SKIP( ( orig_nprops - nprops ) * PCF_PROPERTY_SIZE ) )
565  {
566  error = FT_THROW( Invalid_Stream_Skip );
567  goto Bail;
568  }
569 
570  /* pad the property array */
571  /* */
572  /* clever here - nprops is the same as the number of odd-units read, */
573  /* as only isStringProp are odd length (Keith Packard) */
574  /* */
575  if ( orig_nprops & 3 )
576  {
577  i = 4 - ( orig_nprops & 3 );
578  if ( FT_STREAM_SKIP( i ) )
579  {
580  error = FT_THROW( Invalid_Stream_Skip );
581  goto Bail;
582  }
583  }
584 
585  if ( PCF_BYTE_ORDER( format ) == MSBFirst )
586  (void)FT_READ_ULONG( string_size );
587  else
588  (void)FT_READ_ULONG_LE( string_size );
589  if ( error )
590  goto Bail;
591 
592  FT_TRACE4(( " string size: %ld\n", string_size ));
593 
594  /* rough estimate */
595  if ( string_size > size - orig_nprops * PCF_PROPERTY_SIZE )
596  {
597  error = FT_THROW( Invalid_Table );
598  goto Bail;
599  }
600 
601  /* the strings in the `strings' array are PostScript strings, */
602  /* which can have a maximum length of 65536 characters each */
603  if ( string_size > 16777472 ) /* 256 * (65536 + 1) */
604  {
605  FT_TRACE0(( "pcf_get_properties:"
606  " loading only 16777472 bytes of strings array\n" ));
607  string_size = 16777472;
608  }
609 
610  /* allocate one more byte so that we have a final null byte */
611  if ( FT_NEW_ARRAY( strings, string_size + 1 ) )
612  goto Bail;
613 
614  error = FT_Stream_Read( stream, (FT_Byte*)strings, string_size );
615  if ( error )
616  goto Bail;
617 
618  if ( FT_NEW_ARRAY( properties, nprops ) )
619  goto Bail;
620 
621  face->properties = properties;
622 
623  FT_TRACE4(( "\n" ));
624  for ( i = 0; i < nprops; i++ )
625  {
626  FT_Long name_offset = props[i].name;
627 
628 
629  if ( ( name_offset < 0 ) ||
630  ( (FT_ULong)name_offset > string_size ) )
631  {
632  error = FT_THROW( Invalid_Offset );
633  goto Bail;
634  }
635 
636  if ( FT_STRDUP( properties[i].name, strings + name_offset ) )
637  goto Bail;
638 
639  FT_TRACE4(( " %s:", properties[i].name ));
640 
641  properties[i].isString = props[i].isString;
642 
643  if ( props[i].isString )
644  {
645  FT_Long value_offset = props[i].value;
646 
647 
648  if ( ( value_offset < 0 ) ||
649  ( (FT_ULong)value_offset > string_size ) )
650  {
651  error = FT_THROW( Invalid_Offset );
652  goto Bail;
653  }
654 
655  if ( FT_STRDUP( properties[i].value.atom, strings + value_offset ) )
656  goto Bail;
657 
658  FT_TRACE4(( " `%s'\n", properties[i].value.atom ));
659  }
660  else
661  {
662  properties[i].value.l = props[i].value;
663 
664  FT_TRACE4(( " %d\n", properties[i].value.l ));
665  }
666  }
667 
668  error = FT_Err_Ok;
669 
670  Bail:
671  FT_FREE( props );
672  FT_FREE( strings );
673 
674  return error;
675  }
676 
677 
678  static FT_Error
680  PCF_Face face )
681  {
682  FT_Error error;
683  FT_Memory memory = FT_FACE( face )->memory;
686  FT_ULong nmetrics, orig_nmetrics, i;
687 
688 
690  face->toc.tables,
691  face->toc.count,
692  PCF_METRICS,
693  &format,
694  &size );
695  if ( error )
696  return error;
697 
698  if ( FT_READ_ULONG_LE( format ) )
699  goto Bail;
700 
701  FT_TRACE4(( "pcf_get_metrics:\n"
702  " format: 0x%lX (%s, %s)\n",
703  format,
704  PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB",
706  "compressed" : "uncompressed" ));
707 
710  return FT_THROW( Invalid_File_Format );
711 
713  {
714  if ( PCF_BYTE_ORDER( format ) == MSBFirst )
715  (void)FT_READ_ULONG( orig_nmetrics );
716  else
717  (void)FT_READ_ULONG_LE( orig_nmetrics );
718  }
719  else
720  {
721  if ( PCF_BYTE_ORDER( format ) == MSBFirst )
722  (void)FT_READ_USHORT( orig_nmetrics );
723  else
724  (void)FT_READ_USHORT_LE( orig_nmetrics );
725  }
726  if ( error )
727  return FT_THROW( Invalid_File_Format );
728 
729  FT_TRACE4(( " number of metrics: %ld\n", orig_nmetrics ));
730 
731  /* rough estimate */
733  {
734  if ( orig_nmetrics > size / PCF_METRIC_SIZE )
735  return FT_THROW( Invalid_Table );
736  }
737  else
738  {
739  if ( orig_nmetrics > size / PCF_COMPRESSED_METRIC_SIZE )
740  return FT_THROW( Invalid_Table );
741  }
742 
743  if ( !orig_nmetrics )
744  return FT_THROW( Invalid_Table );
745 
746  /* PCF is a format from ancient times; Unicode was in its */
747  /* infancy, and widely used two-byte character sets for CJK */
748  /* scripts (Big 5, GB 2312, JIS X 0208, etc.) did have at most */
749  /* 15000 characters. Even the more exotic CNS 11643 and CCCII */
750  /* standards, which were essentially three-byte character sets, */
751  /* provided less then 65536 assigned characters. */
752  /* */
753  /* While technically possible to have a larger number of glyphs */
754  /* in PCF files, we thus limit the number to 65536. */
755  if ( orig_nmetrics > 65536 )
756  {
757  FT_TRACE0(( "pcf_get_metrics:"
758  " only loading first 65536 metrics\n" ));
759  nmetrics = 65536;
760  }
761  else
762  nmetrics = orig_nmetrics;
763 
764  face->nmetrics = nmetrics;
765 
766  if ( FT_NEW_ARRAY( face->metrics, nmetrics ) )
767  return error;
768 
769  metrics = face->metrics;
770 
771  FT_TRACE4(( "\n" ));
772  for ( i = 0; i < nmetrics; i++, metrics++ )
773  {
774  FT_TRACE5(( " idx %ld:", i ));
776 
777  metrics->bits = 0;
778 
779  if ( error )
780  break;
781 
782  /* sanity checks -- those values are used in `PCF_Glyph_Load' to */
783  /* compute a glyph's bitmap dimensions, thus setting them to zero in */
784  /* case of an error disables this particular glyph only */
785  if ( metrics->rightSideBearing < metrics->leftSideBearing ||
786  metrics->ascent < -metrics->descent )
787  {
788  metrics->characterWidth = 0;
789  metrics->leftSideBearing = 0;
790  metrics->rightSideBearing = 0;
791  metrics->ascent = 0;
792  metrics->descent = 0;
793 
794  FT_TRACE0(( "pcf_get_metrics:"
795  " invalid metrics for glyph %d\n", i ));
796  }
797  }
798 
799  if ( error )
800  FT_FREE( face->metrics );
801 
802  Bail:
803  return error;
804  }
805 
806 
807  static FT_Error
809  PCF_Face face )
810  {
811  FT_Error error;
812  FT_Memory memory = FT_FACE( face )->memory;
813  FT_Long* offsets = NULL;
814  FT_Long bitmapSizes[GLYPHPADOPTIONS];
816  FT_ULong nbitmaps, orig_nbitmaps, i, sizebitmaps = 0;
817 
818 
820  face->toc.tables,
821  face->toc.count,
822  PCF_BITMAPS,
823  &format,
824  &size );
825  if ( error )
826  return error;
827 
829  if ( error )
830  return error;
831 
833  if ( PCF_BYTE_ORDER( format ) == MSBFirst )
834  orig_nbitmaps = FT_GET_ULONG();
835  else
836  orig_nbitmaps = FT_GET_ULONG_LE();
837 
839 
840  FT_TRACE4(( "pcf_get_bitmaps:\n"
841  " format: 0x%lX\n"
842  " (%s, %s,\n"
843  " padding=%d bit%s, scanning=%d bit%s)\n",
844  format,
846  ? "most significant byte first"
847  : "least significant byte first",
849  ? "most significant bit first"
850  : "least significant bit first",
851  8 << PCF_GLYPH_PAD_INDEX( format ),
852  ( 8 << PCF_GLYPH_PAD_INDEX( format ) ) == 1 ? "" : "s",
853  8 << PCF_SCAN_UNIT_INDEX( format ),
854  ( 8 << PCF_SCAN_UNIT_INDEX( format ) ) == 1 ? "" : "s" ));
855 
857  return FT_THROW( Invalid_File_Format );
858 
859  FT_TRACE4(( " number of bitmaps: %ld\n", orig_nbitmaps ));
860 
861  /* see comment in `pcf_get_metrics' */
862  if ( orig_nbitmaps > 65536 )
863  {
864  FT_TRACE0(( "pcf_get_bitmaps:"
865  " only loading first 65536 bitmaps\n" ));
866  nbitmaps = 65536;
867  }
868  else
869  nbitmaps = orig_nbitmaps;
870 
871  if ( nbitmaps != face->nmetrics )
872  return FT_THROW( Invalid_File_Format );
873 
874  if ( FT_NEW_ARRAY( offsets, nbitmaps ) )
875  return error;
876 
877  FT_TRACE5(( "\n" ));
878  for ( i = 0; i < nbitmaps; i++ )
879  {
880  if ( PCF_BYTE_ORDER( format ) == MSBFirst )
881  (void)FT_READ_LONG( offsets[i] );
882  else
883  (void)FT_READ_LONG_LE( offsets[i] );
884 
885  FT_TRACE5(( " bitmap %ld: offset %ld (0x%lX)\n",
886  i, offsets[i], offsets[i] ));
887  }
888  if ( error )
889  goto Bail;
890 
891  for ( i = 0; i < GLYPHPADOPTIONS; i++ )
892  {
893  if ( PCF_BYTE_ORDER( format ) == MSBFirst )
894  (void)FT_READ_LONG( bitmapSizes[i] );
895  else
896  (void)FT_READ_LONG_LE( bitmapSizes[i] );
897  if ( error )
898  goto Bail;
899 
900  sizebitmaps = (FT_ULong)bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
901 
902  FT_TRACE4(( " %ld-bit padding implies a size of %ld\n",
903  8 << i, bitmapSizes[i] ));
904  }
905 
906  FT_TRACE4(( " %ld bitmaps, using %ld-bit padding\n",
907  nbitmaps,
908  8 << PCF_GLYPH_PAD_INDEX( format ) ));
909  FT_TRACE4(( " bitmap size: %ld\n", sizebitmaps ));
910 
911  FT_UNUSED( sizebitmaps ); /* only used for debugging */
912 
913  /* right now, we only check the bitmap offsets; */
914  /* actual bitmaps are only loaded on demand */
915  for ( i = 0; i < nbitmaps; i++ )
916  {
917  /* rough estimate */
918  if ( ( offsets[i] < 0 ) ||
919  ( (FT_ULong)offsets[i] > size ) )
920  {
921  FT_TRACE0(( "pcf_get_bitmaps:"
922  " invalid offset to bitmap data of glyph %ld\n", i ));
923  }
924  else
925  face->metrics[i].bits = stream->pos + (FT_ULong)offsets[i];
926  }
927 
928  face->bitmapsFormat = format;
929 
930  Bail:
931  FT_FREE( offsets );
932  return error;
933  }
934 
935 
936  static FT_Error
938  PCF_Face face )
939  {
940  FT_Error error;
941  FT_Memory memory = FT_FACE( face )->memory;
943  int firstCol, lastCol;
944  int firstRow, lastRow;
945  FT_ULong nencoding;
946  FT_UShort encodingOffset;
947  int i, j;
948  FT_ULong k;
950 
951 
953  face->toc.tables,
954  face->toc.count,
956  &format,
957  &size );
958  if ( error )
959  return error;
960 
962  if ( error )
963  return error;
964 
966 
967  if ( PCF_BYTE_ORDER( format ) == MSBFirst )
968  {
969  firstCol = FT_GET_SHORT();
970  lastCol = FT_GET_SHORT();
971  firstRow = FT_GET_SHORT();
972  lastRow = FT_GET_SHORT();
973  face->defaultChar = FT_GET_SHORT();
974  }
975  else
976  {
977  firstCol = FT_GET_SHORT_LE();
978  lastCol = FT_GET_SHORT_LE();
979  firstRow = FT_GET_SHORT_LE();
980  lastRow = FT_GET_SHORT_LE();
981  face->defaultChar = FT_GET_SHORT_LE();
982  }
983 
985 
986  FT_TRACE4(( "pcf_get_encodings:\n"
987  " format: 0x%lX (%s)\n",
988  format,
989  PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB" ));
990 
992  return FT_THROW( Invalid_File_Format );
993 
994  FT_TRACE4(( " firstCol 0x%X, lastCol 0x%X\n"
995  " firstRow 0x%X, lastRow 0x%X\n",
996  firstCol, lastCol,
997  firstRow, lastRow ));
998 
999  /* sanity checks; we limit numbers of rows and columns to 256 */
1000  if ( firstCol < 0 ||
1001  firstCol > lastCol ||
1002  lastCol > 0xFF ||
1003  firstRow < 0 ||
1004  firstRow > lastRow ||
1005  lastRow > 0xFF )
1006  return FT_THROW( Invalid_Table );
1007 
1008  nencoding = (FT_ULong)( lastCol - firstCol + 1 ) *
1009  (FT_ULong)( lastRow - firstRow + 1 );
1010 
1011  if ( FT_NEW_ARRAY( encoding, nencoding ) )
1012  return error;
1013 
1014  error = FT_Stream_EnterFrame( stream, 2 * nencoding );
1015  if ( error )
1016  goto Bail;
1017 
1018  FT_TRACE5(( "\n" ));
1019 
1020  k = 0;
1021  for ( i = firstRow; i <= lastRow; i++ )
1022  {
1023  for ( j = firstCol; j <= lastCol; j++ )
1024  {
1025  /* X11's reference implementation uses the equivalent to */
1026  /* `FT_GET_SHORT', however PCF fonts with more than 32768 */
1027  /* characters (e.g. `unifont.pcf') clearly show that an */
1028  /* unsigned value is needed. */
1029  if ( PCF_BYTE_ORDER( format ) == MSBFirst )
1030  encodingOffset = FT_GET_USHORT();
1031  else
1032  encodingOffset = FT_GET_USHORT_LE();
1033 
1034  if ( encodingOffset != 0xFFFFU )
1035  {
1036  encoding[k].enc = i * 256 + j;
1037  encoding[k].glyph = encodingOffset;
1038 
1039  FT_TRACE5(( " code %d (0x%04X): idx %d\n",
1040  encoding[k].enc, encoding[k].enc, encoding[k].glyph ));
1041 
1042  k++;
1043  }
1044  }
1045  }
1047 
1048  if ( FT_RENEW_ARRAY( encoding, nencoding, k ) )
1049  goto Bail;
1050 
1051  face->nencodings = k;
1052  face->encodings = encoding;
1053 
1054  return error;
1055 
1056  Bail:
1057  FT_FREE( encoding );
1058  return error;
1059  }
1060 
1061 
1062  static
1064  {
1065 #undef FT_STRUCTURE
1066 #define FT_STRUCTURE PCF_AccelRec
1067 
1068  FT_FRAME_START( 20 ),
1069  FT_FRAME_BYTE ( noOverlap ),
1070  FT_FRAME_BYTE ( constantMetrics ),
1071  FT_FRAME_BYTE ( terminalFont ),
1072  FT_FRAME_BYTE ( constantWidth ),
1073  FT_FRAME_BYTE ( inkInside ),
1074  FT_FRAME_BYTE ( inkMetrics ),
1075  FT_FRAME_BYTE ( drawDirection ),
1076  FT_FRAME_SKIP_BYTES( 1 ),
1077  FT_FRAME_LONG_LE ( fontAscent ),
1078  FT_FRAME_LONG_LE ( fontDescent ),
1079  FT_FRAME_LONG_LE ( maxOverlap ),
1080  FT_FRAME_END
1081  };
1082 
1083 
1084  static
1086  {
1087 #undef FT_STRUCTURE
1088 #define FT_STRUCTURE PCF_AccelRec
1089 
1090  FT_FRAME_START( 20 ),
1091  FT_FRAME_BYTE ( noOverlap ),
1092  FT_FRAME_BYTE ( constantMetrics ),
1093  FT_FRAME_BYTE ( terminalFont ),
1094  FT_FRAME_BYTE ( constantWidth ),
1095  FT_FRAME_BYTE ( inkInside ),
1096  FT_FRAME_BYTE ( inkMetrics ),
1097  FT_FRAME_BYTE ( drawDirection ),
1098  FT_FRAME_SKIP_BYTES( 1 ),
1099  FT_FRAME_LONG ( fontAscent ),
1100  FT_FRAME_LONG ( fontDescent ),
1101  FT_FRAME_LONG ( maxOverlap ),
1102  FT_FRAME_END
1103  };
1104 
1105 
1106  static FT_Error
1108  PCF_Face face,
1109  FT_ULong type )
1110  {
1111  FT_ULong format, size;
1112  FT_Error error;
1113  PCF_Accel accel = &face->accel;
1114 
1115 
1117  face->toc.tables,
1118  face->toc.count,
1119  type,
1120  &format,
1121  &size );
1122  if ( error )
1123  goto Bail;
1124 
1125  if ( FT_READ_ULONG_LE( format ) )
1126  goto Bail;
1127 
1128  FT_TRACE4(( "pcf_get_accel%s:\n"
1129  " format: 0x%lX (%s, %s)\n",
1130  type == PCF_BDF_ACCELERATORS ? " (getting BDF accelerators)"
1131  : "",
1132  format,
1133  PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB",
1135  "accelerated" : "not accelerated" ));
1136 
1139  goto Bail;
1140 
1141  if ( PCF_BYTE_ORDER( format ) == MSBFirst )
1142  {
1144  goto Bail;
1145  }
1146  else
1147  {
1148  if ( FT_STREAM_READ_FIELDS( pcf_accel_header, accel ) )
1149  goto Bail;
1150  }
1151 
1152  FT_TRACE5(( " noOverlap=%s, constantMetrics=%s,"
1153  " terminalFont=%s, constantWidth=%s\n"
1154  " inkInside=%s, inkMetrics=%s, drawDirection=%s\n"
1155  " fontAscent=%ld, fontDescent=%ld, maxOverlap=%ld\n",
1156  accel->noOverlap ? "yes" : "no",
1157  accel->constantMetrics ? "yes" : "no",
1158  accel->terminalFont ? "yes" : "no",
1159  accel->constantWidth ? "yes" : "no",
1160  accel->inkInside ? "yes" : "no",
1161  accel->inkMetrics ? "yes" : "no",
1162  accel->drawDirection ? "RTL" : "LTR",
1163  accel->fontAscent,
1164  accel->fontDescent,
1165  accel->maxOverlap ));
1166 
1167  /* sanity checks */
1168  if ( FT_ABS( accel->fontAscent ) > 0x7FFF )
1169  {
1170  accel->fontAscent = accel->fontAscent < 0 ? -0x7FFF : 0x7FFF;
1171  FT_TRACE0(( "pfc_get_accel: clamping font ascent to value %d\n",
1172  accel->fontAscent ));
1173  }
1174  if ( FT_ABS( accel->fontDescent ) > 0x7FFF )
1175  {
1176  accel->fontDescent = accel->fontDescent < 0 ? -0x7FFF : 0x7FFF;
1177  FT_TRACE0(( "pfc_get_accel: clamping font descent to value %d\n",
1178  accel->fontDescent ));
1179  }
1180 
1181  FT_TRACE5(( " minbounds:" ));
1183  format & ( ~PCF_FORMAT_MASK ),
1184  &(accel->minbounds) );
1185  if ( error )
1186  goto Bail;
1187 
1188  FT_TRACE5(( " maxbounds:" ));
1190  format & ( ~PCF_FORMAT_MASK ),
1191  &(accel->maxbounds) );
1192  if ( error )
1193  goto Bail;
1194 
1196  {
1197  FT_TRACE5(( " ink minbounds:" ));
1199  format & ( ~PCF_FORMAT_MASK ),
1200  &(accel->ink_minbounds) );
1201  if ( error )
1202  goto Bail;
1203 
1204  FT_TRACE5(( " ink maxbounds:" ));
1206  format & ( ~PCF_FORMAT_MASK ),
1207  &(accel->ink_maxbounds) );
1208  if ( error )
1209  goto Bail;
1210  }
1211  else
1212  {
1213  accel->ink_minbounds = accel->minbounds;
1214  accel->ink_maxbounds = accel->maxbounds;
1215  }
1216 
1217  Bail:
1218  return error;
1219  }
1220 
1221 
1222  static FT_Error
1224  {
1226  FT_Face face = FT_FACE( pcf );
1227  FT_Memory memory = face->memory;
1228 
1229  PCF_Property prop;
1230 
1231  size_t nn, len;
1232  char* strings[4] = { NULL, NULL, NULL, NULL };
1233  size_t lengths[4];
1234 
1235 
1236  face->style_flags = 0;
1237 
1238  prop = pcf_find_property( pcf, "SLANT" );
1239  if ( prop && prop->isString &&
1240  ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ||
1241  *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) )
1242  {
1243  face->style_flags |= FT_STYLE_FLAG_ITALIC;
1244  strings[2] = ( *(prop->value.atom) == 'O' ||
1245  *(prop->value.atom) == 'o' ) ? (char *)"Oblique"
1246  : (char *)"Italic";
1247  }
1248 
1249  prop = pcf_find_property( pcf, "WEIGHT_NAME" );
1250  if ( prop && prop->isString &&
1251  ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) )
1252  {
1253  face->style_flags |= FT_STYLE_FLAG_BOLD;
1254  strings[1] = (char*)"Bold";
1255  }
1256 
1257  prop = pcf_find_property( pcf, "SETWIDTH_NAME" );
1258  if ( prop && prop->isString &&
1259  *(prop->value.atom) &&
1260  !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
1261  strings[3] = (char*)( prop->value.atom );
1262 
1263  prop = pcf_find_property( pcf, "ADD_STYLE_NAME" );
1264  if ( prop && prop->isString &&
1265  *(prop->value.atom) &&
1266  !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
1267  strings[0] = (char*)( prop->value.atom );
1268 
1269  for ( len = 0, nn = 0; nn < 4; nn++ )
1270  {
1271  lengths[nn] = 0;
1272  if ( strings[nn] )
1273  {
1274  lengths[nn] = ft_strlen( strings[nn] );
1275  len += lengths[nn] + 1;
1276  }
1277  }
1278 
1279  if ( len == 0 )
1280  {
1281  strings[0] = (char*)"Regular";
1282  lengths[0] = ft_strlen( strings[0] );
1283  len = lengths[0] + 1;
1284  }
1285 
1286  {
1287  char* s;
1288 
1289 
1290  if ( FT_ALLOC( face->style_name, len ) )
1291  return error;
1292 
1293  s = face->style_name;
1294 
1295  for ( nn = 0; nn < 4; nn++ )
1296  {
1297  char* src = strings[nn];
1298 
1299 
1300  len = lengths[nn];
1301 
1302  if ( !src )
1303  continue;
1304 
1305  /* separate elements with a space */
1306  if ( s != face->style_name )
1307  *s++ = ' ';
1308 
1309  ft_memcpy( s, src, len );
1310 
1311  /* need to convert spaces to dashes for */
1312  /* add_style_name and setwidth_name */
1313  if ( nn == 0 || nn == 3 )
1314  {
1315  size_t mm;
1316 
1317 
1318  for ( mm = 0; mm < len; mm++ )
1319  if ( s[mm] == ' ' )
1320  s[mm] = '-';
1321  }
1322 
1323  s += len;
1324  }
1325  *s = 0;
1326  }
1327 
1328  return error;
1329  }
1330 
1331 
1334  PCF_Face face,
1335  FT_Long face_index )
1336  {
1337  FT_Face root = FT_FACE( face );
1338  FT_Error error;
1339  FT_Memory memory = FT_FACE( face )->memory;
1340  FT_Bool hasBDFAccelerators;
1341 
1342 
1343  error = pcf_read_TOC( stream, face );
1344  if ( error )
1345  goto Exit;
1346 
1347  root->num_faces = 1;
1348  root->face_index = 0;
1349 
1350  /* If we are performing a simple font format check, exit immediately. */
1351  if ( face_index < 0 )
1352  return FT_Err_Ok;
1353 
1355  if ( error )
1356  goto Exit;
1357 
1358  /* Use the old accelerators if no BDF accelerators are in the file. */
1359  hasBDFAccelerators = pcf_has_table_type( face->toc.tables,
1360  face->toc.count,
1362  if ( !hasBDFAccelerators )
1363  {
1365  if ( error )
1366  goto Exit;
1367  }
1368 
1369  /* metrics */
1371  if ( error )
1372  goto Exit;
1373 
1374  /* bitmaps */
1376  if ( error )
1377  goto Exit;
1378 
1379  /* encodings */
1381  if ( error )
1382  goto Exit;
1383 
1384  /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
1385  if ( hasBDFAccelerators )
1386  {
1388  if ( error )
1389  goto Exit;
1390  }
1391 
1392  /* XXX: TO DO: inkmetrics and glyph_names are missing */
1393 
1394  /* now construct the face object */
1395  {
1396  PCF_Property prop;
1397 
1398 
1399  root->face_flags |= FT_FACE_FLAG_FIXED_SIZES |
1402 
1403  if ( face->accel.constantWidth )
1404  root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
1405 
1407  goto Exit;
1408 
1409  prop = pcf_find_property( face, "FAMILY_NAME" );
1410  if ( prop && prop->isString )
1411  {
1412 
1413 #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES
1414 
1416 
1417 
1418  if ( !driver->no_long_family_names )
1419  {
1420  /* Prepend the foundry name plus a space to the family name. */
1421  /* There are many fonts just called `Fixed' which look */
1422  /* completely different, and which have nothing to do with each */
1423  /* other. When selecting `Fixed' in KDE or Gnome one gets */
1424  /* results that appear rather random, the style changes often if */
1425  /* one changes the size and one cannot select some fonts at all. */
1426  /* */
1427  /* We also check whether we have `wide' characters; all put */
1428  /* together, we get family names like `Sony Fixed' or `Misc */
1429  /* Fixed Wide'. */
1430 
1431  PCF_Property foundry_prop, point_size_prop, average_width_prop;
1432 
1433  int l = ft_strlen( prop->value.atom ) + 1;
1434  int wide = 0;
1435 
1436 
1437  foundry_prop = pcf_find_property( face, "FOUNDRY" );
1438  point_size_prop = pcf_find_property( face, "POINT_SIZE" );
1439  average_width_prop = pcf_find_property( face, "AVERAGE_WIDTH" );
1440 
1441  if ( point_size_prop && average_width_prop )
1442  {
1443  if ( average_width_prop->value.l >= point_size_prop->value.l )
1444  {
1445  /* This font is at least square shaped or even wider */
1446  wide = 1;
1447  l += ft_strlen( " Wide" );
1448  }
1449  }
1450 
1451  if ( foundry_prop && foundry_prop->isString )
1452  {
1453  l += ft_strlen( foundry_prop->value.atom ) + 1;
1454 
1455  if ( FT_NEW_ARRAY( root->family_name, l ) )
1456  goto Exit;
1457 
1458  ft_strcpy( root->family_name, foundry_prop->value.atom );
1459  ft_strcat( root->family_name, " " );
1460  ft_strcat( root->family_name, prop->value.atom );
1461  }
1462  else
1463  {
1464  if ( FT_NEW_ARRAY( root->family_name, l ) )
1465  goto Exit;
1466 
1467  ft_strcpy( root->family_name, prop->value.atom );
1468  }
1469 
1470  if ( wide )
1471  ft_strcat( root->family_name, " Wide" );
1472  }
1473  else
1474 
1475 #endif /* PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
1476 
1477  {
1478  if ( FT_STRDUP( root->family_name, prop->value.atom ) )
1479  goto Exit;
1480  }
1481  }
1482  else
1483  root->family_name = NULL;
1484 
1485  /*
1486  * Note: We shift all glyph indices by +1 since we must
1487  * respect the convention that glyph 0 always corresponds
1488  * to the `missing glyph'.
1489  *
1490  * This implies bumping the number of `available' glyphs by 1.
1491  */
1492  root->num_glyphs = (FT_Long)( face->nmetrics + 1 );
1493 
1494  root->num_fixed_sizes = 1;
1495  if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
1496  goto Exit;
1497 
1498  {
1499  FT_Bitmap_Size* bsize = root->available_sizes;
1500  FT_Short resolution_x = 0, resolution_y = 0;
1501 
1502 
1503  FT_ZERO( bsize );
1504 
1505  /* for simplicity, we take absolute values of integer properties */
1506 
1507 #if 0
1508  bsize->height = face->accel.maxbounds.ascent << 6;
1509 #endif
1510 
1511 #ifdef FT_DEBUG_LEVEL_TRACE
1512  if ( face->accel.fontAscent + face->accel.fontDescent < 0 )
1513  FT_TRACE0(( "pcf_load_font: negative height\n" ));
1514 #endif
1515  if ( FT_ABS( face->accel.fontAscent +
1516  face->accel.fontDescent ) > 0x7FFF )
1517  {
1518  bsize->height = 0x7FFF;
1519  FT_TRACE0(( "pcf_load_font: clamping height to value %d\n",
1520  bsize->height ));
1521  }
1522  else
1523  bsize->height = FT_ABS( (FT_Short)( face->accel.fontAscent +
1524  face->accel.fontDescent ) );
1525 
1526  prop = pcf_find_property( face, "AVERAGE_WIDTH" );
1527  if ( prop )
1528  {
1529 #ifdef FT_DEBUG_LEVEL_TRACE
1530  if ( prop->value.l < 0 )
1531  FT_TRACE0(( "pcf_load_font: negative average width\n" ));
1532 #endif
1533  if ( ( FT_ABS( prop->value.l ) > 0x7FFFL * 10 - 5 ) )
1534  {
1535  bsize->width = 0x7FFF;
1536  FT_TRACE0(( "pcf_load_font: clamping average width to value %d\n",
1537  bsize->width ));
1538  }
1539  else
1540  bsize->width = FT_ABS( (FT_Short)( ( prop->value.l + 5 ) / 10 ) );
1541  }
1542  else
1543  {
1544  /* this is a heuristical value */
1545  bsize->width = (FT_Short)FT_MulDiv( bsize->height, 2, 3 );
1546  }
1547 
1548  prop = pcf_find_property( face, "POINT_SIZE" );
1549  if ( prop )
1550  {
1551 #ifdef FT_DEBUG_LEVEL_TRACE
1552  if ( prop->value.l < 0 )
1553  FT_TRACE0(( "pcf_load_font: negative point size\n" ));
1554 #endif
1555  /* convert from 722.7 decipoints to 72 points per inch */
1556  if ( FT_ABS( prop->value.l ) > 0x504C2L ) /* 0x7FFF * 72270/7200 */
1557  {
1558  bsize->size = 0x7FFF;
1559  FT_TRACE0(( "pcf_load_font: clamping point size to value %d\n",
1560  bsize->size ));
1561  }
1562  else
1563  bsize->size = FT_MulDiv( FT_ABS( prop->value.l ),
1564  64 * 7200,
1565  72270L );
1566  }
1567 
1568  prop = pcf_find_property( face, "PIXEL_SIZE" );
1569  if ( prop )
1570  {
1571 #ifdef FT_DEBUG_LEVEL_TRACE
1572  if ( prop->value.l < 0 )
1573  FT_TRACE0(( "pcf_load_font: negative pixel size\n" ));
1574 #endif
1575  if ( FT_ABS( prop->value.l ) > 0x7FFF )
1576  {
1577  bsize->y_ppem = 0x7FFF << 6;
1578  FT_TRACE0(( "pcf_load_font: clamping pixel size to value %d\n",
1579  bsize->y_ppem ));
1580  }
1581  else
1582  bsize->y_ppem = FT_ABS( (FT_Short)prop->value.l ) << 6;
1583  }
1584 
1585  prop = pcf_find_property( face, "RESOLUTION_X" );
1586  if ( prop )
1587  {
1588 #ifdef FT_DEBUG_LEVEL_TRACE
1589  if ( prop->value.l < 0 )
1590  FT_TRACE0(( "pcf_load_font: negative X resolution\n" ));
1591 #endif
1592  if ( FT_ABS( prop->value.l ) > 0x7FFF )
1593  {
1594  resolution_x = 0x7FFF;
1595  FT_TRACE0(( "pcf_load_font: clamping X resolution to value %d\n",
1596  resolution_x ));
1597  }
1598  else
1599  resolution_x = FT_ABS( (FT_Short)prop->value.l );
1600  }
1601 
1602  prop = pcf_find_property( face, "RESOLUTION_Y" );
1603  if ( prop )
1604  {
1605 #ifdef FT_DEBUG_LEVEL_TRACE
1606  if ( prop->value.l < 0 )
1607  FT_TRACE0(( "pcf_load_font: negative Y resolution\n" ));
1608 #endif
1609  if ( FT_ABS( prop->value.l ) > 0x7FFF )
1610  {
1611  resolution_y = 0x7FFF;
1612  FT_TRACE0(( "pcf_load_font: clamping Y resolution to value %d\n",
1613  resolution_y ));
1614  }
1615  else
1616  resolution_y = FT_ABS( (FT_Short)prop->value.l );
1617  }
1618 
1619  if ( bsize->y_ppem == 0 )
1620  {
1621  bsize->y_ppem = bsize->size;
1622  if ( resolution_y )
1623  bsize->y_ppem = FT_MulDiv( bsize->y_ppem, resolution_y, 72 );
1624  }
1625  if ( resolution_x && resolution_y )
1626  bsize->x_ppem = FT_MulDiv( bsize->y_ppem,
1627  resolution_x,
1628  resolution_y );
1629  else
1630  bsize->x_ppem = bsize->y_ppem;
1631  }
1632 
1633  /* set up charset */
1634  {
1635  PCF_Property charset_registry, charset_encoding;
1636 
1637 
1638  charset_registry = pcf_find_property( face, "CHARSET_REGISTRY" );
1639  charset_encoding = pcf_find_property( face, "CHARSET_ENCODING" );
1640 
1641  if ( charset_registry && charset_registry->isString &&
1642  charset_encoding && charset_encoding->isString )
1643  {
1644  if ( FT_STRDUP( face->charset_encoding,
1645  charset_encoding->value.atom ) ||
1646  FT_STRDUP( face->charset_registry,
1647  charset_registry->value.atom ) )
1648  goto Exit;
1649  }
1650  }
1651  }
1652 
1653  Exit:
1654  if ( error )
1655  {
1656  /* This is done to respect the behaviour of the original */
1657  /* PCF font driver. */
1658  error = FT_THROW( Invalid_File_Format );
1659  }
1660 
1661  return error;
1662  }
1663 
1664 
1665 /* END */
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:303
int FT_Error
Definition: fttypes.h:300
PCF_MetricRec ink_minbounds
Definition: pcf.h:121
FT_Stream_EnterFrame(FT_Stream stream, FT_ULong count)
Definition: ftstream.c:234
#define FT_FRAME_LONG(f)
Definition: ftstream.h:120
signed long FT_Long
Definition: fttypes.h:242
#define TRUE
Definition: types.h:120
static const FT_Frame_Field pcf_property_msb_header[]
Definition: pcfread.c:444
unsigned long FT_ULong
Definition: fttypes.h:253
PCF_MetricRec ink_maxbounds
Definition: pcf.h:122
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
FT_Pos x_ppem
Definition: freetype.h:378
#define FT_READ_USHORT_LE(var)
Definition: ftstream.h:316
static const FT_Frame_Field pcf_metric_msb_header[]
Definition: pcfread.c:284
#define error(str)
Definition: mkdosfs.c:1605
#define PCF_BDF_ENCODINGS
Definition: pcf.h:230
static const FT_Frame_Field pcf_accel_msb_header[]
Definition: pcfread.c:1085
GLsizei GLenum const GLvoid GLuint GLsizei GLfloat * metrics
Definition: glext.h:11745
#define FT_FACE_FLAG_FAST_GLYPHS
Definition: freetype.h:1245
union PCF_PropertyRec_::@3876 value
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define FT_ABS(a)
Definition: ftobjs.h:74
#define PCF_ACCEL_W_INKBOUNDS
Definition: pcf.h:187
FT_ULong version
Definition: pcf.h:51
GLintptr offset
Definition: glext.h:5920
static FT_Bool pcf_has_table_type(PCF_Table tables, FT_ULong ntables, FT_ULong type)
Definition: pcfread.c:412
GLdouble n
Definition: glext.h:7729
FT_BEGIN_HEADER struct PCF_TableRec_ * PCF_Table
FT_Byte constantMetrics
Definition: pcf.h:110
pcf_find_property(PCF_Face face, const FT_String *prop)
Definition: pcfread.c:458
PCF_MetricRec minbounds
Definition: pcf.h:119
#define MSBFirst
Definition: pcf.h:178
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define FT_MIN(a, b)
Definition: ftobjs.h:71
FT_BEGIN_HEADER struct PCF_TableRec_ PCF_TableRec
#define ft_strcat
Definition: ftstdlib.h:85
#define FT_FACE_FLAG_FIXED_SIZES
Definition: freetype.h:1239
FT_Long fontDescent
Definition: pcf.h:117
#define FT_FRAME_SHORT_LE(f)
Definition: ftstream.h:131
FT_Long l
Definition: pcf.h:75
#define PCF_DEFAULT_FORMAT
Definition: pcf.h:185
return FT_Err_Ok
Definition: ftbbox.c:511
static char memory[1024 *256]
Definition: process.c:116
#define FT_READ_USHORT(var)
Definition: ftstream.h:309
static int compr(const void *a, const void *b)
Definition: bidi.c:685
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
#define FT_FRAME_ULONG_LE(f)
Definition: ftstream.h:130
FT_Short descent
Definition: pcf.h:100
#define PCF_BDF_ACCELERATORS
Definition: pcf.h:233
#define FT_FACE_DRIVER(x)
Definition: ftobjs.h:634
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:108
static FT_Error pcf_get_metric(FT_Stream stream, FT_ULong format, PCF_Metric metric)
Definition: pcfread.c:319
static const FT_Frame_Field pcf_compressed_metric_header[]
Definition: pcfread.c:303
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define PCF_COMPRESSED_METRICS
Definition: pcf.h:188
unsigned char FT_Byte
Definition: fttypes.h:154
#define FT_THROW(e)
Definition: ftdebug.h:213
#define PCF_GLYPH_PAD_INDEX(f)
Definition: pcf.h:202
#define FT_STYLE_FLAG_BOLD
Definition: freetype.h:1518
#define FT_FRAME_SKIP_BYTES(count)
Definition: ftstream.h:147
#define FT_TRACE4(varformat)
Definition: ftdebug.h:161
PCF_MetricRec maxbounds
Definition: pcf.h:120
static FT_Error pcf_get_properties(FT_Stream stream, PCF_Face face)
Definition: pcfread.c:480
smooth NULL
Definition: ftsmooth.c:416
#define FT_STREAM_READ_FIELDS(fields, object)
Definition: ftstream.h:508
static const WCHAR version[]
Definition: asmname.c:66
FT_Short rightSideBearing
Definition: pcf.h:97
#define PCF_BYTE_ORDER(f)
Definition: pcf.h:198
FT_Short attributes
Definition: pcf.h:101
static FT_Error pcf_interpret_style(PCF_Face pcf)
Definition: pcfread.c:1223
static const FT_Frame_Field pcf_accel_header[]
Definition: pcfread.c:1063
#define FT_GET_USHORT()
Definition: ftstream.h:289
#define FT_FREE(ptr)
Definition: ftmemory.h:329
#define FT_FRAME_END
Definition: ftstream.h:118
#define FT_STREAM_SKIP(distance)
Definition: ftstream.h:493
#define PCF_PROPERTY_SIZE
Definition: pcfread.c:427
#define FT_FACE_FLAG_FIXED_WIDTH
Definition: freetype.h:1240
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:388
FT_Stream_Read(FT_Stream stream, FT_Byte *buffer, FT_ULong count)
Definition: ftstream.c:110
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
r l[0]
Definition: byte_order.h:167
static const FT_Frame_Field pcf_property_header[]
Definition: pcfread.c:430
FT_MulDiv(FT_Long a, FT_Long b, FT_Long c)
Definition: ftcalc.c:416
#define FT_ERR(e)
Definition: fttypes.h:586
#define FT_READ_ULONG(var)
Definition: ftstream.h:313
#define FT_TRACE0(varformat)
Definition: ftdebug.h:157
char FT_String
Definition: fttypes.h:187
GLsizeiptr size
Definition: glext.h:5919
#define FT_ZERO(p)
Definition: ftmemory.h:237
#define FT_FACE_FLAG_HORIZONTAL
Definition: freetype.h:1242
static const FT_Frame_Field pcf_table_header[]
Definition: pcfread.c:80
#define FT_GET_USHORT_LE()
Definition: ftstream.h:297
static void Exit(void)
Definition: sock.c:1331
FT_Byte noOverlap
Definition: pcf.h:109
static FT_Error pcf_get_metrics(FT_Stream stream, PCF_Face face)
Definition: pcfread.c:679
FT_Byte terminalFont
Definition: pcf.h:111
#define FT_GET_SHORT_LE()
Definition: ftstream.h:296
static const FT_Frame_Field pcf_metric_header[]
Definition: pcfread.c:267
FT_Pos y_ppem
Definition: freetype.h:379
#define FT_RENEW_ARRAY(ptr, curcnt, newcnt)
Definition: ftmemory.h:336
FT_Short width
Definition: freetype.h:374
FT_String * atom
Definition: pcf.h:74
static FT_Error pcf_get_bitmaps(FT_Stream stream, PCF_Face face)
Definition: pcfread.c:808
#define FT_READ_ULONG_LE(var)
Definition: ftstream.h:318
#define FT_READ_LONG(var)
Definition: ftstream.h:312
FT_Byte isString
Definition: pcf.h:70
GLsizei const GLchar *const * strings
Definition: glext.h:7622
FT_Byte drawDirection
Definition: pcf.h:115
static const WCHAR L[]
Definition: oid.c:1250
unsigned int size
Definition: parse.h:27
Definition: parse.h:22
#define PCF_FORMAT_MATCH(a, b)
Definition: pcf.h:190
#define PCF_SCAN_UNIT_INDEX(f)
Definition: pcf.h:206
signed short FT_Short
Definition: fttypes.h:198
FT_Byte inkInside
Definition: pcf.h:113
#define FT_READ_LONG_LE(var)
Definition: ftstream.h:317
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
GLenum GLsizei len
Definition: glext.h:6722
FT_Short leftSideBearing
Definition: pcf.h:96
GLdouble s
Definition: gl.h:2039
GLenum src
Definition: glext.h:6340
#define PCF_BITMAPS
Definition: pcf.h:228
#define PCF_METRICS
Definition: pcf.h:227
#define FT_NEW_ARRAY(ptr, count)
Definition: ftmemory.h:333
#define FT_STREAM_SEEK(position)
Definition: ftstream.h:489
ed encoding
Definition: write.c:2839
Definition: hiveinit.c:368
ULARGE_INTEGER pos
Definition: request.c:4080
static const FT_Frame_Field pcf_toc_header[]
Definition: pcfread.c:67
struct @1623::@1624 driver
#define FT_FACE(x)
Definition: ftobjs.h:630
#define FT_SET_ERROR(expression)
Definition: ftmemory.h:42
FT_ULong count
Definition: pcf.h:52
#define PCF_FORMAT_MASK
Definition: pcf.h:183
unsigned int FT_UInt
Definition: fttypes.h:231
#define FT_FRAME_BYTE(f)
Definition: ftstream.h:126
static FT_Error pcf_read_TOC(FT_Stream stream, PCF_Face face)
Definition: pcfread.c:95
#define PCF_BIT_ORDER(f)
Definition: pcf.h:200
#define FT_TRACE5(varformat)
Definition: ftdebug.h:162
FT_Byte inkMetrics
Definition: pcf.h:114
struct PCF_DriverRec_ * PCF_Driver
static FT_Error pcf_get_accel(FT_Stream stream, PCF_Face face, FT_ULong type)
Definition: pcfread.c:1107
#define PCF_ACCELERATORS
Definition: pcf.h:226
FT_Byte constantWidth
Definition: pcf.h:112
#define FT_GET_SHORT()
Definition: ftstream.h:288
#define PCF_METRIC_SIZE
Definition: pcfread.c:264
FT_Stream_ExitFrame(FT_Stream stream)
Definition: ftstream.c:314
static FT_Error pcf_get_encodings(FT_Stream stream, PCF_Face face)
Definition: pcfread.c:937
FT_Short ascent
Definition: pcf.h:99
#define FT_GET_ULONG()
Definition: ftstream.h:293
Definition: name.c:36
static const WCHAR props[]
Definition: wbemdisp.c:288
#define const
Definition: zconf.h:230
struct nls_table * tables
Definition: nls_base.c:22
#define FT_STRDUP(dst, str)
Definition: ftmemory.h:364
#define PCF_FILE_VERSION
Definition: pcf.h:180
static FT_Error pcf_seek_to_table_type(FT_Stream stream, PCF_Table tables, FT_ULong ntables, FT_ULong type, FT_ULong *aformat, FT_ULong *asize)
Definition: pcfread.c:373
#define PCF_PROPERTIES
Definition: pcf.h:225
#define FT_FRAME_LONG_LE(f)
Definition: ftstream.h:129
#define ft_strcpy
Definition: ftstdlib.h:87
#define FT_STYLE_FLAG_ITALIC
Definition: freetype.h:1517
unsigned short FT_UShort
Definition: fttypes.h:209
pcf_load_font(FT_Stream stream, PCF_Face face, FT_Long face_index)
Definition: pcfread.c:1333
FT_Long maxOverlap
Definition: pcf.h:118
GLsizei GLenum GLenum GLuint GLenum GLsizei * lengths
Definition: glext.h:7753
#define ft_memcpy
Definition: ftstdlib.h:82
#define FT_FRAME_SHORT(f)
Definition: ftstream.h:122
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
#define PCF_COMPRESSED_METRIC_SIZE
Definition: pcfread.c:300
int k
Definition: mpi.c:3369
#define ft_strlen
Definition: ftstdlib.h:88
FT_Short characterWidth
Definition: pcf.h:98
FT_Short height
Definition: freetype.h:373
#define FT_FRAME_START(size)
Definition: ftstream.h:117
GLenum GLuint GLint GLenum face
Definition: glext.h:7025
#define FT_GET_ULONG_LE()
Definition: ftstream.h:299
FT_Long fontAscent
Definition: pcf.h:116
#define ft_strcmp
Definition: ftstdlib.h:86
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define GLYPHPADOPTIONS
Definition: pcf.h:235