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

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

PDF plugin: freetype library updated to version 2.3.9

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