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 
13 U_NAMESPACE_BEGIN
14 
sortMarks(le_int32 * indices,const le_int32 * combiningClasses,le_int32 index,le_int32 limit)15 void 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 
reorderMarks(const LEUnicode * inChars,le_int32 charCount,le_bool rightToLeft,LEUnicode * outChars,LEGlyphStorage & glyphStorage)34 void 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 
81 U_NAMESPACE_END
82