PageRenderTime 86ms CodeModel.GetById 27ms app.highlight 53ms RepoModel.GetById 1ms app.codeStats 0ms

/src/freetype/src/pfr/pfrsbit.c

https://bitbucket.org/cabalistic/ogredeps/
C | 698 lines | 496 code | 137 blank | 65 comment | 71 complexity | 99a0e9b0bea3b526f9f56c1805eddc1c MD5 | raw file
  1/***************************************************************************/
  2/*                                                                         */
  3/*  pfrsbit.c                                                              */
  4/*                                                                         */
  5/*    FreeType PFR bitmap loader (body).                                   */
  6/*                                                                         */
  7/*  Copyright 2002, 2003, 2006, 2009, 2010 by                              */
  8/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  9/*                                                                         */
 10/*  This file is part of the FreeType project, and may only be used,       */
 11/*  modified, and distributed under the terms of the FreeType project      */
 12/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
 13/*  this file you indicate that you have read the license and              */
 14/*  understand and accept it fully.                                        */
 15/*                                                                         */
 16/***************************************************************************/
 17
 18
 19#include "pfrsbit.h"
 20#include "pfrload.h"
 21#include FT_INTERNAL_DEBUG_H
 22#include FT_INTERNAL_STREAM_H
 23
 24#include "pfrerror.h"
 25
 26#undef  FT_COMPONENT
 27#define FT_COMPONENT  trace_pfr
 28
 29
 30  /*************************************************************************/
 31  /*************************************************************************/
 32  /*****                                                               *****/
 33  /*****                      PFR BIT WRITER                           *****/
 34  /*****                                                               *****/
 35  /*************************************************************************/
 36  /*************************************************************************/
 37
 38  typedef struct  PFR_BitWriter_
 39  {
 40    FT_Byte*  line;      /* current line start                    */
 41    FT_Int    pitch;     /* line size in bytes                    */
 42    FT_Int    width;     /* width in pixels/bits                  */
 43    FT_Int    rows;      /* number of remaining rows to scan      */
 44    FT_Int    total;     /* total number of bits to draw          */
 45
 46  } PFR_BitWriterRec, *PFR_BitWriter;
 47
 48
 49  static void
 50  pfr_bitwriter_init( PFR_BitWriter  writer,
 51                      FT_Bitmap*     target,
 52                      FT_Bool        decreasing )
 53  {
 54    writer->line   = target->buffer;
 55    writer->pitch  = target->pitch;
 56    writer->width  = target->width;
 57    writer->rows   = target->rows;
 58    writer->total  = writer->width * writer->rows;
 59
 60    if ( !decreasing )
 61    {
 62      writer->line += writer->pitch * ( target->rows-1 );
 63      writer->pitch = -writer->pitch;
 64    }
 65  }
 66
 67
 68  static void
 69  pfr_bitwriter_decode_bytes( PFR_BitWriter  writer,
 70                              FT_Byte*       p,
 71                              FT_Byte*       limit )
 72  {
 73    FT_Int    n, reload;
 74    FT_Int    left = writer->width;
 75    FT_Byte*  cur  = writer->line;
 76    FT_UInt   mask = 0x80;
 77    FT_UInt   val  = 0;
 78    FT_UInt   c    = 0;
 79
 80
 81    n = (FT_Int)( limit - p ) * 8;
 82    if ( n > writer->total )
 83      n = writer->total;
 84
 85    reload = n & 7;
 86
 87    for ( ; n > 0; n-- )
 88    {
 89      if ( ( n & 7 ) == reload )
 90        val = *p++;
 91
 92      if ( val & 0x80 )
 93        c |= mask;
 94
 95      val  <<= 1;
 96      mask >>= 1;
 97
 98      if ( --left <= 0 )
 99      {
100        cur[0] = (FT_Byte)c;
101        left   = writer->width;
102        mask   = 0x80;
103
104        writer->line += writer->pitch;
105        cur           = writer->line;
106        c             = 0;
107      }
108      else if ( mask == 0 )
109      {
110        cur[0] = (FT_Byte)c;
111        mask   = 0x80;
112        c      = 0;
113        cur ++;
114      }
115    }
116
117    if ( mask != 0x80 )
118      cur[0] = (FT_Byte)c;
119  }
120
121
122  static void
123  pfr_bitwriter_decode_rle1( PFR_BitWriter  writer,
124                             FT_Byte*       p,
125                             FT_Byte*       limit )
126  {
127    FT_Int    n, phase, count, counts[2], reload;
128    FT_Int    left = writer->width;
129    FT_Byte*  cur  = writer->line;
130    FT_UInt   mask = 0x80;
131    FT_UInt   c    = 0;
132
133
134    n = writer->total;
135
136    phase     = 1;
137    counts[0] = 0;
138    counts[1] = 0;
139    count     = 0;
140    reload    = 1;
141
142    for ( ; n > 0; n-- )
143    {
144      if ( reload )
145      {
146        do
147        {
148          if ( phase )
149          {
150            FT_Int  v;
151
152
153            if ( p >= limit )
154              break;
155
156            v         = *p++;
157            counts[0] = v >> 4;
158            counts[1] = v & 15;
159            phase     = 0;
160            count     = counts[0];
161          }
162          else
163          {
164            phase = 1;
165            count = counts[1];
166          }
167
168        } while ( count == 0 );
169      }
170
171      if ( phase )
172        c |= mask;
173
174      mask >>= 1;
175
176      if ( --left <= 0 )
177      {
178        cur[0] = (FT_Byte) c;
179        left   = writer->width;
180        mask   = 0x80;
181
182        writer->line += writer->pitch;
183        cur           = writer->line;
184        c             = 0;
185      }
186      else if ( mask == 0 )
187      {
188        cur[0] = (FT_Byte)c;
189        mask   = 0x80;
190        c      = 0;
191        cur ++;
192      }
193
194      reload = ( --count <= 0 );
195    }
196
197    if ( mask != 0x80 )
198      cur[0] = (FT_Byte) c;
199  }
200
201
202  static void
203  pfr_bitwriter_decode_rle2( PFR_BitWriter  writer,
204                             FT_Byte*       p,
205                             FT_Byte*       limit )
206  {
207    FT_Int    n, phase, count, reload;
208    FT_Int    left = writer->width;
209    FT_Byte*  cur  = writer->line;
210    FT_UInt   mask = 0x80;
211    FT_UInt   c    = 0;
212
213
214    n = writer->total;
215
216    phase  = 1;
217    count  = 0;
218    reload = 1;
219
220    for ( ; n > 0; n-- )
221    {
222      if ( reload )
223      {
224        do
225        {
226          if ( p >= limit )
227            break;
228
229          count = *p++;
230          phase = phase ^ 1;
231
232        } while ( count == 0 );
233      }
234
235      if ( phase )
236        c |= mask;
237
238      mask >>= 1;
239
240      if ( --left <= 0 )
241      {
242        cur[0] = (FT_Byte) c;
243        c      = 0;
244        mask   = 0x80;
245        left   = writer->width;
246
247        writer->line += writer->pitch;
248        cur           = writer->line;
249      }
250      else if ( mask == 0 )
251      {
252        cur[0] = (FT_Byte)c;
253        c      = 0;
254        mask   = 0x80;
255        cur ++;
256      }
257
258      reload = ( --count <= 0 );
259    }
260
261    if ( mask != 0x80 )
262      cur[0] = (FT_Byte) c;
263  }
264
265
266  /*************************************************************************/
267  /*************************************************************************/
268  /*****                                                               *****/
269  /*****                  BITMAP DATA DECODING                         *****/
270  /*****                                                               *****/
271  /*************************************************************************/
272  /*************************************************************************/
273
274  static void
275  pfr_lookup_bitmap_data( FT_Byte*   base,
276                          FT_Byte*   limit,
277                          FT_UInt    count,
278                          FT_UInt    flags,
279                          FT_UInt    char_code,
280                          FT_ULong*  found_offset,
281                          FT_ULong*  found_size )
282  {
283    FT_UInt   left, right, char_len;
284    FT_Bool   two = FT_BOOL( flags & 1 );
285    FT_Byte*  buff;
286
287
288    char_len = 4;
289    if ( two )       char_len += 1;
290    if ( flags & 2 ) char_len += 1;
291    if ( flags & 4 ) char_len += 1;
292
293    left  = 0;
294    right = count;
295
296    while ( left < right )
297    {
298      FT_UInt  middle, code;
299
300
301      middle = ( left + right ) >> 1;
302      buff   = base + middle * char_len;
303
304      /* check that we are not outside of the table -- */
305      /* this is possible with broken fonts...         */
306      if ( buff + char_len > limit )
307        goto Fail;
308
309      if ( two )
310        code = PFR_NEXT_USHORT( buff );
311      else
312        code = PFR_NEXT_BYTE( buff );
313
314      if ( code == char_code )
315        goto Found_It;
316
317      if ( code < char_code )
318        left = middle;
319      else
320        right = middle;
321    }
322
323  Fail:
324    /* Not found */
325    *found_size   = 0;
326    *found_offset = 0;
327    return;
328
329  Found_It:
330    if ( flags & 2 )
331      *found_size = PFR_NEXT_USHORT( buff );
332    else
333      *found_size = PFR_NEXT_BYTE( buff );
334
335    if ( flags & 4 )
336      *found_offset = PFR_NEXT_ULONG( buff );
337    else
338      *found_offset = PFR_NEXT_USHORT( buff );
339  }
340
341
342  /* load bitmap metrics.  "*padvance" must be set to the default value */
343  /* before calling this function...                                    */
344  /*                                                                    */
345  static FT_Error
346  pfr_load_bitmap_metrics( FT_Byte**  pdata,
347                           FT_Byte*   limit,
348                           FT_Long    scaled_advance,
349                           FT_Long   *axpos,
350                           FT_Long   *aypos,
351                           FT_UInt   *axsize,
352                           FT_UInt   *aysize,
353                           FT_Long   *aadvance,
354                           FT_UInt   *aformat )
355  {
356    FT_Error  error = PFR_Err_Ok;
357    FT_Byte   flags;
358    FT_Char   b;
359    FT_Byte*  p = *pdata;
360    FT_Long   xpos, ypos, advance;
361    FT_UInt   xsize, ysize;
362
363
364    PFR_CHECK( 1 );
365    flags = PFR_NEXT_BYTE( p );
366
367    xpos    = 0;
368    ypos    = 0;
369    xsize   = 0;
370    ysize   = 0;
371    advance = 0;
372
373    switch ( flags & 3 )
374    {
375    case 0:
376      PFR_CHECK( 1 );
377      b    = PFR_NEXT_INT8( p );
378      xpos = b >> 4;
379      ypos = ( (FT_Char)( b << 4 ) ) >> 4;
380      break;
381
382    case 1:
383      PFR_CHECK( 2 );
384      xpos = PFR_NEXT_INT8( p );
385      ypos = PFR_NEXT_INT8( p );
386      break;
387
388    case 2:
389      PFR_CHECK( 4 );
390      xpos = PFR_NEXT_SHORT( p );
391      ypos = PFR_NEXT_SHORT( p );
392      break;
393
394    case 3:
395      PFR_CHECK( 6 );
396      xpos = PFR_NEXT_LONG( p );
397      ypos = PFR_NEXT_LONG( p );
398      break;
399
400    default:
401      ;
402    }
403
404    flags >>= 2;
405    switch ( flags & 3 )
406    {
407    case 0:
408      /* blank image */
409      xsize = 0;
410      ysize = 0;
411      break;
412
413    case 1:
414      PFR_CHECK( 1 );
415      b     = PFR_NEXT_BYTE( p );
416      xsize = ( b >> 4 ) & 0xF;
417      ysize = b & 0xF;
418      break;
419
420    case 2:
421      PFR_CHECK( 2 );
422      xsize = PFR_NEXT_BYTE( p );
423      ysize = PFR_NEXT_BYTE( p );
424      break;
425
426    case 3:
427      PFR_CHECK( 4 );
428      xsize = PFR_NEXT_USHORT( p );
429      ysize = PFR_NEXT_USHORT( p );
430      break;
431
432    default:
433      ;
434    }
435
436    flags >>= 2;
437    switch ( flags & 3 )
438    {
439    case 0:
440      advance = scaled_advance;
441      break;
442
443    case 1:
444      PFR_CHECK( 1 );
445      advance = PFR_NEXT_INT8( p ) << 8;
446      break;
447
448    case 2:
449      PFR_CHECK( 2 );
450      advance = PFR_NEXT_SHORT( p );
451      break;
452
453    case 3:
454      PFR_CHECK( 3 );
455      advance = PFR_NEXT_LONG( p );
456      break;
457
458    default:
459      ;
460    }
461
462    *axpos    = xpos;
463    *aypos    = ypos;
464    *axsize   = xsize;
465    *aysize   = ysize;
466    *aadvance = advance;
467    *aformat  = flags >> 2;
468    *pdata    = p;
469
470  Exit:
471    return error;
472
473  Too_Short:
474    error = PFR_Err_Invalid_Table;
475    FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" ));
476    goto Exit;
477  }
478
479
480  static FT_Error
481  pfr_load_bitmap_bits( FT_Byte*    p,
482                        FT_Byte*    limit,
483                        FT_UInt     format,
484                        FT_Bool     decreasing,
485                        FT_Bitmap*  target )
486  {
487    FT_Error          error = PFR_Err_Ok;
488    PFR_BitWriterRec  writer;
489
490
491    if ( target->rows > 0 && target->width > 0 )
492    {
493      pfr_bitwriter_init( &writer, target, decreasing );
494
495      switch ( format )
496      {
497      case 0: /* packed bits */
498        pfr_bitwriter_decode_bytes( &writer, p, limit );
499        break;
500
501      case 1: /* RLE1 */
502        pfr_bitwriter_decode_rle1( &writer, p, limit );
503        break;
504
505      case 2: /* RLE2 */
506        pfr_bitwriter_decode_rle2( &writer, p, limit );
507        break;
508
509      default:
510        FT_ERROR(( "pfr_read_bitmap_data: invalid image type\n" ));
511        error = PFR_Err_Invalid_File_Format;
512      }
513    }
514
515    return error;
516  }
517
518
519  /*************************************************************************/
520  /*************************************************************************/
521  /*****                                                               *****/
522  /*****                     BITMAP LOADING                            *****/
523  /*****                                                               *****/
524  /*************************************************************************/
525  /*************************************************************************/
526
527  FT_LOCAL( FT_Error )
528  pfr_slot_load_bitmap( PFR_Slot  glyph,
529                        PFR_Size  size,
530                        FT_UInt   glyph_index )
531  {
532    FT_Error     error;
533    PFR_Face     face   = (PFR_Face) glyph->root.face;
534    FT_Stream    stream = face->root.stream;
535    PFR_PhyFont  phys   = &face->phy_font;
536    FT_ULong     gps_offset;
537    FT_ULong     gps_size;
538    PFR_Char     character;
539    PFR_Strike   strike;
540
541
542    character = &phys->chars[glyph_index];
543
544    /* Look-up a bitmap strike corresponding to the current */
545    /* character dimensions                                 */
546    {
547      FT_UInt  n;
548
549
550      strike = phys->strikes;
551      for ( n = 0; n < phys->num_strikes; n++ )
552      {
553        if ( strike->x_ppm == (FT_UInt)size->root.metrics.x_ppem &&
554             strike->y_ppm == (FT_UInt)size->root.metrics.y_ppem )
555        {
556          goto Found_Strike;
557        }
558
559        strike++;
560      }
561
562      /* couldn't find it */
563      return PFR_Err_Invalid_Argument;
564    }
565
566  Found_Strike:
567
568    /* Now lookup the glyph's position within the file */
569    {
570      FT_UInt  char_len;
571
572
573      char_len = 4;
574      if ( strike->flags & 1 ) char_len += 1;
575      if ( strike->flags & 2 ) char_len += 1;
576      if ( strike->flags & 4 ) char_len += 1;
577
578      /* Access data directly in the frame to speed lookups */
579      if ( FT_STREAM_SEEK( phys->bct_offset + strike->bct_offset ) ||
580           FT_FRAME_ENTER( char_len * strike->num_bitmaps )        )
581        goto Exit;
582
583      pfr_lookup_bitmap_data( stream->cursor,
584                              stream->limit,
585                              strike->num_bitmaps,
586                              strike->flags,
587                              character->char_code,
588                              &gps_offset,
589                              &gps_size );
590
591      FT_FRAME_EXIT();
592
593      if ( gps_size == 0 )
594      {
595        /* Could not find a bitmap program string for this glyph */
596        error = PFR_Err_Invalid_Argument;
597        goto Exit;
598      }
599    }
600
601    /* get the bitmap metrics */
602    {
603      FT_Long   xpos = 0, ypos = 0, advance = 0;
604      FT_UInt   xsize = 0, ysize = 0, format = 0;
605      FT_Byte*  p;
606
607
608      /* compute linear advance */
609      advance = character->advance;
610      if ( phys->metrics_resolution != phys->outline_resolution )
611        advance = FT_MulDiv( advance,
612                             phys->outline_resolution,
613                             phys->metrics_resolution );
614
615      glyph->root.linearHoriAdvance = advance;
616
617      /* compute default advance, i.e., scaled advance.  This can be */
618      /* overridden in the bitmap header of certain glyphs.          */
619      advance = FT_MulDiv( (FT_Fixed)size->root.metrics.x_ppem << 8,
620                           character->advance,
621                           phys->metrics_resolution );
622
623      if ( FT_STREAM_SEEK( face->header.gps_section_offset + gps_offset ) ||
624           FT_FRAME_ENTER( gps_size )                                     )
625        goto Exit;
626
627      p     = stream->cursor;
628      error = pfr_load_bitmap_metrics( &p, stream->limit,
629                                       advance,
630                                       &xpos, &ypos,
631                                       &xsize, &ysize,
632                                       &advance, &format );
633
634      /*
635       * XXX: on 16bit system, we return an error for huge bitmap
636       *      which causes a size truncation, because truncated
637       *      size properties makes bitmap glyph broken.
638       */
639      if ( xpos > FT_INT_MAX || ( ypos + ysize ) > FT_INT_MAX )
640      {
641        FT_TRACE1(( "pfr_slot_load_bitmap:" ));
642        FT_TRACE1(( "huge bitmap glyph %dx%d over FT_GlyphSlot\n",
643                     xpos, ypos ));
644        error = PFR_Err_Invalid_Pixel_Size;
645      }
646
647      if ( !error )
648      {
649        glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
650
651        /* Set up glyph bitmap and metrics */
652
653        /* XXX: needs casts to fit FT_Bitmap.{width|rows|pitch} */
654        glyph->root.bitmap.width      = (FT_Int)xsize;
655        glyph->root.bitmap.rows       = (FT_Int)ysize;
656        glyph->root.bitmap.pitch      = (FT_Int)( xsize + 7 ) >> 3;
657        glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
658
659        /* XXX: needs casts to fit FT_Glyph_Metrics.{width|height} */
660        glyph->root.metrics.width        = (FT_Pos)xsize << 6;
661        glyph->root.metrics.height       = (FT_Pos)ysize << 6;
662        glyph->root.metrics.horiBearingX = xpos << 6;
663        glyph->root.metrics.horiBearingY = ypos << 6;
664        glyph->root.metrics.horiAdvance  = FT_PIX_ROUND( ( advance >> 2 ) );
665        glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1;
666        glyph->root.metrics.vertBearingY = 0;
667        glyph->root.metrics.vertAdvance  = size->root.metrics.height;
668
669        /* XXX: needs casts fit FT_GlyphSlotRec.bitmap_{left|top} */
670        glyph->root.bitmap_left = (FT_Int)xpos;
671        glyph->root.bitmap_top  = (FT_Int)(ypos + ysize);
672
673        /* Allocate and read bitmap data */
674        {
675          FT_ULong  len = glyph->root.bitmap.pitch * ysize;
676
677
678          error = ft_glyphslot_alloc_bitmap( &glyph->root, len );
679          if ( !error )
680          {
681            error = pfr_load_bitmap_bits(
682                      p,
683                      stream->limit,
684                      format,
685                      FT_BOOL(face->header.color_flags & 2),
686                      &glyph->root.bitmap );
687          }
688        }
689      }
690
691      FT_FRAME_EXIT();
692    }
693
694  Exit:
695    return error;
696  }
697
698/* END */