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 105