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. 2002-2013 - All Rights Reserved
29 *
30 */
31
32#include "LETypes.h"
33#include "LEGlyphStorage.h"
34#include "MPreFixups.h"
35
36U_NAMESPACE_BEGIN
37
38struct FixupData
39{
40    le_int32 fBaseIndex;
41    le_int32 fMPreIndex;
42};
43
44MPreFixups::MPreFixups(le_int32 charCount)
45    : fFixupData(NULL), fFixupCount(0)
46{
47    fFixupData = LE_NEW_ARRAY(FixupData, charCount);
48}
49
50MPreFixups::~MPreFixups()
51{
52    LE_DELETE_ARRAY(fFixupData);
53    fFixupData = NULL;
54}
55
56void MPreFixups::add(le_int32 baseIndex, le_int32 mpreIndex)
57{
58    // NOTE: don't add the fixup data if the mpre is right
59    // before the base consonant glyph.
60    if (baseIndex - mpreIndex > 1) {
61        fFixupData[fFixupCount].fBaseIndex = baseIndex;
62        fFixupData[fFixupCount].fMPreIndex = mpreIndex;
63
64        fFixupCount += 1;
65    }
66}
67
68void MPreFixups::apply(LEGlyphStorage &glyphStorage, LEErrorCode& success)
69{
70    if (LE_FAILURE(success)) {
71        return;
72    }
73
74    for (le_int32 fixup = 0; fixup < fFixupCount; fixup += 1) {
75        le_int32 baseIndex = fFixupData[fixup].fBaseIndex;
76        le_int32 mpreIndex = fFixupData[fixup].fMPreIndex;
77        le_int32 mpreLimit = mpreIndex + 1;
78
79        while (glyphStorage[baseIndex] == 0xFFFF || glyphStorage[baseIndex] == 0xFFFE) {
80            baseIndex -= 1;
81        }
82
83        while (glyphStorage[mpreLimit] == 0xFFFF || glyphStorage[mpreLimit] == 0xFFFE) {
84            mpreLimit += 1;
85        }
86
87        if (mpreLimit == baseIndex) {
88            continue;
89        }
90
91        LEErrorCode success = LE_NO_ERROR;
92        le_int32   mpreCount = mpreLimit - mpreIndex;
93        le_int32   moveCount = baseIndex - mpreLimit;
94        le_int32   mpreDest  = baseIndex - mpreCount;
95        LEGlyphID *mpreSave  = LE_NEW_ARRAY(LEGlyphID, mpreCount);
96        le_int32  *indexSave = LE_NEW_ARRAY(le_int32, mpreCount);
97
98        if (mpreSave == NULL || indexSave == NULL) {
99            LE_DELETE_ARRAY(mpreSave);
100            LE_DELETE_ARRAY(indexSave);
101            success = LE_MEMORY_ALLOCATION_ERROR;
102            return;
103        }
104
105        le_int32   i;
106
107        for (i = 0; i < mpreCount; i += 1) {
108            mpreSave[i]  = glyphStorage[mpreIndex + i];
109            indexSave[i] = glyphStorage.getCharIndex(mpreIndex + i, success); //charIndices[mpreIndex + i];
110        }
111
112        for (i = 0; i < moveCount; i += 1) {
113            LEGlyphID glyph = glyphStorage[mpreLimit + i];
114            le_int32 charIndex = glyphStorage.getCharIndex(mpreLimit + i, success);
115
116            glyphStorage[mpreIndex + i] = glyph;
117            glyphStorage.setCharIndex(mpreIndex + i, charIndex, success);
118        }
119
120        for (i = 0; i < mpreCount; i += 1) {
121            glyphStorage[mpreDest + i] = mpreSave[i];
122            glyphStorage.setCharIndex(mpreDest, indexSave[i], success);
123        }
124
125        LE_DELETE_ARRAY(indexSave);
126        LE_DELETE_ARRAY(mpreSave);
127    }
128}
129
130U_NAMESPACE_END
131