summaryrefslogtreecommitdiff
path: root/Build/source/libs/graphite/engine-2.3.1/src/segment/GrEngine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/graphite/engine-2.3.1/src/segment/GrEngine.cpp')
-rw-r--r--Build/source/libs/graphite/engine-2.3.1/src/segment/GrEngine.cpp2031
1 files changed, 2031 insertions, 0 deletions
diff --git a/Build/source/libs/graphite/engine-2.3.1/src/segment/GrEngine.cpp b/Build/source/libs/graphite/engine-2.3.1/src/segment/GrEngine.cpp
new file mode 100644
index 00000000000..91db0dfb80a
--- /dev/null
+++ b/Build/source/libs/graphite/engine-2.3.1/src/segment/GrEngine.cpp
@@ -0,0 +1,2031 @@
+/*--------------------------------------------------------------------*//*: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: GrEngine.cpp
+Responsibility: Sharon Correll
+Last reviewed: Not yet.
+
+Description: Contains the implementation of the GrEngine class.
+----------------------------------------------------------------------------------------------*/
+
+//:>********************************************************************************************
+//:> Include files
+//:>********************************************************************************************
+#include "Main.h"
+#include <functional>
+#include <cstring>
+#ifdef _MSC_VER
+#pragma hdrstop
+#endif
+// any other headers (not precompiled)
+
+#undef THIS_FILE
+DEFINE_THIS_FILE
+
+//:End Ignore
+
+namespace gr
+{
+
+//:>********************************************************************************************
+//:> Forward declarations
+//:>********************************************************************************************
+
+//:>********************************************************************************************
+//:> Local Constants and static variables
+//:>********************************************************************************************
+
+
+//:>********************************************************************************************
+//:> General functions
+//:>********************************************************************************************
+
+bool compareCmap(const byte *lhs, const byte *rhs)
+{
+ using namespace gr;
+
+ typedef const struct index {data16 version; data16 numberSubtables;} *const IndexPtr;
+ typedef const struct enc {data16 platID; data16 platSpecID; data32 offset;} *const EncPtr;
+
+ // Calculate the size of the cmap.
+
+ IndexPtr rhsIndex = IndexPtr(rhs);
+ size_t numSubTbl = lsbf(rhsIndex->numberSubtables);
+ size_t cbCmapSz = sizeof(index) + sizeof(enc) * numSubTbl;
+ EncPtr encTbl = EncPtr(rhs + sizeof(index));
+
+ for (size_t iSubTbl = 0; iSubTbl < numSubTbl; iSubTbl++)
+ //for (int iSubTbl = numSubTbl - 1; iSubTbl >= 0; --iSubTbl)
+ {
+ const data16 *const mapTbl = reinterpret_cast<const data16 *>(rhs + lsbf((int)encTbl[iSubTbl].offset));
+ int format = lsbf(*mapTbl);
+ switch (format)
+ {
+ // 16-bit lengths
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ cbCmapSz += lsbf((data16)unsigned(mapTbl[1]));
+ break;
+ // 32-bit lengths
+ case 8:
+ case 10:
+ case 12:
+ cbCmapSz += lsbf((int)unsigned(reinterpret_cast<const data32 *>(mapTbl)[1]));
+ break;
+ default:
+ Assert(false);
+ }
+ }
+
+ // Do the comparison.
+ return (memcmp(lhs, rhs, cbCmapSz) ? false : true);
+}
+
+
+//:>********************************************************************************************
+//:> GrEngine class.
+//:>********************************************************************************************
+
+GrEngine::GrEngine()
+{
+ /////////////_CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF); ////////////////
+
+
+ m_cref = 1;
+ BasicInit();
+}
+
+void GrEngine::BasicInit()
+{
+ m_pfface = NULL;
+
+ m_ptman = NULL;
+ m_pctbl = NULL;
+ m_pgtbl = NULL;
+ m_prgpsd = NULL;
+ m_cpsd = 0;
+ m_cfeat = 0;
+ m_mFontEmUnits = -1;
+ m_dysOffset = 0;
+
+ ////m_tbufCmap.reset();
+ m_pCmap_3_1 = NULL;
+ m_pCmap_3_10 = NULL;
+ ////m_tbufNameTbl.reset();
+ // new interface stuff:
+ m_pCmapTbl = NULL;
+ m_pNameTbl = NULL;
+ m_fCmapTblCopy = false;
+ m_fNameTblCopy = false;
+
+ m_fLogXductn = false;
+
+ m_resFontValid = kresInvalidArg; // not yet initialized
+ m_ferr = kferrUninitialized;
+ m_fxdBadVersion = 0;
+
+ m_fSmartReg = false;
+ m_fSmartBold = false;
+ m_fSmartItalic = false;
+ m_fSmartBI = false;
+ m_fFakeItalicCache = false;
+ m_fFakeBICache = false;
+ m_strCtrlFileReg.erase();
+ m_strCtrlFileBold.erase();
+ m_strCtrlFileItalic.erase();
+ m_strCtrlFileBI.erase();
+ m_fFakeItalic = false;
+ m_stuCtrlFile.erase();
+ m_stuInitError.erase();
+ m_stuErrCtrlFile.erase();
+ m_stuFaceName.erase();
+ m_stuBaseFaceName.erase();
+ m_fUseSepBase = false;
+ m_stuFeatures.erase();
+
+ m_nFontCheckSum = 0;
+
+ m_fInErrorState = false;
+
+ m_rglcidFeatLabelLangs = NULL; // initialize lazily, when needed
+ m_clcidFeatLabelLangs = 0;
+}
+
+GrEngine::~GrEngine()
+{
+ DestroyEverything();
+ #ifdef _MSC_VER
+ if (!_CrtCheckMemory())
+ {
+ OutputDebugString(L"bad memory");
+ }
+ #endif
+}
+
+/*----------------------------------------------------------------------------------------------
+ Clean everything out (destructor or reinitializing with a different face name).
+----------------------------------------------------------------------------------------------*/
+void GrEngine::DestroyEverything()
+{
+ DestroyContents();
+ #ifdef _MSC_VER
+ if (!_CrtCheckMemory())
+ {
+ OutputDebugString(L"bad memory");
+ }
+ #endif
+
+ m_strCtrlFileReg.erase();
+ m_strCtrlFileBold.erase();
+ m_strCtrlFileItalic.erase();
+ m_strCtrlFileBI.erase();
+ m_fSmartReg = false;
+ m_fSmartBold = false;
+ m_fSmartItalic = false;
+ m_fSmartBI = false;
+ m_fFakeItalicCache = false;
+ m_fFakeBICache = false;
+ m_stuBaseFaceName.erase();
+
+ //m_stuFaceName.erase();
+ //m_stuFaceName = L"this is not a usable or valid string";
+ m_fUseSepBase = false;
+ m_stuFeatures.erase();
+}
+
+void GrEngine::DestroyContents(bool fDestroyCmap)
+{
+ if (fDestroyCmap)
+ {
+ ////m_tbufCmap.reset();
+ m_pCmap_3_1 = NULL;
+ m_pCmap_3_10 = NULL;
+
+ if (m_fCmapTblCopy)
+ delete[] m_pCmapTbl;
+ if (m_fNameTblCopy)
+ delete[] m_pNameTbl;
+ m_pCmapTbl = NULL;
+ m_pNameTbl = NULL;
+ m_fCmapTblCopy = false;
+ m_fNameTblCopy = false;
+ }
+
+ delete m_ptman;
+ delete m_pctbl;
+ delete m_pgtbl;
+ delete[] m_prgpsd;
+ m_ptman = NULL;
+ m_pctbl = NULL;
+ m_pgtbl = NULL;
+ m_prgpsd = NULL;
+
+ ////m_tbufNameTbl.reset();
+
+ m_stuCtrlFile.erase();
+ m_stuInitError.erase();
+
+ m_resFontValid = kresInvalidArg;
+ m_ferr = kferrUninitialized;
+}
+
+/*----------------------------------------------------------------------------------------------
+ For FontFace: return the number of features.
+----------------------------------------------------------------------------------------------*/
+size_t GrEngine::NumberOfFeatures_ff()
+{
+ return (size_t)m_cfeat;
+}
+
+/*----------------------------------------------------------------------------------------------
+ For FontFace: return the feature ID for the ifeat-th feature.
+----------------------------------------------------------------------------------------------*/
+featid GrEngine::FeatureID_ff(size_t ifeat)
+{
+ return (featid)m_rgfeat[ifeat].ID();
+}
+
+/*----------------------------------------------------------------------------------------------
+ For FontFace: return the index of the feature with the given ID.
+----------------------------------------------------------------------------------------------*/
+size_t GrEngine::FeatureWithID_ff(featid fid)
+{
+ int ifeatRet;
+ /* GrFeature * pfeat = */
+ FeatureWithID(fid, &ifeatRet);
+ return (size_t)ifeatRet;
+}
+
+/*----------------------------------------------------------------------------------------------
+ For FontFace: return the label for the ifeat-th feature.
+----------------------------------------------------------------------------------------------*/
+bool GrEngine::GetFeatureLabel_ff(size_t ifeat, lgid nLanguage, utf16 * rgchwLabel)
+{
+ std::wstring stu = m_rgfeat[ifeat].Label(this, nLanguage);
+
+ int cch = stu.size();
+ cch = min(cch, 127); // 1 char for zero-termination
+ std::copy(stu.data(), stu.data() + cch, rgchwLabel);
+ rgchwLabel[cch] = 0;
+
+ return (cch > 0);
+}
+
+/*----------------------------------------------------------------------------------------------
+ For FontFace: return the index of the default setting. Return -1 if it cannot be found.
+----------------------------------------------------------------------------------------------*/
+int GrEngine::GetFeatureDefault_ff(size_t ifeat)
+{
+ GrFeature * pfeat = m_rgfeat + ifeat;
+ int defaultValue = pfeat->DefaultValue();
+ int cfset = pfeat->NumberOfSettings();
+ int rgnSettings[100];
+ pfeat->Settings(100, rgnSettings);
+ Assert(cfset < 100); // TODO: improve this
+ for (int ifset = 0; ifset < cfset; ifset++)
+ {
+ if (rgnSettings[ifset] == defaultValue)
+ return ifset;
+ }
+ return -1;
+}
+
+/*----------------------------------------------------------------------------------------------
+ For FontFace: return the number of settings for the ifeat-th feature.
+----------------------------------------------------------------------------------------------*/
+size_t GrEngine::NumberOfSettings_ff(size_t ifeat)
+{
+ return m_rgfeat[ifeat].NumberOfSettings();
+}
+
+/*----------------------------------------------------------------------------------------------
+ For FontFace: return the value of the ifset-th setting for the ifeat-th feature.
+----------------------------------------------------------------------------------------------*/
+int GrEngine::GetFeatureSettingValue_ff(size_t ifeat, size_t ifset)
+{
+ return m_rgfeat[ifeat].NthSetting(ifset);
+}
+
+/*----------------------------------------------------------------------------------------------
+ For FontFace: return the UI label for the given feature setting.
+----------------------------------------------------------------------------------------------*/
+bool GrEngine::GetFeatureSettingLabel_ff(size_t ifeat, size_t ifset, lgid language,
+ utf16 * rgchwLabel)
+{
+ std::wstring stu = m_rgfeat[ifeat].NthSettingLabel(this, ifset, language);
+
+ int cch = stu.size();
+ cch = min(cch, 127); // 1 char for zero-termination
+ // Note: the wchar_t label was originally assigned from utf16 data, so although wchar_t is
+ // utf32 on some platforms the conversion back to utf16 should still give correct results.
+ std::copy(stu.data(), stu.data() + cch, rgchwLabel);
+ rgchwLabel[cch] = 0;
+
+ return (cch > 0);
+}
+
+/*----------------------------------------------------------------------------------------------
+ For FontFace: return the number of languages that are possible among the feature labels.
+----------------------------------------------------------------------------------------------*/
+size_t GrEngine::NumberOfFeatLangs_ff()
+{
+ SetUpFeatLangList();
+ return m_clcidFeatLabelLangs;
+}
+
+/*----------------------------------------------------------------------------------------------
+ For FontFace: return the language LCID for the feature-label language with the given index.
+----------------------------------------------------------------------------------------------*/
+short GrEngine::GetFeatLabelLang_ff(size_t ilang)
+{
+ SetUpFeatLangList();
+ return m_rglcidFeatLabelLangs[ilang];
+}
+
+/*----------------------------------------------------------------------------------------------
+ For FontFace: return the number of supported languages.
+----------------------------------------------------------------------------------------------*/
+size_t GrEngine::NumberOfLanguages_ff()
+{
+ return (size_t)m_langtbl.NumberOfLanguages();
+}
+
+/*----------------------------------------------------------------------------------------------
+ For FontFace: return the language code for the language with the given index.
+----------------------------------------------------------------------------------------------*/
+isocode GrEngine::GetLanguageCode_ff(size_t ilang)
+{
+ return m_langtbl.LanguageCode(ilang);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Set up the list of all the languages that are present in the feature labels.
+----------------------------------------------------------------------------------------------*/
+void GrEngine::SetUpFeatLangList()
+{
+ if (m_rglcidFeatLabelLangs)
+ return;
+
+ int rgnNameIDs[kMaxFeatures];
+ for (int ifeat = 0; ifeat < m_cfeat; ifeat++)
+ rgnNameIDs[ifeat] = m_rgfeat[ifeat].NameId();
+ short rglcid[128]; // 128 is the number expected by TtfUtil::GetLangsForNames
+ m_clcidFeatLabelLangs = TtfUtil::GetLangsForNames(m_pNameTbl, 3, 1, rgnNameIDs, m_cfeat, rglcid);
+ m_rglcidFeatLabelLangs = new short[m_clcidFeatLabelLangs];
+ memcpy(m_rglcidFeatLabelLangs, rglcid, sizeof(short) * m_clcidFeatLabelLangs);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return the maximum size needed for the block of data to pass between segments, that is,
+ to reinitialize the engine based on the results of the previously generated segment.
+ This value must match what is in GrTableManager::InitializeStreams() and
+ InitializeForNextSeg(). 256 is an absolute maximum imposed by the interface.
+
+ In Graphite, what this block of data will contain is information about cross-line
+ contextualization and some directionality information.
+
+ Assumes InitNew() has already been called to set the font name.
+----------------------------------------------------------------------------------------------*/
+GrResult GrEngine::get_SegDatMaxLength(int * pcb)
+{
+ ChkGrOutPtr(pcb);
+
+ if (m_resFontValid == kresInvalidArg)
+ ReturnResult(kresUnexpected); // engine not initialized
+
+ GrResult res = m_resFontValid;
+ if (m_resFontValid == kresFail || m_resFontValid == kresUnexpected || m_resFontValid == kresFalse)
+ res = kresOk; // invalid font
+ if (ResultFailed(res))
+ ReturnResult(res);
+
+ Assert(m_ptman);
+ if (!m_ptman)
+ *pcb = 256;
+ else
+ *pcb = m_ptman->NumberOfPasses() + 4;
+
+ ReturnResult(res);
+}
+
+/*----------------------------------------------------------------------------------------------
+ @return The supported script direction(s). If more than one, the application is
+ responsible for choosing the most appropriate.
+----------------------------------------------------------------------------------------------*/
+GrResult GrEngine::get_ScriptDirection(unsigned int * pgrfsdc, OLECHAR * prgchwErrMsg, int cchMaxErrMsg)
+{
+ ChkGrOutPtr(pgrfsdc);
+ ChkGrArrayArg(prgchwErrMsg, cchMaxErrMsg);
+
+ if (m_resFontValid == kresInvalidArg)
+ ReturnResult(kresUnexpected); // engine not initialized
+
+ GrResult res = m_resFontValid;
+
+ *pgrfsdc = m_grfsdc;
+
+// ClearFontError(prgchwErrMsg, cchMaxErrMsg);
+// try
+// {
+// if (m_resFontValid == kresFail || m_resFontValid == kresUnexpected || m_resFontValid == kresFalse)
+// {
+// RecordFontLoadError(prgchwErrMsg, cchMaxErrMsg);
+// res = kresOk;
+// }
+// *pgrfsdc = m_grfsdc;
+// }
+// catch (Throwable & thr)
+// {
+// res = (GrResult)thr.Error();
+// *pgrfsdc = kfsdcHorizLtr;
+// }
+// catch (...)
+// {
+// res = WARN(kresFail);
+// *pgrfsdc = kfsdcHorizLtr;
+// }
+
+ ReturnResult(res);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Get an glyph attribute from the engine that will help the GrJustifier in its work.
+----------------------------------------------------------------------------------------------*/
+GrResult GrEngine::getGlyphAttribute(int iGlyph, int jgat, int nLevel, float * pValueRet)
+{
+ return m_ptman->State()->GetGlyphAttrForJustification(iGlyph, jgat, nLevel, pValueRet);
+}
+
+GrResult GrEngine::getGlyphAttribute(int iGlyph, int jgat, int nLevel, int * pValueRet)
+{
+ return m_ptman->State()->GetGlyphAttrForJustification(iGlyph, jgat, nLevel, pValueRet);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Set an glyph attribute in the engine as a result of the decisions made by the
+ GrJustifier.
+----------------------------------------------------------------------------------------------*/
+GrResult GrEngine::setGlyphAttribute(int iGlyph, int jgat, int nLevel, float value)
+{
+ return m_ptman->State()->SetGlyphAttrForJustification(iGlyph, jgat, nLevel, value);
+}
+
+GrResult GrEngine::setGlyphAttribute(int iGlyph, int jgat, int nLevel, int value)
+{
+ return m_ptman->State()->SetGlyphAttrForJustification(iGlyph, jgat, nLevel, value);
+}
+
+//:>********************************************************************************************
+//:> Non-FieldWorks interface methods
+//:>********************************************************************************************
+
+/*----------------------------------------------------------------------------------------------
+ Make a complete segment that can be used to measure and do line-breaking.
+
+ OBSOLETE - delete
+----------------------------------------------------------------------------------------------*/
+/*
+GrResult GrEngine::MakeMeasuredSegment(
+ Font * pfont, ITextSource * pgts,
+ int ichMin, int ichLim,
+ bool fParaRtl,
+ Segment ** ppsegRet, SegEnd * pest,
+ std::ostream * pstrmLog,
+ OLECHAR * prgchwErrMsg, int cchMaxErrMsg)
+{
+ int dichContext, dichLimSeg;
+ float dxWidth;
+ return MakeSegment(ksegmodeMsfr,
+ pfont, pgts, NULL, ichMin, ichLim, false, false,
+ 100000, klbClipBreak, ktwshAll, // not used
+ fParaRtl,
+ ppsegRet, &dxWidth,
+ 0, NULL, 0, NULL, NULL, &dichContext, // not used
+ pstrmLog,
+ prgchwErrMsg, cchMaxErrMsg,
+ -1, false, false, klbClipBreak, // not used
+ &dichLimSeg, pest,
+ false, 100000, kestMoreLines); // not used
+}
+*/
+
+/*----------------------------------------------------------------------------------------------
+ Make a segment from the given range, regardless of the kind of line-break that results.
+
+ OBSOLETE - delete
+----------------------------------------------------------------------------------------------*/
+/*
+GrResult GrEngine::MakeSegmentFromRange(
+ Font * pfont, ITextSource * pgts, IGrJustifier * pgj,
+ int ichMin, int ichLim,
+ bool fStartLine, bool fEndLine,
+ TrWsHandling twsh, bool fParaRtl,
+ Segment ** ppsegRet, float * pdxWidth, SegEnd * pest,
+ int cbPrev, byte * pbPrevSegDat, int cbNextMax, byte * pbNextSegDat, int * pcbNextSegDat,
+ int * pdichwContext,
+ std::ostream * pstrmLog,
+ OLECHAR * prgchwErrMsg, int cchwMaxErrMsg)
+{
+ int dichLimSegBogus;
+ return MakeSegment(ksegmodeMsfr, pfont, pgts, pgj,
+ ichMin, ichLim,
+ fStartLine, fEndLine,
+ 10000, klbWordBreak, // not used
+ twsh, fParaRtl,
+ ppsegRet, pdxWidth,
+ //cbPrev, pbPrevSegDat, cbNextMax, pbNextSegDat, pcbNextSegDat, pdichwContext,
+ 0, NULL, 0, NULL, NULL, NULL,
+ pstrmLog,
+ prgchwErrMsg, cchwMaxErrMsg,
+ ichLim, false, false, klbClipBreak, // not used
+ &dichLimSegBogus, pest,
+ 10000, kestMoreLines); // not used
+}
+*/
+
+
+//:>********************************************************************************************
+//:> Other methods
+//:>********************************************************************************************
+
+/*----------------------------------------------------------------------------------------------
+ Create a segment.
+----------------------------------------------------------------------------------------------*/
+void GrEngine::MakeSegment(
+ // Common parameters
+ Segment * psegNew,
+ Font * pfont, ITextSource * pgts, IGrJustifier * pjus,
+ LayoutEnvironment & layout,
+ int ichMin, int ichLim,
+ // for finding a break point
+ float dxMaxWidth,
+ bool fBacktracking,
+ // for justification
+ bool fJust, float dxJustifiedWidthJ, SegEnd estJ)
+{
+ ChkGrArgPtr(pgts);
+ ChkGrArgPtrN(pjus);
+ ChkGrOutPtr(psegNew);
+ Assert(layout.bestBreak() <= layout.worstBreak());
+
+ if (pjus == NULL)
+ pjus = layout.justifier();
+
+ if (m_resFontValid == kresInvalidArg)
+ // Uninitialized.
+ return; // ReturnResult(kresUnexpected);
+
+ SetCmapAndNameTables(pfont);
+
+ int segmode = ksegmodeRange; // segment from range
+ if (fJust)
+ segmode = ksegmodeJust; // justified segment
+ else if (dxMaxWidth < kPosInfFloat)
+ segmode = ksegmodeBreak; // find break point
+
+ // Temporary:
+ if (!this->m_ptman)
+ {
+ Warn("No Graphite tables");
+ m_ptman = new GrTableManager(this);
+ CreateEmpty();
+ }
+
+ // GrResult hr = kresOk;
+ m_fInErrorState = false;
+
+ bool fBold, fItalic;
+ GetStyles(pfont, ichMin, &fBold, &fItalic);
+
+ GetWritingSystemDirection(pgts, ichMin);
+
+ // Find the end of the range to render with the current font.
+ int nDirDepth = 0;
+ int ichFontLim = FindFontLim(pgts, ichMin, &nDirDepth);
+ int ichStrmLim = 0;
+ int ichSegLim = 0;
+ switch (segmode)
+ {
+ case ksegmodeBreak: // find break point
+ // Here ichLim should be the end of the text-source, unless we're backtracking.
+ ichStrmLim = min(ichFontLim, ichLim);
+ ichSegLim = -1; // unknown
+ break;
+ case ksegmodeJust: // stretching an existing segment to achieve justification
+ ichStrmLim = ichFontLim;
+ ichSegLim = ichLim;
+ break;
+ //case ksegmodeMms: // MakeMeasuredSegment
+ // ichLim = ichFontLim;
+ // ichStrmLim = ichFontLim;
+ // ichSegLim = -1; // process to the end of the stream
+ // break;
+ case ksegmodeRange: // segment from range
+ ichLim = min(ichLim, ichFontLim);
+ ichStrmLim = ichFontLim;
+ ichSegLim = (ichLim == kPosInfinity) ? -1 : ichLim;
+ break;
+ default:
+ Assert(false);
+ }
+
+ // Initialize the graphics object with the font and character properties.
+ // SILE
+ ////if (m_fUseSepBase)
+ ////{
+ //// Assert(m_stuBaseFaceName.size() > 0);
+ //// SetUpGraphics(pgg, pgts, ichMin, m_stuBaseFaceName);
+ ////}
+ ////else
+ //// SetUpGraphics(pgg, pgts, ichMin, m_stuFaceName);
+
+ GrResult res = kresOk;
+
+ Assert(m_ptman);
+ m_ptman->State()->SetFont(pfont);
+
+ // Create a character stream on the text source.
+ GrCharStream * pchstrm = new GrCharStream(pgts, ichMin, ichStrmLim,
+ layout.startOfLine(), layout.endOfLine());
+
+ // TODO: change vertical offset to work on a character-by-character basis
+ m_dysOffset = (pgts->getVerticalOffset(ichMin) * pfont->getDPIy()) / 72;
+
+ // Run the tables and get back a segment.
+
+ bool fMoreText = false;
+ int ichCallerBtLim = -1;
+ bool fInfiniteWidth = false;
+ switch (segmode)
+ {
+ //case ksegmodeMms:
+ case ksegmodeBreak:
+ case ksegmodeRange:
+ if (segmode == ksegmodeBreak)
+ {
+ fMoreText = ((ichFontLim < ichLim) || fBacktracking);
+ ichCallerBtLim = (fBacktracking) ? ichLim : -1;
+ fInfiniteWidth = false;
+ }
+ //else if (segmode == ksegmodeMms)
+ //{
+ // fMoreText = false;
+ // ichCallerBtLim = -1;
+ // fInfiniteWidth = true;
+ // Assert(twsh == ktwshAll);
+ //}
+ else if (segmode == ksegmodeRange)
+ {
+ int ichTextLim;
+ ichTextLim = pgts->getLength();
+ fMoreText = (ichLim < ichTextLim);
+ ichCallerBtLim = -1;
+ fInfiniteWidth = true;
+ }
+ try {
+ m_ptman->Run(psegNew, pfont, pchstrm, pjus,
+ ((pjus) ? kjmodiCanShrink : kjmodiNormal),
+ layout,
+ ichSegLim, dxMaxWidth, 0,
+ fBacktracking, fMoreText, ichFontLim, fInfiniteWidth, false,
+ ichCallerBtLim,
+ nDirDepth, estJ);
+ }
+ catch (...)
+ {
+ // Disastrous problem in rendering.
+ if (!layout.dumbFallback())
+ throw; // throws original exception
+
+ // Try dumb rendering.
+ if (m_fUseSepBase)
+ SwitchGraphicsFont(true); // use the base font, which has real glyphs
+
+ m_fInErrorState = true;
+ res = RunUsingEmpty(psegNew, pfont, pchstrm, layout,
+ ichSegLim,
+ dxMaxWidth,
+ fBacktracking, fMoreText, fInfiniteWidth,
+ ichCallerBtLim,
+ nDirDepth, estJ);
+ }
+ break;
+
+ case ksegmodeJust: // justified segment
+ {
+ m_ptman->Run(psegNew, pfont, pchstrm, pjus, kjmodiJustify, layout,
+ ichSegLim,
+ dxJustifiedWidthJ, dxMaxWidth,
+ false, false, // not used
+ ichFontLim,
+ true, // infinite width
+ false, // kludge
+ -1,
+ nDirDepth, estJ);
+ //&dxWidth, &est);
+ Assert((ichLim - ichMin) == (psegNew->stopCharacter() - psegNew->startCharacter()));
+ break;
+ }
+
+ default:
+ Assert(false);
+ }
+
+ delete pchstrm;
+
+ if (m_fUseSepBase)
+ SwitchGraphicsFont(false);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return an indication of whether an error happened in trying to load Graphite tables.
+----------------------------------------------------------------------------------------------*/
+FontErrorCode GrEngine::IsValidForGraphite(int * pnVersion, int * pnSubVersion)
+{
+ if (pnVersion)
+ *pnVersion = m_fxdBadVersion >> 16;
+ if (pnSubVersion)
+ *pnSubVersion = m_fxdBadVersion & 0x0000FFFF;
+
+ return m_ferr;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Record a system error indicating that the font could not be loaded properly.
+ OBSOLETE
+----------------------------------------------------------------------------------------------*/
+void GrEngine::RecordFontLoadError(OLECHAR * prgchwErrMsg, int cchMax)
+{
+ if (prgchwErrMsg == NULL || cchMax == 0)
+ return;
+
+ std::wstring stuMessage = L"Error in initializing Graphite font \"";
+ stuMessage.append(m_stuFaceName);
+ if (m_stuErrCtrlFile.size())
+ {
+ stuMessage.append(L"\" (");
+ stuMessage.append(m_stuErrCtrlFile);
+ stuMessage.append(L")");
+ }
+ else
+ stuMessage.append(L"\"");
+ if (m_stuInitError.size())
+ {
+ stuMessage.append(L"--\n");
+ stuMessage.append(m_stuInitError);
+ }
+
+ std::fill_n(prgchwErrMsg, cchMax, 0);
+ std::copy(stuMessage.data(), stuMessage.data() + min(cchMax - 1, signed(stuMessage.size())),
+ prgchwErrMsg);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Record a system error indicating a bad error in rendering using a supposedly valid font.
+ OBSOLETE
+----------------------------------------------------------------------------------------------*/
+void GrEngine::RecordFontRunError(OLECHAR * prgchwErrMsg, int cchMax, GrResult res)
+{
+ if (prgchwErrMsg == NULL || cchMax == 0)
+ return;
+
+ std::wstring stuMessage = L"Error in rendering using Graphite font \"";
+ stuMessage.append(m_stuFaceName);
+ if (m_stuErrCtrlFile.size())
+ {
+ stuMessage.append(L"\" (");
+ stuMessage.append(m_stuErrCtrlFile);
+ stuMessage.append(L")");
+ }
+ else
+ stuMessage.append(L"\"");
+
+ std::fill_n(prgchwErrMsg, cchMax, 0);
+ std::copy(stuMessage.data(), stuMessage.data() + min(cchMax - 1, signed(stuMessage.size())),
+ prgchwErrMsg);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Initialize the font error message buffer to zero. This way we can be sure to recognize
+ an error condition by the fact that the buffer is non-zero.
+ OBSOLETE
+----------------------------------------------------------------------------------------------*/
+void GrEngine::ClearFontError(OLECHAR * prgchwErrMsg, int cchMaxErrMsg)
+{
+ std::fill_n(prgchwErrMsg, cchMaxErrMsg, 0);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Set the overall direction of the writing system based on the text properties.
+----------------------------------------------------------------------------------------------*/
+void GrEngine::GetWritingSystemDirection(ITextSource * pgts, int ichwMin)
+{
+#ifdef OLD_TEST_STUFF
+ // for test procedures:
+ if (m_stuInitialize == "RightToLeftLayout")
+ {
+ m_fRightToLeft = true;
+ return;
+ }
+#endif // OLD_TEST_STUFF
+
+ m_fRightToLeft = pgts->getRightToLeft(ichwMin);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Find the end of the range that uses the current font.
+
+ @param pgts - contains text to render
+ @param ichwMinFont - beginning of range to render with this font
+ @param pnDirDepth - return direction depth: 0=LTR, 1=RTL
+
+ @return The lim of the range that could be rendered by this font. Also the direction depth.
+----------------------------------------------------------------------------------------------*/
+int GrEngine::FindFontLim(ITextSource * pgts, int ichwMinFont, int * pnDirDepth)
+{
+ int ichwTextLen = (int)pgts->getLength();
+
+ int ichwLimRange; // range that can be rendered without breaking contextualization.
+ int ichwMinNext = ichwMinFont;
+
+ while (true)
+ {
+ std::pair<toffset, toffset> pairRange = pgts->propertyRange(ichwMinNext);
+ // int ichwMinRun = pairRange.first;
+ int ichwLimRun = pairRange.second;
+ *pnDirDepth = pgts->getDirectionDepth(ichwMinNext);
+
+ //if (ichwLim > -1 && ichwLim < ichwLimRun)
+ //{
+ // // Stopping in the middle of a run
+ // return ichwLim;
+ //}
+
+ // We can at least go to the end of this run.
+ ichwLimRange = ichwLimRun;
+ if (ichwLimRun >= ichwTextLen)
+ {
+ // Hit the end of the text-source
+ return ichwLimRange;
+ }
+ else
+ {
+ // If the following run is the same as this run except for color and underlining,
+ // we don't have to break here.
+ if (!pgts->sameSegment(ichwMinNext, ichwLimRun))
+ return ichwLimRange;
+ }
+ ichwMinNext = ichwLimRun;
+ }
+
+ return ichwLimRange;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Read the version number from the tables, and return false if any are a version this
+ implementation of the engine can't handle.
+----------------------------------------------------------------------------------------------*/
+bool GrEngine::CheckTableVersions(GrIStream * pgrstrm,
+ const byte *pSilfTbl, int lSilfStart,
+ const byte *pGlobTbl, int lGlocStart,
+ const byte *pFeatTbl, int lFeatStart,
+ int * pfxdBadVersion)
+{
+ pgrstrm->OpenBuffer(pSilfTbl, isizeof(int));
+ pgrstrm->SetPositionInFont(lSilfStart);
+ *pfxdBadVersion = ReadVersion(*pgrstrm);
+ pgrstrm->CloseBuffer();
+ if (*pfxdBadVersion > kSilfVersion)
+ return false;
+
+ pgrstrm->OpenBuffer(pGlobTbl, lGlocStart + isizeof(int));
+ pgrstrm->SetPositionInFont(lGlocStart);
+ *pfxdBadVersion = ReadVersion(*pgrstrm);
+ pgrstrm->CloseBuffer();
+ if (*pfxdBadVersion > kGlocVersion)
+ return false;
+
+ pgrstrm->OpenBuffer(pFeatTbl, isizeof(int));
+ pgrstrm->SetPositionInFont(lFeatStart);
+ *pfxdBadVersion = ReadVersion(*pgrstrm);
+ pgrstrm->CloseBuffer();
+ if (*pfxdBadVersion > kFeatVersion)
+ return false;
+
+ *pfxdBadVersion = 0;
+ return true;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Reinterpret the version number from a font table.
+----------------------------------------------------------------------------------------------*/
+int GrEngine::ReadVersion(GrIStream & grstrm)
+{
+ int fxdVersion = grstrm.ReadIntFromFont();
+
+ if (fxdVersion < 0x00010000)
+ fxdVersion = 0x00010000; // kludge for bug with which some fonts were generated
+
+ return fxdVersion;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Initialize the engine from the test file. Used for test procedures.
+----------------------------------------------------------------------------------------------*/
+//:Ignore
+#ifdef OLD_TEST_STUFF
+void GrEngine::InitFromControlFileTest()
+{
+ IStreamPtr qstrm;
+ FileStream::Create(m_stuCtrlFile, STGM_READ, &qstrm);
+
+ int nSilfOffset, nGlocOffset, nGlatOffset, nFeatOffset;
+
+ nSilfOffset = ReadIntFromFont(qstrm);
+ nGlocOffset = ReadIntFromFont(qstrm);
+ nGlatOffset = ReadIntFromFont(qstrm);
+ nFeatOffset = ReadIntFromFont(qstrm);
+ nSill
+
+ // Read the "Silf" table.
+ int chwMaxGlyphID;
+ int fxdVersion;
+ ReadSilfTable(qstrm, nSilOffset, 0, &chwMaxGlyphID, &fxdVersion);
+
+ // Read the "Gloc" and "Glat" tables.
+ ReadGlocAndGlatTables(qstrm, nGlocOffset, qstrm, nGlatOffset, chwMaxGlyphID, fxdVersion);
+
+ // Read the "Feat" table.
+ ReadFeatTable(qstrm, nFeatOffset);
+}
+#endif // OLD_TEST_STUFF
+//:End Ignore
+
+
+/*----------------------------------------------------------------------------------------------
+ Return whether the text is asking for bold and/or italic text.
+----------------------------------------------------------------------------------------------*/
+void GrEngine::GetStyles(Font * pfont, int ichwMin, bool * pfBold, bool * pfItalic)
+{
+ *pfBold = pfont->bold();
+ *pfItalic = pfont->italic();
+}
+
+/*----------------------------------------------------------------------------------------------
+ Switch the Graphics object between the Graphite table file and the base font.
+ Should only be called when we know we are using a base font, or when we are reading
+ the base font to see if it is valid.
+----------------------------------------------------------------------------------------------*/
+void GrEngine::SwitchGraphicsFont(bool fBase)
+{
+ Assert(!fBase || m_stuBaseFaceName.size() > 0);
+
+ //LgCharRenderProps chrp;
+ //pgg->get_FontCharProperties(&chrp);
+ //if (fBase)
+ //{
+ // wcsncpy(chrp.szFaceName, m_stuBaseFaceName.data(), m_stuBaseFaceName.size() + 1);
+ // chrp.szFaceName[31] = 0;
+ //}
+ //else
+ //{
+ // wcsncpy(chrp.szFaceName, m_stuFaceName.data(), m_stuFaceName.size() + 1);
+ // chrp.szFaceName[31] = 0;
+ //}
+ //pgg->SetupGraphics(&chrp);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Read the contents of the "Silf" table from the stream, which is on an extended
+ TrueType font file. Specifically, read the iSubTable-th sub-table (for now there is
+ only one).
+
+ WARNING: any changes to this method must be accompanied by equivalent changes to
+ CreateEmpty().
+----------------------------------------------------------------------------------------------*/
+bool GrEngine::ReadSilfTable(GrIStream & grstrm, long lTableStart, int iSubTable,
+ int * pchwMaxGlyphID, int * pfxdSilfVersion)
+{
+ grstrm.SetPositionInFont(lTableStart);
+
+ // version
+ *pfxdSilfVersion = ReadVersion(grstrm);
+ if (*pfxdSilfVersion > kSilfVersion)
+ // Version we don't know how to handle.
+ return false;
+
+ if (*pfxdSilfVersion >= 0x00030000)
+ // compiler version
+ grstrm.ReadIntFromFont();
+
+ // number of tables
+ unsigned short cSubTables = grstrm.ReadUShortFromFont();
+ Assert(cSubTables == 1); // for now
+ Assert(cSubTables <= kMaxSubTablesInFont);
+ if (cSubTables != 1 || cSubTables > kMaxSubTablesInFont)
+ return false;
+
+ if (*pfxdSilfVersion >= 0x00020000)
+ // reserved
+ grstrm.ReadShortFromFont();
+
+ // subtable offsets
+ int nSubTableOffsets[kMaxSubTablesInFont];
+ int i;
+ for (i = 0; i < cSubTables; i++)
+ {
+ nSubTableOffsets[i] = grstrm.ReadIntFromFont();
+ }
+
+ grstrm.SetPositionInFont(lTableStart + nSubTableOffsets[iSubTable]);
+
+ // Now we are at the beginning of the desired sub-table.
+
+ // Get the position of the start of the table.
+ long lSubTableStart;
+ grstrm.GetPositionInFont(&lSubTableStart);
+
+ // rule version
+ int fxdRuleVersion = (*pfxdSilfVersion >= 0x00030000) ?
+ ReadVersion(grstrm) :
+ *pfxdSilfVersion;
+
+ long lPassBlockPos = -1;
+ long lPseudosPos = -1;
+ if (*pfxdSilfVersion >= 0x00030000)
+ {
+ lPassBlockPos = grstrm.ReadUShortFromFont() + lSubTableStart;
+ lPseudosPos = grstrm.ReadUShortFromFont() + lSubTableStart;
+ }
+
+ // maximum glyph ID
+ data16 chwTmp;
+ *pchwMaxGlyphID = grstrm.ReadUShortFromFont();
+
+ // extra ascent and descent
+ m_mXAscent = grstrm.ReadShortFromFont();
+ m_mXDescent = grstrm.ReadShortFromFont();
+
+ // TODO: decide whether we want these:
+ m_mXAscent = 0;
+ m_mXDescent = 0;
+
+ // number of passes
+ byte cPasses = grstrm.ReadByteFromFont();
+ // index of first substitution pass
+ byte ipassSub1 = grstrm.ReadByteFromFont();
+ // index of first positioning pass
+ byte ipassPos1 = grstrm.ReadByteFromFont();
+ // index of first justification pass
+ byte ipassJust1 = grstrm.ReadByteFromFont();
+ // index of first reordered pass, or 0xFF if no reordering
+ byte ipassReordered1 = grstrm.ReadByteFromFont();
+ if (*pfxdSilfVersion < 0x00020000)
+ {
+ Assert(ipassJust1 == cPasses || ipassJust1 == ipassPos1);
+ ipassJust1 = ipassPos1;
+ }
+
+ // Sanity checks.
+ if (cPasses > kMaxPasses || ipassSub1 > cPasses || ipassPos1 > cPasses)
+ return false; // bad table
+
+ // line-break flag
+ int nLineBreak = grstrm.ReadByteFromFont();
+ if (nLineBreak != 0 && nLineBreak != 1)
+ return false; // bad table
+ m_fLineBreak = (bool)nLineBreak;
+
+ // range of possible cross-line-boundary contextualization
+ m_cchwPreXlbContext = grstrm.ReadByteFromFont();
+ m_cchwPostXlbContext = grstrm.ReadByteFromFont();
+
+ // actual glyph ID for pseudo-glyph (ID of bogus attribute)
+ byte bTmp; // unsigned
+ bTmp = grstrm.ReadByteFromFont();
+ m_chwPseudoAttr = bTmp;
+ // breakweight
+ bTmp = grstrm.ReadByteFromFont();
+ m_chwBWAttr = bTmp;
+ // directionality
+ bTmp = grstrm.ReadByteFromFont();
+ m_chwDirAttr = bTmp;
+
+ // Sanity checks--don't bother with these, I don't seem to be able to know what are reasonable values.
+ //if (m_chwPseudoAttr > 200 || m_chwBWAttr > 200 || m_chwDirAttr > 200)
+ // return false; // bad table
+
+ if (*pfxdSilfVersion >= 0x00020000)
+ {
+ // reserved
+ grstrm.ReadByteFromFont();
+ grstrm.ReadByteFromFont();
+
+ // justification levels
+ m_cJLevels = grstrm.ReadByteFromFont();
+ if (m_cJLevels > kMaxJLevels)
+ return false; // bad table
+ m_fBasicJust = (m_cJLevels == 0);
+ m_chwJStretch0 = 0xffff; // if no justification
+ m_chwJShrink0 = 0xffff;
+ m_chwJStep0 = 0xffff;
+ m_chwJWeight0 = 0xffff;
+ for (int i = 0; i < m_cJLevels; i++)
+ {
+ // justification glyph attribute IDs
+ bTmp = grstrm.ReadByteFromFont();
+ if (i == 0)
+ m_chwJStretch0 = bTmp;
+ bTmp = grstrm.ReadByteFromFont();
+ if (i == 0)
+ m_chwJShrink0 = bTmp;
+ bTmp = grstrm.ReadByteFromFont();
+ if (i == 0)
+ m_chwJStep0 = bTmp;
+ bTmp = grstrm.ReadByteFromFont();
+ if (i == 0)
+ m_chwJWeight0 = bTmp;
+ bTmp = grstrm.ReadByteFromFont(); // runto
+ // reserved
+ grstrm.ReadByteFromFont();
+ grstrm.ReadByteFromFont();
+ grstrm.ReadByteFromFont();
+ }
+ }
+ else
+ {
+ m_cJLevels = 0;
+ m_fBasicJust = true;
+ m_chwJStretch0 = 0xffff;
+ m_chwJShrink0 = 0xffff;
+ m_chwJStep0 = 0xffff;
+ m_chwJWeight0 = 0xffff;
+ }
+
+ // number of component attributes
+ chwTmp = grstrm.ReadUShortFromFont();
+ m_cComponents = chwTmp;
+
+ // number of user-defined slot attributes
+ m_cnUserDefn = grstrm.ReadByteFromFont();
+ if (m_cnUserDefn > kMaxUserDefinableSlotAttrs)
+ return false; // bad table
+
+ // max number of ligature components per glyph
+ m_cnCompPerLig = grstrm.ReadByteFromFont();
+ if (m_cnCompPerLig > 16)
+ return false; // bad table
+
+ // directions supported
+ bTmp = grstrm.ReadByteFromFont();
+ m_grfsdc = bTmp;
+ if (m_grfsdc > kfsdcHorizLtr + kfsdcHorizRtl + kfsdcVertFromLeft + kfsdcVertFromRight)
+ return false; // bad table
+
+ // reserved
+ bTmp = grstrm.ReadByteFromFont();
+ bTmp = grstrm.ReadByteFromFont();
+ bTmp = grstrm.ReadByteFromFont();
+
+ // critical features
+ int cCriticalFeatures;
+ if (*pfxdSilfVersion >= 0x00020000)
+ {
+ // reserved
+ bTmp = grstrm.ReadByteFromFont();
+
+ cCriticalFeatures = grstrm.ReadByteFromFont();
+ Assert(cCriticalFeatures == 0);
+ if (cCriticalFeatures != 0)
+ return false; // bad table
+
+ // reserved
+ bTmp = grstrm.ReadByteFromFont();
+ }
+
+ // rendering behaviors--ignore for now
+ byte cBehaviors = grstrm.ReadByteFromFont();
+ unsigned int nBehaviors[kMaxRenderingBehavior];
+ for (i = 0; i < cBehaviors; i++)
+ {
+ nBehaviors[i] = unsigned(grstrm.ReadIntFromFont());
+ }
+
+ // linebreak glyph ID
+ m_chwLBGlyphID = grstrm.ReadUShortFromFont();
+
+ // Jump to the beginning of the pass offset block, if we have this information.
+ if (*pfxdSilfVersion >= 0x00030000)
+ grstrm.SetPositionInFont(lPassBlockPos);
+ else
+ // Otherwise assume that's where we are!
+ Assert(lPassBlockPos == -1);
+
+ // offsets to passes, relative to the start of this subtable;
+ // note that we read (cPasses + 1) of these
+ int nPassOffsets[kMaxPasses];
+ for (i = 0; i <= cPasses; i++)
+ {
+ nPassOffsets[i] = grstrm.ReadIntFromFont();
+ }
+
+ // Jump to the beginning of the pseudo-glyph info block, if we have this information.
+ if (*pfxdSilfVersion >= 0x00030000)
+ grstrm.SetPositionInFont(lPseudosPos);
+ else
+ // Otherwise assume that's where we are!
+ Assert(lPseudosPos == -1);
+
+ // number of pseudo-glyphs and search constants
+ short snTmp;
+ snTmp = grstrm.ReadShortFromFont();
+ m_cpsd = snTmp;
+ snTmp = grstrm.ReadShortFromFont();
+ m_dipsdInit = snTmp;
+ snTmp = grstrm.ReadShortFromFont();
+ m_cPsdLoop = snTmp;
+ snTmp = grstrm.ReadShortFromFont();
+ m_ipsdStart = snTmp;
+
+ // unicode-to-pseudo map
+ m_prgpsd = new GrPseudoMap[m_cpsd];
+ for (i = 0; i < m_cpsd; i++)
+ {
+ if (*pfxdSilfVersion <= 0x00010000)
+ {
+ utf16 chwUnicode = grstrm.ReadUShortFromFont();
+ m_prgpsd[i].SetUnicode(chwUnicode);
+ }
+ else
+ {
+ int nUnicode = grstrm.ReadIntFromFont();
+ m_prgpsd[i].SetUnicode(nUnicode);
+ }
+ gid16 chwPseudo = grstrm.ReadUShortFromFont();
+ m_prgpsd[i].SetPseudoGlyph(chwPseudo);
+ }
+
+ // class table
+ m_pctbl = new GrClassTable();
+ if (!m_pctbl->ReadFromFont(grstrm, *pfxdSilfVersion))
+ return false;
+
+ // passes
+ return m_ptman->CreateAndReadPasses(grstrm, *pfxdSilfVersion, fxdRuleVersion,
+ cPasses, lSubTableStart, nPassOffsets,
+ ipassSub1, ipassPos1, ipassJust1, ipassReordered1);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Set up the engine with no Graphite smarts at all, just dummy tables.
+----------------------------------------------------------------------------------------------*/
+void GrEngine::CreateEmpty()
+{
+ // Silf table
+
+ m_mXAscent = 0;
+ m_mXDescent = 0;
+
+ m_fLineBreak = false;
+
+ // range of possible cross-line-boundary contextualization
+ m_cchwPreXlbContext = 0;
+ m_cchwPostXlbContext = 0;
+
+ // Bogus attribute IDs:
+ m_chwPseudoAttr = 1; // actual glyph ID for pseudo-glyph (ID of bogus attribute)
+ m_chwBWAttr = 2; // breakweight
+ m_chwDirAttr = 3; // directionality
+
+ m_cComponents = 0; // number of component attributes
+
+ m_cnUserDefn = 0; // number of user-defined slot attributes
+ m_cnCompPerLig = 0; // max number of ligature components
+
+ m_grfsdc = kfsdcHorizLtr; // supported script direction
+
+ // linebreak glyph ID
+ m_chwLBGlyphID = 0xFFFE;
+
+ // number of pseudo-glyphs and search constants
+ m_cpsd = 0;
+ m_dipsdInit = 0;
+ m_cPsdLoop = 0;
+ m_ipsdStart = 0;
+
+ // class table
+ m_pctbl = new GrClassTable();
+ m_pctbl->CreateEmpty();
+
+ // passes
+ if (m_ptman != 0)
+ m_ptman->CreateEmpty();
+
+ // Gloc and Glat tables
+ m_pgtbl = new GrGlyphTable();
+ m_pgtbl->SetNumberOfGlyphs(0);
+ m_pgtbl->SetNumberOfComponents(0);
+ m_pgtbl->SetNumberOfStyles(1); // for now
+
+ m_pgtbl->CreateEmpty();
+
+ // Feat table
+ m_cfeat = 0;
+ m_rglcidFeatLabelLangs = NULL;
+ m_clcidFeatLabelLangs = 0;
+
+ // Language table
+ m_langtbl.CreateEmpty();
+}
+
+/*----------------------------------------------------------------------------------------------
+ Create the glyph table and fill it in from the font stream.
+----------------------------------------------------------------------------------------------*/
+bool GrEngine::ReadGlocAndGlatTables(GrIStream & grstrmGloc, long lGlocStart,
+ GrIStream & grstrmGlat, long lGlatStart,
+ int chwGlyphIDMax, int fxdSilfVersion)
+{
+ // Determine the highest used glyph ID number.
+// int chwGlyphIDMax = m_chwLBGlyphID;
+// for (int ipsd = 0; ipsd < m_cpsd; ipsd++)
+// {
+// if (m_prgpsd[ipsd].PseudoGlyph() > chwGlyphIDMax)
+// chwGlyphIDMax = m_prgpsd[ipsd].PseudoGlyph();
+// }
+
+ // Create the glyph table.
+ m_pgtbl = new GrGlyphTable();
+ m_pgtbl->SetNumberOfGlyphs(chwGlyphIDMax + 1);
+ m_pgtbl->SetNumberOfComponents(m_cComponents);
+ m_pgtbl->SetNumberOfStyles(1); // for now
+
+ return m_pgtbl->ReadFromFont(grstrmGloc, lGlocStart, grstrmGlat, lGlatStart,
+ m_chwBWAttr, m_chwJStretch0, m_cJLevels, m_cnCompPerLig, fxdSilfVersion);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Read the contents of the "Feat" table from the stream, which is on an extended
+ TrueType font file.
+----------------------------------------------------------------------------------------------*/
+bool GrEngine::ReadFeatTable(GrIStream & grstrm, long lTableStart)
+{
+ short snTmp;
+ data16 chwTmp;
+ int nTmp;
+
+ grstrm.SetPositionInFont(lTableStart);
+
+ // version
+ int fxdVersion = ReadVersion(grstrm);
+ if (fxdVersion > kFeatVersion)
+ return false;
+
+ // number of features
+ int cfeat;
+ cfeat = grstrm.ReadUShortFromFont();
+ if (cfeat > kMaxFeatures)
+ return false; // bad table;
+
+ // reserved
+ chwTmp = grstrm.ReadUShortFromFont();
+ nTmp = grstrm.ReadIntFromFont();
+
+ std::vector<featid> vnIDs; // unsigned ints
+ std::vector<int> vnOffsets;
+ std::vector<int> vcfset;
+
+ m_cfeat = 0;
+ int ifeat;
+ for (ifeat = 0; ifeat < cfeat; ifeat++)
+ {
+ // ID
+ featid nID;
+ if (fxdVersion >= 0x00020000)
+ nID = (unsigned int)grstrm.ReadIntFromFont();
+ else
+ nID = grstrm.ReadUShortFromFont();
+ vnIDs.push_back(nID);
+ // number of settings
+ data16 cfset = grstrm.ReadUShortFromFont();
+ vcfset.push_back(cfset);
+ if (fxdVersion >= 0x00020000)
+ grstrm.ReadShortFromFont(); // pad bytes
+ // offset to settings list
+ nTmp = grstrm.ReadIntFromFont();
+ vnOffsets.push_back(nTmp);
+ // flags
+ chwTmp = grstrm.ReadUShortFromFont();
+ Assert(chwTmp == 0x8000); // mutually exclusive
+ // index into name table of UI label
+ int nNameId = grstrm.ReadShortFromFont();
+
+ if (fxdVersion <= 0x00020000 && nID == GrFeature::knLangFeatV2)
+ {
+ // Ignore the obsolete "lang" feature which has ID = 1
+ vnIDs.pop_back();
+ vcfset.pop_back();
+ vnOffsets.pop_back();
+ continue;
+ }
+ AddFeature(nID, nNameId, cfset);
+ }
+
+ // default feature setting value and name strings;
+ for (ifeat = 0; ifeat < m_cfeat; ifeat++)
+ {
+ GrFeature * pfeat = m_rgfeat + ifeat;
+ Assert(pfeat->ID() == vnIDs[ifeat]);
+
+ grstrm.SetPositionInFont(lTableStart + vnOffsets[ifeat]);
+
+ // Each feature has been initialized with blank spots for the number of settings
+ // it has.
+ int cfset = vcfset[ifeat];
+ Assert(pfeat->NumberOfSettings() == cfset);
+ for (int ifset = 0; ifset < cfset; ifset++)
+ {
+ snTmp = grstrm.ReadShortFromFont(); // yes, signed (TT feat table spec says unsigned)
+ short snTmp2 = grstrm.ReadShortFromFont();
+ pfeat->AddSetting(snTmp, snTmp2);
+
+ if (ifset == 0)
+ {
+ // default setting value--first in list
+ pfeat->SetDefault(snTmp);
+ }
+ }
+ }
+
+ return true;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Read the contents of the "Sill" table from the stream, which is on an extended
+ TrueType font file.
+----------------------------------------------------------------------------------------------*/
+bool GrEngine::ReadSillTable(GrIStream & grstrm, long lTableStart)
+{
+ grstrm.SetPositionInFont(lTableStart);
+
+ // version
+ int fxdVersion = ReadVersion(grstrm);
+ if (fxdVersion > kSillVersion)
+ return false;
+
+ return m_langtbl.ReadFromFont(&grstrm, fxdVersion);
+}
+
+/*----------------------------------------------------------------------------------------------
+ An error happened in running the tables. Set up temporary dummy tables, and try running
+ with dumb rendering.
+ Return kresUnexpected if even running the empty tables crashed, kresFail otherwise.
+----------------------------------------------------------------------------------------------*/
+GrResult GrEngine::RunUsingEmpty(Segment * psegNew, Font * pfont,
+ GrCharStream * pchstrm, LayoutEnvironment & layout,
+ int ichStop,
+ float dxMaxWidth,
+ bool fNeedFinalBreak, bool fMoreText, bool fInfiniteWidth,
+ int ichwCallerBtLim,
+ int nDirDepth, SegEnd estJ)
+{
+ // Save the current state of the engine.
+ int mXAscentSave = m_mXAscent;
+ int mXDescentSave = m_mXDescent;
+ bool fLineBreakSave = m_fLineBreak;
+ int cchwPreXlbContextSave = m_cchwPreXlbContext;
+ int cchwPostXlbContextSave = m_cchwPostXlbContext;
+ data16 chwPseudoAttrSave = m_chwPseudoAttr;
+ data16 chwBWAttrSave = m_chwBWAttr;
+ data16 chwDirAttrSave = m_chwDirAttr;
+ int cComponentsSave = m_cComponents;
+ int cnUserDefnSave = m_cnUserDefn;
+ int cnCompPerLigSave = m_cnCompPerLig;
+ unsigned int grfsdcSave = m_grfsdc;
+ gid16 chwLBGlyphIDSave = m_chwLBGlyphID;
+ int cpsdSave = m_cpsd;
+ int dipsdInitSave = m_dipsdInit;
+ int cPsdLoopSave = m_cPsdLoop;
+ int ipsdStartSave = m_ipsdStart;
+ GrTableManager * ptmanSave = m_ptman;
+ GrClassTable * pctblSave = m_pctbl;
+ GrGlyphTable * pgtblSave = m_pgtbl;
+ int cfeatSave = m_cfeat;
+ GrResult resFontReadSave = m_resFontRead;
+
+ GrResult res = kresFail;
+
+ pchstrm->Restart();
+
+ // Create dummy versions of the tables and run them.
+ m_pctbl = NULL;
+ m_pgtbl = NULL;
+ m_ptman = new GrTableManager(this);
+ m_ptman->State()->SetFont(pfont);
+ CreateEmpty();
+
+ try
+ {
+ m_ptman->Run(psegNew, pfont, pchstrm, NULL, kjmodiNormal, layout,
+ ichStop, dxMaxWidth, 0,
+ fNeedFinalBreak, fMoreText, -1, fInfiniteWidth, false,
+ ichwCallerBtLim,
+ nDirDepth, estJ);
+ }
+ catch(...)
+ {
+ // Still didn't work. Oh, well, not much we can do.
+ res = kresUnexpected;
+ }
+
+ psegNew->SetErroneous(true);
+
+ if (m_ptman)
+ delete m_ptman;
+ if (m_pctbl)
+ delete m_pctbl;
+ if (m_pgtbl)
+ delete m_pgtbl;
+
+ // Put everything back the way it was.
+ m_mXAscent = mXAscentSave;
+ m_mXDescent = mXDescentSave;
+ m_fLineBreak = fLineBreakSave;
+ m_cchwPreXlbContext = cchwPreXlbContextSave;
+ m_cchwPostXlbContext = cchwPostXlbContextSave;
+ m_chwPseudoAttr = chwPseudoAttrSave;
+ m_chwBWAttr = chwBWAttrSave;
+ m_chwDirAttr = chwDirAttrSave;
+ m_cComponents = cComponentsSave;
+ m_cnUserDefn = cnUserDefnSave;
+ m_cnCompPerLig = cnCompPerLigSave;
+ m_grfsdc = grfsdcSave;
+ m_chwLBGlyphID = chwLBGlyphIDSave;
+ m_cpsd = cpsdSave;
+ m_dipsdInit = dipsdInitSave;
+ m_cPsdLoop = cPsdLoopSave;
+ m_ipsdStart = ipsdStartSave;
+ m_ptman = ptmanSave;
+ m_pctbl = pctblSave;
+ m_pgtbl = pgtblSave;
+ m_cfeat = cfeatSave;
+ m_resFontRead = resFontReadSave;
+
+ return res;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return the glyph ID for the given Unicode value.
+----------------------------------------------------------------------------------------------*/
+gid16 GrEngine::GetGlyphIDFromUnicode(int nUnicode)
+{
+ gid16 chwGlyphID = MapToPseudo(nUnicode);
+ if (chwGlyphID != 0)
+ return chwGlyphID; // return a pseudo-glyph
+
+#ifdef OLD_TEST_STUFF
+ if (!m_pCmap31)
+ // test procedures
+ return chwUnicode;
+#endif // OLD_TEST_STUFF
+
+ // Otherwise, get the glyph ID from the font's cmap.
+
+ if (m_pCmap_3_10)
+ return gid16(TtfUtil::Cmap310Lookup(m_pCmap_3_10, nUnicode));
+ else if (m_pCmap_3_1)
+ return gid16(TtfUtil::Cmap31Lookup(m_pCmap_3_1, nUnicode));
+ else
+ return 0;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return the pseudo-glyph corresponding to the given Unicode input, or 0 if none.
+----------------------------------------------------------------------------------------------*/
+gid16 GrEngine::MapToPseudo(int nUnicode)
+{
+ if (m_cpsd == 0)
+ return 0;
+
+#ifdef _DEBUG
+ int nPowerOf2 = 1;
+ while (nPowerOf2 <= m_cpsd)
+ nPowerOf2 <<= 1;
+ nPowerOf2 >>= 1;
+ // Now nPowerOf2 is the max power of 2 <= m_cpds
+ Assert((1 << m_cPsdLoop) == nPowerOf2); // m_cPsdLoop == log2(nPowerOf2)
+ Assert(m_dipsdInit == nPowerOf2);
+ Assert(m_ipsdStart == m_cpsd - m_dipsdInit);
+#endif // _DEBUG
+
+ int dipsdCurr = m_dipsdInit;
+
+ GrPseudoMap * ppsdCurr = m_prgpsd + m_ipsdStart;
+ while (dipsdCurr > 0)
+ {
+ int nTest;
+ if (ppsdCurr < m_prgpsd)
+ nTest = -1;
+ else
+ nTest = ppsdCurr->Unicode() - nUnicode;
+
+ if (nTest == 0)
+ return ppsdCurr->PseudoGlyph();
+
+ dipsdCurr >>= 1; // divide by 2
+ if (nTest < 0)
+ ppsdCurr += dipsdCurr;
+ else // (nTest > 0)
+ ppsdCurr -= dipsdCurr;
+ }
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return the actual glyph ID to use for glyph metrics and output. For most glyphs, this
+ is just the glyph ID we're already working with, but for pseudo-glyphs it will something
+ different.
+----------------------------------------------------------------------------------------------*/
+gid16 GrEngine::ActualGlyphForOutput(gid16 chwGlyphID)
+{
+ gid16 chwActual = gid16(GlyphAttrValue(chwGlyphID, m_chwPseudoAttr));
+ if (chwActual == 0)
+ return chwGlyphID; // not a pseudo, we're already working with the actual glyph ID
+ else
+ return chwActual;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Look up name based on lang id and name id in name table.
+ Currently used to look up feature names.
+----------------------------------------------------------------------------------------------*/
+std::wstring GrEngine::StringFromNameTable(int nLangID, int nNameID)
+{
+ std::wstring stuName;
+ stuName.erase();
+ size_t lOffset = 0;
+ size_t lSize = 0;
+
+ // The Graphite compiler stores our names in either
+ // the MS (platform id = 3) Unicode (writing system id = 1) table
+ // or the MS Symbol (writing system id = 0) table. Try MS Unicode first.
+ // lOffset & lSize are in bytes.
+ // new interface:
+ if (!TtfUtil::GetNameInfo(m_pNameTbl, 3, 1, nLangID, nNameID, lOffset, lSize))
+ {
+ if (!TtfUtil::GetNameInfo(m_pNameTbl, 3, 0, nLangID, nNameID, lOffset, lSize))
+ {
+ return stuName;
+ }
+ }
+
+ size_t cchw = (unsigned(lSize) / sizeof(utf16));
+ utf16 * pchwName = new utf16[cchw+1]; // lSize - byte count for Uni str
+ const utf16 *pchwSrcName = reinterpret_cast<const utf16*>(m_pNameTbl + lOffset);
+ std::transform(pchwSrcName, pchwSrcName + cchw, pchwName, std::ptr_fun<utf16,utf16>(lsbf));
+ pchwName[cchw] = 0; // zero terminate
+ #ifdef _WIN32
+ stuName.assign((const wchar_t*)pchwName, cchw);
+ #else
+ wchar_t * pchwName32 = new wchar_t[cchw+1]; // lSize - byte count for Uni str
+ for (int i = 0; i <= signed(cchw); i++) {
+ pchwName32[i] = pchwName[i];
+ }
+ stuName.assign(pchwName32, cchw);
+ delete [] pchwName32;
+ #endif
+
+ delete [] pchwName;
+ return stuName;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Add a feature (eg, when loading from the font).
+----------------------------------------------------------------------------------------------*/
+void GrEngine::AddFeature(featid nID, int nNameId, int cfset, int nDefault)
+{
+ if (m_cfeat >= kMaxFeatures)
+ return;
+
+ int ifeat = m_cfeat;
+ m_rgfeat[ifeat].Initialize(nID, nNameId, cfset, nDefault);
+// m_hmnifeat.Insert(nID, ifeat);
+ m_cfeat++;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return the feature with the given ID, or NULL if none.
+----------------------------------------------------------------------------------------------*/
+GrFeature * GrEngine::FeatureWithID(featid nID, int * pifeat)
+{
+ for (int ifeat = 0; ifeat < m_cfeat; ifeat++)
+ {
+ if (m_rgfeat[ifeat].ID() == nID)
+ {
+ *pifeat = ifeat;
+ return m_rgfeat + ifeat;
+ }
+ }
+ *pifeat = -1;
+ return NULL;
+
+
+ // Alternate implementation if we end up with so many features that we need to use
+ // a hash map:
+// int ifeat;
+// if (m_hmnifeat.Retrieve(nID, &ifeat))
+// {
+// Assert(ifeat < kMaxFeatures);
+// return m_rgfeat + ifeat; // may be NULL
+// }
+// else
+// return NULL;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return the default for the feature at the given index in the array.
+----------------------------------------------------------------------------------------------*/
+int GrEngine::DefaultForFeatureAt(int ifeat)
+{
+ Assert(ifeat < kMaxFeatures);
+ if (ifeat >= m_cfeat || ifeat < 0)
+ return 0; // undefined feature
+
+ return m_rgfeat[ifeat].DefaultValue();
+}
+
+/*----------------------------------------------------------------------------------------------
+ Set the default for the feature at the given index in the array.
+----------------------------------------------------------------------------------------------*/
+void GrEngine::SetDefaultForFeatureAt(int ifeat, int nValue)
+{
+ Assert(ifeat < kMaxFeatures);
+ Assert(ifeat < m_cfeat);
+ if (ifeat >= 0)
+ m_rgfeat[ifeat].SetDefault(nValue);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return the default feature settings for the given language.
+----------------------------------------------------------------------------------------------*/
+void GrEngine::DefaultsForLanguage(isocode lgcode,
+ std::vector<featid> & vnFeats, std::vector<int> & vnValues)
+{
+ m_langtbl.LanguageFeatureSettings(lgcode, vnFeats, vnValues);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Initialize the directionality and breakweight attributes of a new slot based on its
+ glyph ID.
+ REVIEW: we could optimize by not initializing from the glyph table right away,
+ but waiting until we need the value.
+----------------------------------------------------------------------------------------------*/
+void GrEngine::InitSlot(GrSlotState * pslot, int nUnicode)
+{
+ gid16 chwGlyphID = pslot->GlyphID();
+
+ if (m_ptman->InternalJustificationMode() != kjmodiNormal)
+ {
+ if (m_cJLevels > 0)
+ {
+ Assert(m_cJLevels == 1); // for now
+ // TODO: do this at level 0.
+ pslot->SetJStretch(m_pgtbl->GlyphAttrValue(chwGlyphID, m_chwJStretch0));
+ pslot->SetJShrink( m_pgtbl->GlyphAttrValue(chwGlyphID, m_chwJShrink0));
+ pslot->SetJStep( m_pgtbl->GlyphAttrValue(chwGlyphID, m_chwJStep0));
+ pslot->SetJWeight( m_pgtbl->GlyphAttrValue(chwGlyphID, m_chwJWeight0));
+ }
+ else if (nUnicode == knSpace)
+ {
+ // Basic stretch/shrink for whitespace.
+ // TODO: do this at level 0.
+ Assert(m_fBasicJust);
+ int mAdv = pslot->AdvanceX(m_ptman);
+ pslot->SetJStretch(mAdv * 100); // stretch up to 100 times natural width
+ pslot->SetJShrink(mAdv / 4); // shrink to 75%
+ pslot->SetJWeight(1);
+ }
+ }
+
+ if (m_pgtbl && !m_pgtbl->IsEmpty())
+ {
+ // Initialize from glyph table.
+ pslot->SetBreakWeight(m_pgtbl->GlyphAttrValue(chwGlyphID, m_chwBWAttr));
+
+ DirCode dirc = DirCode(m_pgtbl->GlyphAttrValue(chwGlyphID, m_chwDirAttr));
+ if (BidiCode(nUnicode) && (chwGlyphID == 0 || dirc == kdircNeutral))
+ // A built-in character for the bidi algorithm that is not defined in the font but
+ // must be given a special directionality:
+ goto LDefaults;
+
+ pslot->SetDirectionality(dirc);
+
+ return;
+ }
+
+LDefaults:
+ // Otherwise, in fill defaults for some basic values.
+ if (pslot->BreakWeight() == GrSlotState::kNotYetSet8)
+ {
+ switch (nUnicode)
+ {
+ case knSpace:
+ pslot->SetBreakWeight(klbWordBreak);
+ break;
+ case knHyphen:
+ pslot->SetBreakWeight(klbHyphenBreak);
+ break;
+ default:
+ pslot->SetBreakWeight(klbLetterBreak);
+ }
+ }
+
+ if ((int)pslot->Directionality() == GrSlotState::kNotYetSet8)
+ {
+ switch (nUnicode)
+ {
+ case knSpace:
+ pslot->SetDirectionality(kdircWhiteSpace);
+ break;
+ case knLRM:
+ pslot->SetDirectionality(kdircL);
+ break;
+ case knRLM:
+ pslot->SetDirectionality(kdircR);
+ break;
+ case knLRO:
+ pslot->SetDirectionality(kdircLRO);
+ break;
+ case knRLO:
+ pslot->SetDirectionality(kdircRLO);
+ break;
+ case knLRE:
+ pslot->SetDirectionality(kdircLRE);
+ break;
+ case knRLE:
+ pslot->SetDirectionality(kdircRLE);
+ break;
+ case knPDF:
+ pslot->SetDirectionality(kdircPDF);
+ break;
+ default:
+ if (chwGlyphID == LBGlyphID())
+ pslot->SetDirectionality(kdircNeutral);
+ else
+ pslot->SetDirectionality(kdircL);
+ }
+ }
+ else
+ Assert(false); // currently no way to set directionality ahead of time
+}
+
+/*----------------------------------------------------------------------------------------------
+ We have just changed this slot's glyph ID. Change the directionality and breakweight
+ attributes of a new slot based on its glyph ID.
+----------------------------------------------------------------------------------------------*/
+void GrEngine::SetSlotAttrsFromGlyphAttrs(GrSlotState * pslot)
+{
+ InitSlot(pslot);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Create a new segment.
+----------------------------------------------------------------------------------------------*/
+void GrEngine::NewSegment(Segment ** ppseg)
+{
+ *ppseg = new Segment;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Methods to pass on to the tables.
+----------------------------------------------------------------------------------------------*/
+gid16 GrEngine::GetClassGlyphIDAt(int nClass, int nIndex)
+{
+ if (nIndex < 0)
+ return 0;
+ if (nClass < 0)
+ return 0;
+
+ try {
+ return m_pctbl->GetGlyphID(nClass, nIndex);
+ }
+ catch (...)
+ {
+ return 0;
+ }
+}
+
+int GrEngine::GetIndexInGlyphClass(int nClass, gid16 chwGlyphID)
+{
+ try {
+ return m_pctbl->FindIndex(nClass, chwGlyphID);
+ }
+ catch (...)
+ {
+ return -1;
+ }
+}
+
+size_t GrEngine::NumberOfGlyphsInClass(int nClass)
+{
+ try {
+ return m_pctbl->NumberOfGlyphsInClass(nClass);
+ }
+ catch (...)
+ {
+ return 0;
+ }
+}
+
+int GrEngine::GlyphAttrValue(gid16 chwGlyphID, int nAttrID)
+{
+#ifdef OLD_TEST_STUFF
+ if (!m_pgtbl) // test procedures
+ return 0;
+#endif // OLD_TEST_STUFF
+
+ return m_pgtbl->GlyphAttrValue(chwGlyphID, nAttrID);
+}
+
+int GrEngine::ComponentIndexForGlyph(gid16 chwGlyphID, int nCompID)
+{
+#ifdef OLD_TEST_STUFF
+ if (!m_pgtbl) // test procedures
+ return -1;
+#endif // OLD_TEST_STUFF
+
+ return m_pgtbl->ComponentIndexForGlyph(chwGlyphID, nCompID);
+}
+
+
+//:>********************************************************************************************
+//:> For test procedures
+//:>********************************************************************************************
+
+//:Ignore
+
+#ifdef OLD_TEST_STUFF
+
+void GrEngine::SetUpPseudoGlyphTest()
+{
+ m_cpsd = 5;
+
+ m_prgpsd = new GrPseudoMap[m_cpsd];
+
+ m_prgpsd[0].SetUnicode(65);
+ m_prgpsd[0].SetPseudoGlyph(1065);
+
+ m_prgpsd[1].SetUnicode(66);
+ m_prgpsd[1].SetPseudoGlyph(1066);
+
+ m_prgpsd[2].SetUnicode(67);
+ m_prgpsd[2].SetPseudoGlyph(1067);
+
+ m_prgpsd[3].SetUnicode(68);
+ m_prgpsd[3].SetPseudoGlyph(1068);
+
+ m_prgpsd[4].SetUnicode(69);
+ m_prgpsd[4].SetPseudoGlyph(1069);
+
+ m_dipsdInit = 4;
+ m_cPsdLoop = 2;
+ m_ipsdStart = 1;
+}
+
+#endif // OLD_TEST_STUFF
+
+
+//:>********************************************************************************************
+//:> New interface
+//:>********************************************************************************************
+/*----------------------------------------------------------------------------------------------
+ Store the default features values as specified by the client.
+----------------------------------------------------------------------------------------------*/
+void GrEngine::AssignDefaultFeatures(int cfeat, FeatureSetting * prgfset)
+{
+ for (int ifeatIn = 0; ifeatIn < cfeat; ifeatIn++)
+ {
+ int ifeat;
+ FeatureWithID(prgfset[ifeatIn].id, &ifeat);
+ if (ifeat >= 0 )
+ SetDefaultForFeatureAt(ifeat, prgfset[ifeatIn].value);
+ }
+}
+
+bool GrEngine::LoggingTransduction()
+{
+ Assert(false);
+ //return m_pfface->getLogging();
+ //return m_fLogXductn;
+ return true;
+}
+
+} // namespace gr
+
+//:End Ignore
+