1/*
2 *
3 * (C) Copyright IBM Corp. 1998-2006 - All Rights Reserved
4 *
5 */
6
7#include "LETypes.h"
8#include "OpenTypeTables.h"
9#include "OpenTypeUtilities.h"
10#include "LESwaps.h"
11
12U_NAMESPACE_BEGIN
13
14//
15// Finds the high bit by binary searching
16// through the bits in n.
17//
18le_int8 OpenTypeUtilities::highBit(le_int32 value)
19{
20    if (value <= 0) {
21        return -32;
22    }
23
24    le_uint8 bit = 0;
25
26    if (value >= 1 << 16) {
27        value >>= 16;
28        bit += 16;
29    }
30
31    if (value >= 1 << 8) {
32        value >>= 8;
33        bit += 8;
34    }
35
36    if (value >= 1 << 4) {
37        value >>= 4;
38        bit += 4;
39    }
40
41    if (value >= 1 << 2) {
42        value >>= 2;
43        bit += 2;
44    }
45
46    if (value >= 1 << 1) {
47        value >>= 1;
48        bit += 1;
49    }
50
51    return bit;
52}
53
54Offset OpenTypeUtilities::getTagOffset(LETag tag, const TagAndOffsetRecord *records, le_int32 recordCount)
55{
56    le_uint8 bit = highBit(recordCount);
57    le_int32 power = 1 << bit;
58    le_int32 extra = recordCount - power;
59    le_int32 probe = power;
60    le_int32 index = 0;
61
62    if (SWAPT(records[extra].tag) <= tag) {
63        index = extra;
64    }
65
66    while (probe > (1 << 0)) {
67        probe >>= 1;
68
69        if (SWAPT(records[index + probe].tag) <= tag) {
70            index += probe;
71        }
72    }
73
74    if (SWAPT(records[index].tag) == tag) {
75        return SWAPW(records[index].offset);
76    }
77
78    return 0;
79}
80
81le_int32 OpenTypeUtilities::getGlyphRangeIndex(TTGlyphID glyphID, const GlyphRangeRecord *records, le_int32 recordCount)
82{
83    le_uint8 bit = highBit(recordCount);
84    le_int32 power = 1 << bit;
85    le_int32 extra = recordCount - power;
86    le_int32 probe = power;
87    le_int32 range = 0;
88
89	if (recordCount == 0) {
90		return -1;
91	}
92
93    if (SWAPW(records[extra].firstGlyph) <= glyphID) {
94        range = extra;
95    }
96
97    while (probe > (1 << 0)) {
98        probe >>= 1;
99
100        if (SWAPW(records[range + probe].firstGlyph) <= glyphID) {
101            range += probe;
102        }
103    }
104
105    if (SWAPW(records[range].firstGlyph) <= glyphID && SWAPW(records[range].lastGlyph) >= glyphID) {
106        return range;
107    }
108
109    return -1;
110}
111
112le_int32 OpenTypeUtilities::search(le_uint32 value, const le_uint32 array[], le_int32 count)
113{
114    le_int32 power = 1 << highBit(count);
115    le_int32 extra = count - power;
116    le_int32 probe = power;
117    le_int32 index = 0;
118
119    if (value >= array[extra]) {
120        index = extra;
121    }
122
123    while (probe > (1 << 0)) {
124        probe >>= 1;
125
126        if (value >= array[index + probe]) {
127            index += probe;
128        }
129    }
130
131    return index;
132}
133
134le_int32 OpenTypeUtilities::search(le_uint16 value, const le_uint16 array[], le_int32 count)
135{
136    le_int32 power = 1 << highBit(count);
137    le_int32 extra = count - power;
138    le_int32 probe = power;
139    le_int32 index = 0;
140
141    if (value >= array[extra]) {
142        index = extra;
143    }
144
145    while (probe > (1 << 0)) {
146        probe >>= 1;
147
148        if (value >= array[index + probe]) {
149            index += probe;
150        }
151    }
152
153    return index;
154}
155
156//
157// Straight insertion sort from Knuth vol. III, pg. 81
158//
159void OpenTypeUtilities::sort(le_uint16 *array, le_int32 count)
160{
161    for (le_int32 j = 1; j < count; j += 1) {
162        le_int32 i;
163        le_uint16 v = array[j];
164
165        for (i = j - 1; i >= 0; i -= 1) {
166            if (v >= array[i]) {
167                break;
168            }
169
170            array[i + 1] = array[i];
171        }
172
173        array[i + 1] = v;
174    }
175}
176
177
178
179U_NAMESPACE_END
180