2 *******************************************************************************
4 * © 2016 and later: Unicode, Inc. and others.
5 * License & terms of use: http://www.unicode.org/copyright.html#License
7 *******************************************************************************
8 ****************************************************************************** *
10 * Copyright (C) 1999-2003, International Business Machines
11 * Corporation and others. All Rights Reserved.
13 ****************************************************************************** *
14 * file name: cmaps.cpp
16 * created on: ??/??/2001
17 * created by: Eric R. Mader
20 #include "layout/LETypes.h"
21 #include "layout/LESwaps.h"
26 #define SWAPU16(code) ((LEUnicode16) SWAPW(code))
27 #define SWAPU32(code) ((LEUnicode32) SWAPL(code))
30 // Finds the high bit by binary searching
31 // through the bits in value.
33 le_uint8
highBit(le_uint32 value
)
37 if (value
>= 1 << 16) {
42 if (value
>= 1 << 8) {
47 if (value
>= 1 << 4) {
52 if (value
>= 1 << 2) {
57 if (value
>= 1 << 1) {
65 CMAPMapper
*CMAPMapper::createUnicodeMapper(const CMAPTable
*cmap
)
68 le_uint16 nSubtables
= SWAPW(cmap
->numberSubtables
);
69 const CMAPEncodingSubtable
*subtable
= NULL
;
70 le_uint32 offset1
= 0, offset10
= 0;
72 for (i
= 0; i
< nSubtables
; i
+= 1) {
73 const CMAPEncodingSubtableHeader
*esh
= &cmap
->encodingSubtableHeaders
[i
];
75 if (SWAPW(esh
->platformID
) == 3) {
76 switch (SWAPW(esh
->platformSpecificID
)) {
78 offset1
= SWAPL(esh
->encodingOffset
);
82 offset10
= SWAPL(esh
->encodingOffset
);
91 subtable
= (const CMAPEncodingSubtable
*) ((const char *) cmap
+ offset10
);
92 } else if (offset1
!= 0) {
93 subtable
= (const CMAPEncodingSubtable
*) ((const char *) cmap
+ offset1
);
98 switch (SWAPW(subtable
->format
)) {
100 return new CMAPFormat4Mapper(cmap
, (const CMAPFormat4Encoding
*) subtable
);
104 const CMAPFormat12Encoding
*encoding
= (const CMAPFormat12Encoding
*) subtable
;
106 return new CMAPGroupMapper(cmap
, encoding
->groups
, SWAPL(encoding
->nGroups
));
116 CMAPFormat4Mapper::CMAPFormat4Mapper(const CMAPTable
*cmap
, const CMAPFormat4Encoding
*header
)
119 le_uint16 segCount
= SWAPW(header
->segCountX2
) / 2;
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
];
129 LEGlyphID
CMAPFormat4Mapper::unicodeToGlyph(LEUnicode32 unicode32
) const
131 if (unicode32
>= 0x10000) {
135 LEUnicode16 unicode
= (LEUnicode16
) unicode32
;
137 le_uint16 probe
= 1 << fEntrySelector
;
138 TTGlyphID result
= 0;
140 if (SWAPU16(fStartCodes
[fRangeShift
]) <= unicode
) {
144 while (probe
> (1 << 0)) {
147 if (SWAPU16(fStartCodes
[index
+ probe
]) <= unicode
) {
152 if (unicode
>= SWAPU16(fStartCodes
[index
]) && unicode
<= SWAPU16(fEndCodes
[index
])) {
153 if (fIdRangeOffset
[index
] == 0) {
154 result
= (TTGlyphID
) unicode
;
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
);
160 result
= SWAPW(glyphIndexTable
[offset
]);
163 result
+= SWAPW(fIdDelta
[index
]);
168 return LE_SET_GLYPH(0, result
);
171 CMAPFormat4Mapper::~CMAPFormat4Mapper()
173 // parent destructor does it all
176 CMAPGroupMapper::CMAPGroupMapper(const CMAPTable
*cmap
, const CMAPGroup
*groups
, le_uint32 nGroups
)
177 : CMAPMapper(cmap
), fGroups(groups
)
179 le_uint8 bit
= highBit(nGroups
);
181 fRangeOffset
= nGroups
- fPower
;
184 LEGlyphID
CMAPGroupMapper::unicodeToGlyph(LEUnicode32 unicode32
) const
186 le_int32 probe
= fPower
;
189 if (SWAPU32(fGroups
[fRangeOffset
].startCharCode
) <= unicode32
) {
190 range
= fRangeOffset
;
193 while (probe
> (1 << 0)) {
196 if (SWAPU32(fGroups
[range
+ probe
].startCharCode
) <= unicode32
) {
201 if (SWAPU32(fGroups
[range
].startCharCode
) <= unicode32
&& SWAPU32(fGroups
[range
].endCharCode
) >= unicode32
) {
202 return (LEGlyphID
) (SWAPU32(fGroups
[range
].startGlyphCode
) + unicode32
- SWAPU32(fGroups
[range
].startCharCode
));
208 CMAPGroupMapper::~CMAPGroupMapper()
210 // parent destructor does it all