]>
Commit | Line | Data |
---|---|---|
b75a7d8f | 1 | /* |
57a6839d | 2 | * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved |
b75a7d8f A |
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 | ||
57a6839d | 14 | LEReferenceTo<LangSysTable> ScriptTable::findLanguage(const LETableReference& base, LETag languageTag, LEErrorCode &success, le_bool exactMatch) const |
b75a7d8f A |
15 | { |
16 | le_uint16 count = SWAPW(langSysCount); | |
17 | Offset langSysTableOffset = exactMatch? 0 : SWAPW(defaultLangSysTableOffset); | |
18 | ||
19 | if (count > 0) { | |
57a6839d A |
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 | } | |
b75a7d8f | 27 | } |
57a6839d | 28 | |
b75a7d8f | 29 | if (langSysTableOffset != 0) { |
57a6839d | 30 | return LEReferenceTo<LangSysTable>(base, success, langSysTableOffset); |
b75a7d8f A |
31 | } |
32 | ||
57a6839d | 33 | return LEReferenceTo<LangSysTable>(); |
b75a7d8f A |
34 | } |
35 | ||
57a6839d | 36 | LEReferenceTo<ScriptTable> ScriptListTable::findScript(const LETableReference &base, LETag scriptTag, LEErrorCode &success) const |
b75a7d8f | 37 | { |
57a6839d A |
38 | if (LE_FAILURE(success) ) { |
39 | return LEReferenceTo<ScriptTable>(); // get out | |
40 | } | |
46f4442e A |
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 | */ | |
b75a7d8f | 53 | le_uint16 count = SWAPW(scriptCount); |
57a6839d A |
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 | ||
46f4442e A |
66 | le_uint16 limit = ((SWAPW(scriptRecordArray[0].offset) - sizeof(ScriptListTable)) / sizeof(scriptRecordArray)) + ANY_NUMBER; |
67 | Offset scriptTableOffset = 0; | |
57a6839d | 68 | |
46f4442e A |
69 | |
70 | if (count > limit) { | |
71 | // the scriptCount value is bogus; do a linear search | |
72 | // because limit may still be too large. | |
57a6839d A |
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 | } | |
46f4442e A |
79 | } |
80 | } else { | |
57a6839d A |
81 | LEReferenceToArrayOf<ScriptRecord> scriptRecordArrayRef(base, success, &scriptRecordArray[0], count); |
82 | ||
83 | scriptTableOffset = OpenTypeUtilities::getTagOffset(scriptTag, scriptRecordArrayRef, success); | |
46f4442e | 84 | } |
b75a7d8f A |
85 | |
86 | if (scriptTableOffset != 0) { | |
57a6839d | 87 | return LEReferenceTo<ScriptTable>(base, success, scriptTableOffset); |
b75a7d8f A |
88 | } |
89 | ||
57a6839d | 90 | return LEReferenceTo<ScriptTable>(); |
b75a7d8f A |
91 | } |
92 | ||
57a6839d | 93 | LEReferenceTo<LangSysTable> ScriptListTable::findLanguage(const LETableReference &base, LETag scriptTag, LETag languageTag, LEErrorCode &success, le_bool exactMatch) const |
b75a7d8f | 94 | { |
57a6839d | 95 | const LEReferenceTo<ScriptTable> scriptTable = findScript(base, scriptTag, success); |
b75a7d8f | 96 | |
57a6839d A |
97 | if (scriptTable.isEmpty()) { |
98 | return LEReferenceTo<LangSysTable>(); | |
99 | } | |
b75a7d8f | 100 | |
57a6839d | 101 | return scriptTable->findLanguage(scriptTable, languageTag, success, exactMatch).reparent(base); |
b75a7d8f A |
102 | } |
103 | ||
104 | U_NAMESPACE_END |