summaryrefslogtreecommitdiff
path: root/Build/source/libs/graphite/engine-2.3.1/src/segment/TestFSM.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/graphite/engine-2.3.1/src/segment/TestFSM.cpp')
-rw-r--r--Build/source/libs/graphite/engine-2.3.1/src/segment/TestFSM.cpp3416
1 files changed, 3416 insertions, 0 deletions
diff --git a/Build/source/libs/graphite/engine-2.3.1/src/segment/TestFSM.cpp b/Build/source/libs/graphite/engine-2.3.1/src/segment/TestFSM.cpp
new file mode 100644
index 00000000000..6dad1dc9dc8
--- /dev/null
+++ b/Build/source/libs/graphite/engine-2.3.1/src/segment/TestFSM.cpp
@@ -0,0 +1,3416 @@
+/*--------------------------------------------------------------------*//*:Ignore this sentence.
+Copyright (C) 1999, 2001 SIL International. All rights reserved.
+
+Distributable under the terms of either the Common Public License or the
+GNU Lesser General Public License, as specified in the LICENSING.txt file.
+
+File: TestFSM.cpp
+Responsibility: Sharon Correll
+Last reviewed: Not yet.
+
+Description:
+ Hard-coded FSMs for test procedures.
+-------------------------------------------------------------------------------*//*:End Ignore*/
+
+//:Ignore
+
+//:>********************************************************************************************
+//:> Include files
+//:>********************************************************************************************
+#include "Main.h"
+
+#ifdef _MSC_VER
+#pragma hdrstop
+#endif
+#undef THIS_FILE
+DEFINE_THIS_FILE
+
+#ifdef OLD_TEST_STUFF
+
+//:>********************************************************************************************
+//:> Forward declarations
+//:>********************************************************************************************
+
+//:>********************************************************************************************
+//:> Local Constants and static variables
+//:>********************************************************************************************
+
+namespace gr
+{
+
+//:>********************************************************************************************
+//:> Methods
+//:>********************************************************************************************
+
+#ifndef _DEBUG
+
+bool GrLineBreakPass::RunTestRules(GrTableManager * ptman, int ruln,
+ GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput)
+{
+ return false;
+}
+
+bool GrSubPass::RunTestRules(GrTableManager * ptman, int ruln,
+ GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput)
+{
+ return false;
+}
+
+bool GrPosPass::RunTestRules(GrTableManager * ptman, int ruln,
+ GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput)
+{
+ return false;
+}
+#endif // !_DEBUG
+
+
+#ifdef _DEBUG
+
+/*----------------------------------------------------------------------------------------------
+ Call the appropriate test function.
+----------------------------------------------------------------------------------------------*/
+
+bool GrLineBreakPass::RunTestRules(GrTableManager * ptman, int ruln,
+ GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput)
+{
+ return false;
+}
+
+bool GrSubPass::RunTestRules(GrTableManager * ptman, int ruln,
+ GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput)
+{
+ if (m_staBehavior == "SimpleFSM")
+ return RunSimpleFSMTest(ptman, ruln, psstrmInput, psstrmOutput);
+ else if (m_staBehavior == "RuleAction")
+ return false;
+ else if (m_staBehavior == "RuleAction2")
+ return false;
+ else if (m_staBehavior == "Assoc")
+ return false;
+ else
+ return false;
+}
+
+bool GrPosPass::RunTestRules(GrTableManager * ptman, int ruln,
+ GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput)
+{
+ return false;
+}
+
+
+/*----------------------------------------------------------------------------------------------
+ A simple FSM.
+
+ Rules:
+ r1. clsCons clsVowel clsDiacrAcute
+ r2. clsCons clsVowelAE clsDiacr
+ r3. clsCons clsVowelI
+ r4. clsCons clsVowelI clsDiacrGrave
+ r5. clsCons clsVowelI clsDiacr
+
+ Machine classes:
+ mcCons: b,c,d / f,g,h / j,k,l,m,n / p,q,r,s,t / v,w,x,y,z
+ mcVae: a 97/ e 101
+ mcVi: i 105
+ mcVou: o 111 / u 117
+ mcDa: acute '/' 47
+ mcDg: grave '\' 92
+ mcDct: other diacritics-circumflex '^' 94 / tilde '~' 126
+
+
+ FSM: (T=transition, F=final, A=accepting, NA=non-accepting)
+
+ | mcCons mcVae mcVi mcVou mcDa mcDg mcDct
+ ---------------------------------------------------------------------------
+ T NA s0 | s1
+ | - - - - - - -
+ T NA s1 | s2 s4 s3
+ | - - - - - - -
+ T NA s2 | s5 s6 s6
+ | - - - - - - -
+ T NA s3 | s10
+ | - - - - - - -
+ T A s4 | s7 s8 s9
+ | - - - - - - -
+ F A s5 |
+ | - - - - - - -
+ F A s6 |
+ | - - - - - - -
+ F A s7 |
+ | - - - - - - -
+ F A s8 |
+ | - - - - - - -
+ F A s9 |
+ | - - - - - - -
+ F A s10 |
+ | - - - - - - -
+
+ Rules Matched:
+ s4: r3
+ s5: r1, r2
+ s6: r2
+ s7: r1, r5
+ s8: r4, r5
+ s9: r5
+ s10: r1
+
+----------------------------------------------------------------------------------------------*/
+
+void GrSubPass::SetUpSimpleFSMTest()
+{
+ m_nMaxRuleContext = m_nMaxChunk = 3;
+ m_nMaxRuleLoop = 2;
+ m_staBehavior = "SimpleFSM";
+
+ m_pfsm = new GrFSM();
+ Assert(m_pfsm);
+ m_pfsm->SetUpSimpleFSMTest();
+}
+
+void GrFSM::SetUpSimpleFSMTest()
+{
+ // Create machine class ranges.
+ m_cmcr = 14;
+ m_prgmcr = new GrFSMClassRange[14];
+ m_prgmcr[0].m_chwFirst = 47; // forward slash (acute): mcDa
+ m_prgmcr[0].m_chwLast = 47;
+ m_prgmcr[0].m_col = 4;
+
+ m_prgmcr[1].m_chwFirst = 92; // backslash: mcDg
+ m_prgmcr[1].m_chwLast = 92;
+ m_prgmcr[1].m_col = 5;
+
+ m_prgmcr[2].m_chwFirst = 94; // caret: mcDct
+ m_prgmcr[2].m_chwLast = 94;
+ m_prgmcr[2].m_col = 6;
+
+ m_prgmcr[3].m_chwFirst = 97; // a: mcVae
+ m_prgmcr[3].m_chwLast = 97;
+ m_prgmcr[3].m_col = 1;
+
+ m_prgmcr[4].m_chwFirst = 98; // b - d: mcCons
+ m_prgmcr[4].m_chwLast = 100;
+ m_prgmcr[4].m_col = 0;
+
+ m_prgmcr[5].m_chwFirst = 101; // e: mcVae
+ m_prgmcr[5].m_chwLast = 101;
+ m_prgmcr[5].m_col = 1;
+
+ m_prgmcr[6].m_chwFirst = 102; // f - h: mcCons
+ m_prgmcr[6].m_chwLast = 104;
+ m_prgmcr[6].m_col = 0;
+
+ m_prgmcr[7].m_chwFirst = 105; // i: mcVi
+ m_prgmcr[7].m_chwLast = 105;
+ m_prgmcr[7].m_col = 2;
+
+ m_prgmcr[8].m_chwFirst = 106; // j - n: mcCons
+ m_prgmcr[8].m_chwLast = 110;
+ m_prgmcr[8].m_col = 0;
+
+ m_prgmcr[9].m_chwFirst = 111; // o: mcVou
+ m_prgmcr[9].m_chwLast = 111;
+ m_prgmcr[9].m_col = 3;
+
+ m_prgmcr[10].m_chwFirst = 112; // p - t: mcCons
+ m_prgmcr[10].m_chwLast = 116;
+ m_prgmcr[10].m_col = 0;
+
+ m_prgmcr[11].m_chwFirst = 117; // u: mcVou
+ m_prgmcr[11].m_chwLast = 117;
+ m_prgmcr[11].m_col = 3;
+
+ m_prgmcr[12].m_chwFirst = 118; // v - z: mcCons
+ m_prgmcr[12].m_chwLast = 122;
+ m_prgmcr[12].m_col = 0;
+
+ m_prgmcr[13].m_chwFirst = 126; // tilde: mcDct
+ m_prgmcr[13].m_chwLast = 126;
+ m_prgmcr[13].m_col = 6;
+
+ m_dimcrInit = 8; // (max power of 2 <= m_cmcr);
+ m_cLoop = 3; // log2(max power of 2 <= m_cmcr);
+ m_imcrStart = m_cmcr - m_dimcrInit;
+
+
+ m_crow = 11;
+ m_crowNonAcpt = 4;
+ m_crowFinal = 6;
+ m_rowFinalMin = m_crow - m_crowFinal;
+ m_ccol = 7;
+
+ // Set up transition table.
+ m_prgrowTransitions = new short[35]; // 35 = (m_crow-m_crowFinal) * m_ccol
+ short * psn = m_prgrowTransitions;
+ *psn++ = 1; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 2; *psn++ = 4; *psn++ = 3; *psn++ = 0; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 5; *psn++ = 6; *psn++ = 6;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ =10; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 7; *psn++ = 8; *psn++ = 9;
+
+ // Set up matched-rules tables.
+ m_prgrulnMatched = new data16[10]; // 10 = sum of rules matched for each accepting state
+ m_prgirulnMin = new data16[7+1]; // 7 = m_crow - m_crowNonAcpt
+
+ m_prgirulnMin[0] = 0; // s4: r3
+ m_prgrulnMatched[0] = 3;
+
+ m_prgirulnMin[1] = 1; // s5: r1, r2
+ m_prgrulnMatched[1] = 1;
+ m_prgrulnMatched[2] = 2;
+
+ m_prgirulnMin[2] = 3; // s6: r2
+ m_prgrulnMatched[3] = 2;
+
+ m_prgirulnMin[3] = 4; // s7: r1, r5
+ m_prgrulnMatched[4] = 1;
+ m_prgrulnMatched[5] = 5;
+
+ m_prgirulnMin[4] = 6; // s8: r4, r5
+ m_prgrulnMatched[6] = 4;
+ m_prgrulnMatched[7] = 5;
+
+ m_prgirulnMin[5] = 8; // s9: r5
+ m_prgrulnMatched[8] = 5;
+
+ m_prgirulnMin[6] = 9; // s10: r1
+ m_prgrulnMatched[9] = 1;
+
+ m_prgirulnMin[7] = 10;
+}
+
+
+/*----------------------------------------------------------------------------------------------
+ The "rule" does something silly: just inserts *'s--the number equals the number of the
+ rule.
+----------------------------------------------------------------------------------------------*/
+bool GrSubPass::RunSimpleFSMTest(GrTableManager * ptman, int ruln, GrSlotStream * psstrmInput,
+ GrSlotStream * psstrmOutput)
+{
+ int cslotMatched = (ruln == 3)? 2: 3;
+
+ GrSlotState * pslot0 = psstrmInput->Peek(0);
+
+ for (int islot = 0; islot < cslotMatched; islot++)
+ psstrmOutput->CopyOneSlotFrom(psstrmInput);
+
+ for (islot = 0; islot < ruln; islot++)
+ {
+ GrSlotState * pslot;
+ ptman->NewSlot('*', pslot0, NULL, m_ipass, &pslot);
+ pslot->Associate(pslot0);
+ psstrmOutput->NextPut(pslot);
+ }
+
+ return true;
+}
+
+
+/*----------------------------------------------------------------------------------------------
+ A simple set of rules with actions.
+
+ Rules:
+ r0. clsDigit gSlash clsDigit _ > @3 _ @1 gTilde; // tilde = 126
+ r1. _ clsDigit gBackSlash clsDigit > gDollar @4 _ @2; // dollar sign = 36
+
+ Machine classes:
+ mcDigit: '0' - '9' 48 - 57
+ mcSlash: '/' 47
+ mcBSlash: '\' 92
+
+
+ FSM: (T=transition, F=final, A=accepting, NA=non-accepting)
+
+ | clsDig mcSlash mcBSlash
+ ------------------------------------------------------
+ T NA s0 | s1
+ | - - -
+ T NA s1 | s2 s3
+ | - - -
+ T NA s2 | s4
+ | - - -
+ T NA s3 | s5
+ | - - -
+ F A s4 |
+ | - - -
+ F A s5 |
+ | - - -
+
+ Rules Matched:
+ s4: r0
+ s5: r1
+
+----------------------------------------------------------------------------------------------*/
+void GrEngine::SetUpRuleActionTest()
+{
+ if (m_pctbl)
+ delete m_pctbl;
+
+ m_pctbl = new GrClassTable();
+ m_pctbl->SetUpRuleActionTest();
+}
+
+void GrClassTable::SetUpRuleActionTest()
+{
+ m_ccls = 2; // number of classes
+ m_cclsLinear = 2; // number of classes in linear format
+
+ m_prgchwBIGGlyphList = new data16[100];
+
+ m_prgichwOffsets = new data16[2+1];
+
+ gid16 * pchw = m_prgchwBIGGlyphList;
+
+ // Output class 0: tilde
+ m_prgichwOffsets[0] = 0;
+ *pchw++ = msbf(data16(126)); // '~'
+
+ // Output class 1: dollar
+ m_prgichwOffsets[1] = 1;
+ *pchw++ = msbf(data16(36)); // '$'
+
+ m_prgichwOffsets[2] = 2;
+}
+
+void GrSubPass::SetUpRuleActionTest()
+{
+ m_nMaxRuleContext = m_nMaxChunk = 3;
+ m_nMaxRuleLoop = 2;
+ m_staBehavior = "RuleAction";
+
+ m_pfsm = new GrFSM();
+ Assert(m_pfsm);
+ m_pfsm->SetUpRuleActionTest();
+
+ m_crul = 2;
+
+ // Set up constraint code--succeed trivially.
+ m_prgbConstraintBlock = new byte[3];
+ byte * pb = m_prgbConstraintBlock;
+ *pb++ = kopPushByte; *pb++ = 1; // Push true
+ *pb++ = kopPopRet; // PopAndRet
+
+ m_prgibConstraintStart = new data16[m_crul];
+ m_prgibConstraintStart[0] = 0;
+ m_prgibConstraintStart[1] = 0;
+
+ // Set up rule action code.
+ m_prgbActionBlock = new byte[30];
+ pb = m_prgbActionBlock;
+
+ // Rule 1: clsDigit gSlash clsDigit _ > @3 _ @1 gTilde;
+
+ *pb++ = kopPutCopy; *pb++ = 2; // PutCopy 2
+ *pb++ = kopNext; // Next
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopPutCopy; *pb++ = -2; // PutCopy -2
+ *pb++ = kopNext; // Next
+ *pb++ = kopInsert; // Insert
+ *pb++ = kopPutGlyph8bitObs; *pb++ = 0; // PutGlyph 0 ('~' = 126)
+ *pb++ = kopNext; // Next
+ *pb++ = kopPushByte; *pb++ = 0; // Push 0
+ *pb++ = kopPopRet; // PopAndRet
+
+ // Rule 2: _ clsDigit gBackSlash clsDigit > gDollar @4 _ @2;
+
+ *pb++ = kopInsert; // Insert
+ *pb++ = kopPutGlyph8bitObs; *pb++ = 1; // PutGlyph 1 ('$' = 36)
+ *pb++ = kopNext; // Next
+ *pb++ = kopPutCopy; *pb++ = 2; // PutCopy 2
+ *pb++ = kopNext; // Next
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopPutCopy; *pb++ = -2; // PutCopy -2
+ *pb++ = kopNext; // Next
+ *pb++ = kopPushByte; *pb++ = 0; // Push 0
+ *pb++ = kopPopRet; // PopAndRet
+
+ m_prgibActionStart = new data16[m_crul];
+ m_prgibActionStart[0] = 0;
+ m_prgibActionStart[1] = 15;
+}
+
+void GrFSM::SetUpRuleActionTest()
+{
+ // Create machine class ranges.
+ m_cmcr = 3;
+ m_prgmcr = new GrFSMClassRange[3];
+ m_prgmcr[0].m_chwFirst = 47; // forward slash: mcSlash
+ m_prgmcr[0].m_chwLast = 47;
+ m_prgmcr[0].m_col = 1;
+
+ m_prgmcr[1].m_chwFirst = 48; // 0 - 9: mcDigit
+ m_prgmcr[1].m_chwLast = 57;
+ m_prgmcr[1].m_col = 0;
+
+ m_prgmcr[2].m_chwFirst = 92; // backslash
+ m_prgmcr[2].m_chwLast = 92;
+ m_prgmcr[2].m_col = 2;
+
+
+ m_dimcrInit = 2; // (max power of 2 <= m_cmcr);
+ m_cLoop = 1; // log2(max power of 2 <= m_cmcr);
+ m_imcrStart = m_cmcr - m_dimcrInit;
+
+
+ m_crow = 6;
+ m_crowNonAcpt = 4;
+ m_crowFinal = 2;
+ m_rowFinalMin = m_crow - m_crowFinal;
+ m_ccol = 3;
+
+ // Set up transition table.
+ m_prgrowTransitions = new short[12]; // 12 = (m_crow-m_crowFinal) * m_ccol
+ short * psn = m_prgrowTransitions;
+ *psn++ = 1; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 2; *psn++ = 3;
+ *psn++ = 4; *psn++ = 0; *psn++ = 0;
+ *psn++ = 5; *psn++ = 0; *psn++ = 0;
+
+ // Set up matched-rules tables.
+ m_prgrulnMatched = new data16[2]; // 2 = sum of rules matched for each accepting state
+ m_prgirulnMin = new data16[2+1]; // 2 = m_crow - m_crowNonAcpt
+
+ m_prgirulnMin[0] = 0; // s4: r0
+ m_prgrulnMatched[0] = 0;
+
+ m_prgirulnMin[1] = 1; // s5: r1
+ m_prgrulnMatched[1] = 1;
+
+ m_prgirulnMin[2] = 2;
+}
+
+/*----------------------------------------------------------------------------------------------
+ A more complicated set of rules with actions.
+
+ PASS 1:
+ r0. clsDigit > @1 {dir = DIR_RIGHT} / ^ _ {dir == DIR_LEFT};
+ r1. clsSpecial > @2 {dir = DIR_ARABNUMBER} / clsDigit {dir != DIR_LEFT} ^ _;
+ r2. clsSpecial > @2 {dir = @1.dir} / clsSpecial ^ _;
+
+ Pass 1 machine classes:
+ mcDigit: '0' - '9' 48 - 57
+ mcSpecial: '-', '_', '=', '~' 45, 95, 61, 126
+
+ Pass 1 FSM: (T=transition, F=final, A=accepting, NA=non-accepting)
+
+ | mcDigit mcSpecial
+ ------------------------------------------
+ T NA s0 | s2 s1
+ | - _
+ T NA s1 | s4
+ | - -
+ T A s2 | s3
+ | - -
+ F A s3 |
+ | - -
+ F A s4 |
+ | - -
+
+ Rules Matched:
+ s2: r0
+ s3: r1
+ s4: r2
+
+ PASS 2:
+ r0. clsVowel gCaret > clsCirumVowel _;
+ r1. clsVowel gSlash > _ clsAcuteVowel$1;
+
+ Pass 2 machine classes:
+ mcVowel
+ mcCaret: '^' 94
+ mcSlash: '/' 47
+
+
+ Pass 2 FSM:
+ | mcVowel mcCaret mcSlash
+ -----------------------------------------------------
+ T NA s0 | s1
+ | - _
+ T NA s1 | s2 s3
+ | - -
+ F A s2 |
+ | - -
+ F A s3 |
+ | - -
+
+ Rules matched:
+ s2: r0
+ s3: r1
+
+
+ PASS 3:
+ r0. clsLeft > clsRight {dir = @1.dir} / _ clsDir {dir==DIR_RIGHT};
+ r1. clsRight > clsLeft {dir = @1.dir} / clsDir {dir==DIR_RIGHT} _;
+
+ Pass 3 machine classes:
+ mcDir: (clsDigit, clsSpecial)
+ mcLeft: '(', '[', '{' 40, 91, 123
+ mcRight: ')', ']', '}' 41, 93, 125
+
+ Pass 3 FSM:
+ | mcDir mcLeft mcRight
+ -----------------------------------------------------
+ T NA s0 | s2 s1
+ | - _
+ T NA s1 | s3
+ | - -
+ T NA s2 | s4
+ | - -
+ F A s3 |
+ | - -
+ F A s4 |
+ | - -
+
+ Rules matched:
+ s3: r0
+ s4: r1
+
+
+----------------------------------------------------------------------------------------------*/
+void GrEngine::SetUpRuleAction2Test()
+{
+ if (m_pctbl)
+ delete m_pctbl;
+
+ m_pctbl = new GrClassTable();
+ m_pctbl->SetUpRuleAction2Test();
+}
+
+void GrClassTable::SetUpRuleAction2Test()
+{
+ m_ccls = 7; // number of classes
+ m_cclsLinear = 4; // number of classes in linear format
+
+ m_prgchwBIGGlyphList = new data16[70];
+
+ m_prgichwOffsets = new data16[7+1];
+
+ data16 * pchw = m_prgchwBIGGlyphList;
+
+ // Output class 0: clsCirumVowel
+ m_prgichwOffsets[0] = 0;
+ *pchw++ = msbf(data16(226)); // a
+ *pchw++ = msbf(data16(234)); // e
+ *pchw++ = msbf(data16(238)); // i
+ *pchw++ = msbf(data16(244)); // o
+ *pchw++ = msbf(data16(251)); // u
+ *pchw++ = msbf(data16(194)); // A
+ *pchw++ = msbf(data16(202)); // E
+ *pchw++ = msbf(data16(206)); // I
+ *pchw++ = msbf(data16(212)); // O
+ *pchw++ = msbf(data16(219)); // U
+
+ // Output class 1: clsAcuteVowel
+ m_prgichwOffsets[1] = 10;
+ *pchw++ = msbf(data16(225)); // a
+ *pchw++ = msbf(data16(233)); // e
+ *pchw++ = msbf(data16(237)); // i
+ *pchw++ = msbf(data16(243)); // o
+ *pchw++ = msbf(data16(250)); // u
+ *pchw++ = msbf(data16(193)); // A
+ *pchw++ = msbf(data16(201)); // E
+ *pchw++ = msbf(data16(205)); // I
+ *pchw++ = msbf(data16(211)); // O
+ *pchw++ = msbf(data16(218)); // U
+
+ // Output class 2: clsLeft
+ m_prgichwOffsets[2] = 10 + 10;
+ *pchw++ = msbf(data16(40)); // (
+ *pchw++ = msbf(data16(91)); // [
+ *pchw++ = msbf(data16(123)); // {
+
+ // Output class 3: clsRight
+ m_prgichwOffsets[3] = 20 + 3;
+ *pchw++ = msbf(data16(41)); // )
+ *pchw++ = msbf(data16(93)); // ]
+ *pchw++ = msbf(data16(125)); // }
+
+ // Input class 4: clsVowel
+ m_prgichwOffsets[4] = 23 + 3; // 26
+ *pchw++ = msbf(data16(10));
+ *pchw++ = msbf(data16(8)); *pchw++ = msbf(data16(3)); *pchw++ = msbf(data16(10-8));
+ *pchw++ = msbf(data16(65)); *pchw++ = msbf(data16(5)); // A
+ *pchw++ = msbf(data16(69)); *pchw++ = msbf(data16(6)); // E
+ *pchw++ = msbf(data16(73)); *pchw++ = msbf(data16(7)); // I
+ *pchw++ = msbf(data16(79)); *pchw++ = msbf(data16(8)); // O
+ *pchw++ = msbf(data16(85)); *pchw++ = msbf(data16(9)); // U
+ *pchw++ = msbf(data16(97)); *pchw++ = msbf(data16(0)); // a
+ *pchw++ = msbf(data16(101)); *pchw++ = msbf(data16(1)); // e
+ *pchw++ = msbf(data16(105)); *pchw++ = msbf(data16(2)); // i
+ *pchw++ = msbf(data16(111)); *pchw++ = msbf(data16(3)); // o
+ *pchw++ = msbf(data16(117)); *pchw++ = msbf(data16(4)); // u
+
+ // Input class 5: clsLeft
+ m_prgichwOffsets[5] = 26 + 4 + 10*2; // 50
+ *pchw++ = msbf(data16(3));
+ *pchw++ = msbf(data16(2)); *pchw++ = msbf(data16(1)); *pchw++ = msbf(data16(3-2));
+ *pchw++ = msbf(data16(40)); *pchw++ = msbf(data16(0)); // (
+ *pchw++ = msbf(data16(91)); *pchw++ = msbf(data16(1)); // [
+ *pchw++ = msbf(data16(123)); *pchw++ = msbf(data16(2)); // {
+
+ // Input class 6: clsRight
+ m_prgichwOffsets[6] = 50 + 4 + 3*2; // 60
+ *pchw++ = msbf(data16(3));
+ *pchw++ = msbf(data16(2)); *pchw++ = msbf(data16(1)); *pchw++ = msbf(data16(3-2));
+ *pchw++ = msbf(data16(41)); *pchw++ = msbf(data16(0)); // )
+ *pchw++ = msbf(data16(93)); *pchw++ = msbf(data16(1)); // ]
+ *pchw++ = msbf(data16(125)); *pchw++ = msbf(data16(2)); // }
+
+ m_prgichwOffsets[7] = 60 + 4 + 3*2; // 70
+}
+
+void GrSubPass::SetUpRuleAction2Test()
+{
+ if (m_ipass == 1)
+ {
+ m_nMaxRuleContext = m_nMaxChunk = 2;
+ m_nMaxRuleLoop = 5;
+ m_staBehavior = "RuleAction2";
+
+ m_pfsm = new GrFSM();
+ Assert(m_pfsm);
+ m_pfsm->SetUpRuleAction2Test(m_ipass);
+
+ m_crul = 3;
+
+ // Set up constraint code.
+ m_prgbConstraintBlock = new byte[1 + 10 + 10];
+ byte * pb = m_prgbConstraintBlock;
+ *pb++ = kopRetTrue; // RetTrue
+
+ *pb++ = kopCntxtItem; *pb++ = 0; // ContextItem 0
+ *pb++ = kopPushSlotAttr; *pb++= kslatDir; // PushSlotAttr dir 0
+ *pb++ = 0;
+ *pb++ = kopPushByte; *pb++ = kdircL; // Push DIR_LEFT
+ *pb++ = kopEqual; // Equal
+ *pb++ = kopOr; // Or
+ *pb++ = kopPopRet; // PopAndRet
+
+ *pb++ = kopCntxtItem; *pb++ = 0; // ContextItem 0
+ *pb++ = kopPushSlotAttr; *pb++= kslatDir; // PushSlotAttr dir 0
+ *pb++ = 0;
+ *pb++ = kopPushByte; *pb++ = kdircL; // Push DIR_LEFT
+ *pb++ = kopNotEq; // NotEqual
+ *pb++ = kopOr; // Or
+ *pb++ = kopPopRet; // PopAndRet
+
+ m_prgibConstraintStart = new data16[m_crul];
+ m_prgibConstraintStart[0] = 1;
+ m_prgibConstraintStart[1] = 11;
+ m_prgibConstraintStart[2] = 0;
+
+ // Set up rule action code.
+ m_prgbActionBlock = new byte[10 + 11 + 12];
+ pb = m_prgbActionBlock;
+
+ // Rule 0: clsDigit > @1 {dir = DIR_RIGHT} / ^ _ {dir == DIR_LEFT};
+
+ *pb++ = kopPutCopy; *pb++ = 0; // PutCopy 0
+ *pb++ = kopPushByte; *pb++ = kdircR; // PushByte DIR_RIGHT
+ *pb++ = kopAttrSet; *pb++ = kslatDir; // AttrSet dir
+ *pb++ = kopNext; // Next
+ *pb++ = kopPushByte; *pb++ = -1; // Push -1
+ *pb++ = kopPopRet; // PopAndRet
+
+ // Rule 1: clsSpecial > @2 {dir = DIR_ARABNUMBER} / clsDigit {dir != DIR_LEFT} ^ _;
+
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopPutCopy; *pb++ = 0; // PutCopy 0
+ *pb++ = kopPushByte; *pb++ = kdircArabNum; // Push DIR_ARABNUMBER
+ *pb++ = kopAttrSet; *pb++ = kslatDir; // AttrSet dir
+ *pb++ = kopNext; // Next
+ *pb++ = kopPushByte; *pb++ = -1; // Push -1
+ *pb++ = kopPopRet; // PopAndRet
+
+ // Rule 2: clsSpecial > @2 {dir = @1.dir} / clsSpecial ^ _;
+
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopPutCopy; *pb++ = 0; // PutCopy 0
+ *pb++ = kopPushSlotAttr;*pb++ = kslatDir; // PushSlotAttr dir -1
+ *pb++ = -1;
+ *pb++ = kopAttrSet; *pb++ = kslatDir; // AttrSet dir
+ *pb++ = kopNext; // Next
+ *pb++ = kopPushByte; *pb++ = -1; // Push -1
+ *pb++ = kopPopRet; // PopAndRet
+
+ m_prgibActionStart = new data16[m_crul];
+ m_prgibActionStart[0] = 0;
+ m_prgibActionStart[1] = 10;
+ m_prgibActionStart[2] = 10 + 11;
+ }
+ else if (m_ipass == 2)
+ {
+ m_nMaxRuleContext = m_nMaxChunk = 2;
+ m_nMaxRuleLoop = 3;
+ m_staBehavior = "RuleAction2";
+
+ m_pfsm = new GrFSM();
+ Assert(m_pfsm);
+ m_pfsm->SetUpRuleAction2Test(m_ipass);
+
+ m_crul = 2;
+
+ // Set up constraint code--succeed trivially.
+ m_prgbConstraintBlock = new byte[1];
+ byte * pb = m_prgbConstraintBlock;
+ *pb++ = kopRetTrue; // RetTrue
+
+ m_prgibConstraintStart = new data16[m_crul];
+ m_prgibConstraintStart[0] = 0;
+ m_prgibConstraintStart[1] = 0;
+
+ // Set up rule action code.
+ m_prgbActionBlock = new byte[16];
+ pb = m_prgbActionBlock;
+
+ // Rule 0: clsVowel gCaret > clsCirumVowel _;
+
+ *pb++ = kopPutSubs8bitObs; *pb++ = 0; // PutSubs 0 clsVowel clsCircumVowel
+ *pb++ = 4; *pb++ = 0;
+ *pb++ = kopNext; // Next
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 1: clsVowel gSlash > _ clsAcuteVowel$1;
+
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopPutSubs8bitObs; *pb++ = -1; // PutSubs -1 clsVowel clsAcuteVowel
+ *pb++ = 4; *pb++ = 1;
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ m_prgibActionStart = new data16[m_crul];
+ m_prgibActionStart[0] = 0;
+ m_prgibActionStart[1] = 8;
+ }
+ else if (m_ipass == 3)
+ {
+ m_nMaxRuleContext = m_nMaxChunk = 2;
+ m_nMaxRuleLoop = 3;
+ m_staBehavior = "RuleAction2";
+
+ m_pfsm = new GrFSM();
+ Assert(m_pfsm);
+ m_pfsm->SetUpRuleAction2Test(m_ipass);
+
+ m_crul = 2;
+
+ // Set up constraint code.
+ m_prgbConstraintBlock = new byte[1 + 10 + 10];
+ byte * pb = m_prgbConstraintBlock;
+ *pb++ = kopRetTrue; // RetTrue
+
+ *pb++ = kopCntxtItem; *pb++ = 1; // ContextItem 1
+ *pb++ = kopPushSlotAttr;*pb++ = kslatDir; // PushSlotAttr dir 0
+ *pb++ = 0;
+ *pb++ = kopPushByte; *pb++ = kdircR; // Push DIR_RIGHT
+ *pb++ = kopEqual; // Equal
+ *pb++ = kopOr; // Or
+ *pb++ = kopPopRet; // PopAndRet
+
+ *pb++ = kopCntxtItem; *pb++ = 0; // ContextItem 0
+ *pb++ = kopPushSlotAttr;*pb++ = kslatDir; // PushSlotAttr dir 0
+ *pb++ = 0;
+ *pb++ = kopPushByte; *pb++ = kdircR; // Push DIR_RIGHT
+ *pb++ = kopEqual; // Equal
+ *pb++ = kopOr; // Or
+ *pb++ = kopPopRet; // PopAndRet
+
+ m_prgibConstraintStart = new data16[m_crul];
+ m_prgibConstraintStart[0] = 1;
+ m_prgibConstraintStart[1] = 1 + 10;
+
+ // Set up rule action code.
+ m_prgbActionBlock = new byte[23];
+ pb = m_prgbActionBlock;
+
+ // Rule 0: clsLeft > clsRight {dir = @1.dir} / _ clsDir {dir == DIR_RIGHT};
+
+ *pb++ = kopPutSubs8bitObs; *pb++ = 0; // PutSubs 0 clsLeft clsRight
+ *pb++ = 5; *pb++ = 3;
+ *pb++ = kopPushSlotAttr;*pb++ = kslatDir; // PushSlotAttr dir 1
+ *pb++ = 1;
+ *pb++ = kopAttrSet; *pb++ = kslatDir; // AttrSet dir
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 1: clsRight > clsLeft {dir = @1.dir} / clsDir {dir == DIR_RIGHT} _;
+
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopPutSubs8bitObs; *pb++ = 0; // PutSubs 0 clsRight clsLeft
+ *pb++ = 6; *pb++ = 2;
+ *pb++ = kopPushSlotAttr;*pb++ = kslatDir; // PushSlotAttr dir -1
+ *pb++ = -1;
+ *pb++ = kopAttrSet; *pb++ = kslatDir; // AttrSet dir
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ m_prgibActionStart = new data16[m_crul];
+ m_prgibActionStart[0] = 0;
+ m_prgibActionStart[1] = 11;
+ }
+}
+
+
+void GrFSM::SetUpRuleAction2Test(int ipass)
+{
+ if (ipass == 1)
+ {
+ // Create machine class ranges.
+ m_cmcr = 5;
+ m_prgmcr = new GrFSMClassRange[5];
+ m_prgmcr[0].m_chwFirst = 45; // hyphen
+ m_prgmcr[0].m_chwLast = 45;
+ m_prgmcr[0].m_col = 1;
+
+ m_prgmcr[1].m_chwFirst = 48; // 0 - 9: mcDigit
+ m_prgmcr[1].m_chwLast = 57;
+ m_prgmcr[1].m_col = 0;
+
+ m_prgmcr[2].m_chwFirst = 61; // equals sign
+ m_prgmcr[2].m_chwLast = 61;
+ m_prgmcr[2].m_col = 1;
+
+ m_prgmcr[3].m_chwFirst = 95; // underscore
+ m_prgmcr[3].m_chwLast = 95;
+ m_prgmcr[3].m_col = 1;
+
+ m_prgmcr[4].m_chwFirst = 126; // tilde
+ m_prgmcr[4].m_chwLast = 126;
+ m_prgmcr[4].m_col = 1;
+
+ m_dimcrInit = 4; // (max power of 2 <= m_cmcr);
+ m_cLoop = 2; // log2(max power of 2 <= m_cmcr);
+ m_imcrStart = m_cmcr - m_dimcrInit;
+
+
+ m_crow = 5;
+ m_crowNonAcpt = 2;
+ m_crowFinal = 2;
+ m_rowFinalMin = m_crow - m_crowFinal;
+ m_ccol = 2;
+
+ // Set up transition table.
+ m_prgrowTransitions = new short[6]; // 6 = (m_crow-m_crowFinal) * m_ccol
+ short * psn = m_prgrowTransitions;
+ *psn++ = 2; *psn++ = 1;
+ *psn++ = 0; *psn++ = 4;
+ *psn++ = 0; *psn++ = 3;
+
+ // Set up matched-rules tables.
+ m_prgrulnMatched = new data16[3]; // 3 = sum of rules matched for each accepting state
+ m_prgirulnMin = new data16[3+1]; // 3 = m_crow - m_crowNonAcpt
+
+ m_prgirulnMin[0] = 0; // s2: r0
+ m_prgrulnMatched[0] = 0;
+
+ m_prgirulnMin[1] = 1; // s3: r1
+ m_prgrulnMatched[1] = 1;
+
+ m_prgirulnMin[2] = 2; // s3: r2
+ m_prgrulnMatched[2] = 2;
+
+ m_prgirulnMin[3] = 3;
+ }
+ else if (ipass == 2)
+ {
+ // Create machine class ranges.
+ m_cmcr = 12;
+ m_prgmcr = new GrFSMClassRange[12];
+ m_prgmcr[0].m_chwFirst = 47; // slash
+ m_prgmcr[0].m_chwLast = 47;
+ m_prgmcr[0].m_col = 2;
+
+ m_prgmcr[1].m_chwFirst = 65; // A
+ m_prgmcr[1].m_chwLast = 65;
+ m_prgmcr[1].m_col = 0;
+
+ m_prgmcr[2].m_chwFirst = 69; // E
+ m_prgmcr[2].m_chwLast = 69;
+ m_prgmcr[2].m_col = 0;
+
+ m_prgmcr[3].m_chwFirst = 73; // I
+ m_prgmcr[3].m_chwLast = 73;
+ m_prgmcr[3].m_col = 0;
+
+ m_prgmcr[4].m_chwFirst = 79; // O
+ m_prgmcr[4].m_chwLast = 79;
+ m_prgmcr[4].m_col = 0;
+
+ m_prgmcr[5].m_chwFirst = 85; // U
+ m_prgmcr[5].m_chwLast = 85;
+ m_prgmcr[5].m_col = 0;
+
+ m_prgmcr[6].m_chwFirst = 94; // caret
+ m_prgmcr[6].m_chwLast = 94;
+ m_prgmcr[6].m_col = 1;
+
+ m_prgmcr[7].m_chwFirst = 97; // a
+ m_prgmcr[7].m_chwLast = 97;
+ m_prgmcr[7].m_col = 0;
+
+ m_prgmcr[8].m_chwFirst = 101; // e
+ m_prgmcr[8].m_chwLast = 101;
+ m_prgmcr[8].m_col = 0;
+
+ m_prgmcr[9].m_chwFirst = 105; // i
+ m_prgmcr[9].m_chwLast = 105;
+ m_prgmcr[9].m_col = 0;
+
+ m_prgmcr[10].m_chwFirst = 111; // o
+ m_prgmcr[10].m_chwLast = 111;
+ m_prgmcr[10].m_col = 0;
+
+ m_prgmcr[11].m_chwFirst = 117; // u
+ m_prgmcr[11].m_chwLast = 117;
+ m_prgmcr[11].m_col = 0;
+
+ m_dimcrInit = 8; // (max power of 2 <= m_cmcr);
+ m_cLoop = 3; // log2(max power of 2 <= m_cmcr);
+ m_imcrStart = m_cmcr - m_dimcrInit;
+
+
+ m_crow = 4;
+ m_crowNonAcpt = 2;
+ m_crowFinal = 2;
+ m_rowFinalMin = m_crow - m_crowFinal;
+ m_ccol = 3;
+
+ // Set up transition table.
+ m_prgrowTransitions = new short[6]; // 6 = (m_crow-m_crowFinal) * m_ccol
+ short * psn = m_prgrowTransitions;
+ *psn++ = 1; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 2; *psn++ = 3;
+
+ // Set up matched-rules tables.
+ m_prgrulnMatched = new data16[2]; // 2 = sum of rules matched for each accepting state
+ m_prgirulnMin = new data16[2+1]; // 2 = m_crow - m_crowNonAcpt
+
+ m_prgirulnMin[0] = 0; // s1: r0
+ m_prgrulnMatched[0] = 0;
+
+ m_prgirulnMin[1] = 1; // s2: r1
+ m_prgrulnMatched[1] = 1;
+
+ m_prgirulnMin[2] = 2;
+ }
+ else if (ipass == 3)
+ {
+ // Create machine class ranges.
+ m_cmcr = 11;
+ m_prgmcr = new GrFSMClassRange[11];
+ m_prgmcr[0].m_chwFirst = 40; // (
+ m_prgmcr[0].m_chwLast = 40;
+ m_prgmcr[0].m_col = 1;
+
+ m_prgmcr[1].m_chwFirst = 41; // )
+ m_prgmcr[1].m_chwLast = 41;
+ m_prgmcr[1].m_col = 2;
+
+ m_prgmcr[2].m_chwFirst = 45; // hyphen
+ m_prgmcr[2].m_chwLast = 45;
+ m_prgmcr[2].m_col = 0;
+
+ m_prgmcr[3].m_chwFirst = 48; // 0 - 9: mcDigit
+ m_prgmcr[3].m_chwLast = 57;
+ m_prgmcr[3].m_col = 0;
+
+ m_prgmcr[4].m_chwFirst = 61; // =
+ m_prgmcr[4].m_chwLast = 61;
+ m_prgmcr[4].m_col = 0;
+
+ m_prgmcr[5].m_chwFirst = 91; // [
+ m_prgmcr[5].m_chwLast = 91;
+ m_prgmcr[5].m_col = 1;
+
+ m_prgmcr[6].m_chwFirst = 93; // ]
+ m_prgmcr[6].m_chwLast = 93;
+ m_prgmcr[6].m_col = 2;
+
+ m_prgmcr[7].m_chwFirst = 95; // underscore
+ m_prgmcr[7].m_chwLast = 95;
+ m_prgmcr[7].m_col = 0;
+
+ m_prgmcr[8].m_chwFirst = 123; // {
+ m_prgmcr[8].m_chwLast = 123;
+ m_prgmcr[8].m_col = 1;
+
+ m_prgmcr[9].m_chwFirst = 125; // }
+ m_prgmcr[9].m_chwLast = 125;
+ m_prgmcr[9].m_col = 2;
+
+ m_prgmcr[10].m_chwFirst = 126; // tilde
+ m_prgmcr[10].m_chwLast = 126;
+ m_prgmcr[10].m_col = 0;
+
+ m_dimcrInit = 8; // (max power of 2 <= m_cmcr);
+ m_cLoop = 3; // log2(max power of 2 <= m_cmcr);
+ m_imcrStart = m_cmcr - m_dimcrInit;
+
+
+ m_crow = 5;
+ m_crowNonAcpt = 3;
+ m_crowFinal = 2;
+ m_rowFinalMin = m_crow - m_crowFinal;
+ m_ccol = 3;
+
+ // Set up transition table.
+ m_prgrowTransitions = new short[9]; // 9 = (m_crow-m_crowFinal) * m_ccol
+ short * psn = m_prgrowTransitions;
+ *psn++ = 2; *psn++ = 1; *psn++ = 0;
+ *psn++ = 3; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ = 4;
+
+ // Set up matched-rules tables.
+ m_prgrulnMatched = new data16[2]; // 2 = sum of rules matched for each accepting state
+ m_prgirulnMin = new data16[2+1]; // 2 = m_crow - m_crowNonAcpt
+
+ m_prgirulnMin[0] = 0; // s3: r0
+ m_prgrulnMatched[0] = 0;
+
+ m_prgirulnMin[1] = 1; // s4: r1
+ m_prgrulnMatched[1] = 1;
+
+ m_prgirulnMin[2] = 2;
+ }
+}
+
+
+/*----------------------------------------------------------------------------------------------
+ Tests of various kinds of assocations.
+
+ PASS 1 (line-break):
+ r0. gX / # _ ^ ; // do nothing
+ r1. gX {break = -2};
+
+ Pass 1 machine classes:
+ mcX: 'x' 120
+ mcLB: 35
+
+ Pass 1 FSM: (T=transition, F=final, A=accepting, NA=non-accepting)
+
+ | gX gLB
+ --------------------------------
+ T NA s0 | s2 s1
+ |
+ T NA s1 | s3
+ |
+ F A s2 |
+ |
+ F A s3 |
+
+
+ Rules Matched:
+ s2: r1
+ s3: r0
+
+
+
+ PASS 2:
+ r0. clsOA clsE > clsELig:(1 2) _;
+ r1. clsLC _ _ gX > @1 @5 @1 @5 / _ _ # {break==2} _ _ ;
+ r2. _ clsFraction _ > clsNumerator:2 gSlash:2 clsDenom:2;
+
+ Pass 2 machine classes:
+ mcOA: O A 79 65
+ mcOAlc: o a 111 97
+ mcE E e 69 101
+ mcFraction: 188 189 190
+ mcX: x 120
+ mcLCother
+ mcLB: 35
+
+
+ Pass 2 FSM: mcLC
+ | mcOA mcOAlc mcE mcElc other mcX mcFractn mcLB
+ -----------------------------------------------------------------------------------------
+ T NA s0 | s1 s2 s4 s3 s3 s6
+ | - - - - - - -
+ T NA s1 | s7
+ | - - - - - - -
+ T NA s2 | s7 s5
+ | - - - - - - -
+ T NA s3 | s5
+ | - - - - - - -
+ T NA s4 | s5
+ | - - - - - - -
+ T NA s5 | s8
+ | - - - - - - -
+ F A s6 |
+ | - - - - - -
+ F A s7 |
+ | - - - - - -
+ F A s8 |
+ | - - - - - -
+
+ Rules matched:
+ s6: r2
+ s7: r0
+ s8: r1
+
+
+ PASS 3:
+ r0. _ > gHyphen / _ # {break == 2} ^;
+
+ Pass 3 machine classes:
+ mcLB: 35
+
+ Pass 3 FSM:
+
+ | gLB
+ --------------------------------
+ T NA s0 | s1
+ |
+ F A s1 |
+ |
+
+ Rules Matched:
+ s1: r0
+----------------------------------------------------------------------------------------------*/
+void GrEngine::SetUpAssocTest()
+{
+ if (m_pctbl)
+ delete m_pctbl;
+
+ m_pctbl = new GrClassTable();
+ m_pctbl->SetUpAssocTest();
+
+ m_fLineBreak = true;
+ m_cchwPreXlbContext = 1;
+ m_cchwPostXlbContext = 1;
+}
+
+void GrClassTable::SetUpAssocTest()
+{
+ m_ccls = 11; // number of classes
+ m_cclsLinear = 5; // number of classes in linear format (output classes)
+
+ m_prgchwBIGGlyphList = new data16[143];
+
+ m_prgichwOffsets = new data16[m_ccls+1];
+
+ data16 * pchw = m_prgchwBIGGlyphList;
+
+ // Output class 0: clsELig
+ m_prgichwOffsets[0] = 0;
+ *pchw++ = msbf(data16(140)); // OE
+ *pchw++ = msbf(data16(198)); // AE
+ *pchw++ = msbf(data16(156)); // oe
+ *pchw++ = msbf(data16(230)); // ae
+
+ // Output class 1: clsNumerator
+ m_prgichwOffsets[1] = 4;
+ *pchw++ = msbf(data16(49)); // 1
+ *pchw++ = msbf(data16(49)); // 1
+ *pchw++ = msbf(data16(51)); // 3
+
+ // Output class 2: clsDenom
+ m_prgichwOffsets[2] = 4 + 3;
+ *pchw++ = msbf(data16(52)); // 4
+ *pchw++ = msbf(data16(50)); // 2
+ *pchw++ = msbf(data16(52)); // 4
+
+ // Output class 3: gSlash
+ m_prgichwOffsets[3] = 7 + 3;
+ *pchw++ = msbf(data16(47)); // '/'
+
+ // Output class 4: gHyphen
+ m_prgichwOffsets[4] = 10 + 1;
+ *pchw++ = msbf(data16(45)); // '-'
+
+ // Input class 5: clsOA
+ m_prgichwOffsets[5] = 11 + 1;
+ *pchw++ = msbf(data16(4));
+ *pchw++ = msbf(data16(4)); *pchw++ = msbf(data16(2)); *pchw++ = msbf(data16(0));
+ *pchw++ = msbf(data16(65)); *pchw++ = msbf(data16(1)); // A
+ *pchw++ = msbf(data16(79)); *pchw++ = msbf(data16(0)); // O
+ *pchw++ = msbf(data16(97)); *pchw++ = msbf(data16(3)); // a
+ *pchw++ = msbf(data16(111)); *pchw++ = msbf(data16(2)); // o
+
+ // Input class 6: clsE
+ m_prgichwOffsets[6] = 12 + 4 + 4*2; // 24
+ *pchw++ = msbf(data16(3));
+ *pchw++ = msbf(data16(2)); *pchw++ = msbf(data16(1)); *pchw++ = msbf(data16(3-2));
+ *pchw++ = msbf(data16(40)); *pchw++ = msbf(data16(0)); // E
+ *pchw++ = msbf(data16(91)); *pchw++ = msbf(data16(1)); // e
+
+ // Input class 7: clsLC
+ m_prgichwOffsets[7] = 24 + 4 + 2*2; // 32
+ *pchw++ = msbf(data16(26));
+ *pchw++ = msbf(data16(16)); *pchw++ = msbf(data16(4)); *pchw++ = msbf(data16(26-16));
+ for (int i = 0; i < 26; ++i)
+ {
+ *pchw++ = msbf(data16(97+i)); *pchw++ = msbf(data16(i));
+ }
+
+ // Input class 8: gX
+ m_prgichwOffsets[8] = 32 + 4 + 26*2; // 88
+ *pchw++ = msbf(data16(1));
+ *pchw++ = msbf(data16(1)); *pchw++ = msbf(data16(0)); *pchw++ = msbf(data16(0));
+ *pchw++ = msbf(data16(120)); *pchw++ = msbf(data16(0));
+
+ // Input class 9: clsFraction
+ m_prgichwOffsets[9] = 88 + 4 + 1*2; // 127
+ *pchw++ = msbf(data16(3));
+ *pchw++ = msbf(data16(2)); *pchw++ = msbf(data16(1)); *pchw++ = msbf(data16(3-2));
+ *pchw++ = msbf(data16(188)); *pchw++ = msbf(data16(0)); // 1/4
+ *pchw++ = msbf(data16(189)); *pchw++ = msbf(data16(1)); // 1/2
+ *pchw++ = msbf(data16(190)); *pchw++ = msbf(data16(2)); // 3/4
+
+ // Input class 10: #
+ m_prgichwOffsets[10] = 127 + 4 + 3*2; // 137
+ *pchw++ = msbf(data16(1));
+ *pchw++ = msbf(data16(1)); *pchw++ = msbf(data16(0)); *pchw++ = msbf(data16(0));
+ *pchw++ = msbf(data16(35)); *pchw++ = msbf(data16(0)); // 1/4
+
+ m_prgichwOffsets[11] = 137 + 4 + 1*2; // 143
+}
+
+void GrLineBreakPass::SetUpAssocTest()
+{
+ m_nMaxRuleContext = m_nMaxChunk = 1;
+ m_nMaxRuleLoop = 5;
+ m_staBehavior = "Assoc";
+
+ m_pfsm = new GrFSM();
+ Assert(m_pfsm);
+ m_pfsm->SetUpAssocTest(m_ipass);
+
+ m_crul = 2;
+
+ // Set up constraint code--succeed trivially.
+ m_prgbConstraintBlock = new byte[1];
+ byte * pb = m_prgbConstraintBlock;
+ *pb++ = kopRetTrue; // RetTrue
+
+ m_prgibConstraintStart = new data16[m_crul];
+ m_prgibConstraintStart[0] = 0;
+ m_prgibConstraintStart[1] = 0;
+
+ // Set up rule action code.
+ m_prgbActionBlock = new byte[7 + 8];
+ pb = m_prgbActionBlock;
+
+ // Rule 0: gX / # _ ^ ; // do nothing
+
+ *pb++ = kopPutCopy; *pb++ = 0; // PutCopy 0
+ *pb++ = kopNext; // Next
+ *pb++ = kopPutCopy; *pb++ = 0; // PutCopy 0
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 1: gX {break = -2};
+
+ *pb++ = kopPutCopy; *pb++ = 0; // PutCopy 0
+ *pb++ = kopPushByte; *pb++ = -2; // PushByte -2
+ *pb++ = kopAttrSet; *pb++ = kslatBreak; // AttrSet breakweight
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ m_prgibActionStart = new data16[m_crul];
+ m_prgibActionStart[0] = 0;
+ m_prgibActionStart[1] = 7;
+}
+
+void GrSubPass::SetUpAssocTest()
+{
+ if (m_ipass == 2)
+ {
+ m_nMaxRuleContext = m_nMaxChunk = 3;
+ m_nMaxRuleLoop = 5;
+ m_staBehavior = "Assoc";
+
+ m_pfsm = new GrFSM();
+ Assert(m_pfsm);
+ m_pfsm->SetUpAssocTest(m_ipass);
+
+ m_crul = 3;
+
+ // Set up constraint code.
+ m_prgbConstraintBlock = new byte[1 + 10];
+ byte * pb = m_prgbConstraintBlock;
+ *pb++ = kopRetTrue; // RetTrue
+
+ *pb++ = kopCntxtItem; *pb++ = 1; // ContextItem 1
+ *pb++ = kopPushSlotAttr;*pb++ = kslatBreak; // PushSlotAttr break 0
+ *pb++ = 0;
+ *pb++ = kopPushByte; *pb++ = 2; // Push 2
+ *pb++ = kopEqual; // Equal
+ *pb++ = kopOr; // Or
+ *pb++ = kopPopRet; // PopAndRet
+
+ m_prgibConstraintStart = new data16[m_crul];
+ m_prgibConstraintStart[0] = 0;
+ m_prgibConstraintStart[1] = 1;
+ m_prgibConstraintStart[2] = 0;
+
+ // Set up rule action code.
+ m_prgbActionBlock = new byte[12 + 12 + 22];
+ pb = m_prgbActionBlock;
+
+ // Rule 0: clsOA clsE > clsELig:(1 2) _ ;
+
+ *pb++ = kopPutSubs8bitObs; *pb++ = 0; // PutSubs 0 clsOA clsELig
+ *pb++ = 5; *pb++ = 0;
+ *pb++ = kopAssoc; *pb++ = 2; // Assoc 2 0 1
+ *pb++ = 0; *pb++ = 1;
+ *pb++ = kopNext; // Next
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 1: clsLC _ _ gX > @1 @5 @1 @5 / _ _ # {break==2} _ _ ;
+
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopInsert; // Insert
+ *pb++ = kopPutCopy; *pb++ = 2; // PutCopy 2
+ *pb++ = kopNext; // Next
+ *pb++ = kopCopyNext; // CopyNext - line break
+ *pb++ = kopInsert; // Insert
+ *pb++ = kopPutCopy; *pb++ = -1; // PutCopy -1
+ *pb++ = kopNext; // Next
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 2: _ clsFraction _ > clsNumerator:2 gSlash:2 clsDenom:2;
+
+ *pb++ = kopInsert; // Insert
+ *pb++ = kopPutSubs8bitObs; *pb++ = 1; // PutSubs 1 clsFraction clsNumerator
+ *pb++ = 9; *pb++ = 1;
+ *pb++ = kopAssoc; *pb++ = 1; // Assoc 1 1
+ *pb++ = 1;
+ *pb++ = kopNext; // Next
+ *pb++ = kopPutGlyph8bitObs; *pb++ = 3; // PutGlyph gSlash
+ *pb++ = kopNext; // Next
+ *pb++ = kopInsert; // Insert
+ *pb++ = kopPutSubs8bitObs; *pb++ = 0; // PutSubs 0 clsFraction clsDenom
+ *pb++ = 9; *pb++ = 2;
+ *pb++ = kopAssoc; *pb++ = 1; // Assoc 1 0
+ *pb++ = 0;
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ m_prgibActionStart = new data16[m_crul];
+ m_prgibActionStart[0] = 0;
+ m_prgibActionStart[1] = 12;
+ m_prgibActionStart[2] = 12 + 12;
+ }
+ else if (m_ipass == 3)
+ {
+ m_nMaxRuleContext = m_nMaxChunk = 1;
+ m_nMaxRuleLoop = 3;
+ m_staBehavior = "Assoc";
+
+ m_pfsm = new GrFSM();
+ Assert(m_pfsm);
+ m_pfsm->SetUpAssocTest(m_ipass);
+
+ m_crul = 1;
+
+ // Set up constraint code.
+ m_prgbConstraintBlock = new byte[1 + 10];
+ byte * pb = m_prgbConstraintBlock;
+ *pb++ = kopRetTrue; // RetTrue
+
+ *pb++ = kopCntxtItem; *pb++ = 0; // ContextItem 0
+ *pb++ = kopPushSlotAttr;*pb++ = kslatBreak; // PushSlotAttr break 0
+ *pb++ = 0;
+ *pb++ = kopPushByte; *pb++ = 2; // Push 2
+ *pb++ = kopEqual; // Equal
+ *pb++ = kopOr; // Or
+ *pb++ = kopPopRet; // PopAndRet
+
+ m_prgibConstraintStart = new data16[m_crul];
+ m_prgibConstraintStart[0] = 1;
+
+ m_prgbActionBlock = new byte[7];
+ pb = m_prgbActionBlock;
+
+ // Rule 0: _ > gHyphen / _ # {break == 2} ^;
+
+ *pb++ = kopInsert; // Insert
+ *pb++ = kopPutGlyph8bitObs; *pb++ = 4; // PutGlyph 4 ('-' = 45)
+ *pb++ = kopNext; // Next
+ *pb++ = kopPushByte; *pb++ = 1; // Push 1
+ *pb++ = kopPopRet; // PopAndRet
+
+ m_prgibActionStart = new data16[m_crul];
+ m_prgibActionStart[0] = 0;
+ }
+ else
+ Assert(false);
+}
+
+
+void GrFSM::SetUpAssocTest(int ipass)
+{
+ if (ipass == 1)
+ {
+ // Create machine class ranges.
+ m_cmcr = 2;
+ m_prgmcr = new GrFSMClassRange[m_cmcr];
+ m_prgmcr[0].m_chwFirst = 35; // #
+ m_prgmcr[0].m_chwLast = 35;
+ m_prgmcr[0].m_col = 1;
+
+ m_prgmcr[1].m_chwFirst = 120; // x
+ m_prgmcr[1].m_chwLast = 120;
+ m_prgmcr[1].m_col = 0;
+
+ m_dimcrInit = 2; // (max power of 2 <= m_cmcr);
+ m_cLoop = 1; // log2(max power of 2 <= m_cmcr);
+ m_imcrStart = m_cmcr - m_dimcrInit;
+
+
+ m_crow = 4;
+ m_crowNonAcpt = 2;
+ m_crowFinal = 2;
+ m_rowFinalMin = m_crow - m_crowFinal;
+ m_ccol = 2;
+
+ // Set up transition table.
+ m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 4
+ short * psn = m_prgrowTransitions;
+ *psn++ = 2; *psn++ = 1;
+ *psn++ = 3; *psn++ = 0;
+
+ // Set up matched-rules tables.
+ m_prgrulnMatched = new data16[2]; // 2 = sum of rules matched for each accepting state
+ m_prgirulnMin = new data16[m_crow - m_crowNonAcpt + 1];
+
+ m_prgirulnMin[0] = 0; // s2: r1
+ m_prgrulnMatched[0] = 1;
+
+ m_prgirulnMin[1] = 1; // s3: r0
+ m_prgrulnMatched[1] = 0;
+
+ m_prgirulnMin[2] = 2;
+ }
+ else if (ipass == 2)
+ {
+ // Create machine class ranges.
+ m_cmcr = 13;
+ m_prgmcr = new GrFSMClassRange[m_cmcr];
+ m_prgmcr[0].m_chwFirst = 35; // #
+ m_prgmcr[0].m_chwLast = 35;
+ m_prgmcr[0].m_col = 7;
+
+ m_prgmcr[1].m_chwFirst = 65; // A
+ m_prgmcr[1].m_chwLast = 65;
+ m_prgmcr[1].m_col = 0;
+
+ m_prgmcr[2].m_chwFirst = 69; // E
+ m_prgmcr[2].m_chwLast = 69;
+ m_prgmcr[2].m_col = 2;
+
+ m_prgmcr[3].m_chwFirst = 79; // O
+ m_prgmcr[3].m_chwLast = 79;
+ m_prgmcr[3].m_col = 0;
+
+ m_prgmcr[4].m_chwFirst = 97; // a
+ m_prgmcr[4].m_chwLast = 97;
+ m_prgmcr[4].m_col = 1;
+
+ m_prgmcr[5].m_chwFirst = 98; // b - d
+ m_prgmcr[5].m_chwLast = 100;
+ m_prgmcr[5].m_col = 4;
+
+ m_prgmcr[6].m_chwFirst = 101; // e
+ m_prgmcr[6].m_chwLast = 101;
+ m_prgmcr[6].m_col = 3;
+
+ m_prgmcr[7].m_chwFirst = 102; // f - n
+ m_prgmcr[7].m_chwLast = 110;
+ m_prgmcr[7].m_col = 4;
+
+ m_prgmcr[8].m_chwFirst = 111; // o
+ m_prgmcr[8].m_chwLast = 111;
+ m_prgmcr[8].m_col = 1;
+
+ m_prgmcr[9].m_chwFirst = 112; // p - w
+ m_prgmcr[9].m_chwLast = 119;
+ m_prgmcr[9].m_col = 4;
+
+ m_prgmcr[10].m_chwFirst = 120; // x
+ m_prgmcr[10].m_chwLast = 120;
+ m_prgmcr[10].m_col = 5;
+
+ m_prgmcr[11].m_chwFirst = 121; // y - z
+ m_prgmcr[11].m_chwLast = 122;
+ m_prgmcr[11].m_col = 4;
+
+ m_prgmcr[12].m_chwFirst = 188; // 1/4, 1/2, 3/4
+ m_prgmcr[12].m_chwLast = 190;
+ m_prgmcr[12].m_col = 6;
+
+
+ m_dimcrInit = 8; // (max power of 2 <= m_cmcr);
+ m_cLoop = 3; // log2(max power of 2 <= m_cmcr);
+ m_imcrStart = m_cmcr - m_dimcrInit;
+
+
+ m_crow = 9;
+ m_crowNonAcpt = 6;
+ m_crowFinal = 3;
+ m_rowFinalMin = m_crow - m_crowFinal;
+ m_ccol = 8;
+
+ // Set up transition table.
+ m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 48
+ short * psn = m_prgrowTransitions;
+ *psn++ = 1; *psn++ = 2; *psn++ = 0; *psn++ = 4; *psn++ = 3; *psn++ = 3; *psn++ = 6; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ = 7; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 7; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 5;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 5;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 5;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 8; *psn++ = 0; *psn++ = 0;
+
+ // Set up matched-rules tables.
+ m_prgrulnMatched = new data16[3]; // 3 = sum of rules matched for each accepting state
+ m_prgirulnMin = new data16[3+1]; // 3 = m_crow - m_crowNonAcpt
+
+ m_prgirulnMin[0] = 0; // s6: r2
+ m_prgrulnMatched[0] = 2;
+
+ m_prgirulnMin[1] = 1; // s7: r0
+ m_prgrulnMatched[1] = 0;
+
+ m_prgirulnMin[2] = 2; // s8: r1
+ m_prgrulnMatched[2] = 1;
+
+ m_prgirulnMin[3] = 3;
+ }
+ else if (ipass == 3)
+ {
+ // Create machine class ranges.
+ m_cmcr = 1;
+ m_prgmcr = new GrFSMClassRange[m_cmcr];
+ m_prgmcr[0].m_chwFirst = 35; // #
+ m_prgmcr[0].m_chwLast = 35;
+ m_prgmcr[0].m_col = 0;
+
+ m_dimcrInit = 1; // (max power of 2 <= m_cmcr);
+ m_cLoop = 0; // log2(max power of 2 <= m_cmcr);
+ m_imcrStart = m_cmcr - m_dimcrInit;
+
+
+ m_crow = 2;
+ m_crowNonAcpt = 1;
+ m_crowFinal = 1;
+ m_rowFinalMin = m_crow - m_crowFinal;
+ m_ccol = 1;
+
+ // Set up transition table.
+ m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 1
+ short * psn = m_prgrowTransitions;
+ *psn++ = 1;
+
+ // Set up matched-rules tables.
+ m_prgrulnMatched = new data16[1]; // 1 = sum of rules matched for each accepting state
+ m_prgirulnMin = new data16[m_crow - m_crowNonAcpt + 1];
+
+ m_prgirulnMin[0] = 0; // s1: r0
+ m_prgrulnMatched[0] = 0;
+
+ m_prgirulnMin[1] = 1;
+ }
+}
+
+
+/*----------------------------------------------------------------------------------------------
+ Second batch of association tests.
+
+ PASS 1:
+ r0. clsSymbol _ > _ @1 / _ gNumber gHyphen # gNumber _;
+ r1. clsSymbol _ > _ @1 / _ gHyphen # _;
+ r2. _ clsSymbol > @6 _ / _ gNumber gHyphen # gNumber _;
+ r3. _ clsSymbol > @4 _ / _ gHyphen # _;
+ r4. clsLeft _ > @1 clsRight$1:1 / _ clsLetter gHyphen # _ gSpace;
+ r5. clsLeft _ > @1 clsRight$1:1 / _ clsLetter gHyphen # clsLetter _ gSpace;
+ r6. clsLeft _ > @1 clsRight$1:1 / _ clsLetter _ gSpace;
+ r7. clsLeft _ > @1 clsRight$1:1 / _ clsLetter clsLetter _ gSpace;
+
+ Pass 1 machine classes:
+ mcSym: @, $, %, & 64, 36, 37, 38
+ mcNum: 48-57
+ mcHyphen: 45
+ mcSpace: 32
+ mcLet: 97-122
+ mcLeft: ( [ { 40, 91, 123
+ mcRight: ) ] } 41, 93, 125
+
+ Pass 1 FSM: (T=transition, F=final, A=accepting, NA=non-accepting)
+
+ | mcSym mcNum mcHyph mcSpace mcLet mcLeft mcLB
+ ----------------------------------------------------------------------------------
+ T NA s0 | s1 s2 s3 s4
+ |
+ T NA s1 | s5 s6
+ |
+ T NA s2 | s7
+ |
+ T NA s3 | s8
+ |
+ T NA s4 | s9
+ |
+ T NA s5 | s10
+ |
+ T NA s6 | s18
+ |
+ T NA s7 | s11
+ |
+ T NA s8 | s19
+ |
+ T NA s9 | s12 s20 s13
+ |
+ T NA s10 | s14
+ |
+ T NA s11 | s15
+ |
+ T NA s12 | s16
+ |
+ T NA s13 | s21
+ |
+ T NA s14 | s22
+ |
+ T NA s15 | s23
+ |
+ T NA s16 | s24 s17
+ |
+ T NA s17 | s25
+ |
+ F A s18 |
+ |
+ F A s19 |
+ |
+ F A s20 |
+ |
+ F A s21 |
+ |
+ F A s22 |
+ |
+ F A s23 |
+ |
+ F A s24 |
+ |
+ F A s25 |
+
+
+ Rules Matched:
+ s18: r1
+ s19: r3
+ s20: r6
+ s21: r7
+ s22: r0
+ s23: r2
+ s24: r4
+ s25: r5
+----------------------------------------------------------------------------------------------*/
+void GrEngine::SetUpAssoc2Test()
+{
+ if (m_pctbl)
+ delete m_pctbl;
+
+ m_pctbl = new GrClassTable();
+ m_pctbl->SetUpAssoc2Test();
+
+ m_fLineBreak = true;
+ m_cchwPreXlbContext = 3;
+ m_cchwPostXlbContext = 2;
+}
+
+void GrClassTable::SetUpAssoc2Test()
+{
+ m_ccls = 2; // number of classes
+ m_cclsLinear = 1; // number of classes in linear format (output classes)
+
+ m_prgchwBIGGlyphList = new data16[13];
+
+ m_prgichwOffsets = new data16[m_ccls+1];
+
+ data16 * pchw = m_prgchwBIGGlyphList;
+
+ // Output class 0: clsRight
+ m_prgichwOffsets[0] = 0;
+ *pchw++ = msbf(data16(41)); // )
+ *pchw++ = msbf(data16(93)); // ]
+ *pchw++ = msbf(data16(125)); // }
+
+ // Input class 1: clsLeft
+ m_prgichwOffsets[1] = 3;
+ *pchw++ = msbf(data16(3));
+ *pchw++ = msbf(data16(2)); *pchw++ = msbf(data16(1)); *pchw++ = msbf(data16(3-2));
+ *pchw++ = msbf(data16(40)); *pchw++ = msbf(data16(0)); // (
+ *pchw++ = msbf(data16(91)); *pchw++ = msbf(data16(1)); // [
+ *pchw++ = msbf(data16(123)); *pchw++ = msbf(data16(2)); // {
+
+ m_prgichwOffsets[2] = 3 + 4 + 3*2; // 13
+}
+
+void GrSubPass::SetUpAssoc2Test()
+{
+ m_nMaxRuleContext = m_nMaxChunk = 6;
+ m_nMaxRuleLoop = 5;
+ m_staBehavior = "Assoc2";
+
+ m_pfsm = new GrFSM();
+ Assert(m_pfsm);
+ m_pfsm->SetUpAssoc2Test(m_ipass);
+
+ m_crul = 8;
+
+ // Set up constraint code.
+ m_prgbConstraintBlock = new byte[1];
+ byte * pb = m_prgbConstraintBlock;
+ *pb++ = kopRetTrue; // RetTrue
+
+ m_prgibConstraintStart = new data16[m_crul];
+ m_prgibConstraintStart[0] = 0;
+ m_prgibConstraintStart[1] = 0;
+ m_prgibConstraintStart[2] = 0;
+ m_prgibConstraintStart[3] = 0;
+ m_prgibConstraintStart[4] = 0;
+ m_prgibConstraintStart[5] = 0;
+ m_prgibConstraintStart[6] = 0;
+ m_prgibConstraintStart[7] = 0;
+
+ // Set up rule action code.
+ m_prgbActionBlock = new byte[11 + 9 + 11 + 9 + 14 + 15 + 12 + 13];
+ pb = m_prgbActionBlock;
+
+ // Rule 0: clsSymbol _ > _ @1 / _ gNumber gHyphen # gNumber _;
+
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopInsert; // Insert
+ *pb++ = kopPutCopy; *pb++ = -4; // PutCopy -4
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 1: clsSymbol _ > _ @1 / _ gHyphen # _;
+
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopInsert; // Insert
+ *pb++ = kopPutCopy; *pb++ = -2; // PutCopy -2
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 2: _ clsSymbol > @6 _ / _ gNumber gHyphen # gNumber _;
+
+ *pb++ = kopInsert; // Insert
+ *pb++ = kopPutCopy; *pb++ = 5; // PutCopy 5
+ *pb++ = kopNext; // Next
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 3: _ clsSymbol > @4 _ / _ gHyphen # _;
+
+ *pb++ = kopInsert; // Insert
+ *pb++ = kopPutCopy; *pb++ = 3; // PutCopy 3
+ *pb++ = kopNext; // Next
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 4: clsLeft _ > @1 clsRight$1 / _ clsLetter gHyphen # _ gSpace;
+
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopInsert; // Insert
+ *pb++ = kopPutSubs8bitObs; *pb++ = -3; // PutSubs -3 1 0
+ *pb++ = 1; *pb++ = 0;
+ *pb++ = kopAssoc; *pb++ = 1; // Assoc 1 -3
+ *pb++ = -3;
+ *pb++ = kopNext; // Next;
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 5: clsLeft _ > @1 clsRight$1 / _ clsLetter gHyphen # clsLetter _ gSpace;
+
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopInsert; // Insert
+ *pb++ = kopPutSubs8bitObs; *pb++ = -4; // PutSubs -4 1 0
+ *pb++ = 1; *pb++ = 0;
+ *pb++ = kopAssoc; *pb++ = 1; // Assoc 1 -4
+ *pb++ = -4;
+ *pb++ = kopNext; // Next;
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 6: clsLeft _ > @1 clsRight$1 / _ clsLetter _ gSpace;
+
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopInsert; // Insert
+ *pb++ = kopPutSubs8bitObs; *pb++ = -1; // PutSubs -1 1 0
+ *pb++ = 1; *pb++ = 0;
+ *pb++ = kopAssoc; *pb++ = 1; // Assoc 1 -1
+ *pb++ = -1;
+ *pb++ = kopNext; // Next;
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 7: clsLeft _ > @1 clsRight$1 / _ clsLetter clsLetter _ gSpace;
+
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopInsert; // Insert
+ *pb++ = kopPutSubs8bitObs; *pb++ = -2; // PutSubs -2 1 0
+ *pb++ = 1; *pb++ = 0;
+ *pb++ = kopAssoc; *pb++ = 1; // Assoc 1 -2
+ *pb++ = -2;
+ *pb++ = kopNext; // Next;
+ *pb++ = kopRetZero; // RetZero
+
+
+ m_prgibActionStart = new data16[m_crul];
+ m_prgibActionStart[0] = 0;
+ m_prgibActionStart[1] = 11;
+ m_prgibActionStart[2] = 11 + 9;
+ m_prgibActionStart[3] = 20 + 11;
+ m_prgibActionStart[4] = 31 + 9;
+ m_prgibActionStart[5] = 40 + 14;
+ m_prgibActionStart[6] = 54 + 15;
+ m_prgibActionStart[7] = 69 + 12;
+}
+
+
+void GrFSM::SetUpAssoc2Test(int ipass)
+{
+ // Create machine class ranges.
+ m_cmcr = 10;
+ m_prgmcr = new GrFSMClassRange[m_cmcr];
+ m_prgmcr[0].m_chwFirst = 32; // space
+ m_prgmcr[0].m_chwLast = 32;
+ m_prgmcr[0].m_col = 3;
+
+ m_prgmcr[1].m_chwFirst = 35; // #
+ m_prgmcr[1].m_chwLast = 35;
+ m_prgmcr[1].m_col = 6;
+
+ m_prgmcr[2].m_chwFirst = 36; // $, %, &
+ m_prgmcr[2].m_chwLast = 38;
+ m_prgmcr[2].m_col = 0;
+
+ m_prgmcr[3].m_chwFirst = 40; // (
+ m_prgmcr[3].m_chwLast = 40;
+ m_prgmcr[3].m_col = 5;
+
+ m_prgmcr[4].m_chwFirst = 45; // -
+ m_prgmcr[4].m_chwLast = 45;
+ m_prgmcr[4].m_col = 2;
+
+ m_prgmcr[5].m_chwFirst = 48; // 0 - 9
+ m_prgmcr[5].m_chwLast = 57;
+ m_prgmcr[5].m_col = 1;
+
+ m_prgmcr[6].m_chwFirst = 64; // @
+ m_prgmcr[6].m_chwLast = 64;
+ m_prgmcr[6].m_col = 0;
+
+ m_prgmcr[7].m_chwFirst = 91; // [
+ m_prgmcr[7].m_chwLast = 91;
+ m_prgmcr[7].m_col = 5;
+
+ m_prgmcr[8].m_chwFirst = 97; // a - z
+ m_prgmcr[8].m_chwLast = 122;
+ m_prgmcr[8].m_col = 4;
+
+ m_prgmcr[9].m_chwFirst = 123; // {
+ m_prgmcr[9].m_chwLast = 123;
+ m_prgmcr[9].m_col = 5;
+
+
+ m_dimcrInit = 8; // (max power of 2 <= m_cmcr);
+ m_cLoop = 3; // log2(max power of 2 <= m_cmcr);
+ m_imcrStart = m_cmcr - m_dimcrInit;
+
+
+ m_crow = 26;
+ m_crowNonAcpt = 18;
+ m_crowFinal = 8;
+ m_rowFinalMin = m_crow - m_crowFinal;
+ m_ccol = 7;
+
+ // Set up transition table.
+ m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 126
+ short * psn = m_prgrowTransitions;
+ *psn++ = 1; *psn++ = 2; *psn++ = 3; *psn++ = 0; *psn++ = 0; *psn++ = 4; *psn++ = 0;
+ *psn++ = 0; *psn++ = 5; *psn++ = 6; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ = 7; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 8;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 9; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ =10; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ =18;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ =11;
+ *psn++ =19; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ =12; *psn++ =20; *psn++ =13; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ =14;
+ *psn++ = 0; *psn++ =15; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ =16;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ =21; *psn++ = 0; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ =22; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0;
+ *psn++ =23; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ =24; *psn++ =17; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ =25; *psn++ = 0; *psn++ = 0; *psn++ = 0;
+
+ // Set up matched-rules tables.
+ m_prgrulnMatched = new data16[8]; // 3 = sum of rules matched for each accepting state
+ m_prgirulnMin = new data16[m_crow - m_crowNonAcpt + 1];
+
+ m_prgirulnMin[0] = 0; // s18: r1
+ m_prgrulnMatched[0] = 1;
+
+ m_prgirulnMin[1] = 1; // s19: r3
+ m_prgrulnMatched[1] = 3;
+
+ m_prgirulnMin[2] = 2; // s20: r6
+ m_prgrulnMatched[2] = 6;
+
+ m_prgirulnMin[3] = 3; // s21: r7
+ m_prgrulnMatched[3] = 7;
+
+ m_prgirulnMin[4] = 4; // s22: r0
+ m_prgrulnMatched[4] = 0;
+
+ m_prgirulnMin[5] = 5; // s23: r2
+ m_prgrulnMatched[5] = 2;
+
+ m_prgirulnMin[6] = 6; // s24: r4
+ m_prgrulnMatched[6] = 4;
+
+ m_prgirulnMin[7] = 7; // s25: r5
+ m_prgrulnMatched[7] = 5;
+
+ m_prgirulnMin[8] = 8;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Test of default associations
+
+ PASS 1:
+ r0. gDollar _ > @1 gEquals;
+ r1. gAtSign > _ ;
+
+ Pass 1 machine classes:
+ mcDollar: $ 36
+ mcAt: @ 64
+
+ Pass 1 FSM: (T=transition, F=final, A=accepting, NA=non-accepting)
+
+ | mcDollar mcAt
+ --------------------------------------
+ T NA s0 | s1 s2
+ |
+ F A s1 |
+ |
+ F A s2 |
+
+
+ Rules Matched:
+ s1: r0
+ s2: r1
+----------------------------------------------------------------------------------------------*/
+void GrEngine::SetUpDefaultAssocTest()
+{
+ if (m_pctbl)
+ delete m_pctbl;
+
+ m_pctbl = new GrClassTable();
+ m_pctbl->SetUpDefaultAssocTest();
+}
+
+void GrClassTable::SetUpDefaultAssocTest()
+{
+ m_ccls = 1; // number of classes
+ m_cclsLinear = 1; // number of classes in linear format
+
+ m_prgchwBIGGlyphList = new data16[1];
+
+ m_prgichwOffsets = new data16[m_ccls+1];
+
+ data16 * pchw = m_prgchwBIGGlyphList;
+
+ // Output class 0: gEquals
+ m_prgichwOffsets[0] = 0;
+ *pchw++ = msbf(data16(61));
+
+ m_prgichwOffsets[1] = 1;
+}
+
+void GrSubPass::SetUpDefaultAssocTest()
+{
+ m_nMaxRuleContext = m_nMaxChunk = 1;
+ m_nMaxRuleLoop = 5;
+ m_staBehavior = "DefaultAssoc";
+
+ m_pfsm = new GrFSM();
+ Assert(m_pfsm);
+ m_pfsm->SetUpDefaultAssocTest();
+
+ m_crul = 2;
+
+ // Set up constraint code.
+ m_prgbConstraintBlock = new byte[1];
+ byte * pb = m_prgbConstraintBlock;
+ *pb++ = kopRetTrue;
+
+ m_prgibConstraintStart = new data16[m_crul];
+ m_prgibConstraintStart[0] = 0;
+ m_prgibConstraintStart[1] = 0;
+
+ // Set up rule action code.
+ m_prgbActionBlock = new byte[6 + 3];
+ pb = m_prgbActionBlock;
+
+ // Rule 0: gDollar _ > @1 gEquals;
+
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopInsert; // Insert
+ *pb++ = kopPutGlyph8bitObs; *pb++ = 0; // PutGlyph 0
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 1: gAtSign > _ ;
+
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ m_prgibActionStart = new data16[m_crul];
+ m_prgibActionStart[0] = 0;
+ m_prgibActionStart[1] = 6;
+}
+
+
+void GrFSM::SetUpDefaultAssocTest()
+{
+ // Create machine class ranges.
+ m_cmcr = 2;
+ m_prgmcr = new GrFSMClassRange[m_cmcr];
+ m_prgmcr[0].m_chwFirst = 36; // $
+ m_prgmcr[0].m_chwLast = 36;
+ m_prgmcr[0].m_col = 0;
+
+ m_prgmcr[1].m_chwFirst = 64; // @
+ m_prgmcr[1].m_chwLast = 64;
+ m_prgmcr[1].m_col = 1;
+
+
+ m_dimcrInit = 2; // (max power of 2 <= m_cmcr);
+ m_cLoop = 1; // log2(max power of 2 <= m_cmcr);
+ m_imcrStart = m_cmcr - m_dimcrInit;
+
+
+ m_crow = 3;
+ m_crowNonAcpt = 1;
+ m_crowFinal = 2;
+ m_rowFinalMin = m_crow - m_crowFinal;
+ m_ccol = 2;
+
+ // Set up transition table.
+ m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 2
+ short * psn = m_prgrowTransitions;
+ *psn++ = 1; *psn++ = 2;
+
+ // Set up matched-rules tables.
+ m_prgrulnMatched = new data16[2]; // 2 = sum of rules matched for each accepting state
+ m_prgirulnMin = new data16[m_crow - m_crowNonAcpt + 1];
+
+ m_prgirulnMin[0] = 0; // s1: r0
+ m_prgrulnMatched[0] = 0;
+
+ m_prgirulnMin[1] = 1; // s2: r1
+ m_prgrulnMatched[1] = 1;
+
+ m_prgirulnMin[2] = 2;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Test of features. The ID of "theFeature" == 234, its index is 0. The default value is 1.
+
+ PASS 1:
+ if (theFeature == 0) // * -> $
+ r0. gAsterisk > gDollar ;
+ else if (theFeature == 1) // * -> %
+ r1. gAsterisk > gPercent ;
+ else // * -> @
+ r2. gAsterisk > gAt ;
+
+ Pass 1 machine classes:
+ mcAsterisk: * 42
+
+ Pass 1 FSM: (T=transition, F=final, A=accepting, NA=non-accepting)
+
+ | mcAsterisk
+ --------------------------------
+ T NA s0 | s1
+ |
+ F A s1 |
+
+
+ Rules Matched:
+ s1: r0, r1, r2
+----------------------------------------------------------------------------------------------*/
+void GrEngine::SetUpFeatureTest()
+{
+ AddFeature(234, 0, 1, 1);
+
+ if (m_pctbl)
+ delete m_pctbl;
+
+ m_pctbl = new GrClassTable();
+ m_pctbl->SetUpFeatureTest();
+}
+
+void GrClassTable::SetUpFeatureTest()
+{
+ m_ccls = 4; // number of classes
+ m_cclsLinear = 4; // number of classes in linear format
+
+ m_prgchwBIGGlyphList = new data16[4];
+
+ m_prgichwOffsets = new data16[m_ccls + 1];
+
+ data16 * pchw = m_prgchwBIGGlyphList;
+
+ m_prgichwOffsets[0] = 0;
+ *pchw++ = msbf(data16(36)); // $
+
+ m_prgichwOffsets[1] = 1;
+ *pchw++ = msbf(data16(37)); // %
+
+ m_prgichwOffsets[2] = 2;
+ *pchw++ = msbf(data16(64)); // @
+
+ m_prgichwOffsets[3] = 3;
+ *pchw++ = msbf(data16(42)); // *
+
+ m_prgichwOffsets[4] = 4;
+}
+
+void GrSubPass::SetUpFeatureTest()
+{
+ m_nMaxRuleContext = m_nMaxChunk = 1;
+ m_nMaxRuleLoop = 5;
+ m_staBehavior = "Feature";
+
+ m_pfsm = new GrFSM();
+ Assert(m_pfsm);
+ m_pfsm->SetUpFeatureTest();
+
+ m_crul = 3;
+
+ // Set up constraint code.
+ m_prgbConstraintBlock = new byte[1 + 6 + 12 + 12];
+ byte * pb = m_prgbConstraintBlock;
+ *pb++ = kopRetTrue;
+
+ // (theFeature == 0)
+ *pb++ = kopPushFeat; *pb++ = 0; // PushFeat 0
+ *pb++ = kopPushByte; *pb++ = 0; // PushByte 0
+ *pb++ = kopEqual; // Equal
+ *pb++ = kopPopRet; // PopAndRet
+
+ // (theFeature != 0 && theFeature == 1)
+ *pb++ = kopPushFeat; *pb++ = 0; // PushFeat 0
+ *pb++ = kopPushByte; *pb++ = 0; // PushByte 0
+ *pb++ = kopNotEq; // NotEq
+ *pb++ = kopPushFeat; *pb++ = 0; // PushFeat 0
+ *pb++ = kopPushByte; *pb++ = 1; // PushByte 1
+ *pb++ = kopEqual; // Equal
+ *pb++ = kopAnd; // And
+ *pb++ = kopPopRet; // PopAndRet
+
+ // (theFeature != 0 && theFeature != 1)
+ *pb++ = kopPushFeat; *pb++ = 0; // PushFeat 0
+ *pb++ = kopPushByte; *pb++ = 0; // PushByte 0
+ *pb++ = kopNotEq; // NotEq
+ *pb++ = kopPushFeat; *pb++ = 0; // PushFeat 0
+ *pb++ = kopPushByte; *pb++ = 1; // PushByte 1
+ *pb++ = kopNotEq; // NotEq
+ *pb++ = kopAnd; // And
+ *pb++ = kopPopRet; // PopAndRet
+
+ m_prgibConstraintStart = new data16[m_crul];
+ m_prgibConstraintStart[0] = 1;
+ m_prgibConstraintStart[1] = 1 + 6;
+ m_prgibConstraintStart[2] = 1 + 6 + 12;
+
+ // Set up rule action code.
+ m_prgbActionBlock = new byte[4 + 4 + 4];
+ pb = m_prgbActionBlock;
+
+ // Rule 0: gAsterisk > gDollar ;
+
+ *pb++ = kopPutGlyph8bitObs; *pb++ = 0; // PutGlyph 0
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 1: gAsterisk > gPercent ;
+
+ *pb++ = kopPutGlyph8bitObs; *pb++ = 1; // PutGlyph 1
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 2: gAsterisk > gAt ;
+
+ *pb++ = kopPutGlyph8bitObs; *pb++ = 2; // PutGlyph 2
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ m_prgibActionStart = new data16[m_crul];
+ m_prgibActionStart[0] = 0;
+ m_prgibActionStart[1] = 4;
+ m_prgibActionStart[2] = 4 + 4;
+}
+
+
+void GrFSM::SetUpFeatureTest()
+{
+ // Create machine class ranges.
+ m_cmcr = 1;
+ m_prgmcr = new GrFSMClassRange[m_cmcr];
+ m_prgmcr[0].m_chwFirst = 42; // *
+ m_prgmcr[0].m_chwLast = 42;
+ m_prgmcr[0].m_col = 0;
+
+
+ m_dimcrInit = 1; // (max power of 2 <= m_cmcr);
+ m_cLoop = 0; // log2(max power of 2 <= m_cmcr);
+ m_imcrStart = m_cmcr - m_dimcrInit;
+
+
+ m_crow = 2;
+ m_crowNonAcpt = 1;
+ m_crowFinal = 1;
+ m_rowFinalMin = m_crow - m_crowFinal;
+ m_ccol = 1;
+
+ // Set up transition table.
+ m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 1
+ short * psn = m_prgrowTransitions;
+ *psn++ = 1;
+
+ // Set up matched-rules tables.
+ m_prgrulnMatched = new data16[3]; // 3 = sum of rules matched for each accepting state
+ m_prgirulnMin = new data16[m_crow - m_crowNonAcpt + 1];
+
+ m_prgirulnMin[0] = 0; // s1: r0, r1, r2
+ m_prgrulnMatched[0] = 0;
+ m_prgrulnMatched[1] = 1;
+ m_prgrulnMatched[2] = 2;
+
+ m_prgirulnMin[1] = 3;
+}
+
+
+/*----------------------------------------------------------------------------------------------
+ Tests of ligatures and components.
+
+ PASS 1 (line-break):
+ r0. clsLetter { break = 2 }
+
+ Pass 1 machine classes:
+ mcLetter: a - z 97 - 122
+
+ Pass 1 FSM: (T=transition, F=final, A=accepting, NA=non-accepting)
+
+ | clsLetter
+ --------------------------------
+ T NA s0 | s1
+ |
+ F A s1 |
+
+
+ Rules Matched:
+ s1: r0
+
+
+ PASS 2 (substitution):
+ r0. gX gY gZ > gCapX:(1 2 4) { comp {X.ref=@1; Y.ref=@2; Z.ref=@4 }} _ _
+ / _ _ # {break==2} _;
+ r1. gX gY gZ > _ _ gCapZ:(1 3 4) { comp {X.ref=@1; Y.ref=@3; Z.ref=@4 }}
+ / _ # {break==2} _ _;
+ r2. gX gY gZ > _ gCapY:(1 2 3) { comp {X.ref=@1; Y.ref=@2; Z.ref=@3 }} gPlus;
+
+ Pass 2 machine classes:
+ mcX: x 120
+ mcY: y 121
+ mcZ: z 122
+ mcLB: 35
+
+
+ Pass 2 FSM:
+ | mcX mcY mcZ mcLB
+ ----------------------------------------------------
+ T NA s0 | s1
+ | - - -
+ T NA s1 | s2 s3
+ | - - -
+ T NA s2 | s6 s4
+ | - - -
+ T NA s3 | s5
+ | - - -
+ T NA s4 | s7
+ | - - -
+ T NA s5 | s8
+ | - - -
+ F A s6 |
+ | - - -
+ F A s7 |
+ | - - -
+ F A s8 |
+ | - - -
+
+ Rules matched:
+ s6: r2
+ s7: r0
+ s8: r1
+----------------------------------------------------------------------------------------------*/
+void GrEngine::SetUpLigatureTest()
+{
+ if (m_pctbl)
+ delete m_pctbl;
+
+ m_pctbl = new GrClassTable();
+ m_pctbl->SetUpLigatureTest();
+
+ m_pgtbl = new GrGlyphTable();
+ m_pgtbl->SetUpLigatureTest();
+
+ m_fLineBreak = true;
+ m_cchwPreXlbContext = 2;
+ m_cchwPostXlbContext = 2;
+}
+
+void GrClassTable::SetUpLigatureTest()
+{
+ m_ccls = 7; // number of classes
+ m_cclsLinear = 7; // number of classes in linear format (all classes are single-item)
+
+ m_prgchwBIGGlyphList = new data16[7];
+
+ m_prgichwOffsets = new data16[m_ccls+1];
+
+ data16 * pchw = m_prgchwBIGGlyphList;
+
+ // Class 0: gCapX
+ m_prgichwOffsets[0] = 0;
+ *pchw++ = msbf(data16(88)); // X
+
+ // Class 1: gCapY
+ m_prgichwOffsets[1] = 1;
+ *pchw++ = msbf(data16(89)); // Y
+
+ // Class 2: gCapZ
+ m_prgichwOffsets[2] = 2;
+ *pchw++ = msbf(data16(90)); // Z
+
+ // Class 3: gPlus
+ m_prgichwOffsets[3] = 3;
+ *pchw++ = msbf(data16(43)); // +
+
+ // Class 4: gX
+ m_prgichwOffsets[4] = 4;
+ *pchw++ = msbf(data16(120)); // x
+
+ // Class 5: gY
+ m_prgichwOffsets[5] = 5;
+ *pchw++ = msbf(data16(121)); // y
+
+ // Class 6: gZ
+ m_prgichwOffsets[6] = 6;
+ *pchw++ = msbf(data16(122)); // z
+
+ m_prgichwOffsets[7] = 7;
+}
+
+void GrGlyphTable::SetUpLigatureTest()
+{
+ SetNumberOfGlyphs(128);
+ SetNumberOfStyles(1);
+
+ GrGlyphSubTable * pgstbl = new GrGlyphSubTable();
+ Assert(pgstbl);
+
+ pgstbl->Initialize(1, 0, 128, 10, 4);
+ SetSubTable(0, pgstbl);
+
+ SetNumberOfComponents(4); // comp.w, comp.x, comp.y, comp.z
+
+ pgstbl->SetUpLigatureTest();
+}
+
+/***********************************************************************************************
+ TODO: This method is BROKEN because m_prgibBIGAttrValues has been changed. It is no
+ longer a data16 *. The Gloc table can contain 16-bit or 32-bit entries and must be
+ accessed accordingly.
+***********************************************************************************************/
+void GrGlyphSubTable::SetUpLigatureTest()
+{
+ m_nAttrIDLim = 20;
+
+ m_pgatbl = new GrGlyphAttrTable();
+ m_pgatbl->Initialize(0, 102);
+
+ for (int i = 0; i < 88; i++)
+ m_prgibBIGAttrValues[i] = (byte)msbf(data16(0));
+
+ m_prgibBIGAttrValues[88] = (byte)msbf(data16(0));
+ m_prgibBIGAttrValues[89] = (byte)msbf(data16(34));
+ m_prgibBIGAttrValues[90] = (byte)msbf(data16(68));
+
+ for (i = 91; i < 128; i++)
+ m_prgibBIGAttrValues[i] = (byte)msbf(data16(102));
+
+ m_pgatbl->SetUpLigatureTest();
+}
+
+void GrGlyphAttrTable::SetUpLigatureTest()
+{
+ // Glyph 88 'X' (2 runs; offset = 0):
+ // 0 = 0 comp.w undefined
+ // 1 = 8 comp.x: (0,0, 25,100)
+ // 2 = 12 comp.y: (25,0, 75,100)
+ // 3 = 16 comp.z: (75,0, 100,100)
+ // 4-7 = 0 comp.w box corners
+ // 8 = 100 comp.x. top
+ // 9 = 0 bottom
+ // 10= 0 left
+ // 11= 25 right
+ // 12= 100 comp.y. top
+ // 13= 0 bottom
+ // 14= 25 left
+ // 15= 75 right
+ // 16= 100 comp.z. top
+ // 17= 0 bottom
+ // 18= 75 left
+ // 19= 100 right
+ //
+ // Glyph 89 (2 runs; offset = 34):
+ // 0 = 0 comp.w undefined
+ // 1 = 8 comp.x: (0,0, 33,100)
+ // 2 = 12 comp.y: (33,0, 67,100)
+ // 3 = 16 comp.z: (67,0, 100,100)
+ // 4-7 = 0 comp.w box corners
+ // 8 = 100 comp.x. top
+ // 9 = 0 bottom
+ // 10= 0 left
+ // 11= 33 right
+ // 12= 100 comp.y. top
+ // 13= 0 bottom
+ // 14= 33 left
+ // 15= 67 right
+ // 16= 100 comp.z. top
+ // 17= 0 bottom
+ // 18= 67 left
+ // 19= 100 right
+ //
+ // Glyph 90 (2 runs; offset = 68):
+ // 0 = 0 comp.w undefined
+ // 1 = 8 comp.x: (0,0, 10,100)
+ // 2 = 12 comp.y: (10,0, 90,100)
+ // 3 = 16 comp.z: (90,0, 100,100)
+ // 4-7 = 0 comp.w box corners
+ // 8 = 100 comp.x. top
+ // 9 = 0 bottom
+ // 10= 0 left
+ // 11= 10 right
+ // 12= 100 comp.y. top
+ // 13= 0 bottom
+ // 14= 10 left
+ // 15= 90 right
+ // 16= 100 comp.z. top
+ // 17= 0 bottom
+ // 18= 90 left
+ // 19= 100 right
+
+ byte * pbBIG = m_prgbBIGEntries;
+
+ GrGlyphAttrRun gatrun;
+
+ // Glyph 88 'X'
+ gatrun.m_bMinAttrID = 1;
+ gatrun.m_cAttrs = 3;
+ gatrun.m_rgchwBIGValues[0] = msbf(data16(8));
+ gatrun.m_rgchwBIGValues[1] = msbf(data16(12));
+ gatrun.m_rgchwBIGValues[2] = msbf(data16(16));
+ memcpy(pbBIG, &gatrun, 8); // 8 = 3*2 + 2
+ pbBIG += 8;
+ gatrun.m_bMinAttrID = 8; // comp.x.top
+ gatrun.m_cAttrs = 12;
+ gatrun.m_rgchwBIGValues[0] = msbf(data16(100));
+ gatrun.m_rgchwBIGValues[1] = msbf(data16(0));
+ gatrun.m_rgchwBIGValues[2] = msbf(data16(0));
+ gatrun.m_rgchwBIGValues[3] = msbf(data16(25));
+ gatrun.m_rgchwBIGValues[4] = msbf(data16(100));
+ gatrun.m_rgchwBIGValues[5] = msbf(data16(0));
+ gatrun.m_rgchwBIGValues[6] = msbf(data16(25));
+ gatrun.m_rgchwBIGValues[7] = msbf(data16(75));
+ gatrun.m_rgchwBIGValues[8] = msbf(data16(100));
+ gatrun.m_rgchwBIGValues[9] = msbf(data16(0));
+ gatrun.m_rgchwBIGValues[10] = msbf(data16(75));
+ gatrun.m_rgchwBIGValues[11] = msbf(data16(100));
+ memcpy(pbBIG, &gatrun, 26); // 26 = 12*2 + 2
+ pbBIG += 26;
+
+ // Glyph 89 'Y'
+ gatrun.m_bMinAttrID = 1;
+ gatrun.m_cAttrs = 3;
+ gatrun.m_rgchwBIGValues[0] = msbf(data16(8));
+ gatrun.m_rgchwBIGValues[1] = msbf(data16(12));
+ gatrun.m_rgchwBIGValues[2] = msbf(data16(16));
+ memcpy(pbBIG, &gatrun, 8); // 8 = 3*2 + 2
+ pbBIG += 8;
+ gatrun.m_bMinAttrID = 8; // comp.x.top
+ gatrun.m_cAttrs = 12;
+ gatrun.m_rgchwBIGValues[0] = msbf(data16(100));
+ gatrun.m_rgchwBIGValues[1] = msbf(data16(0));
+ gatrun.m_rgchwBIGValues[2] = msbf(data16(0));
+ gatrun.m_rgchwBIGValues[3] = msbf(data16(33));
+ gatrun.m_rgchwBIGValues[4] = msbf(data16(100));
+ gatrun.m_rgchwBIGValues[5] = msbf(data16(0));
+ gatrun.m_rgchwBIGValues[6] = msbf(data16(33));
+ gatrun.m_rgchwBIGValues[7] = msbf(data16(67));
+ gatrun.m_rgchwBIGValues[8] = msbf(data16(100));
+ gatrun.m_rgchwBIGValues[9] = msbf(data16(0));
+ gatrun.m_rgchwBIGValues[10] = msbf(data16(67));
+ gatrun.m_rgchwBIGValues[11] = msbf(data16(100));
+ memcpy(pbBIG, &gatrun, 26); // 26 = 12*2 + 2
+ pbBIG += 26;
+
+ // Glyph 90 'Z'
+ gatrun.m_bMinAttrID = 1;
+ gatrun.m_cAttrs = 3;
+ gatrun.m_rgchwBIGValues[0] = msbf(data16(8));
+ gatrun.m_rgchwBIGValues[1] = msbf(data16(12));
+ gatrun.m_rgchwBIGValues[2] = msbf(data16(16));
+ memcpy(pbBIG, &gatrun, 8); // 8 = 3*2 + 2
+ pbBIG += 8;
+ gatrun.m_bMinAttrID = 8; // comp.x.top
+ gatrun.m_cAttrs = 12;
+ gatrun.m_rgchwBIGValues[0] = msbf(data16(100));
+ gatrun.m_rgchwBIGValues[1] = msbf(data16(0));
+ gatrun.m_rgchwBIGValues[2] = msbf(data16(0));
+ gatrun.m_rgchwBIGValues[3] = msbf(data16(10));
+ gatrun.m_rgchwBIGValues[4] = msbf(data16(100));
+ gatrun.m_rgchwBIGValues[5] = msbf(data16(0));
+ gatrun.m_rgchwBIGValues[6] = msbf(data16(10));
+ gatrun.m_rgchwBIGValues[7] = msbf(data16(90));
+ gatrun.m_rgchwBIGValues[8] = msbf(data16(100));
+ gatrun.m_rgchwBIGValues[9] = msbf(data16(0));
+ gatrun.m_rgchwBIGValues[10] = msbf(data16(90));
+ gatrun.m_rgchwBIGValues[11] = msbf(data16(100));
+ memcpy(pbBIG, &gatrun, 26); // 26 = 12*2 + 2
+ pbBIG += 26;
+
+ Assert(pbBIG == m_prgbBIGEntries + 102);
+}
+
+void GrLineBreakPass::SetUpLigatureTest()
+{
+ m_nMaxRuleContext = m_nMaxChunk = 1;
+ m_nMaxRuleLoop = 5;
+ m_staBehavior = "Ligatures";
+
+ m_pfsm = new GrFSM();
+ Assert(m_pfsm);
+ m_pfsm->SetUpLigatureTest(m_ipass);
+
+ m_crul = 1;
+
+ // Set up constraint code--succeed trivially.
+ m_prgbConstraintBlock = new byte[1];
+ byte * pb = m_prgbConstraintBlock;
+ *pb++ = kopRetTrue; // RetTrue
+
+ m_prgibConstraintStart = new data16[m_crul];
+ m_prgibConstraintStart[0] = 0;
+
+ // Set up rule action code.
+ m_prgbActionBlock = new byte[8];
+ pb = m_prgbActionBlock;
+
+ // Rule 0: clsLetter { break = 2 }
+
+ *pb++ = kopPutCopy; *pb++ = 0; // PutCopy 0
+ *pb++ = kopPushByte; *pb++ = 2; // PushByte 2
+ *pb++ = kopAttrSet; *pb++ = kslatBreak; // AttrSet breakweight
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ m_prgibActionStart = new data16[m_crul];
+ m_prgibActionStart[0] = 0;
+}
+
+void GrSubPass::SetUpLigatureTest()
+{
+ if (m_ipass == 2)
+ {
+ m_nMaxRuleContext = m_nMaxChunk = 4;
+ m_nMaxRuleLoop = 5;
+ m_staBehavior = "Ligatures";
+
+ m_pfsm = new GrFSM();
+ Assert(m_pfsm);
+ m_pfsm->SetUpLigatureTest(m_ipass);
+
+ m_crul = 3;
+
+ // Set up constraint code.
+ m_prgbConstraintBlock = new byte[1 + 10 + 10];
+ byte * pb = m_prgbConstraintBlock;
+ *pb++ = kopRetTrue; // RetTrue
+
+ *pb++ = kopCntxtItem; *pb++ = 2; // ContextItem 2
+ *pb++ = kopPushSlotAttr;*pb++ = kslatBreak; // PushSlotAttr break 0
+ *pb++ = 0;
+ *pb++ = kopPushByte; *pb++ = 2; // Push 2
+ *pb++ = kopEqual; // Equal
+ *pb++ = kopOr; // Or
+ *pb++ = kopPopRet; // PopAndRet
+
+ *pb++ = kopCntxtItem; *pb++ = 1; // ContextItem 1
+ *pb++ = kopPushSlotAttr;*pb++ = kslatBreak; // PushSlotAttr break 0
+ *pb++ = 0;
+ *pb++ = kopPushByte; *pb++ = 2; // Push 2
+ *pb++ = kopEqual; // Equal
+ *pb++ = kopOr; // Or
+ *pb++ = kopPopRet; // PopAndRet
+
+ m_prgibConstraintStart = new data16[m_crul];
+ m_prgibConstraintStart[0] = 1;
+ m_prgibConstraintStart[1] = 11;
+ m_prgibConstraintStart[2] = 0;
+
+ // Set up rule action code.
+ m_prgbActionBlock = new byte[29 + 29 + 29];
+ pb = m_prgbActionBlock;
+
+ // Rule 0: gX gY gZ > gCapX:(1 2 4) { comp {X.ref=@1; Y.ref=@2; Z.ref=@4 }} _ _
+ // / _ _ # {break==2} _;
+
+ *pb++ = kopPutGlyph8bitObs; *pb++ = 0; // PutGlyph 0 (gCapX)
+ *pb++ = kopAssoc; *pb++ = 3; // Assoc 3 0 1 3
+ *pb++ = 0; *pb++ = 1; *pb++ = 3;
+ *pb++ = kopPushByte; *pb++ = 0; // Push 0
+ *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref x
+ *pb++ = kslatCompRef; *pb++ = 1;
+ *pb++ = kopPushByte; *pb++ = 1; // Push 1
+ *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref y
+ *pb++ = kslatCompRef; *pb++ = 2;
+ *pb++ = kopPushByte; *pb++ = 3; // Push 3
+ *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref z
+ *pb++ = kslatCompRef; *pb++ = 3;
+ *pb++ = kopNext; // Next
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 1: gX gY gZ > _ _ gCapZ:(1 3 4) { comp {X.ref=@1; Y.ref=@3; Z.ref=@4 }}
+ // / _ # {break==2} _ _;
+
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopCopyNext; // CopyNext
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopPutGlyph8bitObs; *pb++ = 2; // PutGlyph 2 (gCapZ)
+ *pb++ = kopAssoc; *pb++ = 3; // Assoc 3 -3 -1 0
+ *pb++ = -3; *pb++ = -1; *pb++ = 0;
+ *pb++ = kopPushByte; *pb++ = -3; // Push -3
+ *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref x
+ *pb++ = kslatCompRef; *pb++ = 1;
+ *pb++ = kopPushByte; *pb++ = -1; // Push -1
+ *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref y
+ *pb++ = kslatCompRef; *pb++ = 2;
+ *pb++ = kopPushByte; *pb++ = 0; // Push 0
+ *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref z
+ *pb++ = kslatCompRef; *pb++ = 3;
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 2: gX gY gZ > _ gCapY:(1 2 3) { comp {X.ref=@1; Y.ref=@2; Z.ref=@3 }} gPlus;
+
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopPutGlyph8bitObs; *pb++ = 1; // PutGlyph 1 (gCapY)
+ *pb++ = kopAssoc; *pb++ = 3; // Assoc 3 -1 0 1
+ *pb++ = -1; *pb++ = 0; *pb++ = 1;
+ *pb++ = kopPushByte; *pb++ = -1; // Push -1
+ *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref x
+ *pb++ = kslatCompRef; *pb++ = 1;
+ *pb++ = kopPushByte; *pb++ = 0; // Push 0
+ *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref y
+ *pb++ = kslatCompRef; *pb++ = 2;
+ *pb++ = kopPushByte; *pb++ = 1; // Push 1
+ *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref z
+ *pb++ = kslatCompRef; *pb++ = 3;
+ *pb++ = kopNext; // Next
+ *pb++ = kopPutGlyph8bitObs; *pb++ = 3; // PutGlyph 3 (gPlus)
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ m_prgibActionStart = new data16[m_crul];
+ m_prgibActionStart[0] = 0;
+ m_prgibActionStart[1] = 29;
+ m_prgibActionStart[2] = 29 + 29;
+ }
+ else
+ Assert(false);
+}
+
+
+void GrFSM::SetUpLigatureTest(int ipass)
+{
+ if (ipass == 1)
+ {
+ // Create machine class ranges.
+ m_cmcr = 1;
+ m_prgmcr = new GrFSMClassRange[m_cmcr];
+ m_prgmcr[0].m_chwFirst = 97; // a - z
+ m_prgmcr[0].m_chwLast = 122;
+ m_prgmcr[0].m_col = 0;
+
+ m_dimcrInit = 1; // (max power of 2 <= m_cmcr);
+ m_cLoop = 0; // log2(max power of 2 <= m_cmcr);
+ m_imcrStart = m_cmcr - m_dimcrInit;
+
+
+ m_crow = 2;
+ m_crowNonAcpt = 1;
+ m_crowFinal = 1;
+ m_rowFinalMin = m_crow - m_crowFinal;
+ m_ccol = 1;
+
+ // Set up transition table.
+ m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 1
+ short * psn = m_prgrowTransitions;
+ *psn++ = 1;
+
+ // Set up matched-rules tables.
+ m_prgrulnMatched = new data16[1]; // 1 = sum of rules matched for each accepting state
+ m_prgirulnMin = new data16[m_crow - m_crowNonAcpt + 1];
+
+ m_prgirulnMin[0] = 0; // s1: r0
+ m_prgrulnMatched[0] = 0;
+
+ m_prgirulnMin[1] = 1;
+ }
+ else if (ipass == 2)
+ {
+ // Create machine class ranges.
+ m_cmcr = 4;
+ m_prgmcr = new GrFSMClassRange[m_cmcr];
+ m_prgmcr[0].m_chwFirst = 35; // #
+ m_prgmcr[0].m_chwLast = 35;
+ m_prgmcr[0].m_col = 3;
+
+ m_prgmcr[1].m_chwFirst = 120; // x
+ m_prgmcr[1].m_chwLast = 120;
+ m_prgmcr[1].m_col = 0;
+
+ m_prgmcr[2].m_chwFirst = 121; // y
+ m_prgmcr[2].m_chwLast = 121;
+ m_prgmcr[2].m_col = 1;
+
+ m_prgmcr[3].m_chwFirst = 122; // z
+ m_prgmcr[3].m_chwLast = 123;
+ m_prgmcr[3].m_col = 2;
+
+
+ m_dimcrInit = 4; // (max power of 2 <= m_cmcr);
+ m_cLoop = 2; // log2(max power of 2 <= m_cmcr);
+ m_imcrStart = m_cmcr - m_dimcrInit;
+
+
+ m_crow = 9;
+ m_crowNonAcpt = 6;
+ m_crowFinal = 3;
+ m_rowFinalMin = m_crow - m_crowFinal;
+ m_ccol = 4;
+
+ // Set up transition table.
+ m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 24
+ short * psn = m_prgrowTransitions;
+ *psn++ = 1; *psn++ = 0; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 2; *psn++ = 0; *psn++ = 3;
+ *psn++ = 0; *psn++ = 0; *psn++ = 6; *psn++ = 4;
+ *psn++ = 0; *psn++ = 5; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ = 7; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ = 8; *psn++ = 0;
+
+ // Set up matched-rules tables.
+ m_prgrulnMatched = new data16[3]; // 3 = sum of rules matched for each accepting state
+ m_prgirulnMin = new data16[3+1]; // 3 = m_crow - m_crowNonAcpt
+
+ m_prgirulnMin[0] = 0; // s6: r2
+ m_prgrulnMatched[0] = 2;
+
+ m_prgirulnMin[1] = 1; // s7: r0
+ m_prgrulnMatched[1] = 0;
+
+ m_prgirulnMin[2] = 2; // s8: r1
+ m_prgrulnMatched[2] = 1;
+
+ m_prgirulnMin[3] = 3;
+ }
+}
+
+
+/*----------------------------------------------------------------------------------------------
+ Tests of ligatures and components where the components are modified glyphs.
+
+ PASS 1:
+ r0. gX gI > @2 @1;
+ r1. clsPlainVowel gAcute > clsVowelAcute:(1 2) _;
+ r2. clsPlainVowel gGrave > clsVowelGrave:(1 2) _;
+
+ Pass 1 machine classes:
+ mcX: x 120
+ mcI: i 105
+ mcPV: a e o u 97 101 111 117
+ mcAcute: / 47
+ mcGrave: \ 92
+
+ Pass 1 FSM: (T=transition, F=final, A=accepting, NA=non-accepting)
+
+ | mcX mcPV mcI mcAcute mcGrave
+ ---------------------------------------------------------------
+ T NA s0 | s1 s2 s2
+ | - - - -
+ T NA s1 | s3
+ | - - - -
+ T NA s2 | s4 s5
+ | - - - -
+ F A s3 |
+ | - - - -
+ F A s4 |
+ | - - - -
+ F A s5 |
+ | - - - -
+
+
+ Rules Matched:
+ s3: r0
+ s4: r1
+ s5: r2
+
+
+ PASS 2:
+ r0. clsVowel gI > clsCapVowel:(1 2) { comp {v.ref = @1; i.ref = @2}} _;
+
+ Pass 2 machine classes:
+ mcV: 97 101 111 117
+ 224 225 232 233 236 237 242 243 249 250
+ mcI: i 105
+
+
+ Pass 2 FSM:
+ | mcV mcI
+ ----------------------------------------------------
+ T NA s0 | s1 s1
+ | -
+ T NA s1 | s2
+ | -
+ F A s2 |
+ | -
+
+ Rules matched:
+ s2: r0
+----------------------------------------------------------------------------------------------*/
+void GrEngine::SetUpLigature2Test()
+{
+ if (m_pctbl)
+ delete m_pctbl;
+
+ m_pctbl = new GrClassTable();
+ m_pctbl->SetUpLigature2Test();
+
+ m_pgtbl = new GrGlyphTable();
+ m_pgtbl->SetUpLigature2Test();
+}
+
+void GrClassTable::SetUpLigature2Test()
+{
+ m_ccls = 5; // number of classes
+ m_cclsLinear = 3; // number of classes in linear format
+
+ m_prgchwBIGGlyphList = new data16[73];
+
+ m_prgichwOffsets = new data16[m_ccls+1];
+
+ data16 * pchw = m_prgchwBIGGlyphList;
+
+ // Output class 0: clsVowelAcute
+ m_prgichwOffsets[0] = 0;
+ *pchw++ = msbf(data16(225)); // a-acute
+ *pchw++ = msbf(data16(233)); // e-acute
+ *pchw++ = msbf(data16(237)); // i-acute
+ *pchw++ = msbf(data16(243)); // o-acute
+ *pchw++ = msbf(data16(250)); // u-acute
+
+ // Output class 1: clsVowelGrave
+ m_prgichwOffsets[1] = 5;
+ *pchw++ = msbf(data16(224)); // a-grave
+ *pchw++ = msbf(data16(232)); // e-grave
+ *pchw++ = msbf(data16(236)); // i-grave
+ *pchw++ = msbf(data16(242)); // o-grave
+ *pchw++ = msbf(data16(249)); // u-grave
+
+ // Output class 2: clsCapVowel
+ m_prgichwOffsets[2] = 5 + 5; // 10
+ *pchw++ = msbf(data16(65)); // A
+ *pchw++ = msbf(data16(69)); // E
+ *pchw++ = msbf(data16(73)); // I
+ *pchw++ = msbf(data16(79)); // O
+ *pchw++ = msbf(data16(85)); // U
+ *pchw++ = msbf(data16(193)); // A-acute
+ *pchw++ = msbf(data16(201)); // E-acute
+ *pchw++ = msbf(data16(205)); // I-acute
+ *pchw++ = msbf(data16(211)); // O-acute
+ *pchw++ = msbf(data16(218)); // U-acute
+ *pchw++ = msbf(data16(192)); // A-grave
+ *pchw++ = msbf(data16(200)); // E-grave
+ *pchw++ = msbf(data16(204)); // I-grave
+ *pchw++ = msbf(data16(210)); // O-grave
+ *pchw++ = msbf(data16(217)); // U-grave
+
+ // Input class 3: clsPlainVowel
+ m_prgichwOffsets[3] = 10 + 15; // 25
+ *pchw++ = msbf(data16(5));
+ *pchw++ = msbf(data16(4)); *pchw++ = msbf(data16(2)); *pchw++ = msbf(data16(5-4));
+ *pchw++ = msbf(data16(97)); *pchw++ = msbf(data16(0)); // a
+ *pchw++ = msbf(data16(101)); *pchw++ = msbf(data16(1)); // e
+ *pchw++ = msbf(data16(105)); *pchw++ = msbf(data16(2)); // i
+ *pchw++ = msbf(data16(111)); *pchw++ = msbf(data16(3)); // o
+ *pchw++ = msbf(data16(117)); *pchw++ = msbf(data16(4)); // u
+
+ // Input class 4: clsVowel
+ m_prgichwOffsets[4] = 25 + 4+(5*2); // 39
+ *pchw++ = msbf(data16(15));
+ *pchw++ = msbf(data16(8)); *pchw++ = msbf(data16(3)); *pchw++ = msbf(data16(15-8));
+ *pchw++ = msbf(data16(97)); *pchw++ = msbf(data16(0)); // a
+ *pchw++ = msbf(data16(101)); *pchw++ = msbf(data16(1)); // e
+ *pchw++ = msbf(data16(105)); *pchw++ = msbf(data16(2)); // i
+ *pchw++ = msbf(data16(111)); *pchw++ = msbf(data16(3)); // o
+ *pchw++ = msbf(data16(117)); *pchw++ = msbf(data16(4)); // u
+ *pchw++ = msbf(data16(224)); *pchw++ = msbf(data16(10)); // a-grave
+ *pchw++ = msbf(data16(225)); *pchw++ = msbf(data16(5)); // a-acute
+ *pchw++ = msbf(data16(232)); *pchw++ = msbf(data16(11)); // e-grave
+ *pchw++ = msbf(data16(233)); *pchw++ = msbf(data16(6)); // e-acute
+ *pchw++ = msbf(data16(236)); *pchw++ = msbf(data16(12)); // i-grave
+ *pchw++ = msbf(data16(237)); *pchw++ = msbf(data16(7)); // i-acute
+ *pchw++ = msbf(data16(242)); *pchw++ = msbf(data16(13)); // o-grave
+ *pchw++ = msbf(data16(243)); *pchw++ = msbf(data16(8)); // o-acute
+ *pchw++ = msbf(data16(249)); *pchw++ = msbf(data16(14)); // u-grave
+ *pchw++ = msbf(data16(250)); *pchw++ = msbf(data16(9)); // u-acute
+
+ m_prgichwOffsets[5] = 39 + 4+(15*2); // 73
+}
+
+void GrGlyphTable::SetUpLigature2Test()
+{
+ SetNumberOfGlyphs(256);
+ SetNumberOfStyles(1);
+
+ GrGlyphSubTable * pgstbl = new GrGlyphSubTable();
+ Assert(pgstbl);
+
+ pgstbl->Initialize(1, 0, 256, 10, 4);
+ SetSubTable(0, pgstbl);
+
+ SetNumberOfComponents(2); // comp.base, comp.i
+
+ pgstbl->SetUpLigature2Test();
+}
+
+/***********************************************************************************************
+ TODO: This method is BROKEN because m_prgibBIGAttrValues has been changed. It is no
+ longer a data16 *. The Gloc table can contain 16-bit or 32-bit entries and must be
+ accessed accordingly.
+***********************************************************************************************/
+void GrGlyphSubTable::SetUpLigature2Test()
+{
+ m_nAttrIDLim = 10;
+
+ m_pgatbl = new GrGlyphAttrTable();
+ m_pgatbl->Initialize(0, 330);
+
+ for (int i = 0; i <= 65; i++) // A
+ m_prgibBIGAttrValues[i] = (byte)msbf(data16(0));
+
+ for (i = 66; i <= 69; i++) // E
+ m_prgibBIGAttrValues[i] = (byte)msbf(data16(22));
+
+ for (i = 70; i <= 73; i++) // I
+ m_prgibBIGAttrValues[i] = (byte)msbf(data16(44));
+
+ for (i = 74; i <= 79; i++) // O
+ m_prgibBIGAttrValues[i] = (byte)msbf(data16(66));
+
+ for (i = 80; i <= 85; i++) // U
+ m_prgibBIGAttrValues[i] = (byte)msbf(data16(88));
+
+ for (i = 86; i <= 192; i++) // A-grave
+ m_prgibBIGAttrValues[i] = (byte)msbf(data16(110));
+
+ m_prgibBIGAttrValues[193] = (byte)msbf(data16(132)); // A-acute
+
+ for (i = 194; i <= 200; i++) // E-grave
+ m_prgibBIGAttrValues[i] = (byte)msbf(data16(154));
+
+ m_prgibBIGAttrValues[201] = (byte)msbf(data16(176)); // E-acute
+
+ for (i = 202; i <= 204; i++) // I-grave
+ m_prgibBIGAttrValues[i] = (byte)msbf(data16(198));
+
+ m_prgibBIGAttrValues[205] = (byte)msbf(data16(220)); // I-acute
+
+ for (i = 206; i <= 210; i++) // O-grave
+ m_prgibBIGAttrValues[i] = (byte)msbf(data16(242));
+
+ m_prgibBIGAttrValues[211] = (byte)msbf(data16(264)); // O-acute
+
+ for (i = 212; i <= 217; i++) // U-grave
+ m_prgibBIGAttrValues[i] = (byte)msbf(data16(286));
+
+ m_prgibBIGAttrValues[218] = (byte)msbf(data16(308)); // O-acute
+
+ for (i = 219; i < 256; i++)
+ m_prgibBIGAttrValues[i] = (byte)msbf(data16(330));
+
+ m_pgatbl->SetUpLigature2Test();
+}
+
+void GrGlyphAttrTable::SetUpLigature2Test()
+{
+ // All ligatures have the following defined:
+ //
+ // 0 = 2 comp.base (0,30, 100,100)
+ // 1 = 6 comp.i (0,0, 100,30)
+ // 2= 100 comp.base.top
+ // 3= 30 bottom
+ // 4= 0 left
+ // 5= 100 right
+ // 6 = 30 comp.i.top
+ // 7 = 0 bottom
+ // 8= 0 left
+ // 9= 100 right
+
+ byte * pbBIG = m_prgbBIGEntries;
+
+ GrGlyphAttrRun gatrun;
+
+ for (int i = 0; i < 15; i++)
+ {
+ gatrun.m_bMinAttrID = 0;
+ gatrun.m_cAttrs = 10;
+ gatrun.m_rgchwBIGValues[0] = msbf(data16(2));
+ gatrun.m_rgchwBIGValues[1] = msbf(data16(6));
+ gatrun.m_rgchwBIGValues[2] = msbf(data16(100));
+ gatrun.m_rgchwBIGValues[3] = msbf(data16(30));
+ gatrun.m_rgchwBIGValues[4] = msbf(data16(0));
+ gatrun.m_rgchwBIGValues[5] = msbf(data16(100));
+ gatrun.m_rgchwBIGValues[6] = msbf(data16(30));
+ gatrun.m_rgchwBIGValues[7] = msbf(data16(0));
+ gatrun.m_rgchwBIGValues[8] = msbf(data16(0));
+ gatrun.m_rgchwBIGValues[9] = msbf(data16(100));
+ memcpy(pbBIG, &gatrun, 22); // 22 = 10*2 + 2
+ pbBIG += 22;
+ }
+
+ Assert(pbBIG == m_prgbBIGEntries + (22 * 15));
+}
+
+void GrSubPass::SetUpLigature2Test()
+{
+ if (m_ipass == 1)
+ {
+ m_nMaxRuleContext = m_nMaxChunk = 2;
+ m_nMaxRuleLoop = 5;
+ m_staBehavior = "Ligatures2";
+
+ m_pfsm = new GrFSM();
+ Assert(m_pfsm);
+ m_pfsm->SetUpLigature2Test(m_ipass);
+
+ m_crul = 3;
+
+ // Set up constraint code.
+ m_prgbConstraintBlock = new byte[1];
+ byte * pb = m_prgbConstraintBlock;
+ *pb++ = kopRetTrue; // RetTrue
+
+ m_prgibConstraintStart = new data16[m_crul];
+ m_prgibConstraintStart[0] = 0;
+ m_prgibConstraintStart[1] = 0;
+ m_prgibConstraintStart[2] = 0;
+
+ // Set up rule action code.
+ m_prgbActionBlock = new byte[7 + 12 + 12];
+ pb = m_prgbActionBlock;
+
+ // Rule 0: gX gI > @2 @1;
+
+ *pb++ = kopPutCopy; *pb++ = 1; // PutCopy 1
+ *pb++ = kopNext; // Next
+ *pb++ = kopPutCopy; *pb++ = -1; // PutCopy -1
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 1: clsPlainVowel gAcute > clsVowelAcute:(1 2) _;
+
+ *pb++ = kopPutSubs8bitObs; *pb++ = 0; // PutSubs 0 3 0
+ *pb++ = 3; *pb++ = 0;
+ *pb++ = kopAssoc; *pb++ = 2; // Assoc 2 0 1
+ *pb++ = 0; *pb++ = 1;
+ *pb++ = kopNext; // Next
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ // Rule 2: clsPlainVowel gGrave > clsVowelGrave:(1 2) _;
+
+ *pb++ = kopPutSubs8bitObs; *pb++ = 0; // PutSubs 0 3 1
+ *pb++ = 3; *pb++ = 1;
+ *pb++ = kopAssoc; *pb++ = 2; // Assoc 2 0 1
+ *pb++ = 0; *pb++ = 1;
+ *pb++ = kopNext; // Next
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ m_prgibActionStart = new data16[m_crul];
+ m_prgibActionStart[0] = 0;
+ m_prgibActionStart[1] = 7;
+ m_prgibActionStart[2] = 7 + 12;
+ }
+ else if (m_ipass == 2)
+ {
+ m_nMaxRuleContext = m_nMaxChunk = 2;
+ m_nMaxRuleLoop = 5;
+ m_staBehavior = "Ligatures2";
+
+ m_pfsm = new GrFSM();
+ Assert(m_pfsm);
+ m_pfsm->SetUpLigature2Test(m_ipass);
+
+ m_crul = 1;
+
+ // Set up constraint code.
+ m_prgbConstraintBlock = new byte[1];
+ byte * pb = m_prgbConstraintBlock;
+ *pb++ = kopRetTrue; // RetTrue
+
+ m_prgibConstraintStart = new data16[m_crul];
+ m_prgibConstraintStart[0] = 0;
+
+ // Set up rule action code.
+ m_prgbActionBlock = new byte[7 + 12 + 12];
+ pb = m_prgbActionBlock;
+
+ // Rule 0: clsVowel gI > clsCapVowel:(1 2) { comp {v.ref = @1; i.ref = @2}} _;
+
+ *pb++ = kopPutSubs8bitObs; *pb++ = 0; // PutSubs 0 4 2
+ *pb++ = 4; *pb++ = 2;
+ *pb++ = kopAssoc; *pb++ = 2; // Assoc 2 0 1
+ *pb++ = 0; *pb++ = 1;
+ *pb++ = kopPushByte; *pb++ = 0; // Push 0
+ *pb++ = kopIAttrSetSlot; // IAttrSetSlot compRef v
+ *pb++ = kslatCompRef; *pb++ = 0;
+ *pb++ = kopPushByte; *pb++ = 1; // Push 1
+ *pb++ = kopIAttrSetSlot; // IAttrSetSlot compRef i
+ *pb++ = kslatCompRef; *pb++ = 1;
+ *pb++ = kopNext; // Next
+ *pb++ = kopDelete; // Delete
+ *pb++ = kopNext; // Next
+ *pb++ = kopRetZero; // RetZero
+
+ m_prgibActionStart = new data16[m_crul];
+ m_prgibActionStart[0] = 0;
+ }
+ else
+ Assert(false);
+}
+
+
+void GrFSM::SetUpLigature2Test(int ipass)
+{
+ if (ipass == 1)
+ {
+ // Create machine class ranges.
+ m_cmcr = 8;
+ m_prgmcr = new GrFSMClassRange[m_cmcr];
+ m_prgmcr[0].m_chwFirst = 47; // acute
+ m_prgmcr[0].m_chwLast = 47;
+ m_prgmcr[0].m_col = 3;
+
+ m_prgmcr[1].m_chwFirst = 92; // grave
+ m_prgmcr[1].m_chwLast = 92;
+ m_prgmcr[1].m_col = 4;
+
+ m_prgmcr[2].m_chwFirst = 97; // a
+ m_prgmcr[2].m_chwLast = 97;
+ m_prgmcr[2].m_col = 1;
+
+ m_prgmcr[3].m_chwFirst = 101; // e
+ m_prgmcr[3].m_chwLast = 101;
+ m_prgmcr[3].m_col = 1;
+
+ m_prgmcr[4].m_chwFirst = 105; // i
+ m_prgmcr[4].m_chwLast = 105;
+ m_prgmcr[4].m_col = 2;
+
+ m_prgmcr[5].m_chwFirst = 111; // o
+ m_prgmcr[5].m_chwLast = 111;
+ m_prgmcr[5].m_col = 1;
+
+ m_prgmcr[6].m_chwFirst = 117; // u
+ m_prgmcr[6].m_chwLast = 117;
+ m_prgmcr[6].m_col = 1;
+
+ m_prgmcr[7].m_chwFirst = 120; // x
+ m_prgmcr[7].m_chwLast = 120;
+ m_prgmcr[7].m_col = 0;
+
+ m_dimcrInit = 8; // (max power of 2 <= m_cmcr);
+ m_cLoop = 3; // log2(max power of 2 <= m_cmcr);
+ m_imcrStart = m_cmcr - m_dimcrInit;
+
+
+ m_crow = 6;
+ m_crowNonAcpt = 3;
+ m_crowFinal = 3;
+ m_rowFinalMin = m_crow - m_crowFinal;
+ m_ccol = 5;
+
+ // Set up transition table.
+ m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 15
+ short * psn = m_prgrowTransitions;
+ *psn++ = 1; *psn++ = 2; *psn++ = 2; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ = 3; *psn++ = 0; *psn++ = 0;
+ *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 4; *psn++ = 5;
+
+ // Set up matched-rules tables.
+ m_prgrulnMatched = new data16[3]; // 3 = sum of rules matched for each accepting state
+ m_prgirulnMin = new data16[3+1]; // 3 = m_crow - m_crowNonAcpt
+
+ m_prgirulnMin[0] = 0; // s3: r0
+ m_prgrulnMatched[0] = 0;
+
+ m_prgirulnMin[1] = 1; // s4: r1
+ m_prgrulnMatched[1] = 1;
+
+ m_prgirulnMin[2] = 2; // s5: r2
+ m_prgrulnMatched[2] = 2;
+
+ m_prgirulnMin[3] = 3;
+ }
+ else if (ipass == 2)
+ {
+ // Create machine class ranges.
+ m_cmcr = 10;
+ m_prgmcr = new GrFSMClassRange[m_cmcr];
+ m_prgmcr[0].m_chwFirst = 97; // a
+ m_prgmcr[0].m_chwLast = 97;
+ m_prgmcr[0].m_col = 0;
+
+ m_prgmcr[1].m_chwFirst = 101; // e
+ m_prgmcr[1].m_chwLast = 101;
+ m_prgmcr[1].m_col = 0;
+
+ m_prgmcr[2].m_chwFirst = 105; // i
+ m_prgmcr[2].m_chwLast = 105;
+ m_prgmcr[2].m_col = 1;
+
+ m_prgmcr[3].m_chwFirst = 111; // o
+ m_prgmcr[3].m_chwLast = 111;
+ m_prgmcr[3].m_col = 0;
+
+ m_prgmcr[4].m_chwFirst = 117; // u
+ m_prgmcr[4].m_chwLast = 117;
+ m_prgmcr[4].m_col = 0;
+
+ m_prgmcr[5].m_chwFirst = 224; // a-grave, a-acute
+ m_prgmcr[5].m_chwLast = 225;
+ m_prgmcr[5].m_col = 0;
+
+ m_prgmcr[6].m_chwFirst = 232; // e-grave, e-acute
+ m_prgmcr[6].m_chwLast = 233;
+ m_prgmcr[6].m_col = 0;
+
+ m_prgmcr[7].m_chwFirst = 236; // i-grave, i-acute
+ m_prgmcr[7].m_chwLast = 237;
+ m_prgmcr[7].m_col = 0;
+
+ m_prgmcr[8].m_chwFirst = 242; // o-grave, o-acute
+ m_prgmcr[8].m_chwLast = 243;
+ m_prgmcr[8].m_col = 0;
+
+ m_prgmcr[9].m_chwFirst = 249; // u-grave, u-acute
+ m_prgmcr[9].m_chwLast = 250;
+ m_prgmcr[9].m_col = 0;
+
+
+ m_dimcrInit = 8; // (max power of 2 <= m_cmcr);
+ m_cLoop = 3; // log2(max power of 2 <= m_cmcr);
+ m_imcrStart = m_cmcr - m_dimcrInit;
+
+
+ m_crow = 3;
+ m_crowNonAcpt = 2;
+ m_crowFinal = 1;
+ m_rowFinalMin = m_crow - m_crowFinal;
+ m_ccol = 2;
+
+ // Set up transition table.
+ m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 4
+ short * psn = m_prgrowTransitions;
+ *psn++ = 1; *psn++ = 1;
+ *psn++ = 0; *psn++ = 2;
+
+ // Set up matched-rules tables.
+ m_prgrulnMatched = new data16[1]; // 1 = sum of rules matched for each accepting state
+ m_prgirulnMin = new data16[1+1]; // 1 = m_crow - m_crowNonAcpt
+
+ m_prgirulnMin[0] = 0; // s2: r0
+ m_prgrulnMatched[0] = 0;
+
+ m_prgirulnMin[1] = 1;
+ }
+}
+
+#endif // _DEBUG
+
+} // namespace gr
+
+#endif // OLD_TEST_STUFF
+
+//:End Ignore