1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 259d709d503bab6e2b61931737e662dd293b40578ccornelius * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved 3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LETypes.h" 7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "OpenTypeTables.h" 8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "OpenTypeUtilities.h" 9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ScriptAndLanguage.h" 10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LESwaps.h" 11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN 13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1459d709d503bab6e2b61931737e662dd293b40578ccorneliusLEReferenceTo<LangSysTable> ScriptTable::findLanguage(const LETableReference& base, LETag languageTag, LEErrorCode &success, le_bool exactMatch) const 15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 count = SWAPW(langSysCount); 17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru Offset langSysTableOffset = exactMatch? 0 : SWAPW(defaultLangSysTableOffset); 18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (count > 0) { 2059d709d503bab6e2b61931737e662dd293b40578ccornelius LEReferenceToArrayOf<TagAndOffsetRecord> langSysRecords(base, success, langSysRecordArray, count); 2159d709d503bab6e2b61931737e662dd293b40578ccornelius Offset foundOffset = 2259d709d503bab6e2b61931737e662dd293b40578ccornelius OpenTypeUtilities::getTagOffset(languageTag, langSysRecords, success); 2359d709d503bab6e2b61931737e662dd293b40578ccornelius 2459d709d503bab6e2b61931737e662dd293b40578ccornelius if (foundOffset != 0 && LE_SUCCESS(success)) { 2559d709d503bab6e2b61931737e662dd293b40578ccornelius langSysTableOffset = foundOffset; 2659d709d503bab6e2b61931737e662dd293b40578ccornelius } 27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2859d709d503bab6e2b61931737e662dd293b40578ccornelius 29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (langSysTableOffset != 0) { 3059d709d503bab6e2b61931737e662dd293b40578ccornelius return LEReferenceTo<LangSysTable>(base, success, langSysTableOffset); 31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 3359d709d503bab6e2b61931737e662dd293b40578ccornelius return LEReferenceTo<LangSysTable>(); 34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 3659d709d503bab6e2b61931737e662dd293b40578ccorneliusLEReferenceTo<ScriptTable> ScriptListTable::findScript(const LETableReference &base, LETag scriptTag, LEErrorCode &success) const 37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 3859d709d503bab6e2b61931737e662dd293b40578ccornelius if (LE_FAILURE(success) ) { 3959d709d503bab6e2b61931737e662dd293b40578ccornelius return LEReferenceTo<ScriptTable>(); // get out 4059d709d503bab6e2b61931737e662dd293b40578ccornelius } 4185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho /* 4285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * There are some fonts that have a large, bogus value for scriptCount. To try 4385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * and protect against this, we use the offset in the first scriptRecord, 4485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * which we know has to be past the end of the scriptRecordArray, to compute 4585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * a value which is greater than or equal to the actual script count. 4685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * 4785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Note: normally, the first offset will point to just after the scriptRecordArray, 4885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * but there's no guarantee of this, only that it's *after* the scriptRecordArray. 4985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Because of this, a binary serach isn't safe, because the new count may include 5085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * data that's not actually in the scriptRecordArray and hence the array will appear 5185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * to be unsorted. 5285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */ 53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 count = SWAPW(scriptCount); 5459d709d503bab6e2b61931737e662dd293b40578ccornelius 5559d709d503bab6e2b61931737e662dd293b40578ccornelius if (count == 0) { 5659d709d503bab6e2b61931737e662dd293b40578ccornelius return LEReferenceTo<ScriptTable>(); // no items, no search 5759d709d503bab6e2b61931737e662dd293b40578ccornelius } 5859d709d503bab6e2b61931737e662dd293b40578ccornelius 5959d709d503bab6e2b61931737e662dd293b40578ccornelius // attempt to construct a ref with at least one element 6059d709d503bab6e2b61931737e662dd293b40578ccornelius LEReferenceToArrayOf<ScriptRecord> oneElementTable(base, success, &scriptRecordArray[0], 1); 6159d709d503bab6e2b61931737e662dd293b40578ccornelius 6259d709d503bab6e2b61931737e662dd293b40578ccornelius if( LE_FAILURE(success) ) { 6359d709d503bab6e2b61931737e662dd293b40578ccornelius return LEReferenceTo<ScriptTable>(); // couldn't even read the first record - bad font. 6459d709d503bab6e2b61931737e662dd293b40578ccornelius } 6559d709d503bab6e2b61931737e662dd293b40578ccornelius 6685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho le_uint16 limit = ((SWAPW(scriptRecordArray[0].offset) - sizeof(ScriptListTable)) / sizeof(scriptRecordArray)) + ANY_NUMBER; 6785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Offset scriptTableOffset = 0; 6859d709d503bab6e2b61931737e662dd293b40578ccornelius 6985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 7085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (count > limit) { 7185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // the scriptCount value is bogus; do a linear search 7285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // because limit may still be too large. 7359d709d503bab6e2b61931737e662dd293b40578ccornelius LEReferenceToArrayOf<ScriptRecord> scriptRecordArrayRef(base, success, &scriptRecordArray[0], limit); 7459d709d503bab6e2b61931737e662dd293b40578ccornelius for(le_int32 s = 0; (s < limit)&&LE_SUCCESS(success); s += 1) { 7559d709d503bab6e2b61931737e662dd293b40578ccornelius if (SWAPT(scriptRecordArrayRef(s,success).tag) == scriptTag) { 7659d709d503bab6e2b61931737e662dd293b40578ccornelius scriptTableOffset = SWAPW(scriptRecordArrayRef(s,success).offset); 7759d709d503bab6e2b61931737e662dd293b40578ccornelius break; 7859d709d503bab6e2b61931737e662dd293b40578ccornelius } 7985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 8085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else { 8159d709d503bab6e2b61931737e662dd293b40578ccornelius LEReferenceToArrayOf<ScriptRecord> scriptRecordArrayRef(base, success, &scriptRecordArray[0], count); 8259d709d503bab6e2b61931737e662dd293b40578ccornelius 8359d709d503bab6e2b61931737e662dd293b40578ccornelius scriptTableOffset = OpenTypeUtilities::getTagOffset(scriptTag, scriptRecordArrayRef, success); 8485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (scriptTableOffset != 0) { 8759d709d503bab6e2b61931737e662dd293b40578ccornelius return LEReferenceTo<ScriptTable>(base, success, scriptTableOffset); 88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 9059d709d503bab6e2b61931737e662dd293b40578ccornelius return LEReferenceTo<ScriptTable>(); 91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 9359d709d503bab6e2b61931737e662dd293b40578ccorneliusLEReferenceTo<LangSysTable> ScriptListTable::findLanguage(const LETableReference &base, LETag scriptTag, LETag languageTag, LEErrorCode &success, le_bool exactMatch) const 94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 9559d709d503bab6e2b61931737e662dd293b40578ccornelius const LEReferenceTo<ScriptTable> scriptTable = findScript(base, scriptTag, success); 96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 9759d709d503bab6e2b61931737e662dd293b40578ccornelius if (scriptTable.isEmpty()) { 9859d709d503bab6e2b61931737e662dd293b40578ccornelius return LEReferenceTo<LangSysTable>(); 9959d709d503bab6e2b61931737e662dd293b40578ccornelius } 100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 10159d709d503bab6e2b61931737e662dd293b40578ccornelius return scriptTable->findLanguage(scriptTable, languageTag, success, exactMatch).reparent(base); 102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END 105