1/*
2 * (C) Copyright IBM Corp. 1998-2008 - 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
12U_NAMESPACE_BEGIN
13
14const LangSysTable *ScriptTable::findLanguage(LETag languageTag, le_bool exactMatch) const
15{
16    le_uint16 count = SWAPW(langSysCount);
17    Offset langSysTableOffset = exactMatch? 0 : SWAPW(defaultLangSysTableOffset);
18
19    if (count > 0) {
20        Offset foundOffset =
21            OpenTypeUtilities::getTagOffset(languageTag, langSysRecordArray, count);
22
23        if (foundOffset != 0) {
24            langSysTableOffset = foundOffset;
25        }
26    }
27
28    if (langSysTableOffset != 0) {
29        return (const LangSysTable *) ((char *)this + langSysTableOffset);
30    }
31
32    return NULL;
33}
34
35const ScriptTable *ScriptListTable::findScript(LETag scriptTag) const
36{
37    /*
38     * There are some fonts that have a large, bogus value for scriptCount. To try
39     * and protect against this, we use the offset in the first scriptRecord,
40     * which we know has to be past the end of the scriptRecordArray, to compute
41     * a value which is greater than or equal to the actual script count.
42     *
43     * Note: normally, the first offset will point to just after the scriptRecordArray,
44     * but there's no guarantee of this, only that it's *after* the scriptRecordArray.
45     * Because of this, a binary serach isn't safe, because the new count may include
46     * data that's not actually in the scriptRecordArray and hence the array will appear
47     * to be unsorted.
48     */
49    le_uint16 count = SWAPW(scriptCount);
50    le_uint16 limit = ((SWAPW(scriptRecordArray[0].offset) - sizeof(ScriptListTable)) / sizeof(scriptRecordArray)) + ANY_NUMBER;
51    Offset scriptTableOffset = 0;
52
53    if (count > limit) {
54        // the scriptCount value is bogus; do a linear search
55        // because limit may still be too large.
56        for(le_int32 s = 0; s < limit; s += 1) {
57            if (SWAPT(scriptRecordArray[s].tag) == scriptTag) {
58                scriptTableOffset = SWAPW(scriptRecordArray[s].offset);
59                break;
60            }
61        }
62    } else {
63        scriptTableOffset = OpenTypeUtilities::getTagOffset(scriptTag, scriptRecordArray, count);
64    }
65
66    if (scriptTableOffset != 0) {
67        return (const ScriptTable *) ((char *)this + scriptTableOffset);
68    }
69
70    return NULL;
71}
72
73const LangSysTable *ScriptListTable::findLanguage(LETag scriptTag, LETag languageTag, le_bool exactMatch) const
74{
75    const ScriptTable *scriptTable = findScript(scriptTag);
76
77    if (scriptTable == 0) {
78        return NULL;
79    }
80
81    return scriptTable->findLanguage(languageTag, exactMatch);
82}
83
84U_NAMESPACE_END
85