]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved | |
3 | * | |
4 | */ | |
5 | ||
6 | #include "LETypes.h" | |
7 | #include "OpenTypeTables.h" | |
8 | #include "OpenTypeUtilities.h" | |
9 | #include "ScriptAndLanguage.h" | |
10 | #include "LESwaps.h" | |
11 | ||
12 | U_NAMESPACE_BEGIN | |
13 | ||
14 | LEReferenceTo<LangSysTable> ScriptTable::findLanguage(const LETableReference& base, LETag languageTag, LEErrorCode &success, le_bool exactMatch) const | |
15 | { | |
16 | le_uint16 count = SWAPW(langSysCount); | |
17 | Offset langSysTableOffset = exactMatch? 0 : SWAPW(defaultLangSysTableOffset); | |
18 | ||
19 | if (count > 0) { | |
20 | LEReferenceToArrayOf<TagAndOffsetRecord> langSysRecords(base, success, langSysRecordArray, count); | |
21 | Offset foundOffset = | |
22 | OpenTypeUtilities::getTagOffset(languageTag, langSysRecords, success); | |
23 | ||
24 | if (foundOffset != 0 && LE_SUCCESS(success)) { | |
25 | langSysTableOffset = foundOffset; | |
26 | } | |
27 | } | |
28 | ||
29 | if (langSysTableOffset != 0) { | |
30 | return LEReferenceTo<LangSysTable>(base, success, langSysTableOffset); | |
31 | } | |
32 | ||
33 | return LEReferenceTo<LangSysTable>(); | |
34 | } | |
35 | ||
36 | LEReferenceTo<ScriptTable> ScriptListTable::findScript(const LETableReference &base, LETag scriptTag, LEErrorCode &success) const | |
37 | { | |
38 | if (LE_FAILURE(success) ) { | |
39 | return LEReferenceTo<ScriptTable>(); // get out | |
40 | } | |
41 | /* | |
42 | * There are some fonts that have a large, bogus value for scriptCount. To try | |
43 | * and protect against this, we use the offset in the first scriptRecord, | |
44 | * which we know has to be past the end of the scriptRecordArray, to compute | |
45 | * a value which is greater than or equal to the actual script count. | |
46 | * | |
47 | * Note: normally, the first offset will point to just after the scriptRecordArray, | |
48 | * but there's no guarantee of this, only that it's *after* the scriptRecordArray. | |
49 | * Because of this, a binary serach isn't safe, because the new count may include | |
50 | * data that's not actually in the scriptRecordArray and hence the array will appear | |
51 | * to be unsorted. | |
52 | */ | |
53 | le_uint16 count = SWAPW(scriptCount); | |
54 | ||
55 | if (count == 0) { | |
56 | return LEReferenceTo<ScriptTable>(); // no items, no search | |
57 | } | |
58 | ||
59 | // attempt to construct a ref with at least one element | |
60 | LEReferenceToArrayOf<ScriptRecord> oneElementTable(base, success, &scriptRecordArray[0], 1); | |
61 | ||
62 | if( LE_FAILURE(success) ) { | |
63 | return LEReferenceTo<ScriptTable>(); // couldn't even read the first record - bad font. | |
64 | } | |
65 | ||
66 | le_uint16 limit = ((SWAPW(scriptRecordArray[0].offset) - sizeof(ScriptListTable)) / sizeof(scriptRecordArray)) + ANY_NUMBER; | |
67 | Offset scriptTableOffset = 0; | |
68 | ||
69 | ||
70 | if (count > limit) { | |
71 | // the scriptCount value is bogus; do a linear search | |
72 | // because limit may still be too large. | |
73 | LEReferenceToArrayOf<ScriptRecord> scriptRecordArrayRef(base, success, &scriptRecordArray[0], limit); | |
74 | for(le_int32 s = 0; (s < limit)&&LE_SUCCESS(success); s += 1) { | |
75 | if (SWAPT(scriptRecordArrayRef(s,success).tag) == scriptTag) { | |
76 | scriptTableOffset = SWAPW(scriptRecordArrayRef(s,success).offset); | |
77 | break; | |
78 | } | |
79 | } | |
80 | } else { | |
81 | LEReferenceToArrayOf<ScriptRecord> scriptRecordArrayRef(base, success, &scriptRecordArray[0], count); | |
82 | ||
83 | scriptTableOffset = OpenTypeUtilities::getTagOffset(scriptTag, scriptRecordArrayRef, success); | |
84 | } | |
85 | ||
86 | if (scriptTableOffset != 0) { | |
87 | return LEReferenceTo<ScriptTable>(base, success, scriptTableOffset); | |
88 | } | |
89 | ||
90 | return LEReferenceTo<ScriptTable>(); | |
91 | } | |
92 | ||
93 | LEReferenceTo<LangSysTable> ScriptListTable::findLanguage(const LETableReference &base, LETag scriptTag, LETag languageTag, LEErrorCode &success, le_bool exactMatch) const | |
94 | { | |
95 | const LEReferenceTo<ScriptTable> scriptTable = findScript(base, scriptTag, success); | |
96 | ||
97 | if (scriptTable.isEmpty()) { | |
98 | return LEReferenceTo<LangSysTable>(); | |
99 | } | |
100 | ||
101 | return scriptTable->findLanguage(scriptTable, languageTag, success, exactMatch).reparent(base); | |
102 | } | |
103 | ||
104 | U_NAMESPACE_END |