1
2/*
3 *
4 * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
5 *
6 */
7
8#include "LETypes.h"
9#include "LayoutEngine.h"
10#include "OpenTypeLayoutEngine.h"
11#include "IndicLayoutEngine.h"
12#include "ScriptAndLanguageTags.h"
13
14#include "GlyphSubstitutionTables.h"
15#include "GlyphDefinitionTables.h"
16#include "GlyphPositioningTables.h"
17
18#include "GDEFMarkFilter.h"
19#include "LEGlyphStorage.h"
20
21#include "IndicReordering.h"
22
23U_NAMESPACE_BEGIN
24
25UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndicOpenTypeLayoutEngine)
26
27IndicOpenTypeLayoutEngine::IndicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
28                                                     le_int32 typoFlags, le_bool version2, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success)
29    : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success), fMPreFixups(NULL)
30{
31	if ( version2 ) {
32		fFeatureMap = IndicReordering::getv2FeatureMap(fFeatureMapCount);
33	} else {
34        fFeatureMap = IndicReordering::getFeatureMap(fFeatureMapCount);
35	}
36	fFeatureOrder = TRUE;
37    fVersion2 = version2;
38    fFilterZeroWidth = IndicReordering::getFilterZeroWidth(fScriptCode);
39}
40
41IndicOpenTypeLayoutEngine::IndicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
42    : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success), fMPreFixups(NULL)
43{
44    fFeatureMap = IndicReordering::getFeatureMap(fFeatureMapCount);
45    fFeatureOrder = TRUE;
46	fVersion2 =  FALSE;
47}
48
49IndicOpenTypeLayoutEngine::~IndicOpenTypeLayoutEngine()
50{
51    // nothing to do
52}
53
54// Input: characters, tags
55// Output: glyphs, char indices
56le_int32 IndicOpenTypeLayoutEngine::glyphProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
57                    LEGlyphStorage &glyphStorage, LEErrorCode &success)
58{
59    if (LE_FAILURE(success)) {
60        return 0;
61    }
62
63    if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
64        success = LE_ILLEGAL_ARGUMENT_ERROR;
65        return 0;
66    }
67
68    le_int32 retCount = OpenTypeLayoutEngine::glyphProcessing(chars, offset, count, max, rightToLeft, glyphStorage, success);
69
70    if (LE_FAILURE(success)) {
71        return 0;
72    }
73
74    if (fVersion2) {
75        IndicReordering::finalReordering(glyphStorage,retCount);
76        IndicReordering::applyPresentationForms(glyphStorage,retCount);
77        OpenTypeLayoutEngine::glyphSubstitution(count,max, rightToLeft, glyphStorage, success);
78    } else {
79        IndicReordering::adjustMPres(fMPreFixups, glyphStorage, success);
80    }
81    return retCount;
82}
83
84// Input: characters
85// Output: characters, char indices, tags
86// Returns: output character count
87le_int32 IndicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
88        LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success)
89{
90    if (LE_FAILURE(success)) {
91        return 0;
92    }
93
94    if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
95        success = LE_ILLEGAL_ARGUMENT_ERROR;
96        return 0;
97    }
98
99    le_int32 worstCase = count * IndicReordering::getWorstCaseExpansion(fScriptCode);
100
101    outChars = LE_NEW_ARRAY(LEUnicode, worstCase);
102
103    if (outChars == NULL) {
104        success = LE_MEMORY_ALLOCATION_ERROR;
105        return 0;
106    }
107
108    glyphStorage.allocateGlyphArray(worstCase, rightToLeft, success);
109    glyphStorage.allocateAuxData(success);
110
111    if (LE_FAILURE(success)) {
112        LE_DELETE_ARRAY(outChars);
113        return 0;
114    }
115
116    // NOTE: assumes this allocates featureTags...
117    // (probably better than doing the worst case stuff here...)
118
119    le_int32 outCharCount;
120    if (fVersion2) {
121        outCharCount = IndicReordering::v2process(&chars[offset], count, fScriptCode, outChars, glyphStorage);
122    } else {
123        outCharCount = IndicReordering::reorder(&chars[offset], count, fScriptCode, outChars, glyphStorage, &fMPreFixups, success);
124    }
125
126    if (LE_FAILURE(success)) {
127        LE_DELETE_ARRAY(outChars);
128        return 0;
129    }
130
131    glyphStorage.adoptGlyphCount(outCharCount);
132    return outCharCount;
133}
134
135U_NAMESPACE_END
136