PageRenderTime 41ms CodeModel.GetById 10ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 1ms

/src/freetype/src/pcf/pcfdrivr.c

https://bitbucket.org/cabalistic/ogredeps/
C | 717 lines | 489 code | 168 blank | 60 comment | 66 complexity | 59344d8203373d2cb0f4d3344661b61b MD5 | raw file
  1/*  pcfdrivr.c
  2
  3    FreeType font driver for pcf files
  4
  5    Copyright (C) 2000-2004, 2006-2011 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_BZIP2_H
 36#include FT_ERRORS_H
 37#include FT_BDF_H
 38#include FT_TRUETYPE_IDS_H
 39
 40#include "pcf.h"
 41#include "pcfdrivr.h"
 42#include "pcfread.h"
 43
 44#include "pcferror.h"
 45#include "pcfutil.h"
 46
 47#undef  FT_COMPONENT
 48#define FT_COMPONENT  trace_pcfread
 49
 50#include FT_SERVICE_BDF_H
 51#include FT_SERVICE_XFREE86_NAME_H
 52
 53
 54  /*************************************************************************/
 55  /*                                                                       */
 56  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
 57  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
 58  /* messages during execution.                                            */
 59  /*                                                                       */
 60#undef  FT_COMPONENT
 61#define FT_COMPONENT  trace_pcfdriver
 62
 63
 64  typedef struct  PCF_CMapRec_
 65  {
 66    FT_CMapRec    root;
 67    FT_UInt       num_encodings;
 68    PCF_Encoding  encodings;
 69
 70  } PCF_CMapRec, *PCF_CMap;
 71
 72
 73  FT_CALLBACK_DEF( FT_Error )
 74  pcf_cmap_init( FT_CMap     pcfcmap,   /* PCF_CMap */
 75                 FT_Pointer  init_data )
 76  {
 77    PCF_CMap  cmap = (PCF_CMap)pcfcmap;
 78    PCF_Face  face = (PCF_Face)FT_CMAP_FACE( pcfcmap );
 79
 80    FT_UNUSED( init_data );
 81
 82
 83    cmap->num_encodings = (FT_UInt)face->nencodings;
 84    cmap->encodings     = face->encodings;
 85
 86    return PCF_Err_Ok;
 87  }
 88
 89
 90  FT_CALLBACK_DEF( void )
 91  pcf_cmap_done( FT_CMap  pcfcmap )         /* PCF_CMap */
 92  {
 93    PCF_CMap  cmap = (PCF_CMap)pcfcmap;
 94
 95
 96    cmap->encodings     = NULL;
 97    cmap->num_encodings = 0;
 98  }
 99
