17d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod/*************************************************************************** 27d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod* 37d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod* Copyright (C) 1998-2003, International Business Machines 47d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod* Corporation and others. All Rights Reserved. 57d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod* 67d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod************************************************************************/ 77d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 87d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod#include "layout/LETypes.h" 97d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod#include "layout/LESwaps.h" 107d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 117d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod#include "sfnt.h" 127d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod#include "cmaps.h" 137d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 147d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod#define SWAPU16(code) ((LEUnicode16) SWAPW(code)) 157d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod#define SWAPU32(code) ((LEUnicode32) SWAPL(code)) 167d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 177d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod// 187d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod// Finds the high bit by binary searching 197d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod// through the bits in value. 207d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod// 212eef71737ea29ffadbb5a2be4a898b44f53f66acBehdad Esfahbodstatic inline le_int8 highBit(le_uint32 value) 227d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod{ 237d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod le_uint8 bit = 0; 247d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 257d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod if (value >= 1 << 16) { 267d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod value >>= 16; 277d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod bit += 16; 287d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 297d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 307d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod if (value >= 1 << 8) { 317d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod value >>= 8; 327d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod bit += 8; 337d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 347d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 357d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod if (value >= 1 << 4) { 367d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod value >>= 4; 377d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod bit += 4; 387d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 397d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 407d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod if (value >= 1 << 2) { 417d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod value >>= 2; 427d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod bit += 2; 437d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 447d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 457d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod if (value >= 1 << 1) { 467d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod value >>= 1; 477d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod bit += 1; 487d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 497d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 507d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod return bit; 517d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod} 527d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 537d242364ea647f655a7092bda25f9a10774c57f5Behdad EsfahbodCMAPMapper *CMAPMapper::createUnicodeMapper(const CMAPTable *cmap) 547d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod{ 557d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod le_uint16 i; 567d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod le_uint16 nSubtables = SWAPW(cmap->numberSubtables); 577d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod const CMAPEncodingSubtable *subtable = NULL; 587d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod le_uint32 offset1 = 0, offset10 = 0; 597d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 607d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod for (i = 0; i < nSubtables; i += 1) { 617d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod const CMAPEncodingSubtableHeader *esh = &cmap->encodingSubtableHeaders[i]; 627d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 637d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod if (SWAPW(esh->platformID) == 3) { 647d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod switch (SWAPW(esh->platformSpecificID)) { 657d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod case 1: 667d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod offset1 = SWAPL(esh->encodingOffset); 677d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod break; 687d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 697d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod case 10: 707d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod offset10 = SWAPL(esh->encodingOffset); 717d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod break; 727d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 737d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 747d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 757d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 767d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 777d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod if (offset10 != 0) 787d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod { 797d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + offset10); 807d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } else if (offset1 != 0) { 817d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + offset1); 827d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } else { 837d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod return NULL; 847d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 857d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 867d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod switch (SWAPW(subtable->format)) { 877d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod case 4: 887d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod return new CMAPFormat4Mapper(cmap, (const CMAPFormat4Encoding *) subtable); 897d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 907d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod case 12: 917d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod { 927d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod const CMAPFormat12Encoding *encoding = (const CMAPFormat12Encoding *) subtable; 937d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 947d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod return new CMAPGroupMapper(cmap, encoding->groups, SWAPL(encoding->nGroups)); 957d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 967d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 977d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod default: 987d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod break; 997d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 1007d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1017d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod return NULL; 1027d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod} 1037d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1047d242364ea647f655a7092bda25f9a10774c57f5Behdad EsfahbodCMAPFormat4Mapper::CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Encoding *header) 1057d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod : CMAPMapper(cmap) 1067d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod{ 1077d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod le_uint16 segCount = SWAPW(header->segCountX2) / 2; 1087d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1097d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod fEntrySelector = SWAPW(header->entrySelector); 1107d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod fRangeShift = SWAPW(header->rangeShift) / 2; 1117d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod fEndCodes = &header->endCodes[0]; 1127d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod fStartCodes = &header->endCodes[segCount + 1]; // + 1 for reservedPad... 1137d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod fIdDelta = &fStartCodes[segCount]; 1147d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod fIdRangeOffset = &fIdDelta[segCount]; 1157d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod} 1167d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1177d242364ea647f655a7092bda25f9a10774c57f5Behdad EsfahbodLEGlyphID CMAPFormat4Mapper::unicodeToGlyph(LEUnicode32 unicode32) const 1187d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod{ 1197d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod if (unicode32 >= 0x10000) { 1207d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod return 0; 1217d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 1227d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1237d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod LEUnicode16 unicode = (LEUnicode16) unicode32; 1247d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod le_uint16 index = 0; 1257d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod le_uint16 probe = 1 << fEntrySelector; 1267d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod TTGlyphID result = 0; 1277d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1287d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod if (SWAPU16(fStartCodes[fRangeShift]) <= unicode) { 1297d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod index = fRangeShift; 1307d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 1317d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1327d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod while (probe > (1 << 0)) { 1337d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod probe >>= 1; 1347d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1357d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod if (SWAPU16(fStartCodes[index + probe]) <= unicode) { 1367d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod index += probe; 1377d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 1387d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 1397d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1407d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod if (unicode >= SWAPU16(fStartCodes[index]) && unicode <= SWAPU16(fEndCodes[index])) { 1417d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod if (fIdRangeOffset[index] == 0) { 1427d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod result = (TTGlyphID) unicode; 1437d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } else { 1447d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod le_uint16 offset = unicode - SWAPU16(fStartCodes[index]); 1457d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod le_uint16 rangeOffset = SWAPW(fIdRangeOffset[index]); 1467d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &fIdRangeOffset[index] + rangeOffset); 1477d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1487d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod result = SWAPW(glyphIndexTable[offset]); 1497d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 1507d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1517d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod result += SWAPW(fIdDelta[index]); 1527d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } else { 1537d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod result = 0; 1547d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 1557d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1567d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod return LE_SET_GLYPH(0, result); 1577d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod} 1587d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1597d242364ea647f655a7092bda25f9a10774c57f5Behdad EsfahbodCMAPFormat4Mapper::~CMAPFormat4Mapper() 1607d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod{ 1617d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod // parent destructor does it all 1627d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod} 1637d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1647d242364ea647f655a7092bda25f9a10774c57f5Behdad EsfahbodCMAPGroupMapper::CMAPGroupMapper(const CMAPTable *cmap, const CMAPGroup *groups, le_uint32 nGroups) 1657d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod : CMAPMapper(cmap), fGroups(groups) 1667d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod{ 1677d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod le_uint8 bit = highBit(nGroups); 1687d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod fPower = 1 << bit; 1697d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod fRangeOffset = nGroups - fPower; 1707d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod} 1717d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1727d242364ea647f655a7092bda25f9a10774c57f5Behdad EsfahbodLEGlyphID CMAPGroupMapper::unicodeToGlyph(LEUnicode32 unicode32) const 1737d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod{ 1747d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod le_int32 probe = fPower; 1757d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod le_int32 range = 0; 1767d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1777d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod if (SWAPU32(fGroups[fRangeOffset].startCharCode) <= unicode32) { 1787d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod range = fRangeOffset; 1797d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 1807d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1817d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod while (probe > (1 << 0)) { 1827d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod probe >>= 1; 1837d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1847d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod if (SWAPU32(fGroups[range + probe].startCharCode) <= unicode32) { 1857d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod range += probe; 1867d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 1877d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 1887d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1897d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod if (SWAPU32(fGroups[range].startCharCode) <= unicode32 && SWAPU32(fGroups[range].endCharCode) >= unicode32) { 1907d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod return (LEGlyphID) (SWAPU32(fGroups[range].startGlyphCode) + unicode32 - SWAPU32(fGroups[range].startCharCode)); 1917d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod } 1927d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1937d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod return 0; 1947d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod} 1957d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 1967d242364ea647f655a7092bda25f9a10774c57f5Behdad EsfahbodCMAPGroupMapper::~CMAPGroupMapper() 1977d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod{ 1987d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod // parent destructor does it all 1997d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod} 2007d242364ea647f655a7092bda25f9a10774c57f5Behdad Esfahbod 201