os/textandloc/fontservices/textshaperplugin/test/letest/PortableFontInstance.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2  *******************************************************************************
     3  *
     4  *   Copyright (C) 1999-2003, International Business Machines
     5  *   Corporation and others.  All Rights Reserved.
     6  *
     7  *******************************************************************************
     8  *   file name:  PortableFontInstance.cpp
     9  *
    10  *   created on: 11/22/1999
    11  *   created by: Eric R. Mader
    12  */
    13 
    14 #include <stdio.h>
    15 
    16 #include "layout/LETypes.h"
    17 #include "layout/LEFontInstance.h"
    18 #include "layout/LESwaps.h"
    19 
    20 #include "PortableFontInstance.h"
    21 
    22 #include "sfnt.h"
    23 
    24 #include <string.h>
    25 
    26 //
    27 // Finds the high bit by binary searching
    28 // through the bits in n.
    29 //
    30 le_int8 PortableFontInstance::highBit(le_int32 value)
    31 {
    32     if (value <= 0) {
    33         return -32;
    34     }
    35 
    36     le_uint8 bit = 0;
    37 
    38     if (value >= 1 << 16) {
    39         value >>= 16;
    40         bit += 16;
    41     }
    42 
    43     if (value >= 1 << 8) {
    44         value >>= 8;
    45         bit += 8;
    46     }
    47 
    48     if (value >= 1 << 4) {
    49         value >>= 4;
    50         bit += 4;
    51     }
    52 
    53     if (value >= 1 << 2) {
    54         value >>= 2;
    55         bit += 2;
    56     }
    57 
    58     if (value >= 1 << 1) {
    59         value >>= 1;
    60         bit += 1;
    61     }
    62 
    63     return bit;
    64 }
    65 
    66 
    67 PortableFontInstance::PortableFontInstance(char *fileName, float pointSize, LEErrorCode &status)
    68     : fFile(NULL), fUnitsPerEM(0), fPointSize(pointSize), fAscent(0), fDescent(0), fLeading(0),
    69       fDirectory(NULL), fCMAPMapper(NULL), fHMTXTable(NULL), fNumGlyphs(0), fNumLongHorMetrics(0)
    70 {
    71     if (LE_FAILURE(status)) {
    72         return;
    73     }
    74 
    75     // open the font file
    76     fFile = fopen(fileName, "rb");
    77 
    78     if (fFile == NULL) {
    79         status = LE_FONT_FILE_NOT_FOUND_ERROR;
    80         return;
    81     }
    82 
    83     // read in the directory
    84     SFNTDirectory tempDir;
    85 
    86     fread(&tempDir, sizeof tempDir, 1, fFile);
    87 
    88     le_int32 dirSize = sizeof tempDir + ((SWAPW(tempDir.numTables) - ANY_NUMBER) * sizeof(DirectoryEntry));
    89     const LETag headTag = LE_HEAD_TABLE_TAG;
    90     const LETag hheaTag = LE_HHEA_TABLE_TAG;
    91     const HEADTable *headTable = NULL;
    92     const HHEATable *hheaTable = NULL;
    93     le_uint16 numTables = 0;
    94 
    95     fDirectory = (const SFNTDirectory *) LE_NEW_ARRAY(char, dirSize);
    96 
    97     if (fDirectory == NULL) {
    98         status = LE_MEMORY_ALLOCATION_ERROR;
    99         goto error_exit;
   100     }
   101 
   102     fseek(fFile, 0L, SEEK_SET);
   103     fread((void *) fDirectory, sizeof(char), dirSize, fFile);
   104 
   105     //
   106     // We calculate these numbers 'cause some fonts
   107     // have bogus values for them in the directory header.
   108     //
   109     numTables = SWAPW(fDirectory->numTables);
   110     fDirPower = 1 << highBit(numTables);
   111     fDirExtra = numTables - fDirPower;
   112 
   113     // read unitsPerEm from 'head' table
   114     headTable = (const HEADTable *) readFontTable(headTag);
   115 
   116     if (headTable == NULL) {
   117         status = LE_MISSING_FONT_TABLE_ERROR;
   118         goto error_exit;
   119     }
   120 
   121     fUnitsPerEM = SWAPW(headTable->unitsPerEm);
   122     deleteTable(headTable);
   123 
   124     hheaTable = (HHEATable *) readFontTable(hheaTag);
   125 
   126     if (hheaTable == NULL) {
   127         status = LE_MISSING_FONT_TABLE_ERROR;
   128         goto error_exit;
   129     }
   130 
   131     fAscent  = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->ascent));
   132     fDescent = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->descent));
   133     fLeading = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->lineGap));
   134 
   135     fNumLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics);
   136 
   137     deleteTable((void *) hheaTable);
   138 
   139     fCMAPMapper = findUnicodeMapper();
   140 
   141     if (fCMAPMapper == NULL) {
   142         status = LE_MISSING_FONT_TABLE_ERROR;
   143         goto error_exit;
   144     }
   145 
   146     return;
   147 
   148 error_exit:
   149     fclose(fFile);
   150     fFile = NULL;
   151     return;
   152 }
   153 
   154 PortableFontInstance::~PortableFontInstance()
   155 {
   156     if (fFile != NULL) {
   157         fclose(fFile);
   158 
   159         deleteTable(fHMTXTable);
   160 
   161         delete fCMAPMapper;
   162 
   163         LE_DELETE_ARRAY(fDirectory);
   164     }
   165 };
   166 
   167 void PortableFontInstance::deleteTable(const void *table) const
   168 {
   169     LE_DELETE_ARRAY(table);
   170 }
   171 
   172 const DirectoryEntry *PortableFontInstance::findTable(LETag tag) const
   173 {
   174     if (fDirectory != NULL) {
   175         le_uint16 table = 0;
   176         le_uint16 probe = fDirPower;
   177 
   178         if (SWAPL(fDirectory->tableDirectory[fDirExtra].tag) <= tag) {
   179             table = fDirExtra;
   180         }
   181 
   182         while (probe > (1 << 0)) {
   183             probe >>= 1;
   184 
   185             if (SWAPL(fDirectory->tableDirectory[table + probe].tag) <= tag) {
   186                 table += probe;
   187             }
   188         }
   189 
   190         if (SWAPL(fDirectory->tableDirectory[table].tag) == tag) {
   191             return &fDirectory->tableDirectory[table];
   192         }
   193     }
   194 
   195     return NULL;
   196 }
   197 
   198 const void *PortableFontInstance::readTable(LETag tag, le_uint32 *length) const
   199 {
   200     const DirectoryEntry *entry = findTable(tag);
   201 
   202     if (entry == NULL) {
   203         *length = 0;
   204         return NULL;
   205     }
   206 
   207     *length = SWAPL(entry->length);
   208 
   209     void *table = LE_NEW_ARRAY(char, *length);
   210 
   211     if (table != NULL) {
   212         fseek(fFile, SWAPL(entry->offset), SEEK_SET);
   213         fread(table, sizeof(char), *length, fFile);
   214     }
   215 
   216     return table;
   217 }
   218 
   219 const void *PortableFontInstance::getFontTable(LETag tableTag) const
   220 {
   221     return FontTableCache::find(tableTag);
   222 }
   223 
   224 const void *PortableFontInstance::readFontTable(LETag tableTag) const
   225 {
   226     le_uint32 len;
   227 
   228     return readTable(tableTag, &len);
   229 }
   230 
   231 CMAPMapper *PortableFontInstance::findUnicodeMapper()
   232 {
   233     LETag cmapTag = LE_CMAP_TABLE_TAG;
   234     const CMAPTable *cmap = (CMAPTable *) readFontTable(cmapTag);
   235 
   236     if (cmap == NULL) {
   237         return NULL;
   238     }
   239 
   240     return CMAPMapper::createUnicodeMapper(cmap);
   241 }
   242 
   243 
   244 void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const
   245 {
   246     TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyph);
   247 
   248     if (fHMTXTable == NULL) {
   249         LETag maxpTag = LE_MAXP_TABLE_TAG;
   250         LETag hmtxTag = LE_HMTX_TABLE_TAG;
   251         const MAXPTable *maxpTable = (MAXPTable *) readFontTable(maxpTag);
   252         PortableFontInstance *realThis = (PortableFontInstance *) this;
   253 
   254         if (maxpTable != NULL) {
   255             realThis->fNumGlyphs = SWAPW(maxpTable->numGlyphs);
   256             deleteTable(maxpTable);
   257         }
   258 
   259         realThis->fHMTXTable = (const HMTXTable *) readFontTable(hmtxTag);
   260     }
   261 
   262     le_uint16 index = ttGlyph;
   263 
   264     if (ttGlyph >= fNumGlyphs || fHMTXTable == NULL) {
   265         advance.fX = advance.fY = 0;
   266         return;
   267     }
   268 
   269     if (ttGlyph >= fNumLongHorMetrics) {
   270         index = fNumLongHorMetrics - 1;
   271     }
   272 
   273     advance.fX = xUnitsToPoints(SWAPW(fHMTXTable->hMetrics[index].advanceWidth));
   274     advance.fY = 0;
   275 }
   276 
   277 le_bool PortableFontInstance::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const
   278 {
   279     return FALSE;
   280 }
   281