1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
459d709d503bab6e2b61931737e662dd293b40578ccornelius * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "LETypes.h"
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "LayoutEngine.h"
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ThaiLayoutEngine.h"
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ScriptAndLanguageTags.h"
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "LEGlyphStorage.h"
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "KernTable.h"
1585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ThaiShaping.h"
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(ThaiLayoutEngine)
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2285bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoThaiLayoutEngine::ThaiLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
2385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    : LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success)
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fErrorChar = 0x25CC;
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Figure out which presentation forms the font uses
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (! fontInstance->canDisplay(0x0E01)) {
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // No Thai in font; don't use presentation forms.
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGlyphSet = 3;
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (fontInstance->canDisplay(0x0E64)) {
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // WorldType uses reserved space in Thai block
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGlyphSet = 0;
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (fontInstance->canDisplay(0xF701)) {
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Microsoft corporate zone
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGlyphSet = 1;
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (!fontInstance->canDisplay(fErrorChar)) {
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fErrorChar = 0xF71B;
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (fontInstance->canDisplay(0xF885)) {
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Apple corporate zone
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGlyphSet = 2;
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // no presentation forms in the font
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGlyphSet = 3;
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThaiLayoutEngine::~ThaiLayoutEngine()
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // nothing to do
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Input: characters (0..max provided for context)
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Output: glyphs, char indices
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Returns: the glyph count
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// NOTE: this assumes that ThaiShaping::compose will allocate the outChars array...
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 ThaiLayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool /*rightToLeft*/, LEGlyphStorage &glyphStorage, LEErrorCode &success)
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (LE_FAILURE(success)) {
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        success = LE_ILLEGAL_ARGUMENT_ERROR;
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LEUnicode *outChars;
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    le_int32 glyphCount;
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // This is enough room for the worst-case expansion
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // (it says here...)
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    outChars = LE_NEW_ARRAY(LEUnicode, count * 2);
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (outChars == NULL) {
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        success = LE_MEMORY_ALLOCATION_ERROR;
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphStorage.allocateGlyphArray(count * 2, FALSE, success);
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (LE_FAILURE(success)) {
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LE_DELETE_ARRAY(outChars);
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        success = LE_MEMORY_ALLOCATION_ERROR;
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphCount = ThaiShaping::compose(chars, offset, count, fGlyphSet, fErrorChar, outChars, glyphStorage);
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    mapCharsToGlyphs(outChars, 0, glyphCount, FALSE, FALSE, glyphStorage, success);
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    LE_DELETE_ARRAY(outChars);
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    glyphStorage.adoptGlyphCount(glyphCount);
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return glyphCount;
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
9985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// This is the same as LayoutEngline::adjustGlyphPositions() except that it doesn't call adjustMarkGlyphs
10085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hovoid ThaiLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool  /*reverse*/,
10185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                        LEGlyphStorage &glyphStorage, LEErrorCode &success)
10285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho{
10385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (LE_FAILURE(success)) {
10485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return;
10585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
10685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
10785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (chars == NULL || offset < 0 || count < 0) {
10885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        success = LE_ILLEGAL_ARGUMENT_ERROR;
10985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return;
11085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
11185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
11259d709d503bab6e2b61931737e662dd293b40578ccornelius    if (fTypoFlags & LE_Kerning_FEATURE_FLAG) { /* kerning enabled */
11359d709d503bab6e2b61931737e662dd293b40578ccornelius      LETableReference kernTable(fFontInstance, LE_KERN_TABLE_TAG, success);
11459d709d503bab6e2b61931737e662dd293b40578ccornelius      KernTable kt(kernTable, success);
11559d709d503bab6e2b61931737e662dd293b40578ccornelius      kt.process(glyphStorage, success);
11685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
11785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
11885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // default is no adjustments
11985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return;
12085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
12185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
123