os/textandloc/fontservices/textshaperplugin/test/letest/FontObject.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /***************************************************************************
     2 *
     3 *   Copyright (C) 1998-2002, International Business Machines
     4 *   Corporation and others.  All Rights Reserved.
     5 *
     6 ************************************************************************/
     7 
     8 #include <stdio.h>
     9 
    10 #include "LETypes.h"
    11 #include "FontObject.h"
    12 #include "LESwaps.h"
    13 
    14 FontObject::FontObject(char *fileName)
    15   : directory(NULL), numTables(0), searchRange(0),entrySelector(0),
    16     cmapTable(NULL), cmSegCount(0), cmSearchRange(0), cmEntrySelector(0),
    17     cmEndCodes(NULL), cmStartCodes(NULL), cmIdDelta(0), cmIdRangeOffset(0),
    18     headTable(NULL), hmtxTable(NULL), numGlyphs(0), numOfLongHorMetrics(0), file(NULL)
    19 {
    20     file = fopen(fileName, "rb");
    21 
    22     if (file == NULL) {
    23         printf("?? Couldn't open %s", fileName);
    24         return;
    25     }
    26 
    27     SFNTDirectory tempDir;
    28 
    29     fread(&tempDir, sizeof tempDir, 1, file);
    30 
    31     numTables       = SWAPW(tempDir.numTables);
    32     searchRange     = SWAPW(tempDir.searchRange) >> 4;
    33     entrySelector   = SWAPW(tempDir.entrySelector);
    34     rangeShift      = SWAPW(tempDir.rangeShift) >> 4;
    35 
    36     int dirSize = sizeof tempDir + ((numTables - ANY_NUMBER) * sizeof(DirectoryEntry));
    37 
    38     directory = (SFNTDirectory *) new char[dirSize];
    39 
    40     fseek(file, 0L, SEEK_SET);
    41     fread(directory, sizeof(char), dirSize, file);
    42 
    43     initUnicodeCMAP();
    44 }
    45 
    46 FontObject::~FontObject()
    47 {
    48     fclose(file);
    49     delete[] directory;
    50     delete[] cmapTable;
    51     delete[] headTable;
    52     delete[] hmtxTable;
    53 }
    54 
    55 void FontObject::deleteTable(void *table)
    56 {
    57     delete[] (char *) table;
    58 }
    59 
    60 DirectoryEntry *FontObject::findTable(LETag tag)
    61 {
    62     le_uint16 table = 0;
    63     le_uint16 probe = 1 << entrySelector;
    64 
    65     if (SWAPL(directory->tableDirectory[rangeShift].tag) <= tag) {
    66         table = rangeShift;
    67     }
    68 
    69     while (probe > (1 << 0)) {
    70         probe >>= 1;
    71 
    72         if (SWAPL(directory->tableDirectory[table + probe].tag) <= tag) {
    73             table += probe;
    74         }
    75     }
    76 
    77     if (SWAPL(directory->tableDirectory[table].tag) == tag) {
    78         return &directory->tableDirectory[table];
    79     }
    80 
    81     return NULL;
    82 }
    83 
    84 void *FontObject::readTable(LETag tag, le_uint32 *length)
    85 {
    86     DirectoryEntry *entry = findTable(tag);
    87 
    88     if (entry == NULL) {
    89         *length = 0;
    90         return NULL;
    91     }
    92 
    93     *length = SWAPL(entry->length);
    94 
    95     void *table = new char[*length];
    96 
    97     fseek(file, SWAPL(entry->offset), SEEK_SET);
    98     fread(table, sizeof(char), *length, file);
    99 
   100     return table;
   101 }
   102 
   103 CMAPEncodingSubtable *FontObject::findCMAP(le_uint16 platformID, le_uint16 platformSpecificID)
   104 {
   105     LETag cmapTag = 0x636D6170; // 'cmap'
   106 
   107     if (cmapTable == NULL) {
   108         le_uint32 length;
   109 
   110         cmapTable = (CMAPTable *) readTable(cmapTag, &length);
   111     }
   112 
   113     if (cmapTable != NULL) {
   114         le_uint16 i;
   115         le_uint16 nSubtables = SWAPW(cmapTable->numberSubtables);
   116 
   117 
   118         for (i = 0; i < nSubtables; i += 1) {
   119             CMAPEncodingSubtableHeader *esh = &cmapTable->encodingSubtableHeaders[i];
   120 
   121             if (SWAPW(esh->platformID) == platformID &&
   122                 SWAPW(esh->platformSpecificID) == platformSpecificID) {
   123                 return (CMAPEncodingSubtable *) ((char *) cmapTable + SWAPL(esh->encodingOffset));
   124             }
   125         }
   126     }
   127 
   128     return NULL;
   129 }
   130 
   131 void FontObject::initUnicodeCMAP()
   132 {
   133     CMAPEncodingSubtable *encodingSubtable = findCMAP(3, 1);
   134 
   135     if (encodingSubtable == 0 ||
   136         SWAPW(encodingSubtable->format) != 4) {
   137         printf("Can't find unicode 'cmap'");
   138         return;
   139     }
   140 
   141     CMAPFormat4Encoding *header = (CMAPFormat4Encoding *) encodingSubtable;
   142 
   143     cmSegCount = SWAPW(header->segCountX2) / 2;
   144     cmSearchRange = SWAPW(header->searchRange);
   145     cmEntrySelector = SWAPW(header->entrySelector);
   146     cmRangeShift = SWAPW(header->rangeShift) / 2;
   147     cmEndCodes = &header->endCodes[0];
   148     cmStartCodes = &header->endCodes[cmSegCount + 1]; // + 1 for reservedPad...
   149     cmIdDelta = &cmStartCodes[cmSegCount];
   150     cmIdRangeOffset = &cmIdDelta[cmSegCount];
   151 }
   152 
   153 LEGlyphID FontObject::unicodeToGlyph(LEUnicode32 unicode32)
   154 {
   155     if (unicode32 >= 0x10000) {
   156         return 0;
   157     }
   158 
   159     LEUnicode16 unicode = (LEUnicode16) unicode32;
   160     le_uint16 index = 0;
   161     le_uint16 probe = 1 << cmEntrySelector;
   162     LEGlyphID result = 0;
   163 
   164     if (SWAPW(cmStartCodes[cmRangeShift]) <= unicode) {
   165         index = cmRangeShift;
   166     }
   167 
   168     while (probe > (1 << 0)) {
   169         probe >>= 1;
   170 
   171         if (SWAPW(cmStartCodes[index + probe]) <= unicode) {
   172             index += probe;
   173         }
   174     }
   175 
   176     if (unicode >= SWAPW(cmStartCodes[index]) && unicode <= SWAPW(cmEndCodes[index])) {
   177         if (cmIdRangeOffset[index] == 0) {
   178             result = (LEGlyphID) unicode;
   179         } else {
   180             le_uint16 offset = unicode - SWAPW(cmStartCodes[index]);
   181             le_uint16 rangeOffset = SWAPW(cmIdRangeOffset[index]);
   182             le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &cmIdRangeOffset[index] + rangeOffset);
   183 
   184             result = SWAPW(glyphIndexTable[offset]);
   185         }
   186 
   187         result += SWAPW(cmIdDelta[index]);
   188     } else {
   189         result = 0;
   190     }
   191 
   192     return result;
   193 }
   194 
   195 le_uint16 FontObject::getUnitsPerEM()
   196 {
   197     if (headTable == NULL) {
   198         LETag headTag = 0x68656164; // 'head'
   199         le_uint32 length;
   200 
   201         headTable = (HEADTable *) readTable(headTag, &length);
   202     }
   203 
   204     return SWAPW(headTable->unitsPerEm);
   205 }
   206 
   207 le_uint16 FontObject::getGlyphAdvance(LEGlyphID glyph)
   208 {
   209     if (hmtxTable == NULL) {
   210         LETag maxpTag = 0x6D617870; // 'maxp'
   211         LETag hheaTag = 0x68686561; // 'hhea'
   212         LETag hmtxTag = 0x686D7478; // 'hmtx'
   213         le_uint32 length;
   214         HHEATable *hheaTable;
   215         MAXPTable *maxpTable = (MAXPTable *) readTable(maxpTag, &length);
   216 
   217         numGlyphs = SWAPW(maxpTable->numGlyphs);
   218         deleteTable(maxpTable);
   219 
   220         hheaTable = (HHEATable *) readTable(hheaTag, &length);
   221         numOfLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics);
   222         deleteTable(hheaTable);
   223 
   224         hmtxTable = (HMTXTable *) readTable(hmtxTag, &length);
   225     }
   226 
   227     le_uint16 index = glyph;
   228 
   229     if (glyph >= numGlyphs) {
   230         return 0;
   231     }
   232 
   233     if (glyph >= numOfLongHorMetrics) {
   234         index = numOfLongHorMetrics - 1;
   235     }
   236 
   237     return SWAPW(hmtxTable->hMetrics[index].advanceWidth);
   238 }
   239 
   240