source: trunk/poppler/freetype-2.1.10/src/pcf/pcfdrivr.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 16 years ago

First import

File size: 16.2 KB
Line 
1/*  pcfdrivr.c
2
3    FreeType font driver for pcf files
4
5    Copyright (C) 2000, 2001, 2002, 2003, 2004 by
6    Francesco Zappa Nardelli
7
8Permission is hereby granted, free of charge, to any person obtaining a copy
9of this software and associated documentation files (the "Software"), to deal
10in the Software without restriction, including without limitation the rights
11to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12copies of the Software, and to permit persons to whom the Software is
13furnished to do so, subject to the following conditions:
14
15The above copyright notice and this permission notice shall be included in
16all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
21AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24THE 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#include FT_GZIP_H
34#include FT_LZW_H
35#include FT_ERRORS_H
36#include FT_BDF_H
37
38#include "pcf.h"
39#include "pcfdrivr.h"
40#include "pcfread.h"
41
42#include "pcferror.h"
43#include "pcfutil.h"
44
45#undef  FT_COMPONENT
46#define FT_COMPONENT  trace_pcfread
47
48#include FT_SERVICE_BDF_H
49#include FT_SERVICE_XFREE86_NAME_H
50
51
52  /*************************************************************************/
53  /*                                                                       */
54  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
55  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
56  /* messages during execution.                                            */
57  /*                                                                       */
58#undef  FT_COMPONENT
59#define FT_COMPONENT  trace_pcfdriver
60
61
62  typedef struct  PCF_CMapRec_
63  {
64    FT_CMapRec    root;
65    FT_UInt       num_encodings;
66    PCF_Encoding  encodings;
67
68  } PCF_CMapRec, *PCF_CMap;
69
70
71  FT_CALLBACK_DEF( FT_Error )
72  pcf_cmap_init( FT_CMap     pcfcmap,   /* PCF_CMap */
73                 FT_Pointer  init_data )
74  {
75    PCF_CMap  cmap = (PCF_CMap)pcfcmap;
76    PCF_Face  face = (PCF_Face)FT_CMAP_FACE( pcfcmap );
77
78    FT_UNUSED( init_data );
79
80
81    cmap->num_encodings = (FT_UInt)face->nencodings;
82    cmap->encodings     = face->encodings;
83
84    return PCF_Err_Ok;
85  }
86
87
88  FT_CALLBACK_DEF( void )
89  pcf_cmap_done( FT_CMap  pcfcmap )         /* PCF_CMap */
90  {
91    PCF_CMap  cmap = (PCF_CMap)pcfcmap;
92
93
94    cmap->encodings     = NULL;
95    cmap->num_encodings = 0;
96  }
97
98
99  FT_CALLBACK_DEF( FT_UInt )
100  pcf_cmap_char_index( FT_CMap    pcfcmap,  /* PCF_CMap */
101                       FT_UInt32  charcode )
102  {
103    PCF_CMap      cmap      = (PCF_CMap)pcfcmap;
104    PCF_Encoding  encodings = cmap->encodings;
105    FT_UInt       min, max, mid;
106    FT_UInt       result    = 0;
107
108
109    min = 0;
110    max = cmap->num_encodings;
111
112    while ( min < max )
113    {
114      FT_UInt32  code;
115
116
117      mid  = ( min + max ) >> 1;
118      code = encodings[mid].enc;
119
120      if ( charcode == code )
121      {
122        result = encodings[mid].glyph + 1;
123        break;
124      }
125
126      if ( charcode < code )
127        max = mid;
128      else
129        min = mid + 1;
130    }
131
132    return result;
133  }
134
135
136  FT_CALLBACK_DEF( FT_UInt )
137  pcf_cmap_char_next( FT_CMap    pcfcmap,   /* PCF_CMap */
138                      FT_UInt32  *acharcode )
139  {
140    PCF_CMap      cmap      = (PCF_CMap)pcfcmap;
141    PCF_Encoding  encodings = cmap->encodings;
142    FT_UInt       min, max, mid;
143    FT_UInt32     charcode  = *acharcode + 1;
144    FT_UInt       result    = 0;
145
146
147    min = 0;
148    max = cmap->num_encodings;
149
150    while ( min < max )
151    {
152      FT_UInt32  code;
153
154
155      mid  = ( min + max ) >> 1;
156      code = encodings[mid].enc;
157
158      if ( charcode == code )
159      {
160        result = encodings[mid].glyph + 1;
161        goto Exit;
162      }
163
164      if ( charcode < code )
165        max = mid;
166      else
167        min = mid + 1;
168    }
169
170    charcode = 0;
171    if ( min < cmap->num_encodings )
172    {
173      charcode = encodings[min].enc;
174      result   = encodings[min].glyph + 1;
175    }
176
177  Exit:
178    *acharcode = charcode;
179    return result;
180  }
181
182
183  FT_CALLBACK_TABLE_DEF
184  const FT_CMap_ClassRec  pcf_cmap_class =
185  {
186    sizeof ( PCF_CMapRec ),
187    pcf_cmap_init,
188    pcf_cmap_done,
189    pcf_cmap_char_index,
190    pcf_cmap_char_next
191  };
192
193
194  FT_CALLBACK_DEF( void )
195  PCF_Face_Done( FT_Face  pcfface )         /* PCF_Face */
196  {
197    PCF_Face   face   = (PCF_Face)pcfface;
198    FT_Memory  memory = FT_FACE_MEMORY( face );
199
200
201    FT_FREE( face->encodings );
202    FT_FREE( face->metrics );
203
204    /* free properties */
205    {
206      PCF_Property  prop = face->properties;
207      FT_Int        i;
208
209
210      for ( i = 0; i < face->nprops; i++ )
211      {
212        prop = &face->properties[i];
213
214        FT_FREE( prop->name );
215        if ( prop->isString )
216          FT_FREE( prop->value );
217      }
218
219      FT_FREE( face->properties );
220    }
221
222    FT_FREE( face->toc.tables );
223    FT_FREE( pcfface->family_name );
224    FT_FREE( pcfface->style_name );
225    FT_FREE( pcfface->available_sizes );
226    FT_FREE( face->charset_encoding );
227    FT_FREE( face->charset_registry );
228
229    FT_TRACE4(( "PCF_Face_Done: done face\n" ));
230
231    /* close gzip/LZW stream if any */
232    if ( pcfface->stream == &face->gzip_stream )
233    {
234      FT_Stream_Close( &face->gzip_stream );
235      pcfface->stream = face->gzip_source;
236    }
237  }
238
239
240  FT_CALLBACK_DEF( FT_Error )
241  PCF_Face_Init( FT_Stream      stream,
242                 FT_Face        pcfface,        /* PCF_Face */
243                 FT_Int         face_index,
244                 FT_Int         num_params,
245                 FT_Parameter*  params )
246  {
247    PCF_Face  face  = (PCF_Face)pcfface;
248    FT_Error  error = PCF_Err_Ok;
249
250    FT_UNUSED( num_params );
251    FT_UNUSED( params );
252    FT_UNUSED( face_index );
253
254
255    error = pcf_load_font( stream, face );
256    if ( error )
257    {
258      FT_Error  error2;
259
260
261      /* this didn't work, try gzip support! */
262      error2 = FT_Stream_OpenGzip( &face->gzip_stream, stream );
263      if ( FT_ERROR_BASE( error2 ) == FT_Err_Unimplemented_Feature )
264        goto Fail;
265
266      error = error2;
267      if ( error )
268      {
269        FT_Error  error3;
270
271
272        /* this didn't work, try LZW support! */
273        error3 = FT_Stream_OpenLZW( &face->gzip_stream, stream );
274        if ( FT_ERROR_BASE( error3 ) == FT_Err_Unimplemented_Feature )
275          goto Fail;
276
277        error = error3;
278        if ( error )
279          goto Fail;
280
281        face->gzip_source = stream;
282        pcfface->stream   = &face->gzip_stream;
283
284        stream = pcfface->stream;
285
286        error = pcf_load_font( stream, face );
287        if ( error )
288          goto Fail;
289      }
290      else
291      {
292        face->gzip_source = stream;
293        pcfface->stream   = &face->gzip_stream;
294
295        stream = pcfface->stream;
296
297        error = pcf_load_font( stream, face );
298        if ( error )
299          goto Fail;
300      }
301    }
302
303    /* set up charmap */
304    {
305      FT_String  *charset_registry = face->charset_registry;
306      FT_String  *charset_encoding = face->charset_encoding;
307      FT_Bool     unicode_charmap  = 0;
308
309
310      if ( charset_registry && charset_encoding )
311      {
312        char*  s = charset_registry;
313
314
315        /* Uh, oh, compare first letters manually to avoid dependency
316           on locales. */
317        if ( ( s[0] == 'i' || s[0] == 'I' ) &&
318             ( s[1] == 's' || s[1] == 'S' ) &&
319             ( s[2] == 'o' || s[2] == 'O' ) )
320        {
321          s += 3;
322          if ( !ft_strcmp( s, "10646" )                      ||
323               ( !ft_strcmp( s, "8859" ) &&
324                 !ft_strcmp( face->charset_encoding, "1" ) ) )
325          unicode_charmap = 1;
326        }
327      }
328
329      {
330        FT_CharMapRec  charmap;
331
332
333        charmap.face        = FT_FACE( face );
334        charmap.encoding    = FT_ENCODING_NONE;
335        charmap.platform_id = 0;
336        charmap.encoding_id = 0;
337
338        if ( unicode_charmap )
339        {
340          charmap.encoding    = FT_ENCODING_UNICODE;
341          charmap.platform_id = 3;
342          charmap.encoding_id = 1;
343        }
344
345        error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL );
346
347#if 0
348        /* Select default charmap */
349        if ( pcfface->num_charmaps )
350          pcfface->charmap = pcfface->charmaps[0];
351#endif
352      }
353    }
354
355  Exit:
356    return error;
357
358  Fail:
359    FT_TRACE2(( "[not a valid PCF file]\n" ));
360    error = PCF_Err_Unknown_File_Format;  /* error */
361    goto Exit;
362  }
363
364
365  FT_CALLBACK_DEF( FT_Error )
366  PCF_Set_Pixel_Size( FT_Size  size,
367                      FT_UInt  pixel_width,
368                      FT_UInt  pixel_height )
369  {
370    PCF_Face  face = (PCF_Face)FT_SIZE_FACE( size );
371
372    FT_UNUSED( pixel_width );
373
374
375    if ( pixel_height == (FT_UInt)face->root.available_sizes->height )
376    {
377      size->metrics.ascender    = face->accel.fontAscent << 6;
378      size->metrics.descender   = face->accel.fontDescent * (-64);
379#if 0
380      size->metrics.height      = face->accel.maxbounds.ascent << 6;
381#endif
382      size->metrics.height      = size->metrics.ascender -
383                                  size->metrics.descender;
384
385      size->metrics.max_advance = face->accel.maxbounds.characterWidth << 6;
386
387      return PCF_Err_Ok;
388    }
389    else
390    {
391      FT_TRACE4(( "pixel size WRONG\n" ));
392      return PCF_Err_Invalid_Pixel_Size;
393    }
394  }
395
396
397  FT_CALLBACK_DEF( FT_Error )
398  PCF_Set_Point_Size( FT_Size     size,
399                      FT_F26Dot6  char_width,
400                      FT_F26Dot6  char_height,
401                      FT_UInt     horz_resolution,
402                      FT_UInt     vert_resolution )
403  {
404    PCF_Face  face = (PCF_Face)FT_SIZE_FACE( size );
405
406    FT_UNUSED( char_width );
407    FT_UNUSED( char_height );
408    FT_UNUSED( horz_resolution );
409    FT_UNUSED( vert_resolution );
410
411
412    FT_TRACE4(( "rec %d - pres %d\n",
413                size->metrics.y_ppem,
414                face->root.available_sizes->y_ppem >> 6 ));
415
416    if ( size->metrics.y_ppem == face->root.available_sizes->y_ppem >> 6 )
417    {
418      size->metrics.ascender    = face->accel.fontAscent << 6;
419      size->metrics.descender   = face->accel.fontDescent * (-64);
420#if 0
421      size->metrics.height      = face->accel.maxbounds.ascent << 6;
422#endif
423      size->metrics.height      = size->metrics.ascender -
424                                  size->metrics.descender;
425
426      size->metrics.max_advance = face->accel.maxbounds.characterWidth << 6;
427
428      return PCF_Err_Ok;
429    }
430    else
431    {
432      FT_TRACE4(( "size WRONG\n" ));
433      return PCF_Err_Invalid_Pixel_Size;
434    }
435  }
436
437
438  FT_CALLBACK_DEF( FT_Error )
439  PCF_Glyph_Load( FT_GlyphSlot  slot,
440                  FT_Size       size,
441                  FT_UInt       glyph_index,
442                  FT_Int32      load_flags )
443  {
444    PCF_Face    face   = (PCF_Face)FT_SIZE_FACE( size );
445    FT_Stream   stream = face->root.stream;
446    FT_Error    error  = PCF_Err_Ok;
447    FT_Bitmap*  bitmap = &slot->bitmap;
448    PCF_Metric  metric;
449    int         bytes;
450
451    FT_UNUSED( load_flags );
452
453
454    FT_TRACE4(( "load_glyph %d ---", glyph_index ));
455
456    if ( !face )
457    {
458      error = PCF_Err_Invalid_Argument;
459      goto Exit;
460    }
461
462    if ( glyph_index > 0 )
463      glyph_index--;
464
465    metric = face->metrics + glyph_index;
466
467    bitmap->rows       = metric->ascent + metric->descent;
468    bitmap->width      = metric->rightSideBearing - metric->leftSideBearing;
469    bitmap->num_grays  = 1;
470    bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
471
472    FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n",
473                  PCF_BIT_ORDER( face->bitmapsFormat ),
474                  PCF_BYTE_ORDER( face->bitmapsFormat ),
475                  PCF_GLYPH_PAD( face->bitmapsFormat ) ));
476
477    switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
478    {
479    case 1:
480      bitmap->pitch = ( bitmap->width + 7 ) >> 3;
481      break;
482
483    case 2:
484      bitmap->pitch = ( ( bitmap->width + 15 ) >> 4 ) << 1;
485      break;
486
487    case 4:
488      bitmap->pitch = ( ( bitmap->width + 31 ) >> 5 ) << 2;
489      break;
490
491    case 8:
492      bitmap->pitch = ( ( bitmap->width + 63 ) >> 6 ) << 3;
493      break;
494
495    default:
496      return PCF_Err_Invalid_File_Format;
497    }
498
499    /* XXX: to do: are there cases that need repadding the bitmap? */
500    bytes = bitmap->pitch * bitmap->rows;
501
502    error = ft_glyphslot_alloc_bitmap( slot, bytes );
503    if ( error )
504      goto Exit;
505
506    if ( FT_STREAM_SEEK( metric->bits )          ||
507         FT_STREAM_READ( bitmap->buffer, bytes ) )
508      goto Exit;
509
510    if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst )
511      BitOrderInvert( bitmap->buffer, bytes );
512
513    if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) !=
514           PCF_BIT_ORDER( face->bitmapsFormat )  ) )
515    {
516      switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) )
517      {
518      case 1:
519        break;
520
521      case 2:
522        TwoByteSwap( bitmap->buffer, bytes );
523        break;
524
525      case 4:
526        FourByteSwap( bitmap->buffer, bytes );
527        break;
528      }
529    }
530
531    slot->bitmap_left = metric->leftSideBearing;
532    slot->bitmap_top  = metric->ascent;
533
534    slot->metrics.horiAdvance  = metric->characterWidth << 6;
535    slot->metrics.horiBearingX = metric->leftSideBearing << 6;
536    slot->metrics.horiBearingY = metric->ascent << 6;
537    slot->metrics.width        = ( metric->rightSideBearing -
538                                   metric->leftSideBearing ) << 6;
539    slot->metrics.height       = bitmap->rows << 6;
540
541    slot->linearHoriAdvance = (FT_Fixed)bitmap->width << 16;
542    slot->format            = FT_GLYPH_FORMAT_BITMAP;
543
544    FT_TRACE4(( " --- ok\n" ));
545
546  Exit:
547    return error;
548  }
549
550
551 /*
552  *
553  *  BDF SERVICE
554  *
555  */
556
557  static FT_Error
558  pcf_get_bdf_property( PCF_Face          face,
559                        const char*       prop_name,
560                        BDF_PropertyRec  *aproperty )
561  {
562    PCF_Property  prop;
563
564
565    prop = pcf_find_property( face, prop_name );
566    if ( prop != NULL )
567    {
568      if ( prop->isString )
569      {
570        aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
571        aproperty->u.atom = prop->value.atom;
572      }
573      else
574      {
575        /* Apparently, the PCF driver loads all properties as signed integers!
576         * This really doesn't seem to be a problem, because this is
577         * sufficient for any meaningful values.
578         */
579        aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
580        aproperty->u.integer = prop->value.integer;
581      }
582      return 0;
583    }
584
585    return PCF_Err_Invalid_Argument;
586  }
587
588
589  static FT_Error
590  pcf_get_charset_id( PCF_Face      face,
591                      const char*  *acharset_encoding,
592                      const char*  *acharset_registry )
593  {
594    *acharset_encoding = face->charset_encoding;
595    *acharset_registry = face->charset_registry;
596
597    return 0;
598  }
599
600
601  static const FT_Service_BDFRec  pcf_service_bdf =
602  {
603    (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id,
604    (FT_BDF_GetPropertyFunc) pcf_get_bdf_property
605  };
606
607
608 /*
609  *
610  *  SERVICE LIST
611  *
612  */
613
614  static const FT_ServiceDescRec  pcf_services[] =
615  {
616    { FT_SERVICE_ID_BDF,       &pcf_service_bdf },
617    { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_PCF },
618    { NULL, NULL }
619  };
620
621
622  FT_CALLBACK_DEF( FT_Module_Interface )
623  pcf_driver_requester( FT_Module    module,
624                        const char*  name )
625  {
626    FT_UNUSED( module );
627
628    return ft_service_list_lookup( pcf_services, name );
629  }
630
631
632  FT_CALLBACK_TABLE_DEF
633  const FT_Driver_ClassRec  pcf_driver_class =
634  {
635    {
636      FT_MODULE_FONT_DRIVER        |
637      FT_MODULE_DRIVER_NO_OUTLINES,
638      sizeof ( FT_DriverRec ),
639
640      "pcf",
641      0x10000L,
642      0x20000L,
643
644      0,
645
646      0,
647      0,
648      pcf_driver_requester
649    },
650
651    sizeof ( PCF_FaceRec ),
652    sizeof ( FT_SizeRec ),
653    sizeof ( FT_GlyphSlotRec ),
654
655    PCF_Face_Init,
656    PCF_Face_Done,
657    0,                      /* FT_Size_InitFunc */
658    0,                      /* FT_Size_DoneFunc */
659    0,                      /* FT_Slot_InitFunc */
660    0,                      /* FT_Slot_DoneFunc */
661
662    PCF_Set_Point_Size,
663    PCF_Set_Pixel_Size,
664
665    PCF_Glyph_Load,
666
667    0,                      /* FT_Face_GetKerningFunc  */
668    0,                      /* FT_Face_AttachFunc      */
669    0                       /* FT_Face_GetAdvancesFunc */
670  };
671
672
673/* END */
Note: See TracBrowser for help on using the repository browser.