1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * HangulLayoutEngine.cpp: OpenType processing for Han fonts. 3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 459d709d503bab6e2b61931737e662dd293b40578ccornelius * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved. 5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LETypes.h" 8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LEScripts.h" 9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LELanguages.h" 10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LayoutEngine.h" 12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "OpenTypeLayoutEngine.h" 13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "HangulLayoutEngine.h" 14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ScriptAndLanguageTags.h" 15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LEGlyphStorage.h" 16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "OpenTypeTables.h" 17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN 19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(HangulOpenTypeLayoutEngine) 21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define FEATURE_MAP(name) {name ## FeatureTag, name ## FeatureMask} 24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define LJMO_FIRST 0x1100 26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define LJMO_LAST 0x1159 27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define LJMO_FILL 0x115F 28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define LJMO_COUNT 19 29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define VJMO_FIRST 0x1161 31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define VJMO_LAST 0x11A2 32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define VJMO_FILL 0x1160 33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define VJMO_COUNT 21 34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define TJMO_FIRST 0x11A7 36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define TJMO_LAST 0x11F9 37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define TJMO_COUNT 28 38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define HSYL_FIRST 0xAC00 40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define HSYL_COUNT 11172 41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define HSYL_LVCNT (VJMO_COUNT * TJMO_COUNT) 42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Character classes 44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruenum 45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru CC_L = 0, 47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru CC_V, 48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru CC_T, 49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru CC_LV, 50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru CC_LVT, 51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru CC_X, 52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru CC_COUNT 53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Action flags 56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define AF_L 1 57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define AF_V 2 58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define AF_T 4 59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Actions 61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define a_N 0 62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define a_L (AF_L) 63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define a_V (AF_V) 64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define a_T (AF_T) 65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define a_VT (AF_V | AF_T) 66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define a_LV (AF_L | AF_V) 67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define a_LVT (AF_L | AF_V | AF_T) 68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querutypedef struct 70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t newState; 72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t actionFlags; 73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} StateTransition; 74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const StateTransition stateTable[][CC_COUNT] = 76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// L V T LV LVT X 78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru { {1, a_L}, {2, a_LV}, {3, a_LVT}, {2, a_LV}, {3, a_LVT}, {4, a_T}}, // 0 - start 79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru { {1, a_L}, {2, a_V}, {3, a_VT}, {2, a_LV}, {3, a_LVT}, {-1, a_V}}, // 1 - L+ 80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru {{-1, a_N}, {2, a_V}, {3, a_T}, {-1, a_N}, {-1, a_N}, {-1, a_N}}, // 2 - L+V+ 81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru {{-1, a_N}, {-1, a_N}, {3, a_T}, {-1, a_N}, {-1, a_N}, {-1, a_N}}, // 3 - L+V+T* 82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru {{-1, a_N}, {-1, a_N}, {-1, a_N}, {-1, a_N}, {-1, a_N}, {4, a_T}} // 4 - X+ 83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ccmpFeatureTag LE_CCMP_FEATURE_TAG 87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ljmoFeatureTag LE_LJMO_FEATURE_TAG 88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define vjmoFeatureTag LE_VJMO_FEATURE_TAG 89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define tjmoFeatureTag LE_TJMO_FEATURE_TAG 90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ccmpFeatureMask 0x80000000UL 92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ljmoFeatureMask 0x40000000UL 93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define vjmoFeatureMask 0x20000000UL 94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define tjmoFeatureMask 0x10000000UL 95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const FeatureMap featureMap[] = 97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru {ccmpFeatureTag, ccmpFeatureMask}, 99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru {ljmoFeatureTag, ljmoFeatureMask}, 100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru {vjmoFeatureTag, vjmoFeatureMask}, 101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru {tjmoFeatureTag, tjmoFeatureMask} 102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const le_int32 featureMapCount = LE_ARRAY_SIZE(featureMap); 105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define nullFeatures 0 107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ljmoFeatures (ccmpFeatureMask | ljmoFeatureMask) 108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define vjmoFeatures (ccmpFeatureMask | vjmoFeatureMask | ljmoFeatureMask | tjmoFeatureMask) 109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define tjmoFeatures (ccmpFeatureMask | tjmoFeatureMask | ljmoFeatureMask | vjmoFeatureMask) 110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic le_int32 compose(LEUnicode lead, LEUnicode vowel, LEUnicode trail, LEUnicode &syllable) 112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 lIndex = lead - LJMO_FIRST; 114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 vIndex = vowel - VJMO_FIRST; 115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 tIndex = trail - TJMO_FIRST; 116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 result = 3; 117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if ((lIndex < 0 || lIndex >= LJMO_COUNT ) || (vIndex < 0 || vIndex >= VJMO_COUNT)) { 119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (tIndex <= 0 || tIndex >= TJMO_COUNT) { 123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tIndex = 0; 124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru result = 2; 125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru syllable = (LEUnicode) ((lIndex * VJMO_COUNT + vIndex) * TJMO_COUNT + tIndex + HSYL_FIRST); 128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return result; 130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic le_int32 decompose(LEUnicode syllable, LEUnicode &lead, LEUnicode &vowel, LEUnicode &trail) 133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 sIndex = syllable - HSYL_FIRST; 135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (sIndex < 0 || sIndex >= HSYL_COUNT) { 137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru lead = LJMO_FIRST + (sIndex / HSYL_LVCNT); 141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru vowel = VJMO_FIRST + (sIndex % HSYL_LVCNT) / TJMO_COUNT; 142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru trail = TJMO_FIRST + (sIndex % TJMO_COUNT); 143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (trail == TJMO_FIRST) { 145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 2; 146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 3; 149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic le_int32 getCharClass(LEUnicode ch, LEUnicode &lead, LEUnicode &vowel, LEUnicode &trail) 152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru lead = LJMO_FILL; 154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru vowel = VJMO_FILL; 155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru trail = TJMO_FIRST; 156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (ch >= LJMO_FIRST && ch <= LJMO_LAST) { 158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru lead = ch; 159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return CC_L; 160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (ch >= VJMO_FIRST && ch <= VJMO_LAST) { 163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru vowel = ch; 164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return CC_V; 165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (ch > TJMO_FIRST && ch <= TJMO_LAST) { 168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru trail = ch; 169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return CC_T; 170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 c = decompose(ch, lead, vowel, trail); 173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (c == 2) { 175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return CC_LV; 176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (c == 3) { 179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return CC_LVT; 180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru trail = ch; 183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return CC_X; 184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruHangulOpenTypeLayoutEngine::HangulOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 /*languageCode*/, 18759d709d503bab6e2b61931737e662dd293b40578ccornelius le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success) 18885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho : OpenTypeLayoutEngine(fontInstance, scriptCode, korLanguageCode, typoFlags, gsubTable, success) 189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fFeatureMap = featureMap; 191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fFeatureMapCount = featureMapCount; 192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fFeatureOrder = TRUE; 193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruHangulOpenTypeLayoutEngine::HangulOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 /*languageCode*/, 19685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho le_int32 typoFlags, LEErrorCode &success) 19785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho : OpenTypeLayoutEngine(fontInstance, scriptCode, korLanguageCode, typoFlags, success) 198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fFeatureMap = featureMap; 200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fFeatureMapCount = featureMapCount; 201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fFeatureOrder = TRUE; 202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruHangulOpenTypeLayoutEngine::~HangulOpenTypeLayoutEngine() 205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // nothing to do 207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querule_int32 HangulOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, 210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success) 211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (LE_FAILURE(success)) { 213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) { 217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru success = LE_ILLEGAL_ARGUMENT_ERROR; 218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 worstCase = count * 3; 222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru outChars = LE_NEW_ARRAY(LEUnicode, worstCase); 224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (outChars == NULL) { 226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru success = LE_MEMORY_ALLOCATION_ERROR; 227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphStorage.allocateGlyphArray(worstCase, rightToLeft, success); 231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphStorage.allocateAuxData(success); 232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (LE_FAILURE(success)) { 234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru LE_DELETE_ARRAY(outChars); 235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 outCharCount = 0; 239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 limit = offset + count; 240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 i = offset; 241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru while (i < limit) { 243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 state = 0; 244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 inStart = i; 245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 outStart = outCharCount; 246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru while( i < limit) { 248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru LEUnicode lead = 0; 249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru LEUnicode vowel = 0; 250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru LEUnicode trail = 0; 251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t chClass = getCharClass(chars[i], lead, vowel, trail); 252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru const StateTransition transition = stateTable[state][chClass]; 253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (chClass == CC_X) { 255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* Any character of type X will be stored as a trail jamo */ 256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if ((transition.actionFlags & AF_T) != 0) { 257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru outChars[outCharCount] = trail; 258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphStorage.setCharIndex(outCharCount, i-offset, success); 259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphStorage.setAuxData(outCharCount++, nullFeatures, success); 260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* Any Hangul will be fully decomposed. Output the decomposed characters. */ 263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if ((transition.actionFlags & AF_L) != 0) { 264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru outChars[outCharCount] = lead; 265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphStorage.setCharIndex(outCharCount, i-offset, success); 266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphStorage.setAuxData(outCharCount++, ljmoFeatures, success); 267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if ((transition.actionFlags & AF_V) != 0) { 270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru outChars[outCharCount] = vowel; 271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphStorage.setCharIndex(outCharCount, i-offset, success); 272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphStorage.setAuxData(outCharCount++, vjmoFeatures, success); 273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if ((transition.actionFlags & AF_T) != 0) { 276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru outChars[outCharCount] = trail; 277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphStorage.setCharIndex(outCharCount, i-offset, success); 278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphStorage.setAuxData(outCharCount++, tjmoFeatures, success); 279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state = transition.newState; 283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* Negative next state means stop. */ 285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (state < 0) { 286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru i += 1; 290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 inLength = i - inStart; 293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 outLength = outCharCount - outStart; 294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* 296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * See if the syllable can be composed into a single character. There are 5 297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * possible cases: 298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Input Decomposed to Compose to 300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * LV L, V LV 301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * LVT L, V, T LVT 302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * L, V L, V LV, DEL 303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * LV, T L, V, T LVT, DEL 304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * L, V, T L, V, T LVT, DEL, DEL 305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if ((inLength >= 1 && inLength <= 3) && (outLength == 2 || outLength == 3)) { 307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru LEUnicode syllable = 0x0000; 308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru LEUnicode lead = outChars[outStart]; 309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru LEUnicode vowel = outChars[outStart + 1]; 310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru LEUnicode trail = outLength == 3? outChars[outStart + 2] : TJMO_FIRST; 311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* 313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * If the composition consumes the whole decomposed syllable, 314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * we can use it. 315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (compose(lead, vowel, trail, syllable) == outLength) { 317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru outCharCount = outStart; 318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru outChars[outCharCount] = syllable; 319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphStorage.setCharIndex(outCharCount, inStart-offset, success); 320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphStorage.setAuxData(outCharCount++, nullFeatures, success); 321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* 323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Replace the rest of the input characters with DEL. 324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for(le_int32 d = inStart + 1; d < i; d += 1) { 326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru outChars[outCharCount] = 0xFFFF; 327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphStorage.setCharIndex(outCharCount, d - offset, success); 328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphStorage.setAuxData(outCharCount++, nullFeatures, success); 329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphStorage.adoptGlyphCount(outCharCount); 335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return outCharCount; 336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END 339