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