diff options
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.cpp | 2031 |
1 files changed, 0 insertions, 2031 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 deleted file mode 100644 index 91db0dfb80a..00000000000 --- a/Build/source/libs/graphite/engine-2.3.1/src/segment/GrEngine.cpp +++ /dev/null @@ -1,2031 +0,0 @@ -/*--------------------------------------------------------------------*//*: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 - |