1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /***************************************************************************
5 * Copyright (C) 1998-2014, International Business Machines
6 * Corporation and others. All Rights Reserved.
8 ************************************************************************/
10 #include "layout/LETypes.h"
11 #include "layout/LESwaps.h"
17 #define SWAPU16(code) ((LEUnicode16) SWAPW(code))
18 #define SWAPU32(code) ((LEUnicode32) SWAPL(code))
21 // Finds the high bit by binary searching
22 // through the bits in value.
24 le_int8
highBit(le_uint32 value
)
28 if (value
>= 1 << 16) {
33 if (value
>= 1 << 8) {
38 if (value
>= 1 << 4) {
43 if (value
>= 1 << 2) {
48 if (value
>= 1 << 1) {
56 CMAPMapper
*CMAPMapper::createUnicodeMapper(const CMAPTable
*cmap
)
59 le_uint16 nSubtables
= SWAPW(cmap
->numberSubtables
);
60 const CMAPEncodingSubtable
*subtable
= NULL
;
61 le_bool found
= FALSE
;
62 le_uint16 foundPlatformID
= 0xFFFF;
63 le_uint16 foundPlatformSpecificID
= 0xFFFF;
64 le_uint32 foundOffset
= 0;
65 le_uint16 foundTable
= 0xFFFF;
66 // first pass, look for MS table. (preferred?)
67 for (i
= 0; i
< nSubtables
&& !found
; i
+= 1) {
68 const CMAPEncodingSubtableHeader
*esh
= &cmap
->encodingSubtableHeaders
[i
];
70 le_uint16 platformID
= SWAPW(esh
->platformID
);
71 le_uint16 platformSpecificID
= SWAPW(esh
->platformSpecificID
);
72 if (platformID
== 3) { // microsoft
73 switch (platformSpecificID
) {
74 case 1: // Unicode BMP (UCS-2)
75 case 10: // Unicode UCS-4
76 foundOffset
= SWAPL(esh
->encodingOffset
);
77 foundPlatformID
= platformID
;
78 foundPlatformSpecificID
= platformSpecificID
;
84 // printf("%s:%d: microsoft (3) platform specific ID %d (wanted 1 or 10) for subtable %d/%d\n", __FILE__, __LINE__, (SWAPW(esh->platformSpecificID)), i, nSubtables);
87 //printf("%s:%d: platform ID %d (wanted 3, microsoft) for subtable %d/%d\n", __FILE__, __LINE__, (SWAPW(esh->platformID)), i, nSubtables);
91 // second pass, allow non MS table
92 // first pass, look for MS table. (preferred?)
93 for (i
= 0; i
< nSubtables
&& !found
; i
+= 1) {
94 const CMAPEncodingSubtableHeader
*esh
= &cmap
->encodingSubtableHeaders
[i
];
95 le_uint16 platformID
= SWAPW(esh
->platformID
);
96 le_uint16 platformSpecificID
= SWAPW(esh
->platformSpecificID
);
97 //printf("%s:%d: table %d/%d has platform:specific %d:%d\n", __FILE__, __LINE__, i, nSubtables, platformID, platformSpecificID);
99 case 0: // Unicode platform
100 switch(platformSpecificID
) {
105 foundOffset
= SWAPL(esh
->encodingOffset
);
106 foundPlatformID
= platformID
;
107 foundPlatformSpecificID
= platformSpecificID
;
112 default: printf("Error: table %d (psid %d) is unknown. Skipping.\n", i
, platformSpecificID
); break;
117 //printf("Skipping platform id %d\n", platformID);
124 subtable
= (const CMAPEncodingSubtable
*) ((const char *) cmap
+ foundOffset
);
125 //printf("%s:%d: using subtable #%d/%d type %d:%d\n", __FILE__, __LINE__, foundTable, nSubtables, foundPlatformID, foundPlatformSpecificID);
126 (void)foundPlatformID
; // Suppress unused variable compiler warnings.
128 (void)foundPlatformSpecificID
;
130 printf("%s:%d: could not find subtable.\n", __FILE__
, __LINE__
);
134 le_uint16 tableFormat
= SWAPW(subtable
->format
);
135 //printf("%s:%d: table format %d\n", __FILE__, __LINE__, tableFormat);
137 switch (tableFormat
) {
139 return new CMAPFormat4Mapper(cmap
, (const CMAPFormat4Encoding
*) subtable
);
143 const CMAPFormat12Encoding
*encoding
= (const CMAPFormat12Encoding
*) subtable
;
145 return new CMAPGroupMapper(cmap
, encoding
->groups
, SWAPL(encoding
->nGroups
));
152 printf("%s:%d: Unknown format %x.\n", __FILE__
, __LINE__
, (SWAPW(subtable
->format
)));
156 CMAPFormat4Mapper::CMAPFormat4Mapper(const CMAPTable
*cmap
, const CMAPFormat4Encoding
*header
)
159 le_uint16 segCount
= SWAPW(header
->segCountX2
) / 2;
161 fEntrySelector
= SWAPW(header
->entrySelector
);
162 fRangeShift
= SWAPW(header
->rangeShift
) / 2;
163 fEndCodes
= &header
->endCodes
[0];
164 fStartCodes
= &header
->endCodes
[segCount
+ 1]; // + 1 for reservedPad...
165 fIdDelta
= &fStartCodes
[segCount
];
166 fIdRangeOffset
= &fIdDelta
[segCount
];
169 LEGlyphID
CMAPFormat4Mapper::unicodeToGlyph(LEUnicode32 unicode32
) const
171 if (unicode32
>= 0x10000) {
175 LEUnicode16 unicode
= (LEUnicode16
) unicode32
;
177 le_uint16 probe
= 1 << fEntrySelector
;
178 TTGlyphID result
= 0;
180 if (SWAPU16(fStartCodes
[fRangeShift
]) <= unicode
) {
184 while (probe
> (1 << 0)) {
187 if (SWAPU16(fStartCodes
[index
+ probe
]) <= unicode
) {
192 if (unicode
>= SWAPU16(fStartCodes
[index
]) && unicode
<= SWAPU16(fEndCodes
[index
])) {
193 if (fIdRangeOffset
[index
] == 0) {
194 result
= (TTGlyphID
) unicode
;
196 le_uint16 offset
= unicode
- SWAPU16(fStartCodes
[index
]);
197 le_uint16 rangeOffset
= SWAPW(fIdRangeOffset
[index
]);
198 le_uint16
*glyphIndexTable
= (le_uint16
*) ((char *) &fIdRangeOffset
[index
] + rangeOffset
);
200 result
= SWAPW(glyphIndexTable
[offset
]);
203 result
+= SWAPW(fIdDelta
[index
]);
208 return LE_SET_GLYPH(0, result
);
211 CMAPFormat4Mapper::~CMAPFormat4Mapper()
213 // parent destructor does it all
216 CMAPGroupMapper::CMAPGroupMapper(const CMAPTable
*cmap
, const CMAPGroup
*groups
, le_uint32 nGroups
)
217 : CMAPMapper(cmap
), fGroups(groups
)
219 le_uint8 bit
= highBit(nGroups
);
221 fRangeOffset
= nGroups
- fPower
;
224 LEGlyphID
CMAPGroupMapper::unicodeToGlyph(LEUnicode32 unicode32
) const
226 le_int32 probe
= fPower
;
229 if (SWAPU32(fGroups
[fRangeOffset
].startCharCode
) <= unicode32
) {
230 range
= fRangeOffset
;
233 while (probe
> (1 << 0)) {
236 if (SWAPU32(fGroups
[range
+ probe
].startCharCode
) <= unicode32
) {
241 if (SWAPU32(fGroups
[range
].startCharCode
) <= unicode32
&& SWAPU32(fGroups
[range
].endCharCode
) >= unicode32
) {
242 return (LEGlyphID
) (SWAPU32(fGroups
[range
].startGlyphCode
) + unicode32
- SWAPU32(fGroups
[range
].startCharCode
));
248 CMAPGroupMapper::~CMAPGroupMapper()
250 // parent destructor does it all