1/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation.  Oracle designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Oracle in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26/*
27 *
28 * (C) Copyright IBM Corp. 1998 - 2004 - All Rights Reserved
29 *
30 */
31
32
33#include "LETypes.h"
34#include "LayoutTables.h"
35#include "MorphTables.h"
36#include "SubtableProcessor.h"
37#include "IndicRearrangementProcessor.h"
38#include "ContextualGlyphSubstProc.h"
39#include "LigatureSubstProc.h"
40#include "NonContextualGlyphSubstProc.h"
41//#include "ContextualGlyphInsertionProcessor.h"
42#include "LEGlyphStorage.h"
43#include "LESwaps.h"
44
45U_NAMESPACE_BEGIN
46
47void MorphTableHeader::process(const LETableReference &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const
48{
49  le_uint32 chainCount = SWAPL(this->nChains);
50  LEReferenceTo<ChainHeader> chainHeader(base, success, chains); // moving header
51    LEReferenceToArrayOf<ChainHeader> chainHeaderArray(base, success, chains, chainCount);
52    le_uint32 chain;
53
54    for (chain = 0; LE_SUCCESS(success) && (chain < chainCount); chain += 1) {
55        if (chain > 0) {
56            le_uint32 chainLength = SWAPL(chainHeader->chainLength);
57            if (chainLength & 0x03) { // incorrect alignment for 32 bit tables
58                success = LE_MEMORY_ALLOCATION_ERROR; // as good a choice as any
59                return;
60            }
61            chainHeader.addOffset(chainLength, success);
62        }
63        FeatureFlags defaultFlags = SWAPL(chainHeader->defaultFlags);
64        le_int16 nFeatureEntries = SWAPW(chainHeader->nFeatureEntries);
65        le_int16 nSubtables = SWAPW(chainHeader->nSubtables);
66        LEReferenceTo<MorphSubtableHeader> subtableHeader =
67          LEReferenceTo<MorphSubtableHeader>(chainHeader,success, &(chainHeader->featureTable[nFeatureEntries]));
68        le_int16 subtable;
69
70        for (subtable = 0; LE_SUCCESS(success) && (subtable < nSubtables); subtable += 1) {
71            if (subtable > 0) {
72                le_int16 length = SWAPW(subtableHeader->length);
73                if (length & 0x03) { // incorrect alignment for 32 bit tables
74                    success = LE_MEMORY_ALLOCATION_ERROR; // as good a choice as any
75                    return;
76                }
77                subtableHeader.addOffset(length, success);
78                if (LE_FAILURE(success)) break;
79            }
80            SubtableCoverage coverage = SWAPW(subtableHeader->coverage);
81            FeatureFlags subtableFeatures = SWAPL(subtableHeader->subtableFeatures);
82
83            // should check coverage more carefully...
84            if ((coverage & scfVertical) == 0 && (subtableFeatures & defaultFlags) != 0  && LE_SUCCESS(success)) {
85              subtableHeader->process(subtableHeader, glyphStorage, success);
86            }
87        }
88    }
89}
90
91void MorphSubtableHeader::process(const LEReferenceTo<MorphSubtableHeader> &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const
92{
93    SubtableProcessor *processor = NULL;
94
95    if (LE_FAILURE(success)) return;
96
97    switch (SWAPW(coverage) & scfTypeMask)
98    {
99    case mstIndicRearrangement:
100      processor = new IndicRearrangementProcessor(base, success);
101        break;
102
103    case mstContextualGlyphSubstitution:
104      processor = new ContextualGlyphSubstitutionProcessor(base, success);
105        break;
106
107    case mstLigatureSubstitution:
108      processor = new LigatureSubstitutionProcessor(base, success);
109        break;
110
111    case mstReservedUnused:
112        break;
113
114    case mstNonContextualGlyphSubstitution:
115      processor = NonContextualGlyphSubstitutionProcessor::createInstance(base, success);
116        break;
117
118    /*
119    case mstContextualGlyphInsertion:
120        processor = new ContextualGlyphInsertionProcessor(this);
121        break;
122    */
123
124    default:
125        break;
126    }
127
128    if (processor != NULL) {
129      if(LE_SUCCESS(success)) {
130        processor->process(glyphStorage, success);
131      }
132      delete processor;
133    }
134}
135
136U_NAMESPACE_END
137