100
101  FT_CALLBACK_DEF( FT_UInt )
102  pcf_cmap_char_index( FT_CMap    pcfcmap,  /* PCF_CMap */
103                       FT_UInt32  charcode )
104  {
105    PCF_CMap      cmap      = (PCF_CMap)pcfcmap;
106    PCF_Encoding  encodings = cmap->encodings;
107    FT_UInt       min, max, mid;
108    FT_UInt       result    = 0;
109
110
111    min = 0;
112    max = cmap->num_encodings;
113
114    while ( min < max )
115    {
116      FT_ULong  code;
117
118
119      mid  = ( min + max ) >> 1;
120      code = encodings[mid].enc;
121
122      if ( charcode == code )
123      {
124        result = encodings[mid].glyph + 1;
125        break;
126      }
127
128      if ( charcode < code )
129        max = mid;
130      else
131        min = mid + 1;
132    }
133
134    return result;
135  }
136
137
138  FT_CALLBACK_DEF( FT_UInt )
139  pcf_cmap_char_next( FT_CMap    pcfcmap,   /* PCF_CMap */
140                      FT_UInt32  *acharcode )
141  {
142    PCF_CMap      cmap      = (PCF_CMap)pcfcmap;
143    PCF_Encoding  encodings = cmap->encodings;
144    FT_UInt       min, max, mid;
145    FT_ULong      charcode  = *acharcode + 1;
146    FT_UInt       result    = 0;
147
148
149    min = 0;
150    max = cmap->num_encodings;
151
152    while ( min < max )
153    {
154      FT_ULong  code;
155
156
157      mid  = ( min + max ) >> 1;
158      code = encodings[mid].enc;
159
160      if ( charcode == code )
161      {
162        result = encodings[mid].glyph + 1;
163        goto Exit;
164      }
165
166      if ( charcode < code )
167        max = mid;
168      else
169        min = mid + 1;
170    }
171
172    charcode = 0;
173    if ( min < cmap->num_encodings )
174    {
175      charcode = encodings[min].enc;
176      result   = encodings[min].glyph + 1;
177    }
178
179  Exit:
180    if ( charcode > 0xFFFFFFFFUL )
181    {
182      FT_TRACE1(( "pcf_cmap_char_next: charcode 0x%x > 32bit API" ));
183      *acharcode = 0;
184      /* XXX: result should be changed to indicate an overflow error */
185    }
186    else
187      *acharcode = (FT_UInt32)charcode;
188    return result;
189  }
190
191
192  FT_CALLBACK_TABLE_DEF
193  const FT_CMap_ClassRec  pcf_cmap_class =
194  {
195    sizeof ( PCF_CMapRec ),
196    pcf_cmap_init,
197    pcf_cmap_done,
198    pcf_cmap_char_index,
199    pcf_cmap_char_next,
200
201    NULL, NULL, NULL, NULL, NULL
202  };
203
204
205  FT_CALLBACK_DEF( void )
206  PCF_Face_Done( FT_Face  pcfface )         /* PCF_Face */
207  {
208    PCF_Face   face = (PCF_Face)pcfface;
209    FT_Memory  memory;
210
211
212    if ( !face )
213      return;
214
215    memory = FT_FACE_MEMORY( face );
216
217    FT_FREE( face->encodings );
218    FT_FREE( face->metrics );
219
220    /* free properties */
221    {
222      PCF_Property  prop;
223      FT_Int        i;
224
225
226      if ( face->properties )
227      {
228        for ( i = 0; i < face->nprops; i++ )
229        {
230          prop = &face->properties[i];
231
232          if ( prop )
233          {
234            FT_FREE( prop->name );
235            if ( prop->isString )
236              FT_FREE( prop->value.atom );
237          }
238        }
239      }
240      FT_FREE( face->properties );
241    }
242
243    FT_FREE( face->toc.tables );
244    FT_FREE( pcfface->family_name );
245    FT_FREE( pcfface->style_name );
246    FT_FREE( pcfface->available_sizes );
247    FT_FREE( face->charset_encoding );
248    FT_FREE( face->charset_registry );
249
250    /* close compressed stream if any */
251    if ( pcfface->stream == &face->comp_stream )
252    {
253      FT_Stream_Close( &face->comp_stream );
254      pcfface->stream = face->comp_source;
255    }
256  }
257
258
259  FT_CALLBACK_DEF( FT_Error )
260  PCF_Face_Init( FT_Stream      stream,
261                 FT_Face        pcfface,        /* PCF_Face */
262                 FT_Int         face_index,
263                 FT_Int         num_params,
264                 FT_Parameter*  params )
265  {
266    PCF_Face  face  = (PCF_Face)pcfface;
267    FT_Error  error = PCF_Err_Ok;
268
269    FT_UNUSED( num_params );
270    FT_UNUSED( params );
271    FT_UNUSED( face_index );
272
273
274    FT_TRACE2(( "PCF driver\n" ));
275
276    error = pcf_load_font( stream, face );
277    if ( error )
278    {
279      PCF_Face_Done( pcfface );
280
281#if defined( FT_CONFIG_OPTION_USE_ZLIB )  || \
282    defined( FT_CONFIG_OPTION_USE_LZW )   || \
283    defined( FT_CONFIG_OPTION_USE_BZIP2 )
284
285#ifdef FT_CONFIG_OPTION_USE_ZLIB
286      {
287        FT_Error  error2;
288
289
290        /* this didn't work, try gzip support! */
291        error2 = FT_Stream_OpenGzip( &face->comp_stream, stream );
292        if ( FT_ERROR_BASE( error2 ) == FT_Err_Unimplemented_Feature )
293          goto Fail;
294
295        error = error2;
296      }
297#endif /* FT_CONFIG_OPTION_USE_ZLIB */
298
299#ifdef FT_CONFIG_OPTION_USE_LZW
300      if ( error )
301      {
302        FT_Error  error3;
303
304
305        /* this didn't work, try LZW support! */
306        error3 = FT_Stream_OpenLZW( &face->comp_stream, stream );
307        if ( FT_ERROR_BASE( error3 ) == FT_Err_Unimplemented_Feature )
308          goto Fail;
309
310        error = error3;
311      }
312#endif /* FT_CONFIG_OPTION_USE_LZW */
313
314#ifdef FT_CONFIG_OPTION_USE_BZIP2
315      if ( error )
316      {
317        FT_Error  error4;
318
319
320        /* this didn't work, try Bzip2 support! */
321        error4 = FT_Stream_OpenBzip2( &face->comp_stream, stream );
322        if ( FT_ERROR_BASE( error4 ) == FT_Err_Unimplemented_Feature )
323          goto Fail;
324
325        error = error4;
326      }
327#endif /* FT_CONFIG_OPTION_USE_BZIP2 */
328
329      if ( error )
330        goto Fail;
331
332      face->comp_source = stream;
333      pcfface->stream   = &face->comp_stream;
334
335      stream = pcfface->stream;
336
337      error = pcf_load_font( stream, face );
338      if ( error )
339        goto Fail;
340
341#else /* !(FT_CONFIG_OPTION_USE_ZLIB ||
342           FT_CONFIG_OPTION_USE_LZW ||
343           FT_CONFIG_OPTION_USE_BZIP2) */
344
345      goto Fail;
346
347#endif
348    }
349
350    /* set up charmap */
351    {
352      FT_String  *charset_registry = face->charset_registry;
353      FT_String  *charset_encoding = face->charset_encoding;
354      FT_Bool     unicode_charmap  = 0;
355
356
357      if ( charset_registry && charset_encoding )
358      {
359        char*  s = charset_registry;
360
361
362        /* Uh, oh, compare first letters manually to avoid dependency
363           on locales. */
364        if ( ( s[0] == 'i' || s[0] == 'I' ) &&
365             ( s[1] == 's' || s[1] == 'S' ) &&
366             ( s[2] == 'o' || s[2] == 'O' ) )
367        {
368          s += 3;
369          if ( !ft_strcmp( s, "10646" )                      ||
370               ( !ft_strcmp( s, "8859" ) &&
371                 !ft_strcmp( face->charset_encoding, "1" ) ) )
372          unicode_charmap = 1;
373        }
374      }
375
376      {
377        FT_CharMapRec  charmap;
378
379
380        charmap.face        = FT_FACE( face );
381        charmap.encoding    = FT_ENCODING_NONE;
382        /* initial platform/encoding should indicate unset status? */
383        charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
384        charmap.encoding_id = TT_APPLE_ID_DEFAULT;
385
386        if ( unicode_charmap )
387        {
388          charmap.encoding    = FT_ENCODING_UNICODE;
389          charmap.platform_id = TT_PLATFORM_MICROSOFT;
390          charmap.encoding_id = TT_MS_ID_UNICODE_CS;
391        }
392
393        error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL );
394
395#if 0
396        /* Select default charmap */
397        if ( pcfface->num_charmaps )
398          pcfface->charmap = pcfface->charmaps[0];
399#endif
400      }
401    }
402
403  Exit:
404    return error;
405
406  Fail:
407    FT_TRACE2(( "  not a PCF file\n" ));
408    PCF_Face_Done( pcfface );
409    error = PCF_Err_Unknown_File_Format;  /* error */
410    goto Exit;
411  }
412
413
414  FT_CALLBACK_DEF( FT_Error )
415  PCF_Size_Select( FT_Size   size,
416                   FT_ULong  strike_index )
417  {
418    PCF_Accel  accel = &( (PCF_Face)size->face )->accel;
419
420
421    FT_Select_Metrics( size->face, strike_index );
422
423    size->metrics.ascender    =  accel->fontAscent << 6;
424    size->metrics.descender   = -accel->fontDescent << 6;
425    size->metrics.max_advance =  accel->maxbounds.characterWidth << 6;
426
427    return PCF_Err_Ok;
428  }
429
430
431  FT_CALLBACK_DEF( FT_Error )
432  PCF_Size_Request( FT_Size          size,
433                    FT_Size_Request  req )
434  {
435    PCF_Face         face  = (PCF_Face)size->face;
436    FT_Bitmap_Size*  bsize = size->face->available_sizes;
437    FT_Error         error = PCF_Err_Invalid_Pixel_Size;
438    FT_Long          height;
439
440
441    height = FT_REQUEST_HEIGHT( req );
442    height = ( height + 32 ) >> 6;
443
444    switch ( req->type )
445    {
446    case FT_SIZE_REQUEST_TYPE_NOMINAL:
447      if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
448        error = PCF_Err_Ok;
449      break;
450
451    case FT_SIZE_REQUEST_TYPE_REAL_DIM:
452      if ( height == ( face->accel.fontAscent +
453                       face->accel.fontDescent ) )
454        error = PCF_Err_Ok;
455      break;
456
457    default:
458      error = PCF_Err_Unimplemented_Feature;
459      break;
460    }
461
462    if ( error )
463      return error;
464    else
465      return PCF_Size_Select( size, 0 );
466  }
467
468
469  FT_CALLBACK_DEF( FT_Error )
470  PCF_Glyph_Load( FT_GlyphSlot  slot,
471                  FT_Size       size,
472                  FT_UInt       glyph_index,
473                  FT_Int32      load_flags )
474  {
475    PCF_Face    face   = (PCF_Face)FT_SIZE_FACE( size );
476    FT_Stream   stream;
477    FT_Error    error  = PCF_Err_Ok;
478    FT_Bitmap*  bitmap = &slot->bitmap;
479    PCF_Metric  metric;
480    FT_Offset   bytes;
481
482    FT_UNUSED( load_flags );
483
484
485    FT_TRACE4(( "load_glyph %d ---", glyph_index ));
486
487    if ( !face || glyph_index >= (FT_UInt)face->root.num_glyphs )
488    {
489      error = PCF_Err_Invalid_Argument;
490      goto Exit;
491    }
492
493    stream = face->root.stream;
494
495    if ( glyph_index > 0 )
496      glyph_index--;
497
498    metric = face->metrics + glyph_index;
499
500    bitmap->rows       = metric->ascent + metric->descent;
501    bitmap->width      = metric->rightSideBearing - metric->leftSideBearing;
502    bitmap->num_grays  = 1;
503    bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
504
505    FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n",
506                  PCF_BIT_ORDER( face->bitmapsFormat ),
507                  PCF_BYTE_ORDER( face->bitmapsFormat ),
508                  PCF_GLYPH_PAD( face->bitmapsFormat ) ));
509
510    switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
511    {
512    case 1:
513      bitmap->pitch = ( bitmap->width + 7 ) >> 3;
514      break;
515
516    case 2:
517      bitmap->pitch = ( ( bitmap->width + 15 ) >> 4 ) << 1;
518      break;
519
520    case 4:
521      bitmap->pitch = ( ( bitmap->width + 31 ) >> 5 ) << 2;
522      break;
523
524    case 8:
525      bitmap->pitch = ( ( bitmap->width + 63 ) >> 6 ) << 3;
526      break;
527
528    default:
529      return PCF_Err_Invalid_File_Format;
530    }
531
532    /* XXX: to do: are there cases that need repadding the bitmap? */
533    bytes = bitmap->pitch * bitmap->rows;
534
535    error = ft_glyphslot_alloc_bitmap( slot, bytes );
536    if ( error )
537      goto Exit;
538
539    if ( FT_STREAM_SEEK( metric->bits )          ||
540         FT_STREAM_READ( bitmap->buffer, bytes ) )
541      goto Exit;
542
543    if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst )
544      BitOrderInvert( bitmap->buffer, bytes );
545
546    if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) !=
547           PCF_BIT_ORDER( face->bitmapsFormat )  ) )
548    {
549      switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) )
550      {
551      case 1:
552        break;
553
554      case 2:
555        TwoByteSwap( bitmap->buffer, bytes );
556        break;
557
558      case 4:
559        FourByteSwap( bitmap->buffer, bytes );
560        break;
561      }
562    }
563
564    slot->format      = FT_GLYPH_FORMAT_BITMAP;
565    slot->bitmap_left = metric->leftSideBearing;
566    slot->bitmap_top  = metric->ascent;
567
568    slot->metrics.horiAdvance  = metric->characterWidth << 6;
569    slot->metrics.horiBearingX = metric->leftSideBearing << 6;
570    slot->metrics.horiBearingY = metric->ascent << 6;
571    slot->metrics.width        = ( metric->rightSideBearing -
572                                   metric->leftSideBearing ) << 6;
573    slot->metrics.height       = bitmap->rows << 6;
574
575    ft_synthesize_vertical_metrics( &slot->metrics,
576                                    ( face->accel.fontAscent +
577                                      face->accel.fontDescent ) << 6 );
578
579    FT_TRACE4(( " --- ok\n" ));
580
581  Exit:
582    return error;
583  }
584
585
586 /*
587  *
588  *  BDF SERVICE
589  *
590  */
591
592  static FT_Error
593  pcf_get_bdf_property( PCF_Face          face,
594                        const char*       prop_name,
595                        BDF_PropertyRec  *aproperty )
596  {
597    PCF_Property  prop;
598
599
600    prop = pcf_find_property( face, prop_name );
601    if ( prop != NULL )
602    {
603      if ( prop->isString )
604      {
605        aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
606        aproperty->u.atom = prop->value.atom;
607      }
608      else
609      {
610        if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
611        {
612          FT_TRACE1(( "pcf_get_bdf_property: " ));
613          FT_TRACE1(( "too large integer 0x%x is truncated\n" ));
614        }
615        /* Apparently, the PCF driver loads all properties as signed integers!
616         * This really doesn't seem to be a problem, because this is
617         * sufficient for any meaningful values.
618         */
619        aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
620        aproperty->u.integer = (FT_Int32)prop->value.l;
621      }
622      return 0;
623    }
624
625    return PCF_Err_Invalid_Argument;
626  }
627
628
629  static FT_Error
630  pcf_get_charset_id( PCF_Face      face,
631                      const char*  *acharset_encoding,
632                      const char*  *acharset_registry )
633  {
634    *acharset_encoding = face->charset_encoding;
635    *acharset_registry = face->charset_registry;
636
637    return 0;
638  }
639
640
641  static const FT_Service_BDFRec  pcf_service_bdf =
642  {
643    (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id,
644    (FT_BDF_GetPropertyFunc) pcf_get_bdf_property
645  };
646
647
648 /*
649  *
650  *  SERVICE LIST
651  *
652  */
653
654  static const FT_ServiceDescRec  pcf_services[] =
655  {
656    { FT_SERVICE_ID_BDF,       &pcf_service_bdf },
657    { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_PCF },
658    { NULL, NULL }
659  };
660
661
662  FT_CALLBACK_DEF( FT_Module_Interface )
663  pcf_driver_requester( FT_Module    module,
664                        const char*  name )
665  {
666    FT_UNUSED( module );
667
668    return ft_service_list_lookup( pcf_services, name );
669  }
670
671
672  FT_CALLBACK_TABLE_DEF
673  const FT_Driver_ClassRec  pcf_driver_class =
674  {
675    {
676      FT_MODULE_FONT_DRIVER        |
677      FT_MODULE_DRIVER_NO_OUTLINES,
678      sizeof ( FT_DriverRec ),
679
680      "pcf",
681      0x10000L,
682      0x20000L,
683
684      0,
685
686      0,                    /* FT_Module_Constructor */
687      0,                    /* FT_Module_Destructor  */
688      pcf_driver_requester
689    },
690
691    sizeof ( PCF_FaceRec ),
692    sizeof ( FT_SizeRec ),
693    sizeof ( FT_GlyphSlotRec ),
694
695    PCF_Face_Init,
696    PCF_Face_Done,
697    0,                      /* FT_Size_InitFunc */
698    0,                      /* FT_Size_DoneFunc */
699    0,                      /* FT_Slot_InitFunc */
700    0,                      /* FT_Slot_DoneFunc */
701
702#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
703    ft_stub_set_char_sizes,
704    ft_stub_set_pixel_sizes,
705#endif
706    PCF_Glyph_Load,
707
708    0,                      /* FT_Face_GetKerningFunc  */
709    0,                      /* FT_Face_AttachFunc      */
710    0,                      /* FT_Face_GetAdvancesFunc */
711
712    PCF_Size_Request,
713    PCF_Size_Select
714  };
715
716
717/* END */