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