source: trunk/poppler/freetype-2.1.10/src/pfr/pfrsbit.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 15 years ago

First import

File size: 16.8 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  pfrsbit.c                                                              */
4/*                                                                         */
5/*    FreeType PFR bitmap loader (body).                                   */
6/*                                                                         */
7/*  Copyright 2002, 2003 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 = 0;
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 = 0;
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, ypos, advance;
604      FT_UInt   xsize, ysize, format;
605      FT_Byte*  p;
606
607
608      advance = FT_MulDiv( size->root.metrics.x_ppem << 8,
609                           character->advance,
610                           phys->metrics_resolution );
611
612      /* XXX: handle linearHoriAdvance correctly! */
613
614      if ( FT_STREAM_SEEK( face->header.gps_section_offset + gps_offset ) ||
615           FT_FRAME_ENTER( gps_size )                                     )
616        goto Exit;
617
618      p     = stream->cursor;
619      error = pfr_load_bitmap_metrics( &p, stream->limit,
620                                       advance,
621                                       &xpos, &ypos,
622                                       &xsize, &ysize,
623                                       &advance, &format );
624      if ( !error )
625      {
626        glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
627
628        /* Set up glyph bitmap and metrics */
629        glyph->root.bitmap.width      = (FT_Int)xsize;
630        glyph->root.bitmap.rows       = (FT_Int)ysize;
631        glyph->root.bitmap.pitch      = (FT_Long)( xsize + 7 ) >> 3;
632        glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
633
634        glyph->root.metrics.width        = (FT_Long)xsize << 6;
635        glyph->root.metrics.height       = (FT_Long)ysize << 6;
636        glyph->root.metrics.horiBearingX = xpos << 6;
637        glyph->root.metrics.horiBearingY = ypos << 6;
638        glyph->root.metrics.horiAdvance  = FT_PIX_ROUND( ( advance >> 2 ) );
639        glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1;
640        glyph->root.metrics.vertBearingY = 0;
641        glyph->root.metrics.vertAdvance  = size->root.metrics.height;
642
643        glyph->root.bitmap_left = xpos;
644        glyph->root.bitmap_top  = ypos + ysize;
645
646        /* Allocate and read bitmap data */
647        {
648          FT_ULong  len = glyph->root.bitmap.pitch * ysize;
649
650
651          error = ft_glyphslot_alloc_bitmap( &glyph->root, len );
652          if ( !error )
653          {
654            error = pfr_load_bitmap_bits(
655                      p,
656                      stream->limit,
657                      format,
658                      FT_BOOL(face->header.color_flags & 2),
659                      &glyph->root.bitmap );
660          }
661        }
662      }
663
664      FT_FRAME_EXIT();
665    }
666
667  Exit:
668    return error;
669  }
670
671/* END */
Note: See TracBrowser for help on using the repository browser.