1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * (C) Copyright IBM Corp. 1998-2008 - 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
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst LangSysTable *ScriptTable::findLanguage(LETag languageTag, 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) {
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Offset foundOffset =
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            OpenTypeUtilities::getTagOffset(languageTag, langSysRecordArray, count);
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (foundOffset != 0) {
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            langSysTableOffset = foundOffset;
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (langSysTableOffset != 0) {
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return (const LangSysTable *) ((char *)this + langSysTableOffset);
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return NULL;
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst ScriptTable *ScriptListTable::findScript(LETag scriptTag) const
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
3785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*
3885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     * There are some fonts that have a large, bogus value for scriptCount. To try
3985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     * and protect against this, we use the offset in the first scriptRecord,
4085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     * which we know has to be past the end of the scriptRecordArray, to compute
4185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     * a value which is greater than or equal to the actual script count.
4285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     *
4385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     * Note: normally, the first offset will point to just after the scriptRecordArray,
4485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     * but there's no guarantee of this, only that it's *after* the scriptRecordArray.
4585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     * Because of this, a binary serach isn't safe, because the new count may include
4685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     * data that's not actually in the scriptRecordArray and hence the array will appear
4785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     * to be unsorted.
4885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     */
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_uint16 count = SWAPW(scriptCount);
5085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    le_uint16 limit = ((SWAPW(scriptRecordArray[0].offset) - sizeof(ScriptListTable)) / sizeof(scriptRecordArray)) + ANY_NUMBER;
5185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    Offset scriptTableOffset = 0;
5285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
5385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (count > limit) {
5485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // the scriptCount value is bogus; do a linear search
5585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // because limit may still be too large.
5685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        for(le_int32 s = 0; s < limit; s += 1) {
5785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (SWAPT(scriptRecordArray[s].tag) == scriptTag) {
5885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                scriptTableOffset = SWAPW(scriptRecordArray[s].offset);
5985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                break;
6085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
6185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
6285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    } else {
6385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        scriptTableOffset = OpenTypeUtilities::getTagOffset(scriptTag, scriptRecordArray, count);
6485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (scriptTableOffset != 0) {
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return (const ScriptTable *) ((char *)this + scriptTableOffset);
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
7085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return NULL;
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst LangSysTable *ScriptListTable::findLanguage(LETag scriptTag, LETag languageTag, le_bool exactMatch) const
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const ScriptTable *scriptTable = findScript(scriptTag);
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (scriptTable == 0) {
7885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return NULL;
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return scriptTable->findLanguage(languageTag, exactMatch);
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END
85