PageRenderTime 1268ms CodeModel.GetById 333ms app.highlight 502ms RepoModel.GetById 260ms app.codeStats 1ms

/src/compiler/android-ndk/jni/freetype/src/sfnt/ttsbit.c

http://ftk.googlecode.com/
C | 1507 lines | 860 code | 279 blank | 368 comment | 107 complexity | ddda31ee9074399c490171e6f0e77950 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/***************************************************************************/
   2/*                                                                         */
   3/*  ttsbit.c                                                               */
   4/*                                                                         */
   5/*    TrueType and OpenType embedded bitmap support (body).                */
   6/*                                                                         */
   7/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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#include <ft2build.h>
  19#include FT_INTERNAL_DEBUG_H
  20#include FT_INTERNAL_STREAM_H
  21#include FT_TRUETYPE_TAGS_H
  22
  23  /*
  24   *  Alas, the memory-optimized sbit loader can't be used when implementing
  25   *  the `old internals' hack
  26   */
  27#ifndef FT_CONFIG_OPTION_OLD_INTERNALS
  28
  29#include "ttsbit0.c"
  30
  31#else /* FT_CONFIG_OPTION_OLD_INTERNALS */
  32
  33#include <ft2build.h>
  34#include FT_INTERNAL_DEBUG_H
  35#include FT_INTERNAL_STREAM_H
  36#include FT_TRUETYPE_TAGS_H
  37#include "ttsbit.h"
  38
  39#include "sferrors.h"
  40
  41
  42  /*************************************************************************/
  43  /*                                                                       */
  44  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  45  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  46  /* messages during execution.                                            */
  47  /*                                                                       */
  48#undef  FT_COMPONENT
  49#define FT_COMPONENT  trace_ttsbit
  50
  51
  52  /*************************************************************************/
  53  /*                                                                       */
  54  /* <Function>                                                            */
  55  /*    blit_sbit                                                          */
  56  /*                                                                       */
  57  /* <Description>                                                         */
  58  /*    Blits a bitmap from an input stream into a given target.  Supports */
  59  /*    x and y offsets as well as byte padded lines.                      */
  60  /*                                                                       */
  61  /* <Input>                                                               */
  62  /*    target      :: The target bitmap/pixmap.                           */
  63  /*                                                                       */
  64  /*    source      :: The input packed bitmap data.                       */
  65  /*                                                                       */
  66  /*    line_bits   :: The number of bits per line.                        */
  67  /*                                                                       */
  68  /*    byte_padded :: A flag which is true if lines are byte-padded.      */
  69  /*                                                                       */
  70  /*    x_offset    :: The horizontal offset.                              */
  71  /*                                                                       */
  72  /*    y_offset    :: The vertical offset.                                */
  73  /*                                                                       */
  74  /* <Note>                                                                */
  75  /*    IMPORTANT: The x and y offsets are relative to the top corner of   */
  76  /*               the target bitmap (unlike the normal TrueType           */
  77  /*               convention).  A positive y offset indicates a downwards */
  78  /*               direction!                                              */
  79  /*                                                                       */
  80  static void
  81  blit_sbit( FT_Bitmap*  target,
  82             FT_Byte*    source,
  83             FT_Int      line_bits,
  84             FT_Bool     byte_padded,
  85             FT_Int      x_offset,
  86             FT_Int      y_offset,
  87             FT_Int      source_height )
  88  {
  89    FT_Byte*   line_buff;
  90    FT_Int     line_incr;
  91    FT_Int     height;
  92
  93    FT_UShort  acc;
  94    FT_UInt    loaded;
  95
  96
  97    /* first of all, compute starting write position */
  98    line_incr = target->pitch;
  99    line_buff = target->buffer;
 100
 101    if ( line_incr < 0 )
 102      line_buff -= line_incr * ( target->rows - 1 );
 103
 104    line_buff += ( x_offset >> 3 ) + y_offset * line_incr;
 105
 106    /***********************************************************************/
 107    /*                                                                     */
 108    /* We use the extra-classic `accumulator' trick to extract the bits    */
 109    /* from the source byte stream.                                        */
 110    /*                                                                     */
 111    /* Namely, the variable `acc' is a 16-bit accumulator containing the   */
 112    /* last `loaded' bits from the input stream.  The bits are shifted to  */
 113    /* the upmost position in `acc'.                                       */
 114    /*                                                                     */
 115    /***********************************************************************/
 116
 117    acc    = 0;  /* clear accumulator   */
 118    loaded = 0;  /* no bits were loaded */
 119
 120    for ( height = source_height; height > 0; height-- )
 121    {
 122      FT_Byte*  cur   = line_buff;        /* current write cursor          */
 123      FT_Int    count = line_bits;        /* # of bits to extract per line */
 124      FT_Byte   shift = (FT_Byte)( x_offset & 7 ); /* current write shift  */
 125      FT_Byte   space = (FT_Byte)( 8 - shift );
 126
 127
 128      /* first of all, read individual source bytes */
 129      if ( count >= 8 )
 130      {
 131        count -= 8;
 132        {
 133          do
 134          {
 135            FT_Byte  val;
 136
 137
 138            /* ensure that there are at least 8 bits in the accumulator */
 139            if ( loaded < 8 )
 140            {
 141              acc    |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded ));
 142              loaded += 8;
 143            }
 144
 145            /* now write one byte */
 146            val = (FT_Byte)( acc >> 8 );
 147            if ( shift )
 148            {
 149              cur[0] |= (FT_Byte)( val >> shift );
 150              cur[1] |= (FT_Byte)( val << space );
 151            }
 152            else
 153              cur[0] |= val;
 154
 155            cur++;
 156            acc   <<= 8;  /* remove bits from accumulator */
 157            loaded -= 8;
 158            count  -= 8;
 159
 160          } while ( count >= 0 );
 161        }
 162
 163        /* restore `count' to correct value */
 164        count += 8;
 165      }
 166
 167      /* now write remaining bits (count < 8) */
 168      if ( count > 0 )
 169      {
 170        FT_Byte  val;
 171
 172
 173        /* ensure that there are at least `count' bits in the accumulator */
 174        if ( (FT_Int)loaded < count )
 175        {
 176          acc    |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded ));
 177          loaded += 8;
 178        }
 179
 180        /* now write remaining bits */
 181        val     = (FT_Byte)( ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count ) );
 182        cur[0] |= (FT_Byte)( val >> shift );
 183
 184        if ( count > space )
 185          cur[1] |= (FT_Byte)( val << space );
 186
 187        acc   <<= count;
 188        loaded -= count;
 189      }
 190
 191      /* now, skip to next line */
 192      if ( byte_padded )
 193      {
 194        acc    = 0;
 195        loaded = 0;   /* clear accumulator on byte-padded lines */
 196      }
 197
 198      line_buff += line_incr;
 199    }
 200  }
 201
 202
 203  static const FT_Frame_Field  sbit_metrics_fields[] =
 204  {
 205#undef  FT_STRUCTURE
 206#define FT_STRUCTURE  TT_SBit_MetricsRec
 207
 208    FT_FRAME_START( 8 ),
 209      FT_FRAME_BYTE( height ),
 210      FT_FRAME_BYTE( width ),
 211
 212      FT_FRAME_CHAR( horiBearingX ),
 213      FT_FRAME_CHAR( horiBearingY ),
 214      FT_FRAME_BYTE( horiAdvance ),
 215
 216      FT_FRAME_CHAR( vertBearingX ),
 217      FT_FRAME_CHAR( vertBearingY ),
 218      FT_FRAME_BYTE( vertAdvance ),
 219    FT_FRAME_END
 220  };
 221
 222
 223  /*************************************************************************/
 224  /*                                                                       */
 225  /* <Function>                                                            */
 226  /*    Load_SBit_Const_Metrics                                            */
 227  /*                                                                       */
 228  /* <Description>                                                         */
 229  /*    Loads the metrics for `EBLC' index tables format 2 and 5.          */
 230  /*                                                                       */
 231  /* <Input>                                                               */
 232  /*    range  :: The target range.                                        */
 233  /*                                                                       */
 234  /*    stream :: The input stream.                                        */
 235  /*                                                                       */
 236  /* <Return>                                                              */
 237  /*    FreeType error code.  0 means success.                             */
 238  /*                                                                       */
 239  static FT_Error
 240  Load_SBit_Const_Metrics( TT_SBit_Range  range,
 241                           FT_Stream      stream )
 242  {
 243    FT_Error  error;
 244
 245
 246    if ( FT_READ_ULONG( range->image_size ) )
 247      return error;
 248
 249    return FT_STREAM_READ_FIELDS( sbit_metrics_fields, &range->metrics );
 250  }
 251
 252
 253  /*************************************************************************/
 254  /*                                                                       */
 255  /* <Function>                                                            */
 256  /*    Load_SBit_Range_Codes                                              */
 257  /*                                                                       */
 258  /* <Description>                                                         */
 259  /*    Loads the range codes for `EBLC' index tables format 4 and 5.      */
 260  /*                                                                       */
 261  /* <Input>                                                               */
 262  /*    range        :: The target range.                                  */
 263  /*                                                                       */
 264  /*    stream       :: The input stream.                                  */
 265  /*                                                                       */
 266  /*    load_offsets :: A flag whether to load the glyph offset table.     */
 267  /*                                                                       */
 268  /* <Return>                                                              */
 269  /*    FreeType error code.  0 means success.                             */
 270  /*                                                                       */
 271  static FT_Error
 272  Load_SBit_Range_Codes( TT_SBit_Range  range,
 273                         FT_Stream      stream,
 274                         FT_Bool        load_offsets )
 275  {
 276    FT_Error   error;
 277    FT_ULong   count, n, size;
 278    FT_Memory  memory = stream->memory;
 279
 280
 281    if ( FT_READ_ULONG( count ) )
 282      goto Exit;
 283
 284    range->num_glyphs = count;
 285
 286    /* Allocate glyph offsets table if needed */
 287    if ( load_offsets )
 288    {
 289      if ( FT_NEW_ARRAY( range->glyph_offsets, count ) )
 290        goto Exit;
 291
 292      size = count * 4L;
 293    }
 294    else
 295      size = count * 2L;
 296
 297    /* Allocate glyph codes table and access frame */
 298    if ( FT_NEW_ARRAY ( range->glyph_codes, count ) ||
 299         FT_FRAME_ENTER( size )                     )
 300      goto Exit;
 301
 302    for ( n = 0; n < count; n++ )
 303    {
 304      range->glyph_codes[n] = FT_GET_USHORT();
 305
 306      if ( load_offsets )
 307        range->glyph_offsets[n] = (FT_ULong)range->image_offset +
 308                                  FT_GET_USHORT();
 309    }
 310
 311    FT_FRAME_EXIT();
 312
 313  Exit:
 314    return error;
 315  }
 316
 317
 318  /*************************************************************************/
 319  /*                                                                       */
 320  /* <Function>                                                            */
 321  /*    Load_SBit_Range                                                    */
 322  /*                                                                       */
 323  /* <Description>                                                         */
 324  /*    Loads a given `EBLC' index/range table.                            */
 325  /*                                                                       */
 326  /* <Input>                                                               */
 327  /*    range  :: The target range.                                        */
 328  /*                                                                       */
 329  /*    stream :: The input stream.                                        */
 330  /*                                                                       */
 331  /* <Return>                                                              */
 332  /*    FreeType error code.  0 means success.                             */
 333  /*                                                                       */
 334  static FT_Error
 335  Load_SBit_Range( TT_SBit_Range  range,
 336                   FT_Stream      stream )
 337  {
 338    FT_Error   error;
 339    FT_Memory  memory = stream->memory;
 340
 341
 342    switch( range->index_format )
 343    {
 344    case 1:   /* variable metrics with 4-byte offsets */
 345    case 3:   /* variable metrics with 2-byte offsets */
 346      {
 347        FT_ULong  num_glyphs, n;
 348        FT_Int    size_elem;
 349        FT_Bool   large = FT_BOOL( range->index_format == 1 );
 350
 351
 352
 353        if ( range->last_glyph < range->first_glyph )
 354        {
 355          error = SFNT_Err_Invalid_File_Format;
 356          goto Exit;
 357        }
 358
 359        num_glyphs        = range->last_glyph - range->first_glyph + 1L;
 360        range->num_glyphs = num_glyphs;
 361        num_glyphs++;                       /* XXX: BEWARE - see spec */
 362
 363        size_elem = large ? 4 : 2;
 364
 365        if ( FT_NEW_ARRAY( range->glyph_offsets, num_glyphs ) ||
 366             FT_FRAME_ENTER( num_glyphs * size_elem )         )
 367          goto Exit;
 368
 369        for ( n = 0; n < num_glyphs; n++ )
 370          range->glyph_offsets[n] = (FT_ULong)( range->image_offset +
 371                                                ( large ? FT_GET_ULONG()
 372                                                        : FT_GET_USHORT() ) );
 373        FT_FRAME_EXIT();
 374      }
 375      break;
 376
 377    case 2:   /* all glyphs have identical metrics */
 378      error = Load_SBit_Const_Metrics( range, stream );
 379      break;
 380
 381    case 4:
 382      error = Load_SBit_Range_Codes( range, stream, 1 );
 383      break;
 384
 385    case 5:
 386      error = Load_SBit_Const_Metrics( range, stream );
 387      if ( !error )
 388        error = Load_SBit_Range_Codes( range, stream, 0 );
 389      break;
 390
 391    default:
 392      error = SFNT_Err_Invalid_File_Format;
 393    }
 394
 395  Exit:
 396    return error;
 397  }
 398
 399
 400  /*************************************************************************/
 401  /*                                                                       */
 402  /* <Function>                                                            */
 403  /*    tt_face_load_eblc                                                  */
 404  /*                                                                       */
 405  /* <Description>                                                         */
 406  /*    Loads the table of embedded bitmap sizes for this face.            */
 407  /*                                                                       */
 408  /* <Input>                                                               */
 409  /*    face   :: The target face object.                                  */
 410  /*                                                                       */
 411  /*    stream :: The input stream.                                        */
 412  /*                                                                       */
 413  /* <Return>                                                              */
 414  /*    FreeType error code.  0 means success.                             */
 415  /*                                                                       */
 416  FT_LOCAL_DEF( FT_Error )
 417  tt_face_load_eblc( TT_Face    face,
 418                     FT_Stream  stream )
 419  {
 420    FT_Error   error  = 0;
 421    FT_Memory  memory = stream->memory;
 422    FT_Fixed   version;
 423    FT_ULong   num_strikes;
 424    FT_ULong   table_base;
 425
 426    static const FT_Frame_Field  sbit_line_metrics_fields[] =
 427    {
 428#undef  FT_STRUCTURE
 429#define FT_STRUCTURE  TT_SBit_LineMetricsRec
 430
 431      /* no FT_FRAME_START */
 432        FT_FRAME_CHAR( ascender ),
 433        FT_FRAME_CHAR( descender ),
 434        FT_FRAME_BYTE( max_width ),
 435
 436        FT_FRAME_CHAR( caret_slope_numerator ),
 437        FT_FRAME_CHAR( caret_slope_denominator ),
 438        FT_FRAME_CHAR( caret_offset ),
 439
 440        FT_FRAME_CHAR( min_origin_SB ),
 441        FT_FRAME_CHAR( min_advance_SB ),
 442        FT_FRAME_CHAR( max_before_BL ),
 443        FT_FRAME_CHAR( min_after_BL ),
 444        FT_FRAME_CHAR( pads[0] ),
 445        FT_FRAME_CHAR( pads[1] ),
 446      FT_FRAME_END
 447    };
 448
 449    static const FT_Frame_Field  strike_start_fields[] =
 450    {
 451#undef  FT_STRUCTURE
 452#define FT_STRUCTURE  TT_SBit_StrikeRec
 453
 454      /* no FT_FRAME_START */
 455        FT_FRAME_ULONG( ranges_offset ),
 456        FT_FRAME_SKIP_LONG,
 457        FT_FRAME_ULONG( num_ranges ),
 458        FT_FRAME_ULONG( color_ref ),
 459      FT_FRAME_END
 460    };
 461
 462    static const FT_Frame_Field  strike_end_fields[] =
 463    {
 464      /* no FT_FRAME_START */
 465        FT_FRAME_USHORT( start_glyph ),
 466        FT_FRAME_USHORT( end_glyph ),
 467        FT_FRAME_BYTE  ( x_ppem ),
 468        FT_FRAME_BYTE  ( y_ppem ),
 469        FT_FRAME_BYTE  ( bit_depth ),
 470        FT_FRAME_CHAR  ( flags ),
 471      FT_FRAME_END
 472    };
 473
 474
 475    face->num_sbit_strikes = 0;
 476
 477    /* this table is optional */
 478    error = face->goto_table( face, TTAG_EBLC, stream, 0 );
 479    if ( error )
 480      error = face->goto_table( face, TTAG_bloc, stream, 0 );
 481    if ( error )
 482      goto Exit;
 483
 484    table_base = FT_STREAM_POS();
 485    if ( FT_FRAME_ENTER( 8L ) )
 486      goto Exit;
 487
 488    version     = FT_GET_LONG();
 489    num_strikes = FT_GET_ULONG();
 490
 491    FT_FRAME_EXIT();
 492
 493    /* check version number and strike count */
 494    if ( version     != 0x00020000L ||
 495         num_strikes >= 0x10000L    )
 496    {
 497      FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" ));
 498      error = SFNT_Err_Invalid_File_Format;
 499
 500      goto Exit;
 501    }
 502
 503    /* allocate the strikes table */
 504    if ( FT_NEW_ARRAY( face->sbit_strikes, num_strikes ) )
 505      goto Exit;
 506
 507    face->num_sbit_strikes = num_strikes;
 508
 509    /* now read each strike table separately */
 510    {
 511      TT_SBit_Strike  strike = face->sbit_strikes;
 512      FT_ULong        count  = num_strikes;
 513
 514
 515      if ( FT_FRAME_ENTER( 48L * num_strikes ) )
 516        goto Exit;
 517
 518      while ( count > 0 )
 519      {
 520        if ( FT_STREAM_READ_FIELDS( strike_start_fields, strike )             ||
 521             FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->hori ) ||
 522             FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->vert ) ||
 523             FT_STREAM_READ_FIELDS( strike_end_fields, strike )               )
 524          break;
 525
 526        count--;
 527        strike++;
 528      }
 529
 530      FT_FRAME_EXIT();
 531    }
 532
 533    /* allocate the index ranges for each strike table */
 534    {
 535      TT_SBit_Strike  strike = face->sbit_strikes;
 536      FT_ULong        count  = num_strikes;
 537
 538
 539      while ( count > 0 )
 540      {
 541        TT_SBit_Range  range;
 542        FT_ULong       count2 = strike->num_ranges;
 543
 544
 545        /* read each range */
 546        if ( FT_STREAM_SEEK( table_base + strike->ranges_offset ) ||
 547             FT_FRAME_ENTER( strike->num_ranges * 8L )            )
 548          goto Exit;
 549
 550        if ( FT_NEW_ARRAY( strike->sbit_ranges, strike->num_ranges ) )
 551          goto Exit;
 552
 553        range = strike->sbit_ranges;
 554        while ( count2 > 0 )
 555        {
 556          range->first_glyph  = FT_GET_USHORT();
 557          range->last_glyph   = FT_GET_USHORT();
 558          range->table_offset = table_base + strike->ranges_offset +
 559                                  FT_GET_ULONG();
 560          count2--;
 561          range++;
 562        }
 563
 564        FT_FRAME_EXIT();
 565
 566        /* Now, read each index table */
 567        count2 = strike->num_ranges;
 568        range  = strike->sbit_ranges;
 569        while ( count2 > 0 )
 570        {
 571          /* Read the header */
 572          if ( FT_STREAM_SEEK( range->table_offset ) ||
 573               FT_FRAME_ENTER( 8L )                  )
 574            goto Exit;
 575
 576          range->index_format = FT_GET_USHORT();
 577          range->image_format = FT_GET_USHORT();
 578          range->image_offset = FT_GET_ULONG();
 579
 580          FT_FRAME_EXIT();
 581
 582          error = Load_SBit_Range( range, stream );
 583          if ( error )
 584            goto Exit;
 585
 586          count2--;
 587          range++;
 588        }
 589
 590        count--;
 591        strike++;
 592      }
 593    }
 594
 595  Exit:
 596    return error;
 597  }
 598
 599
 600  /*************************************************************************/
 601  /*                                                                       */
 602  /* <Function>                                                            */
 603  /*    tt_face_free_eblc                                                  */
 604  /*                                                                       */
 605  /* <Description>                                                         */
 606  /*    Releases the embedded bitmap tables.                               */
 607  /*                                                                       */
 608  /* <Input>                                                               */
 609  /*    face :: The target face object.                                    */
 610  /*                                                                       */
 611  FT_LOCAL_DEF( void )
 612  tt_face_free_eblc( TT_Face  face )
 613  {
 614    FT_Memory       memory       = face->root.memory;
 615    TT_SBit_Strike  strike       = face->sbit_strikes;
 616    TT_SBit_Strike  strike_limit = strike + face->num_sbit_strikes;
 617
 618
 619    if ( strike )
 620    {
 621      for ( ; strike < strike_limit; strike++ )
 622      {
 623        TT_SBit_Range  range       = strike->sbit_ranges;
 624        TT_SBit_Range  range_limit = range + strike->num_ranges;
 625
 626
 627        if ( range )
 628        {
 629          for ( ; range < range_limit; range++ )
 630          {
 631            /* release the glyph offsets and codes tables */
 632            /* where appropriate                          */
 633            FT_FREE( range->glyph_offsets );
 634            FT_FREE( range->glyph_codes );
 635          }
 636        }
 637        FT_FREE( strike->sbit_ranges );
 638        strike->num_ranges = 0;
 639      }
 640      FT_FREE( face->sbit_strikes );
 641    }
 642    face->num_sbit_strikes = 0;
 643  }
 644
 645
 646  FT_LOCAL_DEF( FT_Error )
 647  tt_face_set_sbit_strike( TT_Face          face,
 648                           FT_Size_Request  req,
 649                           FT_ULong*        astrike_index )
 650  {
 651    return FT_Match_Size( (FT_Face)face, req, 0, astrike_index );
 652  }
 653
 654
 655  FT_LOCAL_DEF( FT_Error )
 656  tt_face_load_strike_metrics( TT_Face           face,
 657                               FT_ULong          strike_index,
 658                               FT_Size_Metrics*  metrics )
 659  {
 660    TT_SBit_Strike  strike;
 661
 662
 663    if ( strike_index >= face->num_sbit_strikes )
 664      return SFNT_Err_Invalid_Argument;
 665
 666    strike = face->sbit_strikes + strike_index;
 667
 668    metrics->x_ppem = strike->x_ppem;
 669    metrics->y_ppem = strike->y_ppem;
 670
 671    metrics->ascender  = strike->hori.ascender << 6;
 672    metrics->descender = strike->hori.descender << 6;
 673
 674    /* XXX: Is this correct? */
 675    metrics->max_advance = ( strike->hori.min_origin_SB  +
 676                             strike->hori.max_width      +
 677                             strike->hori.min_advance_SB ) << 6;
 678
 679    metrics->height = metrics->ascender - metrics->descender;
 680
 681    return SFNT_Err_Ok;
 682  }
 683
 684
 685  /*************************************************************************/
 686  /*                                                                       */
 687  /* <Function>                                                            */
 688  /*    find_sbit_range                                                    */
 689  /*                                                                       */
 690  /* <Description>                                                         */
 691  /*    Scans a given strike's ranges and return, for a given glyph        */
 692  /*    index, the corresponding sbit range, and `EBDT' offset.            */
 693  /*                                                                       */
 694  /* <Input>                                                               */
 695  /*    glyph_index   :: The glyph index.                                  */
 696  /*                                                                       */
 697  /*    strike        :: The source/current sbit strike.                   */
 698  /*                                                                       */
 699  /* <Output>                                                              */
 700  /*    arange        :: The sbit range containing the glyph index.        */
 701  /*                                                                       */
 702  /*    aglyph_offset :: The offset of the glyph data in `EBDT' table.     */
 703  /*                                                                       */
 704  /* <Return>                                                              */
 705  /*    FreeType error code.  0 means the glyph index was found.           */
 706  /*                                                                       */
 707  static FT_Error
 708  find_sbit_range( FT_UInt          glyph_index,
 709                   TT_SBit_Strike   strike,
 710                   TT_SBit_Range   *arange,
 711                   FT_ULong        *aglyph_offset )
 712  {
 713    TT_SBit_RangeRec  *range, *range_limit;
 714
 715
 716    /* check whether the glyph index is within this strike's */
 717    /* glyph range                                           */
 718    if ( glyph_index < (FT_UInt)strike->start_glyph ||
 719         glyph_index > (FT_UInt)strike->end_glyph   )
 720      goto Fail;
 721
 722    /* scan all ranges in strike */
 723    range       = strike->sbit_ranges;
 724    range_limit = range + strike->num_ranges;
 725    if ( !range )
 726      goto Fail;
 727
 728    for ( ; range < range_limit; range++ )
 729    {
 730      if ( glyph_index >= (FT_UInt)range->first_glyph &&
 731           glyph_index <= (FT_UInt)range->last_glyph  )
 732      {
 733        FT_UShort  delta = (FT_UShort)( glyph_index - range->first_glyph );
 734
 735
 736        switch ( range->index_format )
 737        {
 738        case 1:
 739        case 3:
 740          *aglyph_offset = range->glyph_offsets[delta];
 741          break;
 742
 743        case 2:
 744          *aglyph_offset = range->image_offset +
 745                           range->image_size * delta;
 746          break;
 747
 748        case 4:
 749        case 5:
 750          {
 751            FT_ULong  n;
 752
 753
 754            for ( n = 0; n < range->num_glyphs; n++ )
 755            {
 756              if ( (FT_UInt)range->glyph_codes[n] == glyph_index )
 757              {
 758                if ( range->index_format == 4 )
 759                  *aglyph_offset = range->glyph_offsets[n];
 760                else
 761                  *aglyph_offset = range->image_offset +
 762                                   n * range->image_size;
 763                goto Found;
 764              }
 765            }
 766          }
 767
 768        /* fall-through */
 769        default:
 770          goto Fail;
 771        }
 772
 773      Found:
 774        /* return successfully! */
 775        *arange  = range;
 776        return SFNT_Err_Ok;
 777      }
 778    }
 779
 780  Fail:
 781    *arange        = 0;
 782    *aglyph_offset = 0;
 783
 784    return SFNT_Err_Invalid_Argument;
 785  }
 786
 787
 788  /*************************************************************************/
 789  /*                                                                       */
 790  /* <Function>                                                            */
 791  /*    tt_find_sbit_image                                                 */
 792  /*                                                                       */
 793  /* <Description>                                                         */
 794  /*    Checks whether an embedded bitmap (an `sbit') exists for a given   */
 795  /*    glyph, at a given strike.                                          */
 796  /*                                                                       */
 797  /* <Input>                                                               */
 798  /*    face          :: The target face object.                           */
 799  /*                                                                       */
 800  /*    glyph_index   :: The glyph index.                                  */
 801  /*                                                                       */
 802  /*    strike_index  :: The current strike index.                         */
 803  /*                                                                       */
 804  /* <Output>                                                              */
 805  /*    arange        :: The SBit range containing the glyph index.        */
 806  /*                                                                       */
 807  /*    astrike       :: The SBit strike containing the glyph index.       */
 808  /*                                                                       */
 809  /*    aglyph_offset :: The offset of the glyph data in `EBDT' table.     */
 810  /*                                                                       */
 811  /* <Return>                                                              */
 812  /*    FreeType error code.  0 means success.  Returns                    */
 813  /*    SFNT_Err_Invalid_Argument if no sbit exists for the requested      */
 814  /*    glyph.                                                             */
 815  /*                                                                       */
 816  FT_LOCAL( FT_Error )
 817  tt_find_sbit_image( TT_Face          face,
 818                      FT_UInt          glyph_index,
 819                      FT_ULong         strike_index,
 820                      TT_SBit_Range   *arange,
 821                      TT_SBit_Strike  *astrike,
 822                      FT_ULong        *aglyph_offset )
 823  {
 824    FT_Error        error;
 825    TT_SBit_Strike  strike;
 826
 827
 828    if ( !face->sbit_strikes                        ||
 829         ( face->num_sbit_strikes <= strike_index ) )
 830      goto Fail;
 831
 832    strike = &face->sbit_strikes[strike_index];
 833
 834    error = find_sbit_range( glyph_index, strike,
 835                             arange, aglyph_offset );
 836    if ( error )
 837      goto Fail;
 838
 839    *astrike = strike;
 840
 841    return SFNT_Err_Ok;
 842
 843  Fail:
 844    /* no embedded bitmap for this glyph in face */
 845    *arange        = 0;
 846    *astrike       = 0;
 847    *aglyph_offset = 0;
 848
 849    return SFNT_Err_Invalid_Argument;
 850  }
 851
 852
 853  /*************************************************************************/
 854  /*                                                                       */
 855  /* <Function>                                                            */
 856  /*    tt_load_sbit_metrics                                               */
 857  /*                                                                       */
 858  /* <Description>                                                         */
 859  /*    Gets the big metrics for a given SBit.                             */
 860  /*                                                                       */
 861  /* <Input>                                                               */
 862  /*    stream      :: The input stream.                                   */
 863  /*                                                                       */
 864  /*    range       :: The SBit range containing the glyph.                */
 865  /*                                                                       */
 866  /* <Output>                                                              */
 867  /*    big_metrics :: A big SBit metrics structure for the glyph.         */
 868  /*                                                                       */
 869  /* <Return>                                                              */
 870  /*    FreeType error code.  0 means success.                             */
 871  /*                                                                       */
 872  /* <Note>                                                                */
 873  /*    The stream cursor must be positioned at the glyph's offset within  */
 874  /*    the `EBDT' table before the call.                                  */
 875  /*                                                                       */
 876  /*    If the image format uses variable metrics, the stream cursor is    */
 877  /*    positioned just after the metrics header in the `EBDT' table on    */
 878  /*    function exit.                                                     */
 879  /*                                                                       */
 880  FT_LOCAL( FT_Error )
 881  tt_load_sbit_metrics( FT_Stream        stream,
 882                        TT_SBit_Range    range,
 883                        TT_SBit_Metrics  metrics )
 884  {
 885    FT_Error  error = SFNT_Err_Ok;
 886
 887
 888    switch ( range->image_format )
 889    {
 890    case 1:
 891    case 2:
 892    case 8:
 893      /* variable small metrics */
 894      {
 895        TT_SBit_SmallMetricsRec  smetrics;
 896
 897        static const FT_Frame_Field  sbit_small_metrics_fields[] =
 898        {
 899#undef  FT_STRUCTURE
 900#define FT_STRUCTURE  TT_SBit_SmallMetricsRec
 901
 902          FT_FRAME_START( 5 ),
 903            FT_FRAME_BYTE( height ),
 904            FT_FRAME_BYTE( width ),
 905            FT_FRAME_CHAR( bearingX ),
 906            FT_FRAME_CHAR( bearingY ),
 907            FT_FRAME_BYTE( advance ),
 908          FT_FRAME_END
 909        };
 910
 911
 912        /* read small metrics */
 913        if ( FT_STREAM_READ_FIELDS( sbit_small_metrics_fields, &smetrics ) )
 914          goto Exit;
 915
 916        /* convert it to a big metrics */
 917        metrics->height       = smetrics.height;
 918        metrics->width        = smetrics.width;
 919        metrics->horiBearingX = smetrics.bearingX;
 920        metrics->horiBearingY = smetrics.bearingY;
 921        metrics->horiAdvance  = smetrics.advance;
 922
 923        /* these metrics are made up at a higher level when */
 924        /* needed.                                          */
 925        metrics->vertBearingX = 0;
 926        metrics->vertBearingY = 0;
 927        metrics->vertAdvance  = 0;
 928      }
 929      break;
 930
 931    case 6:
 932    case 7:
 933    case 9:
 934      /* variable big metrics */
 935      if ( FT_STREAM_READ_FIELDS( sbit_metrics_fields, metrics ) )
 936        goto Exit;
 937      break;
 938
 939    case 5:
 940    default:  /* constant metrics */
 941      if ( range->index_format == 2 || range->index_format == 5 )
 942        *metrics = range->metrics;
 943      else
 944        return SFNT_Err_Invalid_File_Format;
 945   }
 946
 947  Exit:
 948    return error;
 949  }
 950
 951
 952  /*************************************************************************/
 953  /*                                                                       */
 954  /* <Function>                                                            */
 955  /*    crop_bitmap                                                        */
 956  /*                                                                       */
 957  /* <Description>                                                         */
 958  /*    Crops a bitmap to its tightest bounding box, and adjusts its       */
 959  /*    metrics.                                                           */
 960  /*                                                                       */
 961  /* <InOut>                                                               */
 962  /*    map     :: The bitmap.                                             */
 963  /*                                                                       */
 964  /*    metrics :: The corresponding metrics structure.                    */
 965  /*                                                                       */
 966  static void
 967  crop_bitmap( FT_Bitmap*       map,
 968               TT_SBit_Metrics  metrics )
 969  {
 970    /***********************************************************************/
 971    /*                                                                     */
 972    /* In this situation, some bounding boxes of embedded bitmaps are too  */
 973    /* large.  We need to crop it to a reasonable size.                    */
 974    /*                                                                     */
 975    /*      ---------                                                      */
 976    /*      |       |                -----                                 */
 977    /*      |  ***  |                |***|                                 */
 978    /*      |   *   |                | * |                                 */
 979    /*      |   *   |    ------>     | * |                                 */
 980    /*      |   *   |                | * |                                 */
 981    /*      |   *   |                | * |                                 */
 982    /*      |  ***  |                |***|                                 */
 983    /*      ---------                -----                                 */
 984    /*                                                                     */
 985    /***********************************************************************/
 986
 987    FT_Int    rows, count;
 988    FT_Long   line_len;
 989    FT_Byte*  line;
 990
 991
 992    /***********************************************************************/
 993    /*                                                                     */
 994    /* first of all, check the top-most lines of the bitmap, and remove    */
 995    /* them if they're empty.                                              */
 996    /*                                                                     */
 997    {
 998      line     = (FT_Byte*)map->buffer;
 999      rows     = map->rows;
1000      line_len = map->pitch;
1001
1002
1003      for ( count = 0; count < rows; count++ )
1004      {
1005        FT_Byte*  cur   = line;
1006        FT_Byte*  limit = line + line_len;
1007
1008
1009        for ( ; cur < limit; cur++ )
1010          if ( cur[0] )
1011            goto Found_Top;
1012
1013        /* the current line was empty - skip to next one */
1014        line  = limit;
1015      }
1016
1017    Found_Top:
1018      /* check that we have at least one filled line */
1019      if ( count >= rows )
1020        goto Empty_Bitmap;
1021
1022      /* now, crop the empty upper lines */
1023      if ( count > 0 )
1024      {
1025        line = (FT_Byte*)map->buffer;
1026
1027        FT_MEM_MOVE( line, line + count * line_len,
1028                     ( rows - count ) * line_len );
1029
1030        metrics->height       = (FT_Byte)( metrics->height - count );
1031        metrics->horiBearingY = (FT_Char)( metrics->horiBearingY - count );
1032        metrics->vertBearingY = (FT_Char)( metrics->vertBearingY - count );
1033
1034        map->rows -= count;
1035        rows      -= count;
1036      }
1037    }
1038
1039    /***********************************************************************/
1040    /*                                                                     */
1041    /* second, crop the lower lines                                        */
1042    /*                                                                     */
1043    {
1044      line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len;
1045
1046      for ( count = 0; count < rows; count++ )
1047      {
1048        FT_Byte*  cur   = line;
1049        FT_Byte*  limit = line + line_len;
1050
1051
1052        for ( ; cur < limit; cur++ )
1053          if ( cur[0] )
1054            goto Found_Bottom;
1055
1056        /* the current line was empty - skip to previous one */
1057        line -= line_len;
1058      }
1059
1060    Found_Bottom:
1061      if ( count > 0 )
1062      {
1063        metrics->height  = (FT_Byte)( metrics->height - count );
1064        rows            -= count;
1065        map->rows       -= count;
1066      }
1067    }
1068
1069    /***********************************************************************/
1070    /*                                                                     */
1071    /* third, get rid of the space on the left side of the glyph           */
1072    /*                                                                     */
1073    do
1074    {
1075      FT_Byte*  limit;
1076
1077
1078      line  = (FT_Byte*)map->buffer;
1079      limit = line + rows * line_len;
1080
1081      for ( ; line < limit; line += line_len )
1082        if ( line[0] & 0x80 )
1083          goto Found_Left;
1084
1085      /* shift the whole glyph one pixel to the left */
1086      line  = (FT_Byte*)map->buffer;
1087      limit = line + rows * line_len;
1088
1089      for ( ; line < limit; line += line_len )
1090      {
1091        FT_Int    n, width = map->width;
1092        FT_Byte   old;
1093        FT_Byte*  cur = line;
1094
1095
1096        old = (FT_Byte)(cur[0] << 1);
1097        for ( n = 8; n < width; n += 8 )
1098        {
1099          FT_Byte  val;
1100
1101
1102          val    = cur[1];
1103          cur[0] = (FT_Byte)( old | ( val >> 7 ) );
1104          old    = (FT_Byte)( val << 1 );
1105          cur++;
1106        }
1107        cur[0] = old;
1108      }
1109
1110      map->width--;
1111      metrics->horiBearingX++;
1112      metrics->vertBearingX++;
1113      metrics->width--;
1114
1115    } while ( map->width > 0 );
1116
1117  Found_Left:
1118
1119    /***********************************************************************/
1120    /*                                                                     */
1121    /* finally, crop the bitmap width to get rid of the space on the right */
1122    /* side of the glyph.                                                  */
1123    /*                                                                     */
1124    do
1125    {
1126      FT_Int    right = map->width - 1;
1127      FT_Byte*  limit;
1128      FT_Byte   mask;
1129
1130
1131      line  = (FT_Byte*)map->buffer + ( right >> 3 );
1132      limit = line + rows * line_len;
1133      mask  = (FT_Byte)( 0x80 >> ( right & 7 ) );
1134
1135      for ( ; line < limit; line += line_len )
1136        if ( line[0] & mask )
1137          goto Found_Right;
1138
1139      /* crop the whole glyph to the right */
1140      map->width--;
1141      metrics->width--;
1142
1143    } while ( map->width > 0 );
1144
1145  Found_Right:
1146    /* all right, the bitmap was cropped */
1147    return;
1148
1149  Empty_Bitmap:
1150    map->width      = 0;
1151    map->rows       = 0;
1152    map->pitch      = 0;
1153    map->pixel_mode = FT_PIXEL_MODE_MONO;
1154  }
1155
1156
1157  static FT_Error
1158  Load_SBit_Single( FT_Bitmap*       map,
1159                    FT_Int           x_offset,
1160                    FT_Int           y_offset,
1161                    FT_Int           pix_bits,
1162                    FT_UShort        image_format,
1163                    TT_SBit_Metrics  metrics,
1164                    FT_Stream        stream )
1165  {
1166    FT_Error  error;
1167
1168
1169    /* check that the source bitmap fits into the target pixmap */
1170    if ( x_offset < 0 || x_offset + metrics->width  > map->width ||
1171         y_offset < 0 || y_offset + metrics->height > map->rows  )
1172    {
1173      error = SFNT_Err_Invalid_Argument;
1174
1175      goto Exit;
1176    }
1177
1178    {
1179      FT_Int   glyph_width  = metrics->width;
1180      FT_Int   glyph_height = metrics->height;
1181      FT_Int   glyph_size;
1182      FT_Int   line_bits    = pix_bits * glyph_width;
1183      FT_Bool  pad_bytes    = 0;
1184
1185
1186      /* compute size of glyph image */
1187      switch ( image_format )
1188      {
1189      case 1:  /* byte-padded formats */
1190      case 6:
1191        {
1192          FT_Int  line_length;
1193
1194
1195          switch ( pix_bits )
1196          {
1197          case 1:
1198            line_length = ( glyph_width + 7 ) >> 3;
1199            break;
1200          case 2:
1201            line_length = ( glyph_width + 3 ) >> 2;
1202            break;
1203          case 4:
1204            line_length = ( glyph_width + 1 ) >> 1;
1205            break;
1206          default:
1207            line_length =   glyph_width;
1208          }
1209
1210          glyph_size = glyph_height * line_length;
1211          pad_bytes  = 1;
1212        }
1213        break;
1214
1215      case 2:
1216      case 5:
1217      case 7:
1218        line_bits  =   glyph_width  * pix_bits;
1219        glyph_size = ( glyph_height * line_bits + 7 ) >> 3;
1220        break;
1221
1222      default:  /* invalid format */
1223        return SFNT_Err_Invalid_File_Format;
1224      }
1225
1226      /* Now read data and draw glyph into target pixmap       */
1227      if ( FT_FRAME_ENTER( glyph_size ) )
1228        goto Exit;
1229
1230      /* don't forget to multiply `x_offset' by `map->pix_bits' as */
1231      /* the sbit blitter doesn't make a difference between pixmap */
1232      /* depths.                                                   */
1233      blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes,
1234                 x_offset * pix_bits, y_offset, metrics->height );
1235
1236      FT_FRAME_EXIT();
1237    }
1238
1239  Exit:
1240    return error;
1241  }
1242
1243
1244  static FT_Error
1245  Load_SBit_Image( TT_SBit_Strike   strike,
1246                   TT_SBit_Range    range,
1247                   FT_ULong         ebdt_pos,
1248                   FT_ULong         glyph_offset,
1249                   FT_GlyphSlot     slot,
1250                   FT_Int           x_offset,
1251                   FT_Int           y_offset,
1252                   FT_Stream        stream,
1253                   TT_SBit_Metrics  metrics,
1254                   FT_Int           depth )
1255  {
1256    FT_Memory   memory = stream->memory;
1257    FT_Bitmap*  map    = &slot->bitmap;
1258    FT_Error    error;
1259
1260
1261    /* place stream at beginning of glyph data and read metrics */
1262    if ( FT_STREAM_SEEK( ebdt_pos + glyph_offset ) )
1263      goto Exit;
1264
1265    error = tt_load_sbit_metrics( stream, range, metrics );
1266    if ( error )
1267      goto Exit;
1268
1269    /* This function is recursive.  At the top-level call, we  */
1270    /* compute the dimensions of the higher-level glyph to     */
1271    /* allocate the final pixmap buffer.                       */
1272    if ( depth == 0 )
1273    {
1274      FT_Long  size;
1275
1276
1277      map->width = metrics->width;
1278      map->rows  = metrics->height;
1279
1280      switch ( strike->bit_depth )
1281      {
1282      case 1:
1283        map->pixel_mode = FT_PIXEL_MODE_MONO;
1284        map->pitch      = ( map->width + 7 ) >> 3;
1285        break;
1286
1287      case 2:
1288        map->pixel_mode = FT_PIXEL_MODE_GRAY2;
1289        map->pitch      = ( map->width + 3 ) >> 2;
1290        break;
1291
1292      case 4:
1293        map->pixel_mode = FT_PIXEL_MODE_GRAY4;
1294        map->pitch      = ( map->width + 1 ) >> 1;
1295        break;
1296
1297      case 8:
1298        map->pixel_mode = FT_PIXEL_MODE_GRAY;
1299        map->pitch      = map->width;
1300        break;
1301
1302      default:
1303        return SFNT_Err_Invalid_File_Format;
1304      }
1305
1306      size = map->rows * map->pitch;
1307
1308      /* check that there is no empty image */
1309      if ( size == 0 )
1310        goto Exit;     /* exit successfully! */
1311
1312      error = ft_glyphslot_alloc_bitmap( slot, size );
1313      if (error)
1314        goto Exit;
1315    }
1316
1317    switch ( range->image_format )
1318    {
1319    case 1:  /* single sbit image - load it */
1320    case 2:
1321    case 5:
1322    case 6:
1323    case 7:
1324      return Load_SBit_Single( map, x_offset, y_offset, strike->bit_depth,
1325                               range->image_format, metrics, stream );
1326
1327    case 8:  /* compound format */
1328      if ( FT_STREAM_SKIP( 1L ) )
1329      {
1330        error = SFNT_Err_Invalid_Stream_Skip;
1331        goto Exit;
1332      }
1333      /* fallthrough */
1334
1335    case 9:
1336      break;
1337
1338    default: /* invalid image format */
1339      return SFNT_Err_Invalid_File_Format;
1340    }
1341
1342    /* All right, we have a compound format.  First of all, read */
1343    /* the array of elements.                                    */
1344    {
1345      TT_SBit_Component  components;
1346      TT_SBit_Component  comp;
1347      FT_UShort          num_components, count;
1348
1349
1350      if ( FT_READ_USHORT( num_components )           ||
1351           FT_NEW_ARRAY( components, num_components ) )
1352        goto Exit;
1353
1354      count = num_components;
1355
1356      if ( FT_FRAME_ENTER( 4L * num_components ) )
1357        goto Fail_Memory;
1358
1359      for ( comp = components; count > 0; count--, comp++ )
1360      {
1361        comp->glyph_code = FT_GET_USHORT();
1362        comp->x_offset   = FT_GET_CHAR();
1363        comp->y_offset   = FT_GET_CHAR();
1364      }
1365
1366      FT_FRAME_EXIT();
1367
1368      /* Now recursively load each element glyph */
1369      count = num_components;
1370      comp  = components;
1371      for ( ; count > 0; count--, comp++ )
1372      {
1373        TT_SBit_Range       elem_range;
1374        TT_SBit_MetricsRec  elem_metrics;
1375        FT_ULong            elem_offset;
1376
1377
1378        /* find the range for this element */
1379        error = find_sbit_range( comp->glyph_code,
1380                                 strike,
1381                                 &elem_range,
1382                                 &elem_offset );
1383        if ( error )
1384          goto Fail_Memory;
1385
1386        /* now load the element, recursively */
1387        error = Load_SBit_Image( strike,
1388                                 elem_range,
1389                                 ebdt_pos,
1390                                 elem_offset,
1391                                 slot,
1392                                 x_offset + comp->x_offset,
1393                                 y_offset + comp->y_offset,
1394                                 stream,
1395                                 &elem_metrics,
1396                                 depth + 1 );
1397        if ( error )
1398          goto Fail_Memory;
1399      }
1400
1401    Fail_Memory:
1402      FT_FREE( components );
1403    }
1404
1405  Exit:
1406    return error;
1407  }
1408
1409
1410  /*************************************************************************/
1411  /*                                                                       */
1412  /* <Function>                                                            */
1413  /*    tt_face_load_sbit_image                                            */
1414  /*                                                                       */
1415  /* <Description>                                                         */
1416  /*    Loads a given glyph sbit image from the font resource.  This also  */
1417  /*    returns its metrics.                                               */
1418  /*                   …

Large files files are truncated, but you can click here to view the full file