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

Last change on this file since 251 was 251, checked in by Eugene Romanenko, 13 years ago

PDF plugin: freetype library updated to version 2.3.5

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