1/*
2 *
3 * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
4 *
5 */
6
7#include "LETypes.h"
8#include "LEGlyphStorage.h"
9#include "CanonShaping.h"
10#include "GlyphDefinitionTables.h"
11#include "ClassDefinitionTables.h"
12
13U_NAMESPACE_BEGIN
14
15void CanonShaping::sortMarks(le_int32 *indices, const le_int32 *combiningClasses, le_int32 index, le_int32 limit)
16{
17    for (le_int32 j = index + 1; j < limit; j += 1) {
18        le_int32 i;
19        le_int32 v = indices[j];
20        le_int32 c = combiningClasses[v];
21
22        for (i = j - 1; i >= index; i -= 1) {
23            if (c >= combiningClasses[indices[i]]) {
24                break;
25            }
26
27            indices[i + 1] = indices[i];
28        }
29
30        indices[i + 1] = v;
31    }
32}
33
34void CanonShaping::reorderMarks(const LEUnicode *inChars, le_int32 charCount, le_bool rightToLeft,
35                                LEUnicode *outChars, LEGlyphStorage &glyphStorage)
36{
37    LEErrorCode success = LE_NO_ERROR;
38    LEReferenceTo<GlyphDefinitionTableHeader> gdefTable(CanonShaping::glyphDefinitionTable, CanonShaping::glyphDefinitionTableLen);
39    LEReferenceTo<ClassDefinitionTable> classTable = gdefTable->getMarkAttachClassDefinitionTable(gdefTable, success);
40    le_int32 *combiningClasses = LE_NEW_ARRAY(le_int32, charCount);
41    le_int32 *indices = LE_NEW_ARRAY(le_int32, charCount);
42    le_int32 i;
43
44    for (i = 0; i < charCount; i += 1) {
45      combiningClasses[i] = classTable->getGlyphClass(classTable, (LEGlyphID) inChars[i], success);
46        indices[i] = i;
47    }
48
49    for (i = 0; i < charCount; i += 1) {
50        if (combiningClasses[i] != 0) {
51            le_int32 mark;
52
53            for (mark = i; mark < charCount; mark += 1) {
54                if (combiningClasses[mark] == 0) {
55                    break;
56                }
57            }
58
59            sortMarks(indices, combiningClasses, i, mark);
60        }
61    }
62
63    le_int32 out = 0, dir = 1;
64
65    if (rightToLeft) {
66        out = charCount - 1;
67        dir = -1;
68    }
69
70    for (i = 0; i < charCount; i += 1, out += dir) {
71        le_int32 index = indices[i];
72
73        outChars[i] = inChars[index];
74        glyphStorage.setCharIndex(out, index, success);
75    }
76
77    LE_DELETE_ARRAY(indices);
78    LE_DELETE_ARRAY(combiningClasses);
79}
80
81U_NAMESPACE_END
82