]> git.saurik.com Git - apple/icu.git/blame - icuSources/test/letest/cmaps.cpp
ICU-511.25.tar.gz
[apple/icu.git] / icuSources / test / letest / cmaps.cpp
CommitLineData
b75a7d8f
A
1/***************************************************************************
2*
3* Copyright (C) 1998-2003, International Business Machines
4* Corporation and others. All Rights Reserved.
5*
6************************************************************************/
7
8#include "LETypes.h"
9#include "LESwaps.h"
10
11#include "sfnt.h"
12#include "cmaps.h"
13
14#define SWAPU16(code) ((LEUnicode16) SWAPW(code))
15#define SWAPU32(code) ((LEUnicode32) SWAPL(code))
16
17//
18// Finds the high bit by binary searching
19// through the bits in value.
20//
21le_int8 highBit(le_uint32 value)
22{
23 le_uint8 bit = 0;
24
25 if (value >= 1 << 16) {
26 value >>= 16;
27 bit += 16;
28 }
29
30 if (value >= 1 << 8) {
31 value >>= 8;
32 bit += 8;
33 }
34
35 if (value >= 1 << 4) {
36 value >>= 4;
37 bit += 4;
38 }
39
40 if (value >= 1 << 2) {
41 value >>= 2;
42 bit += 2;
43 }
44
45 if (value >= 1 << 1) {
46 value >>= 1;
47 bit += 1;
48 }
49
50 return bit;
51}
52
53CMAPMapper *CMAPMapper::createUnicodeMapper(const CMAPTable *cmap)
54{
55 le_uint16 i;
56 le_uint16 nSubtables = SWAPW(cmap->numberSubtables);
57 const CMAPEncodingSubtable *subtable = NULL;
58 le_uint32 offset1 = 0, offset10 = 0;
59
60 for (i = 0; i < nSubtables; i += 1) {
61 const CMAPEncodingSubtableHeader *esh = &cmap->encodingSubtableHeaders[i];
62
63 if (SWAPW(esh->platformID) == 3) {
64 switch (SWAPW(esh->platformSpecificID)) {
65 case 1:
66 offset1 = SWAPL(esh->encodingOffset);
67 break;
68
69 case 10:
70 offset10 = SWAPL(esh->encodingOffset);
71 break;
72 }
73 }
74 }
75
76
77 if (offset10 != 0)
78 {
79 subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + offset10);
80 } else if (offset1 != 0) {
81 subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + offset1);
82 } else {
83 return NULL;
84 }
85
86 switch (SWAPW(subtable->format)) {
87 case 4:
88 return new CMAPFormat4Mapper(cmap, (const CMAPFormat4Encoding *) subtable);
89
90 case 12:
91 {
92 const CMAPFormat12Encoding *encoding = (const CMAPFormat12Encoding *) subtable;
93
94 return new CMAPGroupMapper(cmap, encoding->groups, SWAPL(encoding->nGroups));
95 }
96
97 default:
98 break;
99 }
100
101 return NULL;
102}
103
104CMAPFormat4Mapper::CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Encoding *header)
105 : CMAPMapper(cmap)
106{
107 le_uint16 segCount = SWAPW(header->segCountX2) / 2;
108
109 fEntrySelector = SWAPW(header->entrySelector);
110 fRangeShift = SWAPW(header->rangeShift) / 2;
111 fEndCodes = &header->endCodes[0];
112 fStartCodes = &header->endCodes[segCount + 1]; // + 1 for reservedPad...
113 fIdDelta = &fStartCodes[segCount];
114 fIdRangeOffset = &fIdDelta[segCount];
115}
116
117LEGlyphID CMAPFormat4Mapper::unicodeToGlyph(LEUnicode32 unicode32) const
118{
119 if (unicode32 >= 0x10000) {
120 return 0;
121 }
122
123 LEUnicode16 unicode = (LEUnicode16) unicode32;
124 le_uint16 index = 0;
125 le_uint16 probe = 1 << fEntrySelector;
126 TTGlyphID result = 0;
127
128 if (SWAPU16(fStartCodes[fRangeShift]) <= unicode) {
129 index = fRangeShift;
130 }
131
132 while (probe > (1 << 0)) {
133 probe >>= 1;
134
135 if (SWAPU16(fStartCodes[index + probe]) <= unicode) {
136 index += probe;
137 }
138 }
139
140 if (unicode >= SWAPU16(fStartCodes[index]) && unicode <= SWAPU16(fEndCodes[index])) {
141 if (fIdRangeOffset[index] == 0) {
142 result = (TTGlyphID) unicode;
143 } else {
144 le_uint16 offset = unicode - SWAPU16(fStartCodes[index]);
145 le_uint16 rangeOffset = SWAPW(fIdRangeOffset[index]);
146 le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &fIdRangeOffset[index] + rangeOffset);
147
148 result = SWAPW(glyphIndexTable[offset]);
149 }
150
151 result += SWAPW(fIdDelta[index]);
152 } else {
153 result = 0;
154 }
155
156 return LE_SET_GLYPH(0, result);
157}
158
159CMAPFormat4Mapper::~CMAPFormat4Mapper()
160{
161 // parent destructor does it all
162}
163
164CMAPGroupMapper::CMAPGroupMapper(const CMAPTable *cmap, const CMAPGroup *groups, le_uint32 nGroups)
165 : CMAPMapper(cmap), fGroups(groups)
166{
167 le_uint8 bit = highBit(nGroups);
168 fPower = 1 << bit;
169 fRangeOffset = nGroups - fPower;
170}
171
172LEGlyphID CMAPGroupMapper::unicodeToGlyph(LEUnicode32 unicode32) const
173{
174 le_int32 probe = fPower;
175 le_int32 range = 0;
176
177 if (SWAPU32(fGroups[fRangeOffset].startCharCode) <= unicode32) {
178 range = fRangeOffset;
179 }
180
181 while (probe > (1 << 0)) {
182 probe >>= 1;
183
184 if (SWAPU32(fGroups[range + probe].startCharCode) <= unicode32) {
185 range += probe;
186 }
187 }
188
189 if (SWAPU32(fGroups[range].startCharCode) <= unicode32 && SWAPU32(fGroups[range].endCharCode) >= unicode32) {
190 return (LEGlyphID) (SWAPU32(fGroups[range].startGlyphCode) + unicode32 - SWAPU32(fGroups[range].startCharCode));
191 }
192
193 return 0;
194}
195
196CMAPGroupMapper::~CMAPGroupMapper()
197{
198 // parent destructor does it all
199}
200