source: trunk/poppler/freetype2/src/pcf/pcfdrivr.c @ 165

Last change on this file since 165 was 165, checked in by Eugene Romanenko, 15 years ago

update to latest freetype cvs, (closes #76)

File size: 16.5 KB
Line 
1/*  pcfdrivr.c
2
3    FreeType font driver for pcf files
4
5    Copyright (C) 2000, 2001, 2002, 2003, 2004, 2006 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;
207      FT_Int        i;
208
209
210      if ( face->properties )
211      {
212        for ( i = 0; i < face->nprops; i++ )
213        {
214          prop = &face->properties[i];
215
216          if ( prop ) {
217            FT_FREE( prop->name );
218            if ( prop->isString )
219              FT_FREE( prop->value.atom );
220          }
221        }
222      }
223      FT_FREE( face->properties );
224    }
225
226    FT_FREE( face->toc.tables );
227    FT_FREE( pcfface->family_name );
228    FT_FREE( pcfface->style_name );
229    FT_FREE( pcfface->available_sizes );
230    FT_FREE( face->charset_encoding );
231    FT_FREE( face->charset_registry );
232
233    FT_TRACE4(( "PCF_Face_Done: done face\n" ));
234
235    /* close gzip/LZW stream if any */
236    if ( pcfface->stream == &face->gzip_stream )
237    {
238      FT_Stream_Close( &face->gzip_stream );
239      pcfface->stream = face->gzip_source;
240    }
241  }
242
243
244  FT_CALLBACK_DEF( FT_Error )
245  PCF_Face_Init( FT_Stream      stream,
246                 FT_Face        pcfface,        /* PCF_Face */
247                 FT_Int         face_index,
248                 FT_Int         num_params,
249                 FT_Parameter*  params )
250  {
251    PCF_Face  face  = (PCF_Face)pcfface;
252    FT_Error  error = PCF_Err_Ok;
253
254    FT_UNUSED( num_params );
255    FT_UNUSED( params );
256    FT_UNUSED( face_index );
257
258
259    error = pcf_load_font( stream, face );
260    if ( error )
261    {
262      FT_Error  error2;
263
264
265      PCF_Face_Done( pcfface );
266
267      /* this didn't work, try gzip support! */
268      error2 = FT_Stream_OpenGzip( &face->gzip_stream, stream );
269      if ( FT_ERROR_BASE( error2 ) == FT_Err_Unimplemented_Feature )
270        goto Fail;
271
272      error = error2;
273      if ( error )
274      {
275        FT_Error  error3;
276
277
278        /* this didn't work, try LZW support! */
279        error3 = FT_Stream_OpenLZW( &face->gzip_stream, stream );
280        if ( FT_ERROR_BASE( error3 ) == FT_Err_Unimplemented_Feature )
281          goto Fail;
282
283        error = error3;
284        if ( error )
285          goto Fail;
286
287        face->gzip_source = stream;
288        pcfface->stream   = &face->gzip_stream;
289
290        stream = pcfface->stream;
291
292        error = pcf_load_font( stream, face );
293        if ( error )
294          goto Fail;
295      }
296      else
297      {
298        face->gzip_source = stream;
299        pcfface->stream   = &face->gzip_stream;
300
301        stream = pcfface->stream;
302
303        error = pcf_load_font( stream, face );
304        if ( error )
305          goto Fail;
306      }
307    }
308
309    /* set up charmap */
310    {
311      FT_String  *charset_registry = face->charset_registry;
312      FT_String  *charset_encoding = face->charset_encoding;
313      FT_Bool     unicode_charmap  = 0;
314
315
316      if ( charset_registry && charset_encoding )
317      {
318        char*  s = charset_registry;
319
320
321        /* Uh, oh, compare first letters manually to avoid dependency
322           on locales. */
323        if ( ( s[0] == 'i' || s[0] == 'I' ) &&
324             ( s[1] == 's' || s[1] == 'S' ) &&
325             ( s[2] == 'o' || s[2] == 'O' ) )
326        {
327          s += 3;
328          if ( !ft_strcmp( s, "10646" )                      ||
329               ( !ft_strcmp( s, "8859" ) &&
330                 !ft_strcmp( face->charset_encoding, "1" ) ) )
331          unicode_charmap = 1;
332        }
333      }
334
335      {
336        FT_CharMapRec  charmap;
337
338
339        charmap.face        = FT_FACE( face );
340        charmap.encoding    = FT_ENCODING_NONE;
341        charmap.platform_id = 0;
342        charmap.encoding_id = 0;
343
344        if ( unicode_charmap )
345        {
346          charmap.encoding    = FT_ENCODING_UNICODE;
347          charmap.platform_id = 3;
348          charmap.encoding_id = 1;
349        }
350
351        error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL );
352
353#if 0
354        /* Select default charmap */
355        if ( pcfface->num_charmaps )
356          pcfface->charmap = pcfface->charmaps[0];
357#endif
358      }
359    }
360
361  Exit:
362    return error;
363
364  Fail:
365    FT_TRACE2(( "[not a valid PCF file]\n" ));
366    PCF_Face_Done( pcfface );
367    error = PCF_Err_Unknown_File_Format;  /* error */
368    goto Exit;
369  }
370
371
372  FT_CALLBACK_DEF( FT_Error )
373  PCF_Size_Select( FT_Size   size,
374                   FT_ULong  strike_index )
375  {
376    PCF_Accel  accel = &( (PCF_Face)size->face )->accel;
377
378
379    FT_Select_Metrics( size->face, strike_index );
380
381    size->metrics.ascender    =  accel->fontAscent << 6;
382    size->metrics.descender   = -accel->fontDescent << 6;
383    size->metrics.max_advance =  accel->maxbounds.characterWidth << 6;
384
385    return PCF_Err_Ok;
386  }
387
388
389  FT_CALLBACK_DEF( FT_Error )
390  PCF_Size_Request( FT_Size          size,
391                    FT_Size_Request  req )
392  {
393    PCF_Face         face  = (PCF_Face)size->face;
394    FT_Bitmap_Size*  bsize = size->face->available_sizes;
395    FT_Error         error = PCF_Err_Invalid_Pixel_Size;
396    FT_Long          height;
397
398
399    height = FT_REQUEST_HEIGHT( req );
400    height = ( height + 32 ) >> 6;
401
402    switch ( req->type )
403    {
404    case FT_SIZE_REQUEST_TYPE_NOMINAL:
405      if ( height == ( bsize->y_ppem + 32 ) >> 6 )
406        error = PCF_Err_Ok;
407      break;
408
409    case FT_SIZE_REQUEST_TYPE_REAL_DIM:
410      if ( height == ( face->accel.fontAscent +
411                       face->accel.fontDescent ) )
412        error = PCF_Err_Ok;
413      break;
414
415    default:
416      error = PCF_Err_Unimplemented_Feature;
417      break;
418    }
419
420    if ( error )
421      return error;
422    else
423      return PCF_Size_Select( size, 0 );
424  }
425
426
427  FT_CALLBACK_DEF( FT_Error )
428  PCF_Glyph_Load( FT_GlyphSlot  slot,
429                  FT_Size       size,
430                  FT_UInt       glyph_index,
431                  FT_Int32      load_flags )
432  {
433    PCF_Face    face   = (PCF_Face)FT_SIZE_FACE( size );
434    FT_Stream   stream = face->root.stream;
435    FT_Error    error  = PCF_Err_Ok;
436    FT_Bitmap*  bitmap = &slot->bitmap;
437    PCF_Metric  metric;
438    int         bytes;
439
440    FT_UNUSED( load_flags );
441
442
443    FT_TRACE4(( "load_glyph %d ---", glyph_index ));
444
445    if ( !face || glyph_index >= (FT_UInt)face->root.num_glyphs )
446    {
447      error = PCF_Err_Invalid_Argument;
448      goto Exit;
449    }
450
451    if ( glyph_index > 0 )
452      glyph_index--;
453
454    metric = face->metrics + glyph_index;
455
456    bitmap->rows       = metric->ascent + metric->descent;
457    bitmap->width      = metric->rightSideBearing - metric->leftSideBearing;
458    bitmap->num_grays  = 1;
459    bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
460
461    FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n",
462                  PCF_BIT_ORDER( face->bitmapsFormat ),
463                  PCF_BYTE_ORDER( face->bitmapsFormat ),
464                  PCF_GLYPH_PAD( face->bitmapsFormat ) ));
465
466    switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
467    {
468    case 1:
469      bitmap->pitch = ( bitmap->width + 7 ) >> 3;
470      break;
471
472    case 2:
473      bitmap->pitch = ( ( bitmap->width + 15 ) >> 4 ) << 1;
474      break;
475
476    case 4:
477      bitmap->pitch = ( ( bitmap->width + 31 ) >> 5 ) << 2;
478      break;
479
480    case 8:
481      bitmap->pitch = ( ( bitmap->width + 63 ) >> 6 ) << 3;
482      break;
483
484    default:
485      return PCF_Err_Invalid_File_Format;
486    }
487
488    /* XXX: to do: are there cases that need repadding the bitmap? */
489    bytes = bitmap->pitch * bitmap->rows;
490
491    error = ft_glyphslot_alloc_bitmap( slot, bytes );
492    if ( error )
493      goto Exit;
494
495    if ( FT_STREAM_SEEK( metric->bits )          ||
496         FT_STREAM_READ( bitmap->buffer, bytes ) )
497      goto Exit;
498
499    if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst )
500      BitOrderInvert( bitmap->buffer, bytes );
501
502    if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) !=
503           PCF_BIT_ORDER( face->bitmapsFormat )  ) )
504    {
505      switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) )
506      {
507      case 1:
508        break;
509
510      case 2:
511        TwoByteSwap( bitmap->buffer, bytes );
512        break;
513
514      case 4:
515        FourByteSwap( bitmap->buffer, bytes );
516        break;
517      }
518    }
519
520    slot->format      = FT_GLYPH_FORMAT_BITMAP;
521    slot->bitmap_left = metric->leftSideBearing;
522    slot->bitmap_top  = metric->ascent;
523
524    slot->metrics.horiAdvance  = metric->characterWidth << 6;
525    slot->metrics.horiBearingX = metric->leftSideBearing << 6;
526    slot->metrics.horiBearingY = metric->ascent << 6;
527    slot->metrics.width        = ( metric->rightSideBearing -
528                                   metric->leftSideBearing ) << 6;
529    slot->metrics.height       = bitmap->rows << 6;
530
531    ft_synthesize_vertical_metrics( &slot->metrics,
532                                    ( face->accel.fontAscent +
533                                      face->accel.fontDescent ) << 6 );
534
535    FT_TRACE4(( " --- ok\n" ));
536
537  Exit:
538    return error;
539  }
540
541
542 /*
543  *
544  *  BDF SERVICE
545  *
546  */
547
548  static FT_Error
549  pcf_get_bdf_property( PCF_Face          face,
550                        const char*       prop_name,
551                        BDF_PropertyRec  *aproperty )
552  {
553    PCF_Property  prop;
554
555
556    prop = pcf_find_property( face, prop_name );
557    if ( prop != NULL )
558    {
559      if ( prop->isString )
560      {
561        aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
562        aproperty->u.atom = prop->value.atom;
563      }
564      else
565      {
566        /* Apparently, the PCF driver loads all properties as signed integers!
567         * This really doesn't seem to be a problem, because this is
568         * sufficient for any meaningful values.
569         */
570        aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
571        aproperty->u.integer = prop->value.integer;
572      }
573      return 0;
574    }
575
576    return PCF_Err_Invalid_Argument;
577  }
578
579
580  static FT_Error
581  pcf_get_charset_id( PCF_Face      face,
582                      const char*  *acharset_encoding,
583                      const char*  *acharset_registry )
584  {
585    *acharset_encoding = face->charset_encoding;
586    *acharset_registry = face->charset_registry;
587
588    return 0;
589  }
590
591
592  static const FT_Service_BDFRec  pcf_service_bdf =
593  {
594    (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id,
595    (FT_BDF_GetPropertyFunc) pcf_get_bdf_property
596  };
597
598
599 /*
600  *
601  *  SERVICE LIST
602  *
603  */
604
605  static const FT_ServiceDescRec  pcf_services[] =
606  {
607    { FT_SERVICE_ID_BDF,       &pcf_service_bdf },
608    { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_PCF },
609    { NULL, NULL }
610  };
611
612
613  FT_CALLBACK_DEF( FT_Module_Interface )
614  pcf_driver_requester( FT_Module    module,
615                        const char*  name )
616  {
617    FT_UNUSED( module );
618
619    return ft_service_list_lookup( pcf_services, name );
620  }
621
622
623  FT_CALLBACK_TABLE_DEF
624  const FT_Driver_ClassRec  pcf_driver_class =
625  {
626    {
627      FT_MODULE_FONT_DRIVER        |
628      FT_MODULE_DRIVER_NO_OUTLINES,
629      sizeof ( FT_DriverRec ),
630
631      "pcf",
632      0x10000L,
633      0x20000L,
634
635      0,
636
637      0,
638      0,
639      pcf_driver_requester
640    },
641
642    sizeof ( PCF_FaceRec ),
643    sizeof ( FT_SizeRec ),
644    sizeof ( FT_GlyphSlotRec ),
645
646    PCF_Face_Init,
647    PCF_Face_Done,
648    0,                      /* FT_Size_InitFunc */
649    0,                      /* FT_Size_DoneFunc */
650    0,                      /* FT_Slot_InitFunc */
651    0,                      /* FT_Slot_DoneFunc */
652
653#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
654    ft_stub_set_char_sizes,
655    ft_stub_set_pixel_sizes,
656#endif
657    PCF_Glyph_Load,
658
659    0,                      /* FT_Face_GetKerningFunc  */
660    0,                      /* FT_Face_AttachFunc      */
661    0,                      /* FT_Face_GetAdvancesFunc */
662
663    PCF_Size_Request,
664    PCF_Size_Select
665  };
666
667
668/* END */
Note: See TracBrowser for help on using the repository browser.