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

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

PDF plugin: freetype library updated to version 2.3.8

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 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 = 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 || glyph_index >= (FT_UInt)face->root.num_glyphs )
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->format      = FT_GLYPH_FORMAT_BITMAP;
532    slot->bitmap_left = metric->leftSideBearing;
533    slot->bitmap_top  = metric->ascent;
534
535    slot->metrics.horiAdvance  = metric->characterWidth << 6;
536    slot->metrics.horiBearingX = metric->leftSideBearing << 6;
537    slot->metrics.horiBearingY = metric->ascent << 6;
538    slot->metrics.width        = ( metric->rightSideBearing -
539                                   metric->leftSideBearing ) << 6;
540    slot->metrics.height       = bitmap->rows << 6;
541
542    ft_synthesize_vertical_metrics( &slot->metrics,
543                                    ( face->accel.fontAscent +
544                                      face->accel.fontDescent ) << 6 );
545
546    FT_TRACE4(( " --- ok\n" ));
547
548  Exit:
549    return error;
550  }
551
552
553 /*
554  *
555  *  BDF SERVICE
556  *
557  */
558
559  static FT_Error
560  pcf_get_bdf_property( PCF_Face          face,
561                        const char*       prop_name,
562                        BDF_PropertyRec  *aproperty )
563  {
564    PCF_Property  prop;
565
566
567    prop = pcf_find_property( face, prop_name );
568    if ( prop != NULL )
569    {
570      if ( prop->isString )
571      {
572        aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
573        aproperty->u.atom = prop->value.atom;
574      }
575      else
576      {
577        /* Apparently, the PCF driver loads all properties as signed integers!
578         * This really doesn't seem to be a problem, because this is
579         * sufficient for any meaningful values.
580         */
581        aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
582        aproperty->u.integer = prop->value.integer;
583      }
584      return 0;
585    }
586
587    return PCF_Err_Invalid_Argument;
588  }
589
590
591  static FT_Error
592  pcf_get_charset_id( PCF_Face      face,
593                      const char*  *acharset_encoding,
594                      const char*  *acharset_registry )
595  {
596    *acharset_encoding = face->charset_encoding;
597    *acharset_registry = face->charset_registry;
598
599    return 0;
600  }
601
602
603  static const FT_Service_BDFRec  pcf_service_bdf =
604  {
605    (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id,
606    (FT_BDF_GetPropertyFunc) pcf_get_bdf_property
607  };
608
609
610 /*
611  *
612  *  SERVICE LIST
613  *
614  */
615
616  static const FT_ServiceDescRec  pcf_services[] =
617  {
618    { FT_SERVICE_ID_BDF,       &pcf_service_bdf },
619    { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_PCF },
620    { NULL, NULL }
621  };
622
623
624  FT_CALLBACK_DEF( FT_Module_Interface )
625  pcf_driver_requester( FT_Module    module,
626                        const char*  name )
627  {
628    FT_UNUSED( module );
629
630    return ft_service_list_lookup( pcf_services, name );
631  }
632
633
634  FT_CALLBACK_TABLE_DEF
635  const FT_Driver_ClassRec  pcf_driver_class =
636  {
637    {
638      FT_MODULE_FONT_DRIVER        |
639      FT_MODULE_DRIVER_NO_OUTLINES,
640      sizeof ( FT_DriverRec ),
641
642      "pcf",
643      0x10000L,
644      0x20000L,
645
646      0,
647
648      0,
649      0,
650      pcf_driver_requester
651    },
652
653    sizeof ( PCF_FaceRec ),
654    sizeof ( FT_SizeRec ),
655    sizeof ( FT_GlyphSlotRec ),
656
657    PCF_Face_Init,
658    PCF_Face_Done,
659    0,                      /* FT_Size_InitFunc */
660    0,                      /* FT_Size_DoneFunc */
661    0,                      /* FT_Slot_InitFunc */
662    0,                      /* FT_Slot_DoneFunc */
663
664#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
665    ft_stub_set_char_sizes,
666    ft_stub_set_pixel_sizes,
667#endif
668    PCF_Glyph_Load,
669
670    0,                      /* FT_Face_GetKerningFunc  */
671    0,                      /* FT_Face_AttachFunc      */
672    0,                      /* FT_Face_GetAdvancesFunc */
673
674    PCF_Size_Request,
675    PCF_Size_Select
676  };
677
678
679/* END */
Note: See TracBrowser for help on using the repository browser.