diff options
Diffstat (limited to 'Build/source/libs/graphite-engine/src/segment')
39 files changed, 0 insertions, 34210 deletions
diff --git a/Build/source/libs/graphite-engine/src/segment/FileInput.cpp b/Build/source/libs/graphite-engine/src/segment/FileInput.cpp deleted file mode 100644 index 52969532cd3..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/FileInput.cpp +++ /dev/null @@ -1,266 +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: FileInput.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Contains the functions for reading from a TT file. (These are functions, not methods - associated with a class.) -----------------------------------------------------------------------------------------------*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** - -#include "GrCommon.h" -#include "GrData.h" -#ifndef _WIN32 -#include "GrMstypes.h" -#endif -#include "GrDebug.h" -#include <fstream> -#include <iostream> -#include <string> -#include "FileInput.h" -#include "GrResult.h" - -//#ifndef _MSC_VER -//#include "config.h" -//#endif - -#ifdef _MSC_VER -#pragma hdrstop -#endif -#undef THIS_FILE -DEFINE_THIS_FILE - -//:End Ignore - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -namespace gr -{ - -//:>******************************************************************************************** -//:> Methods of GrBufferIStream -//:>******************************************************************************************** - -/*---------------------------------------------------------------------------------------------- - Constructor. -----------------------------------------------------------------------------------------------*/ -GrBufferIStream::GrBufferIStream() -{ - m_pbStart = NULL; - m_pbNext = NULL; - m_pbLim = NULL; -} - -/*---------------------------------------------------------------------------------------------- - Destructor. -----------------------------------------------------------------------------------------------*/ -GrBufferIStream::~GrBufferIStream() -{ - Close(); -} - -/*---------------------------------------------------------------------------------------------- - Initialize the stream. -----------------------------------------------------------------------------------------------*/ -#ifdef GR_FW -bool GrBufferIStream::Open(std::wstring stuFileName, int kMode) -#else -bool GrBufferIStream::Open(const char * pcFileName, std::ios::openmode kMode) -#endif -{ - Assert(false); // use OpenBuffer - return false; -} - -/*---------------------------------------------------------------------------------------------- - Initialize the stream to a buffer. -----------------------------------------------------------------------------------------------*/ -bool GrBufferIStream::OpenBuffer(byte * pbBuffer, int cb) -{ - Assert(m_pbStart == NULL); - Assert(m_pbNext == NULL); - Assert(m_pbLim == NULL); - - m_pbStart = pbBuffer; - m_pbNext = pbBuffer; - if (cb > 0) - m_pbLim = m_pbStart + cb; - // otherwise we don't know the length - - return true; -} - -/*---------------------------------------------------------------------------------------------- - Close the stream. -----------------------------------------------------------------------------------------------*/ -void GrBufferIStream::Close() -{ - m_pbStart = NULL; - m_pbNext = NULL; - m_pbLim = NULL; -} - -/*---------------------------------------------------------------------------------------------- - Read a byte from the stream. -----------------------------------------------------------------------------------------------*/ -byte GrBufferIStream::ReadByteFromFont() -{ - byte bInput = *m_pbNext; - m_pbNext += isizeof(byte); - if (m_pbLim && m_pbNext > m_pbLim) - THROW(kresReadFault); - return bInput; -} - -/*---------------------------------------------------------------------------------------------- - Read a short (signed 16-bit) word from the stream. Switch the bytes from big-endian - to little-endian format. -----------------------------------------------------------------------------------------------*/ -short GrBufferIStream::ReadShortFromFont() -{ - short snInput = *(short *)m_pbNext; - m_pbNext += isizeof(short); - if (m_pbLim && m_pbNext > m_pbLim) - THROW(kresReadFault); - snInput = lsbf(snInput); - return snInput; -} - -/*---------------------------------------------------------------------------------------------- - Read a wide character (unsigned 16-bit word) from the stream. - Switch the bytes from big-endian to little-endian format. -----------------------------------------------------------------------------------------------*/ -utf16 GrBufferIStream::ReadUShortFromFont() -{ - utf16 chwInput = *(utf16 *)m_pbNext; - m_pbNext += isizeof(utf16); - if (m_pbLim && m_pbNext > m_pbLim) - THROW(kresReadFault); - chwInput = lsbf(chwInput); - return chwInput; -} - -/*---------------------------------------------------------------------------------------------- - Read a standard (32-bit) word from the stream. Switch the bytes from big-endian - to little-endian format. -----------------------------------------------------------------------------------------------*/ -int GrBufferIStream::ReadIntFromFont() -{ - int nInput = *(int *)m_pbNext; - m_pbNext += isizeof(int); - if (m_pbLim && m_pbNext > m_pbLim) - THROW(kresReadFault); - nInput = lsbf(nInput); - return nInput; -} - -/*---------------------------------------------------------------------------------------------- - Read a block of data from the stream. DON'T switch the bytes from big-endian - to little-endian format. -----------------------------------------------------------------------------------------------*/ -void GrBufferIStream::ReadBlockFromFont(void * pvInput, int cb) -{ - std::copy(m_pbNext, m_pbNext + cb, reinterpret_cast<byte*>(pvInput)); - m_pbNext += cb; - if (m_pbLim && m_pbNext > m_pbLim) - THROW(kresReadFault); -} - -/*---------------------------------------------------------------------------------------------- - Get the absolute position of the font-file stream (relative to the beginning of - the file). For buffers, we just return the byte position in the buffer. -----------------------------------------------------------------------------------------------*/ -void GrBufferIStream::GetPositionInFont(long * plPos) -{ - *plPos = (m_pbNext - m_pbStart); -} - -/*---------------------------------------------------------------------------------------------- - Set the position of the font-file stream to the given absolute position (relative - to the beginning of the file). For buffers, assume the position is relative to the - beginning of the buffer. -----------------------------------------------------------------------------------------------*/ -void GrBufferIStream::SetPositionInFont(long lPos) -{ - m_pbNext = m_pbStart + lPos; - if (m_pbLim && m_pbNext > m_pbLim) - THROW(kresReadFault); -} - - -//:>******************************************************************************************** -//:> Swap byte order. -//:>******************************************************************************************** -int swapb(int nArg) -{ -#if WORDS_BIGENDIAN -return nArg; -#else - int b1, b2, b3, b4; - b1 = ((nArg & 0xFF000000) >> 24) & 0x000000FF; // remove sign extension - b2 = ((nArg & 0x00FF0000) >> 8); // & 0x0000FF00; - b3 = ((nArg & 0x0000FF00) << 8); // & 0x00FF0000; - b4 = ((nArg & 0x000000FF) << 24); // & 0xFF000000; - int nRet = b1 | b2 | b3 | b4; - return nRet; -#endif -} - -unsigned int swapb(unsigned int nArg) -{ -#if WORDS_BIGENDIAN -return nArg; -#else - int b1, b2, b3, b4; - b1 = ((nArg & 0xFF000000) >> 24) & 0x000000FF; // remove sign extension - b2 = ((nArg & 0x00FF0000) >> 8); // & 0x0000FF00; - b3 = ((nArg & 0x0000FF00) << 8); // & 0x00FF0000; - b4 = ((nArg & 0x000000FF) << 24); // & 0xFF000000; - int nRet = b1 | b2 | b3 | b4; - return nRet; -#endif -} - -utf16 swapb(utf16 chwArg) -{ -#if WORDS_BIGENDIAN -return chwArg; -#else - utf16 b1, b2; - b1 = ((chwArg & 0xFF00) >> 8) & 0x00FF; // remove sign extension - b2 = ((chwArg & 0x00FF) << 8); // & 0xFF00; - utf16 chwRet = b1 | b2; - return chwRet; -#endif -} - -short swapb(short snArg) -{ -#if WORDS_BIGENDIAN -return snArg; -#else - short b1, b2; - b1 = ((snArg & 0xFF00) >> 8) & 0x00FF; // remove sign extension - b2 = ((snArg & 0x00FF) << 8); // & 0xFF00; - short snRet = b1 | b2; - return snRet; -#endif -} - -} //namespace gr - diff --git a/Build/source/libs/graphite-engine/src/segment/FileInput.h b/Build/source/libs/graphite-engine/src/segment/FileInput.h deleted file mode 100644 index f8c32b762eb..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/FileInput.h +++ /dev/null @@ -1,104 +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: FileInput.h -Responsibility: Sharon Correll -Last reviewed: not yet - -Description: - Defines utility functions for reading from a font file. -----------------------------------------------------------------------------------------------*/ - -#ifdef _MSC_VER -#pragma once -#endif -#ifndef FILEINPUT_INCLUDED -#define FILEINPUT_INCLUDED - -//:End Ignore - -namespace gr -{ - -int swapb(int nArg); -unsigned int swapb(unsigned int nArg); -utf16 swapb(utf16 chwArg); -short swapb(short snArg); - -// Most significant byte first (converting from least-sig-first): -inline int msbf(int nArg) { return swapb(nArg); } -inline unsigned int msbf(unsigned int nArg) { return swapb(nArg); } -inline utf16 msbf(utf16 chwArg) { return swapb(chwArg); } -inline short msbf(short chwArg) { return swapb(chwArg); } - -// Least significant byte first (converting from most-sig first): -inline int lsbf(int nArg) { return swapb(nArg); } -inline unsigned int lsbf(unsigned int nArg) { return swapb(nArg); }; -inline utf16 lsbf(utf16 chwArg) { return swapb(chwArg); } -inline short lsbf(short chwArg) { return swapb(chwArg); } - -class GrIStream -{ -public: - virtual void Close() = 0; - - virtual byte ReadByteFromFont() = 0; - virtual short ReadShortFromFont() = 0; - virtual utf16 ReadUShortFromFont() = 0; - virtual int ReadIntFromFont() = 0; - virtual void ReadBlockFromFont(void * pvInput, int cb) = 0; - - virtual void GetPositionInFont(long * plPos) = 0; - virtual void SetPositionInFont(long lPos) = 0; - - virtual bool OpenBuffer(byte * pbBuffer, int cb) = 0; - virtual void CloseBuffer() = 0; - -protected: - virtual ~GrIStream() {} -}; - - -/*---------------------------------------------------------------------------------------------- - A stream that reads from a buffer rather than a file. -----------------------------------------------------------------------------------------------*/ -class GrBufferIStream : public GrIStream -{ -public: - GrBufferIStream(); - ~GrBufferIStream(); - - #ifdef GR_FW - virtual bool Open(std::wstring stuFileName, std::ios::openmode kMode); - #else - virtual bool Open(const char * pcFileName, std::ios::openmode kMode); - #endif - virtual void Close(); - - virtual byte ReadByteFromFont(); - virtual short ReadShortFromFont(); - virtual utf16 ReadUShortFromFont(); - virtual int ReadIntFromFont(); - virtual void ReadBlockFromFont(void * pvInput, int cb); - - virtual void GetPositionInFont(long * plPos); - virtual void SetPositionInFont(long lPos); - - virtual bool OpenBuffer(byte * pbBuffer, int cb); - virtual void CloseBuffer() - { - Close(); - } - -protected: - byte * m_pbStart; - byte * m_pbNext; - byte * m_pbLim; -}; - -} // namespace gr - -#endif // !FILEINPUT_INCLUDED diff --git a/Build/source/libs/graphite-engine/src/segment/FontCache.cpp b/Build/source/libs/graphite-engine/src/segment/FontCache.cpp deleted file mode 100644 index f0540463e3b..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/FontCache.cpp +++ /dev/null @@ -1,308 +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: FontCache.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - A cache of all the font-face objects. -----------------------------------------------------------------------------------------------*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" -#ifdef _MSC_VER -#pragma hdrstop -#endif -// any other headers (not precompiled) - -#undef THIS_FILE -DEFINE_THIS_FILE - -//:End Ignore - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Methods -//:>******************************************************************************************** - -namespace gr -{ - -/*---------------------------------------------------------------------------------------------- - Store the given font-face in the cache. Overwrite whatever was there before. - Return NULL if there is nothing appropriate there. -----------------------------------------------------------------------------------------------*/ -void FontCache::GetFontFace(std::wstring strFaceName, bool fBold, bool fItalic, - FontFace ** ppfface) -{ - int ifci = FindCacheItem(strFaceName); - if (ifci < 0) // no fonts of that family present - { - *ppfface = NULL; - return; - } - - CacheItem * pfci = m_prgfci + ifci; - if (fBold) - { - if (fItalic) - *ppfface = pfci->pffaceBI; - else - *ppfface = pfci->pffaceBold; - } - else - { - if (fItalic) - *ppfface = pfci->pffaceItalic; - else - *ppfface = pfci->pffaceRegular; - } -} - -/*---------------------------------------------------------------------------------------------- - Store the given font-face in the cache. Overwrite whatever was there before. -----------------------------------------------------------------------------------------------*/ -void FontCache::CacheFontFace(std::wstring strFaceName, bool fBold, bool fItalic, - FontFace * pfface) -{ - if (m_prgfci == NULL) - Initialize(); - - int ifciIns = FindCacheItem(strFaceName); - int ifci = ifciIns; - if (ifciIns < 0) - { - ifci = (ifciIns + 1) * -1; - InsertCacheItem(ifci); - std::copy(strFaceName.c_str(), strFaceName.c_str() + - (strFaceName.size() + 1), m_prgfci[ifci].szFaceName); - } - - CacheItem * pfci = m_prgfci + ifci; - - bool fPrevNull; - if (fBold) - { - if (fItalic) - { - fPrevNull = (pfci->pffaceBI == NULL); - pfci->pffaceBI = pfface; - } - else - { - fPrevNull = (pfci->pffaceBold == NULL); - pfci->pffaceBold = pfface; - } - } - else - { - if (fItalic) - { - fPrevNull = (pfci->pffaceItalic == NULL); - pfci->pffaceItalic = pfface; - } - else - { - fPrevNull = (pfci->pffaceRegular == NULL); - pfci->pffaceRegular = pfface; - } - } - - if (fPrevNull && (pfface != NULL)) - m_cfface++; -} - -/*---------------------------------------------------------------------------------------------- - Remove the given font-face from the cache. Return false if it couldn't be found. -----------------------------------------------------------------------------------------------*/ -bool FontCache::RemoveFontFace(std::wstring strFaceName, bool fBold, bool fItalic, - bool fZapCache) -{ - int ifci = FindCacheItem(strFaceName); - if (ifci < 0) - { - return false; - } - - bool fPrevVal; - CacheItem * pfci = m_prgfci + ifci; - if (fBold) - { - if (fItalic) - { - fPrevVal = (pfci->pffaceBI != NULL); - pfci->pffaceBI = NULL; - } - else - { - fPrevVal = (pfci->pffaceBold != NULL); - pfci->pffaceBold = NULL; - } - } - else - { - if (fItalic) - { - fPrevVal = (pfci->pffaceItalic != NULL); - pfci->pffaceItalic = NULL; - } - else - { - fPrevVal = (pfci->pffaceRegular != NULL); - pfci->pffaceRegular = NULL; - } - } - - if (fPrevVal) - m_cfface--; - - Assert(m_cfface >= 0); - - if (m_flush == kflushAuto && fZapCache) - { - DeleteIfEmpty(); - } - - return fPrevVal; -} - -/*---------------------------------------------------------------------------------------------- - Search for the font-family in the cache and return its index. - If not present, return a negative number indicating where it was expected. -----------------------------------------------------------------------------------------------*/ -int FontCache::FindCacheItem(std::wstring strFaceName) -{ - if (m_cfci == 0) - return -1; - - Assert(m_prgfci); - - // Use a binary-chop search. - - int ifciLow = 0; - int ifciHigh = m_cfci; - while (true) - { - int ifciMid = (ifciHigh + ifciLow) >> 1; // divide by 2 - CacheItem * pfci = m_prgfci + ifciMid; - int tst = wcscmp(strFaceName.c_str(), (const wchar_t *)pfci->szFaceName); - if (tst == 0) - return ifciMid; // found it - if (ifciLow + 1 == ifciHigh) - { - // not there; return where expected: 0 -> -1, 1 -> -2 - Assert(ifciMid == ifciLow); - if (tst < 0) - return (ifciLow * -1) - 1; - else - return (ifciHigh * -1) - 1; - } - - // Keep looking. - if (tst < 0) - ifciHigh = ifciMid; - else - ifciLow = ifciMid; - } -} - -/*---------------------------------------------------------------------------------------------- - Insert space in the cache at location ifci. -----------------------------------------------------------------------------------------------*/ -void FontCache::InsertCacheItem(int ifci) -{ - if (m_cfci == m_cfciMax) - { - // Cache is full; double the space. - CacheItem * m_prgfciOld = m_prgfci; - m_prgfci = new CacheItem[m_cfciMax * 2]; - std::copy(m_prgfciOld, m_prgfciOld + m_cfciMax, m_prgfci); - delete[] m_prgfciOld; - m_cfciMax *= 2; - } - - // This copy involves overlapping ranges, so we need copy_backward not copy - // to satisfy the preconditions - std::copy_backward(m_prgfci + ifci, m_prgfci + m_cfci, m_prgfci + m_cfci + 1); - m_cfci++; - - // Initialize inserted item. - CacheItem * pfci = m_prgfci + ifci; - pfci->pffaceRegular = NULL; - pfci->pffaceBold = NULL; - pfci->pffaceItalic = NULL; - pfci->pffaceBI = NULL; -} - -/*---------------------------------------------------------------------------------------------- - Delete the cache if it is empty. -----------------------------------------------------------------------------------------------*/ -void FontCache::DeleteIfEmpty() -{ - if (m_cfface <= 0) - // All items are NULL; delete this cache. Probably this is because - // the program is exiting. - FontFace::ZapFontCache(); -} - -/*---------------------------------------------------------------------------------------------- - Check that the cache is indeed empty. -----------------------------------------------------------------------------------------------*/ -void FontCache::AssertEmpty() -{ -#ifdef _DEBUG - for (int ifci = 0; ifci < m_cfci; ifci++) - { - CacheItem * pfci = m_prgfci + ifci; - Assert(pfci->pffaceRegular == NULL); - Assert(pfci->pffaceBold == NULL); - Assert(pfci->pffaceItalic == NULL); - Assert(pfci->pffaceBI == NULL); - } -#endif // _DEBUG -} - -/*---------------------------------------------------------------------------------------------- - Set the flush mode on the cache to indicate whether or not it should be deleted when - it becomes empty. -----------------------------------------------------------------------------------------------*/ -void FontCache::SetFlushMode(int flush) -{ - m_flush = flush; - - if (m_flush == kflushAuto) - { - // Delete any font faces that have no remaining corresponding fonts. - // Work backwards so as we remove items the loop still works. - for (int ifci = m_cfci; --ifci >= 0; ) - { - CacheItem * pfci = m_prgfci + ifci; - if (pfci->pffaceRegular && pfci->pffaceRegular->NoFonts()) - RemoveFontFace(pfci->szFaceName, false, false, false); - if (pfci->pffaceBold && pfci->pffaceBold->NoFonts()) - RemoveFontFace(pfci->szFaceName, true, false, false); - if (pfci->pffaceItalic && pfci->pffaceItalic->NoFonts()) - RemoveFontFace(pfci->szFaceName, false, true, false); - if (pfci->pffaceBI && pfci->pffaceBI->NoFonts()) - RemoveFontFace(pfci->szFaceName, true, true, false); - } - - if (m_cfface <= 0) - FontFace::ZapFontCache(); - } -} - -} // namespace gr diff --git a/Build/source/libs/graphite-engine/src/segment/FontCache.h b/Build/source/libs/graphite-engine/src/segment/FontCache.h deleted file mode 100644 index 56da5ab26b8..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/FontCache.h +++ /dev/null @@ -1,105 +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: FontCache.h -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - A cache of all the font-face objects known to mankind. There is exactly one instance - of a FontCache. -----------------------------------------------------------------------------------------------*/ -#ifdef _MSC_VER -#pragma once -#endif -#ifndef FONTCACHE_INCLUDED -#define FONTCACHE_INCLUDED - -//:End Ignore - -namespace gr -{ - -class FontFace; -class FontMemoryUsage; - -/*---------------------------------------------------------------------------------------------- - TODO: change from a sorted list to a hash table, if performance so requires. -----------------------------------------------------------------------------------------------*/ -class FontCache { - friend class FontMemoryUsage; - -public: - FontCache() - { - m_cfci = 0; - m_prgfci = NULL; - m_cfciMax = 0; - m_cfface = 0; - m_flush = kflushAuto; - } - - ~FontCache() - { - delete[] m_prgfci; - m_prgfci = NULL; - m_cfci = 0; - m_cfciMax = 0; - m_cfface = 0; - } - - void Initialize() - { - m_cfci = 0; - m_prgfci = new CacheItem[12]; - m_cfciMax = 12; - m_cfface = 0; - } - - struct CacheItem - { - wchar_t szFaceName[32]; // type should match std::wstring - FontFace * pffaceRegular; - FontFace * pffaceBold; - FontFace * pffaceItalic; - FontFace * pffaceBI; - }; - - void GetFontFace(std::wstring strFaceName, bool fBold, bool fItalic, FontFace ** ppfface); - void CacheFontFace(std::wstring strFaceName, bool fBold, bool fItalic, FontFace * pfface); - bool RemoveFontFace(std::wstring strFaceName, bool fBold, bool fItalic, bool fZapCache = true); - void DeleteIfEmpty(); - void AssertEmpty(); - - int GetFlushMode() - { - return m_flush; - } - void SetFlushMode(int); - - // Debugging: - //bool DbgCheckFontCache(); - - void calculateMemoryUsage(FontMemoryUsage & fmu); - -protected: - int FindCacheItem(std::wstring strFaceName); - void InsertCacheItem(int ifci); - -protected: - // member variables; - int m_cfci; // number of items (font-families) - int m_cfciMax; // amount of space available - int m_cfface; // number of font-faces - CacheItem * m_prgfci; - - int m_flush; -}; - -} // namespace gr - - -#endif // !FONTCACHE_INCLUDED diff --git a/Build/source/libs/graphite-engine/src/segment/FontFace.cpp b/Build/source/libs/graphite-engine/src/segment/FontFace.cpp deleted file mode 100644 index 45461fe63ac..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/FontFace.cpp +++ /dev/null @@ -1,598 +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 FontFace class. -----------------------------------------------------------------------------------------------*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" -#include <functional> -#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 -//:>******************************************************************************************** - -FontCache * FontFace::s_pFontCache = 0; - -//:>******************************************************************************************** -//:> New interface -//:>******************************************************************************************** -/*---------------------------------------------------------------------------------------------- - Return the appropriate FontFace, initialized with Graphite tables. - Called from the font constructor. -----------------------------------------------------------------------------------------------*/ -FontFace * FontFace::GetFontFace(Font * pfont, - std::wstring strFaceName, bool fBold, bool fItalic, - bool fDumbFallback) -{ - if (s_pFontCache == NULL) - s_pFontCache = new FontCache; - - FontFace * pfface; - s_pFontCache->GetFontFace(strFaceName, fBold, fItalic, &pfface); - if (pfface) - return pfface; - - // Create a new font face. - pfface = new FontFace(); - pfface->InitFontFace(pfont, strFaceName, fBold, fItalic, fDumbFallback); - return pfface; -} - -/*---------------------------------------------------------------------------------------------- - Initialize the engine using the given Graphite font. -----------------------------------------------------------------------------------------------*/ -GrResult FontFace::InitFontFace(Font * pfont, - std::wstring stuFaceName, bool fBold, bool fItalic, - bool fDumbFallback) -{ - AssertPtrN(pfont); - - m_pgreng = new GrEngine; - m_pgreng->m_pfface = this; - - m_pgreng->m_nScriptTag = 0; // not currently used, but set it to something - - std::wstring stuFeatures; - - //stuFeatures = stuFeaturesArg; - - if (wcscmp(stuFaceName.c_str(), m_pgreng->m_stuFaceName.c_str()) != 0) - { - s_pFontCache->RemoveFontFace(m_pgreng->FaceName(), m_pgreng->Bold(), m_pgreng->Italic()); - - m_pgreng->DestroyEverything(); // nothing we've cached is safe or useful. - m_pgreng->m_stuFaceName = stuFaceName; // if this is buggy, using assign might fix it - } - - //GrResult res = kresFail; -//#ifdef GR_FW -// // Read from the control file indicated by the registry, if any. -// std::wstring stuFaceNameTmp; -// stuFaceNameTmp.assign(rgchFaceName, wcslen(rgchFaceName)); -// res = InitFromControlFile(pfont, stuFaceName.c_str(), fBold, fItalic); -//#endif // GR_FW - - // Read directly from the font. - m_pgreng->DestroyContents(); - GrResult res = kresUnexpected; - try { - res = m_pgreng->ReadFontTables(pfont, fItalic); - } - catch (...) - { - if (fDumbFallback && m_pgreng->DumbFallback() && !m_pgreng->BadFont()) - { - // If we have a basically good font but can't do Graphite, - // just go with empty tables, which should be set up. - res = m_pgreng->m_resFontRead; - } - else - { - if (m_cfonts == 0) - { - //s_pFontCache->DeleteIfEmpty(); - //Assert(s_pFontCache == 0); - delete this; // will also delete GrEngine - } - else - { - delete m_pgreng; - } - m_pgreng = NULL; - throw; // throw original exception - } - } - - m_pgreng->m_resFontValid = res; - - m_pgreng->m_fBold = fBold; - m_pgreng->m_fItalic = fItalic; - - s_pFontCache->CacheFontFace(m_pgreng->FaceName(), fBold, fItalic, this); - - return m_pgreng->m_resFontValid; -} - -/*---------------------------------------------------------------------------------------------- - Read the cmap and Graphite tables from the font that is selected into the graphics - device. - - @return A GrResult indicating whether we were successful in loading the Graphite font: - - kresOk means success - - kresFail means the Graphite font could not be found or the basic font tables - (head, name, cmap) could not be loaded - - kresUnexpected means the Graphite tables could not be loaded - - kresFalse means it is not a Graphite font at all (has no Silf table). -----------------------------------------------------------------------------------------------*/ -GrResult GrEngine::ReadFontTables(Font * pfont, bool fItalic) -{ - GrResult res = kresOk; - m_ferr = kferrOkay; - GrBufferIStream grstrm; - - FontException fexptn; - fexptn.version = -1; - fexptn.subVersion = -1; - - bool fOk = false; - - const void * pHeadTbl; const void * pSileTbl; const void * pSilfTbl; - const void * pFeatTbl; const void * pGlatTbl; const void * pGlocTbl; const void * pSillTbl; - //const void * pCmapTbl; const void * pNameTbl; - size_t cbHeadSz, cbSilfSz, cbFeatSz, cbGlatSz, cbGlocSz, cbSillSz; - //size_t cbCmapSz, cbSileSz, cbNameSz; - - m_fFakeItalic = false; - - bool fBasicTables = false; - bool fSilf = false; // does the font have some sort of Silf table? - int nCheckSum = 0; - - bool fBadBase = false, - fMismatchedBase = false, - fFontIsItalic = false; - - // First read the head table. This gives us the checksum that we are using as a - // unique identifer. If it is the same as the one stored, and things appear set up, - // don't reload the tables. - res = (pHeadTbl = pfont->getTable(TtfUtil::TableIdTag(ktiHead), &cbHeadSz)) ? kresOk : kresFail; - fOk = pHeadTbl && (cbHeadSz == 0 || TtfUtil::CheckTable(ktiHead, pHeadTbl, cbHeadSz)); - if (res == kresFail) - { - m_stuInitError = L"could not locate head table for Graphite rendering"; - m_ferr = kferrFindHeadTable; - goto LUnexpected; - } - if (!fOk) - { - m_stuInitError = L"could not read design units for Graphite rendering"; - m_ferr = kferrReadDesignUnits; - goto LUnexpected; - } - m_mFontEmUnits = TtfUtil::DesignUnits(pHeadTbl); - nCheckSum = TtfUtil::HeadTableCheckSum(pHeadTbl); - fFontIsItalic = TtfUtil::IsItalic(pHeadTbl); - - if (m_nFontCheckSum == nCheckSum && m_ptman) - return m_resFontRead; // already initialized in some form - - DestroyContents(); - - Assert(!m_ptman); - Assert(!m_pctbl); - Assert(!m_pgtbl); - Assert(!m_prgpsd); - m_prgpsd = NULL; - m_cpsd = 0; - - m_ptman = new GrTableManager(this); - - m_fFakeItalic = (fItalic && !fFontIsItalic); - - // Look for an Sile table. If there is one, this is an extension font containing only - // the Graphite tables. Read the base font name out of the Sile table, and use it to - // read the cmap. Then replace the original font name to read the Graphite tables. - - m_fUseSepBase = false; - m_stuBaseFaceName.erase(); - - // TODO: rework the handling of the Sile table. - pSileTbl = NULL; - //pSileTbl = pfont->getTable(TtfUtil::TableIdTag(ktiSile)); - //if (pSileTbl) - //{ - // pgg->get_FontCharProperties(&chrpOriginal); - // grstrm.OpenBuffer(pSileTbl, sile_tbl.size()); - // m_fUseSepBase = ReadSileTable(pgg, grstrm, 0, &m_mFontEmUnits, &fMismatchedBase); - // grstrm.Close(); - - // if (!m_fUseSepBase) - // { - // SwitchGraphicsFont(pgg, false); // back to Graphite table font - // m_stuBaseFaceName.erase(); - // fBadBase = true; - // m_fUseSepBase = false; - // } - // // Otherwise leave the GrGraphics in a state to read from the base font. - //} - - // We don't need the offset table, and there's no way to get it anyway - // without a font file. - - // cmap and name - Assert(!m_fCmapTblCopy); - Assert(!m_fNameTblCopy); - fOk = SetCmapAndNameTables(pfont); - if (!fOk) - { - goto LUnexpected; - } - - fBasicTables = true; - - // If we have a bad base file, don't do Graphite stuff. - if (fBadBase || fMismatchedBase) - goto LUnexpected; - - /**** - Obtain font name from InitNew() now instead of reading from font file. InitNew should - should have a correct font name passed to it since it should come from a font registered - by GrFontInst.exe. This commented code could be use to verify name in font file matches. - NOTE: if we ever use this code again, make sure we're using the base font name table, - not the Graphite wrapper font name table. - // find the font family name - if (!TtfUtil::Get31EngFamilyInfo(vbName.Begin(), lnNameOff, lnNameSz)) - { // use Name table which is Symbol encode instead - // this could cause problems if a real Symbol writing system is used in the name table - // however normally real Unicode values are used instead a Symbol writing system - if (!TtfUtil::Get30EngFamilyInfo(vbName.Begin(), lnNameOff, lnNameSz)) - { - ReturnResult(kresFail); - } - // test for Symbol writing system. first byte of Unicode id should be 0xF0 - if (vbName[lnNameOff + 1] == (unsigned char)0xF0) // 1 - Unicode id is big endian - ReturnResult(kresFail); - } - if (!TtfUtil::SwapWString(vbName.Begin() + lnNameOff, lnNameSz / isizeof(utf16))) - ReturnResult(kresFail); - - m_stuFaceName = std::wstring((utf16 *)(vbName.begin() + lnNameOff), lnNameSz / isizeof(utf16)); - ****/ - - // Silf - res = (pSilfTbl = pfont->getTable(TtfUtil::TableIdTag(ktiSilf), &cbSilfSz)) ? kresOk : kresFail; - fOk = pSilfTbl && (cbSilfSz == 0 || TtfUtil::CheckTable(ktiSilf, pSilfTbl, cbSilfSz)); - if (!fOk) - { - m_stuInitError = L"could not load Silf table for Graphite rendering"; - m_ferr = kferrLoadSilfTable; - goto LUnexpected; - } - - // Feat - res = (pFeatTbl = pfont->getTable(TtfUtil::TableIdTag(ktiFeat), &cbFeatSz)) ? kresOk : kresFail; - fOk = pFeatTbl && (cbFeatSz == 0 || TtfUtil::CheckTable(ktiFeat, pFeatTbl, cbFeatSz)); - if (!fOk) - { - // TODO: just create an empty set of features, since this is not disastrous. - m_stuInitError = L"could not load Feat table for Graphite rendering"; - m_ferr = kferrLoadFeatTable; - goto LUnexpected; - } - - // Glat - res = (pGlatTbl = pfont->getTable(TtfUtil::TableIdTag(ktiGlat), &cbGlatSz)) ? kresOk : kresFail; - fOk = pGlatTbl && (cbGlatSz == 0 || TtfUtil::CheckTable(ktiGlat, pGlatTbl, cbGlatSz)); - if (!fOk) - { - m_stuInitError = L"could not load Glat table for Graphite rendering"; - m_ferr = kferrLoadGlatTable; - goto LUnexpected; - } - - // Gloc - res = (pGlocTbl = pfont->getTable(TtfUtil::TableIdTag(ktiGloc), &cbGlocSz)) ? kresOk : kresFail; - fOk = pGlocTbl && (cbGlocSz == 0 || TtfUtil::CheckTable(ktiGloc, pGlocTbl, cbGlocSz)); - if (!fOk) - { - m_stuInitError = L"could not load Gloc table for Graphite rendering"; - m_ferr = kferrLoadGlocTable; - goto LUnexpected; - } - - // Sill - try { - res = (pSillTbl = pfont->getTable(TtfUtil::TableIdTag(ktiSill), &cbSillSz)) ? kresOk : kresFail; - fOk = pSillTbl && (cbSillSz == 0 || TtfUtil::CheckTable(ktiSill, pSillTbl, cbSillSz)); - } - catch (...) - { - fOk = true; - pSillTbl = NULL; - } - // if table couldn't be loaded, this is not disastrous. - -// ibGlocStart = cbGlatTbl; - fOk = CheckTableVersions(&grstrm, - (byte *)pSilfTbl, 0, - (byte *)pGlocTbl, 0, - (byte *)pFeatTbl, 0, - &m_fxdBadVersion); - if (!fOk) - { -// wchar_t rgch1[50]; -// wchar_t rgch2[50]; -//#if defined(_WIN32) -// // This version does not work in Windows, in spite of being documented: -// // swprintf(rgch, 50, L"%d", (m_fxdBadVersion >> 16)); -// // Removing the size argument make it work. -// swprintf(rgch1, L"%d", (m_fxdBadVersion >> 16)); -// swprintf(rgch2, L"%d", (m_fxdBadVersion & 0x0000FFFF)); -//#else -// swprintf(rgch1, 50, L"%d", (m_fxdBadVersion >> 16)); -// swprintf(rgch2, 50, L"%d", (m_fxdBadVersion & 0x0000FFFF)); -//#endif - char rgch[50]; // more than enough space to print two 16-bit ints - char *pch = &rgch[0]; - sprintf(rgch, "%d.%d", (m_fxdBadVersion >> 16), (m_fxdBadVersion & 0x0000FFFF)); - std::wstring stu = L"unsupported version ("; - //stu.append(rgch1); - //stu.append(L"."); - //stu.append(rgch2); - while (*pch != 0) - stu.push_back((wchar_t)*pch++); - stu.append(L") of Graphite tables"); - m_stuInitError.assign(stu.c_str()); - m_ferr = kferrBadVersion; - goto LUnexpected; - } - - try - { - // Parse the "Silf" table. - grstrm.OpenBuffer((byte*)pSilfTbl, cbSilfSz); - int chwGlyphIDMax, fxdVersion; - bool f = ReadSilfTable(grstrm, 0, 0, &chwGlyphIDMax, &fxdVersion); - grstrm.Close(); - if (!f) - { - m_ferr = kferrReadSilfTable; - fexptn.errorCode = m_ferr; - throw fexptn; - } - - // Parse the "Gloc" and "Glat" tables. - { - GrBufferIStream grstrmGlat; - - grstrm.OpenBuffer((byte *)pGlocTbl, cbGlocSz); - grstrmGlat.OpenBuffer((byte *)pGlatTbl, cbGlatSz); - f = ReadGlocAndGlatTables(grstrm, 0, grstrmGlat, 0, chwGlyphIDMax, fxdVersion); - grstrm.Close(); - grstrmGlat.Close(); - if (!f) - { - m_ferr = kferrReadGlocGlatTable; - fexptn.errorCode = m_ferr; - throw fexptn; - } - } - - // Parse the "Feat" table. - grstrm.OpenBuffer((byte *)pFeatTbl, cbFeatSz); - f = ReadFeatTable(grstrm, 0); - grstrm.Close(); - if (!f) - { - m_ferr = kferrReadFeatTable; - fexptn.errorCode = m_ferr; - throw fexptn; - } - - // Parse the "Sill" table. - if (pSillTbl) - { - grstrm.OpenBuffer((byte *)pSillTbl, cbFeatSz); - f = ReadSillTable(grstrm, 0); - grstrm.Close(); - if (!f) - { - m_ferr = kferrReadSillTable; - fexptn.errorCode = m_ferr; - throw fexptn; - } - } - else - m_langtbl.CreateEmpty(); - } - catch (...) - { - fSilf = false; - m_resFontRead = kresUnexpected; - try { - DestroyContents(false); - } - catch (...) - {} - goto LUnexpected; - } - - m_stuErrCtrlFile.erase(); - m_nFontCheckSum = nCheckSum; - m_resFontRead = kresOk; - m_ferr = kferrOkay; - ReturnResult(kresOk); - -LUnexpected: - // Don't do this, because it is possible to use a base font with an empty Graphite - // engine: - //if (m_fUseSepBase || m_stuBaseFaceName.Length() > 0) - //{ - // SwitchGraphicsFont(pgg, false); // back to Graphite table font - // m_stuBaseFaceName.erase(); - // m_fUseSepBase = false; - //} - - CreateEmpty(); - m_nFontCheckSum = nCheckSum; - if (!fBasicTables) - m_resFontRead = kresFail; // bad font - else if (!fSilf) - m_resFontRead = kresFalse; // no Silf table--not a Graphite font - else - m_resFontRead = kresUnexpected; // couldn't read the Graphite tables - - fexptn.errorCode = m_ferr; - fexptn.version = m_fxdBadVersion >> 16; - fexptn.subVersion = m_fxdBadVersion & 0x0000FFFF; - throw fexptn; - - ReturnResult(m_resFontRead); -} - -/*---------------------------------------------------------------------------------------------- - Read the cmap and name tables. - - This is called from two places. One is when we first initialize the engine. Also, if the - font tables have not been actually copied from the font, they may have been deleted - when the font was deleted. So when reusing the engine, set them to something valid based - on the current font. -----------------------------------------------------------------------------------------------*/ -bool GrEngine::SetCmapAndNameTables(Font * pfont) -{ - GrResult res = kresOk; - bool fOk; - const void * pCmapTbl; - const void * pNameTbl; - size_t cbCmapSz, cbNameSz; - - // cmap - if (!m_fCmapTblCopy) - { - res = (pCmapTbl = pfont->getTable(TtfUtil::TableIdTag(ktiCmap), &cbCmapSz)) ? kresOk : kresFail; - fOk = pCmapTbl && (cbCmapSz == 0 || TtfUtil::CheckTable(ktiCmap, pCmapTbl, cbCmapSz)); - if (!fOk) - { - m_stuInitError = L"could not locate cmap table"; - m_ferr = kferrFindCmapTable; - return false; - } - - if (pCmapTbl && cbCmapSz > 0) - { - // Make a private copy of the cmap for the engine's use. - m_pCmapTbl = new byte[cbCmapSz]; - std::copy(reinterpret_cast<const byte*>(pCmapTbl), - reinterpret_cast<const byte*>(pCmapTbl) + cbCmapSz, m_pCmapTbl); - m_fCmapTblCopy = true; - m_cbCmapTbl = cbCmapSz; - } - else - { - m_pCmapTbl = const_cast<byte*>(reinterpret_cast<const byte*>(pCmapTbl)); - m_fCmapTblCopy = false; - } - - // MS Unicode cmap - m_pCmap_3_1 = TtfUtil::FindCmapSubtable(m_pCmapTbl, 3, 1); - m_pCmap_3_10 = TtfUtil::FindCmapSubtable(m_pCmapTbl, 3, 10); - if (!m_pCmap_3_1) - m_pCmap_3_1 = TtfUtil::FindCmapSubtable(m_pCmapTbl, 3, 0); - if (!m_pCmap_3_1) - { - m_stuInitError = L"failure to load cmap subtable"; - m_ferr = kferrLoadCmapSubtable; - return false; - } - if (!TtfUtil::CheckCmap31Subtable(m_pCmap_3_1)) - { - m_stuInitError = L"checking cmap subtable failed"; - m_ferr = kferrCheckCmapSubtable; - return false; - } - } - else - { - Assert(m_pCmapTbl); - } - - // name table - eventually need feature label strings - - // Currently the only stuff we're getting from the name table are our feature names, - // so use the version from the Graphite font (not the base font if any). - //////if (m_fUseSepBase) - ////// pgg->SetupGraphics(&chrpOriginal); - - if (!m_fNameTblCopy) - { - res = (pNameTbl = (byte *)pfont->getTable(TtfUtil::TableIdTag(ktiName), &cbNameSz)) ? kresOk : kresFail; - fOk = pNameTbl && (cbNameSz == 0 || TtfUtil::CheckTable(ktiName, pNameTbl, cbNameSz)); - if (!fOk) - { - m_stuInitError = L"could not locate name table"; - m_ferr = kferrFindNameTable; - return false; - } - - if (pNameTbl && cbNameSz > 0) - { - // Make a private copy of the name table for the engine's use. - m_pNameTbl = new byte[cbNameSz]; - std::copy(reinterpret_cast<const byte*>(pNameTbl), - reinterpret_cast<const byte*>(pNameTbl) + cbNameSz, m_pNameTbl); - m_fNameTblCopy = true; - m_cbNameTbl = cbNameSz; - } - else - { - m_pNameTbl = const_cast<byte*>(reinterpret_cast<const byte*>(pNameTbl)); - m_fNameTblCopy = false; - } - } - else - { - Assert(m_pNameTbl); - } - - return true; -} - - -//void FontFace::DbgCheckFontFace() -//{ -// Assert(m_cfonts < 5000); -// Assert(m_cfonts >= 0); -// wchar_t chw0 = m_pgreng->m_stuFaceName[0]; -// Assert(chw0 >= 0x0040); // A -// Assert(chw0 <= 0x007A); // z -//} - -} // namespace gr - -//:End Ignore diff --git a/Build/source/libs/graphite-engine/src/segment/FontFace.h b/Build/source/libs/graphite-engine/src/segment/FontFace.h deleted file mode 100644 index 7f2684a5908..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/FontFace.h +++ /dev/null @@ -1,246 +0,0 @@ -/*-------------------------------------------------------------------- -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: FontFace.h -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Contains the definition of the FontFace class. - TODO: Merge with GrEngine. -----------------------------------------------------------------------------------------------*/ -#ifdef _MSC_VER -#pragma once -#endif -#ifndef FONTFACE_INCLUDED -#define FONTFACE_INCLUDED -#include <limits> - -#ifdef _MSC_VER -#include <crtdbg.h> -#endif - -namespace gr -{ - -class IGrJustifier; -class Segment; - - -/*---------------------------------------------------------------------------------------------- - The GrEngine serves as the top level object that knows how to run Graphite tables - and generate Graphite segments. - - Primarily, this class implements IRenderEngine, which allows it to serve as a FW - rendering engine. It also implements ISimpleInit, a general interface for initializing - using a string. Finally, it implements ITraceControl, a very simple interface which - allows a client to flip a flag indicating whether or not we want to output a log of - the Graphite transduction process. - - Hungarian: greng -----------------------------------------------------------------------------------------------*/ -class FontFace -{ - friend class gr::FontMemoryUsage; - -public: - FontFace() - { - m_cfonts = 0; - } - - ~FontFace() - { - if (s_pFontCache) - s_pFontCache->RemoveFontFace(m_pgreng->FaceName(), m_pgreng->Bold(), m_pgreng->Italic()); - delete m_pgreng; - } - - void IncFontCount() - { - m_cfonts++; - } - void DecFontCount() - { - m_cfonts--; - if (m_cfonts <= 0 && (s_pFontCache == NULL || s_pFontCache->GetFlushMode() == kflushAuto)) - delete this; - } - - bool NoFonts() - { - return (m_cfonts <= 0); - } - - static FontFace * GetFontFace(Font * pfont, - std::wstring strFaceName, bool fBold, bool fItalic, - bool fDumbFallback = false); - - GrResult InitFontFace(Font * pfont, - std::wstring stuFaceName, bool fBold, bool fItalic, - bool fDumbLayout); - - FontErrorCode IsValidForGraphite(int * pnVersion, int * pnSubVersion) - { - return m_pgreng->IsValidForGraphite(pnVersion, pnSubVersion); - } - - static void ZapFontCache() - { - if (s_pFontCache) - { - s_pFontCache->AssertEmpty(); - delete s_pFontCache; - } - s_pFontCache = NULL; - } - - static void SetFlushMode(int flush) - { - if (s_pFontCache == NULL) - s_pFontCache = new FontCache; - s_pFontCache->SetFlushMode(flush); - } - static int GetFlushMode() - { - if (s_pFontCache == NULL) - s_pFontCache = new FontCache; - return s_pFontCache->GetFlushMode(); - } - - // Temporary, until interface gets thoroughly reworked: - GrEngine * GraphiteEngine() - { - return m_pgreng; - } - - // Feature access: - size_t NumberOfFeatures() - { - return m_pgreng->NumberOfFeatures_ff(); - } - featid FeatureID(size_t ifeat) - { - return m_pgreng->FeatureID_ff(ifeat); - } - size_t FeatureWithID(featid id) - { - return m_pgreng->FeatureWithID_ff(id); - } - bool GetFeatureLabel(size_t ifeat, lgid language, utf16 * label) - { - return m_pgreng->GetFeatureLabel_ff(ifeat, language, label); - } - int GetFeatureDefault(size_t ifeat) // index of default setting - { - return m_pgreng->GetFeatureDefault_ff(ifeat); - } - size_t NumberOfSettings(size_t ifeat) - { - return m_pgreng->NumberOfSettings_ff(ifeat); - } - int GetFeatureSettingValue(size_t ifeat, size_t ifset) - { - return m_pgreng->GetFeatureSettingValue_ff(ifeat, ifset); - } - bool GetFeatureSettingLabel(size_t ifeat, size_t ifset, lgid language, utf16 * label) - { - return m_pgreng->GetFeatureSettingLabel_ff(ifeat, ifset, language, label); - } - // Feature-label language access: - size_t NumberOfFeatLangs() - { - return m_pgreng->NumberOfFeatLangs_ff(); - } - short FeatLabelLang(int ilang) - { - return m_pgreng->GetFeatLabelLang_ff(ilang); - } - // Language access: - size_t NumberOfLanguages() - { - return m_pgreng->NumberOfLanguages_ff(); - } - isocode LanguageCode(size_t ilang) - { - return m_pgreng->GetLanguageCode_ff(ilang); - } - - // Script Direction access: - ScriptDirCode ScriptDirection() const throw() - { - unsigned int script_dirs = 0; - OLECHAR err_dummy = 0; - m_pgreng->get_ScriptDirection(&script_dirs, &err_dummy, 1); - return ScriptDirCode(script_dirs); - } - - bool BadFont(FontErrorCode * pferr = NULL) - { - return m_pgreng->BadFont(pferr); - } - bool DumbFallback(FontErrorCode * pferr = NULL) - { - return m_pgreng->DumbFallback(pferr); - } - -public: - // For use in segment creation: - void RenderLineFillSegment(Segment * pseg, Font * pfont, ITextSource * pts, - LayoutEnvironment & layout, - toffset ichStart, toffset ichStop, float xsMaxWidth, bool fBacktracking) - { - m_pgreng->MakeSegment(pseg, pfont, pts, NULL, layout, - ichStart, ichStop, xsMaxWidth, fBacktracking, false, 0, kestMoreLines); - } - void RenderRangeSegment(Segment * pseg, Font * pfont, - ITextSource * pts, LayoutEnvironment & layout, - toffset ichStart, toffset ichStop) - { - m_pgreng->MakeSegment(pseg, pfont, pts, NULL, layout, - ichStart, ichStop, kPosInfFloat, false, false, 0, kestMoreLines); - } - void RenderJustifiedSegment(Segment * pseg, Font * pfont, - ITextSource * pts, LayoutEnvironment & layout, - toffset ichStart, toffset ichStop, float xsCurrentWidth, float xsDesiredWidth) - { - m_pgreng->MakeSegment(pseg, pfont, pts, NULL, layout, - ichStart, ichStop, xsCurrentWidth, false, true, xsDesiredWidth, kestMoreLines); - } - - // Debugging. - //static bool DbgCheckFontCache() - //{ - // if (s_pFontCache) - // return s_pFontCache->DbgCheckFontCache(); - // else - // return true; - //} - //void DbgCheckFontFace(); - - static void calculateAllMemoryUsage(FontMemoryUsage & fmu); - void calculateMemoryUsage(FontMemoryUsage & fmu); - -protected: - // Number of fonts in existence that use this face; when it goes to zero, delete. - int m_cfonts; - - // Static variable: - static FontCache * s_pFontCache; - - // Member variables: - GrEngine * m_pgreng; -}; - -} // namespace gr - - -#if defined(GR_NO_NAMESPACE) -using namespace gr; -#endif - - -#endif // !FONTFACE_INCLUDED diff --git a/Build/source/libs/graphite-engine/src/segment/GrCharStream.cpp b/Build/source/libs/graphite-engine/src/segment/GrCharStream.cpp deleted file mode 100644 index 20b5a46ab76..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrCharStream.cpp +++ /dev/null @@ -1,652 +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: GrCharStream.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Implements the GrCharStream class. -----------------------------------------------------------------------------------------------*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" - -#ifdef _MSC_VER -#pragma hdrstop -#endif -#undef THIS_FILE -DEFINE_THIS_FILE - -//:End Ignore - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -namespace gr -{ - -//:>******************************************************************************************** -//:> Methods -//:>******************************************************************************************** - -/*---------------------------------------------------------------------------------------------- - Constructor. -----------------------------------------------------------------------------------------------*/ -GrCharStream::GrCharStream(ITextSource * pgts, int ichrMin, int ichrLim, - bool fStartLine, bool fEndLine) - : m_pgts(pgts), - m_ichrMin(ichrMin), - m_ichrLim(ichrLim), - m_ichrPos(ichrMin), - m_fStartLine(fStartLine), - m_fEndLine(fEndLine), - m_cchrBackedUp(0), - m_ichrRunMin(0), - m_ichrRunLim(0), - m_ichlRunOffset(kPosInfinity), - m_ichrRunOffset(kPosInfinity) -{ - #if 0 // ??? surely m_cnRunMax and m_prgnRunText are undefined at this point - if (m_cchlRunMax > -1) - delete[] m_prgchlRunText; - #endif - m_cchlRunMax = -1; - m_prgchlRunText = NULL; - - m_vislotNextChunkMap.clear(); - - m_utf = m_pgts->utfEncodingForm(); -} - -/*---------------------------------------------------------------------------------------------- - Restart the stream when an error has a occurred and we need to fall back to dumb rendering. -----------------------------------------------------------------------------------------------*/ -void GrCharStream::Restart() -{ - if (m_cchlRunMax > -1) - delete[] m_prgchlRunText; - - m_ichrPos = m_ichrMin; - m_cchrBackedUp = 0; - m_ichrRunMin = 0; - m_ichrRunLim = 0; - m_ichlRunOffset = kPosInfinity; - m_ichrRunOffset = kPosInfinity; - - m_cchlRunMax = -1; - m_prgchlRunText = NULL; - - m_vislotNextChunkMap.clear(); -} - -/*---------------------------------------------------------------------------------------------- - Get the next character from the stream. - - @param pichwSegOffset - index of this character from the beginning of the segment - @param pcchRaw - number of raw (UTF-16 or UTF-8) chars consumed to get one complete - Unicode codepoint. -----------------------------------------------------------------------------------------------*/ -int GrCharStream::NextGet(GrTableManager * ptman, - GrFeatureValues * pfval, int * pichrSegOffset, int * pcchr) -{ - if (AtEnd()) - { - Assert(m_ichrPos == m_ichrLim); - return 0; - } - - int m_ichrMinBackedUp = m_ichrMin - m_cchrBackedUp; - - if ((m_ichrRunOffset + m_ichrRunMin) >= m_ichrRunLim) - { - // Get the next run of characters - - std::pair<toffset, toffset> pairRange = m_pgts->propertyRange(m_ichrPos); - m_ichrRunMin = pairRange.first; - m_ichrRunLim = pairRange.second; - - // The only time the run extends before what we want is on the first run. - Assert((m_ichrRunMin == m_ichrPos) // m_ichwPos is beginning of run - || (m_ichrPos == m_ichrMinBackedUp)); // first run - // Pretend like the run starts where we need it: - m_ichrRunMin = max(m_ichrRunMin, m_ichrMinBackedUp); - Assert(m_ichrRunMin == m_ichrPos); - - if (m_cchlRunMax != -1 && m_cchlRunMax < m_ichrRunLim - m_ichrRunMin) - { - // Text buffer is too small: delete it and create a new one. - delete[] m_prgchlRunText; - m_cchlRunMax = -1; - } - - if (m_cchlRunMax == -1) - { - // Note that combining surrogates or UTF-8 will always result in the same or fewer - // number of characters needed in m_prgchlRunText, so the following is safe: - m_cchlRunMax = m_ichrRunLim - m_ichrRunMin; - m_prgchlRunText = new int[m_cchlRunMax]; - } - - utf32 * prgchlRunText32 = NULL; - utf16 * prgchwRunText16 = NULL; - utf8 * prgchsRunText8 = NULL; - - int cchGot; - switch (m_utf) - { - case kutf8: - prgchsRunText8 = new utf8[m_ichrRunLim - m_ichrRunMin]; - cchGot = m_pgts->fetch(m_ichrRunMin, m_ichrRunLim - m_ichrRunMin, prgchsRunText8); - break; - case kutf16: - prgchwRunText16 = new utf16[m_ichrRunLim - m_ichrRunMin]; - cchGot = m_pgts->fetch(m_ichrRunMin, m_ichrRunLim - m_ichrRunMin, prgchwRunText16); - break; - default: - Assert(false); - // Assume UTF-32: fall through - case kutf32: - prgchlRunText32 = new utf32[m_ichrRunLim - m_ichrRunMin]; - cchGot = m_pgts->fetch(m_ichrRunMin, m_ichrRunLim - m_ichrRunMin, prgchlRunText32); - break; - } - - int ichlUtf32 = 0; - for (int ichr = 0; ichr < m_ichrRunLim - m_ichrRunMin; ichr++) - { - if (ichr == m_ichrPos - m_ichrRunMin) - { - m_ichrRunOffset = ichr; - m_ichlRunOffset = ichlUtf32; - } - Assert(m_ichrRunOffset != kPosInfinity || ichr < m_ichrPos - m_ichrRunMin); - - int cchrUsed; - switch (m_utf) - { - case kutf8: - m_prgchlRunText[ichlUtf32] = Utf8ToUtf32(prgchsRunText8 + ichr, - m_ichrRunLim - m_ichrRunMin - ichr, &cchrUsed); - break; - case kutf16: - m_prgchlRunText[ichlUtf32] = Utf16ToUtf32(prgchwRunText16 + ichr, - m_ichrRunLim - m_ichrRunMin - ichr, &cchrUsed); - break; - default: - Assert(false); - // Assume UTF-32: fall through - case kutf32: - m_prgchlRunText[ichlUtf32] = prgchlRunText32[ichlUtf32]; - cchrUsed = 1; - break; - } - - m_vislotNextChunkMap.push_back(ichlUtf32); - for (int i = 1; i < cchrUsed; i++) - m_vislotNextChunkMap.push_back(-1); - ichr += cchrUsed - 1; - ichlUtf32++; - } - delete[] prgchlRunText32; - delete[] prgchwRunText16; - delete[] prgchsRunText8; - - while (m_ichrLim - m_ichrRunMin < signed(m_vislotNextChunkMap.size()) - && m_vislotNextChunkMap[m_ichrLim - m_ichrRunMin] == -1) - { - // Invalid surrogate boundary; this is really a bug in the application program, - // but adjust here to avoid a crash! - m_ichrLim--; - } - - SetUpFeatureValues(ptman, m_ichrPos); - - Assert(m_ichrRunOffset >= 0); - Assert(m_ichrRunOffset < m_ichrRunLim - m_ichrRunMin); - Assert(m_vislotNextChunkMap.size() == (unsigned) m_ichrRunLim - m_ichrMinBackedUp); - } - - int chlRet = m_prgchlRunText[m_ichlRunOffset]; - *pfval = m_fvalRunFeats; - *pichrSegOffset = m_ichrPos - m_ichrMin; // offset from the official start of the segment - // of the first 16-bit char - int ichrPosPrev = m_ichrPos; - ++m_ichlRunOffset; - do { - ++m_ichrPos; - ++m_ichrRunOffset; - } while (m_ichrPos - m_ichrMinBackedUp < signed(m_vislotNextChunkMap.size()) - && m_vislotNextChunkMap[m_ichrPos - m_ichrMinBackedUp] == -1); - - *pcchr = m_ichrPos - ichrPosPrev; // number of raw chars consumed - Assert(m_utf != kutf8 || *pcchr <= 6); - Assert(m_utf != kutf16 || *pcchr <= 2); - - Assert(m_ichrPos == (m_ichrRunMin + m_ichrRunOffset)); - Assert(m_ichrPos <= m_ichrLim); - - /* KLUDGE for debugging - if (m_ichrPos == 1) - nRet = 0x1018; - else if (m_ichrPos == 2) - nRet = 0x1039; - else if (m_ichrPos == 3) - nRet = 0x101b; - else if (m_ichrPos == 4) - nRet = 0x1032; - else if (m_ichrPos == 5) - nRet = 0x1037; - else if (m_ichrPos == 6) - nRet = 0x1037; - */ - - return chlRet; -} - -/*---------------------------------------------------------------------------------------------- - Convert UTF-8 to UTF-32--a single character's worth. Also pass back the number of 8-bit - items consumed. -----------------------------------------------------------------------------------------------*/ -utf32 GrCharStream::Utf8ToUtf32(utf8 * prgchs, int cchs, int * pcchsUsed) -{ - if (cchs <= 0) - { - *pcchsUsed = 0; - return 0; - } - - long chlRet = DecodeUtf8(prgchs, cchs, pcchsUsed); - Assert(chlRet > 0); - if (chlRet == -1) - { - // Some error occurred. Just treat the UTF-8 as UTF-32. - *pcchsUsed = 1; - return (utf32)prgchs[0]; - } - else - return chlRet; -} - -/*---------------------------------------------------------------------------------------------- - Convert UTF-16 to UTF-32--a single character's worth. Also pass back the number of 16-bit - items consumed. -----------------------------------------------------------------------------------------------*/ -utf32 GrCharStream::Utf16ToUtf32(utf16 * prgchw, int cchw, int * pcchwUsed) -{ - if (cchw <= 0) - { - *pcchwUsed = 0; - return 0; - } - - unsigned int nUtf32; - bool fSurrogate = FromSurrogatePair(prgchw[0], ((cchw < 2) ? 0 : prgchw[1]), &nUtf32); - *pcchwUsed = (fSurrogate) ? 2 : 1; - return (int)nUtf32; - -/* - // For testing: - int nCharRet; - if (cchw >= 2 && prgchw[0] == '^' && prgchw[1] == 'a') - { - nCharRet = 'A'; - *pcchwUsed = 2; - } - else if (cchw >= 3 && prgchw[0] == '#' && prgchw[1] == '#' && - prgchw[2] == 'B') - { - nCharRet = 'b'; - *pcchwUsed = 3; - } - else if (cchw >= 1) - { - nCharRet = prgchw[0]; - *pcchwUsed = 1; - } - else - { - nCharRet = 0; - *pcchwUsed = 0; - } - return nCharRet; -*/ -} - -/*---------------------------------------------------------------------------------------------- - Return true if the given position is at the boundary of a Unicode character; return false - if it is between two parts of pair of surrogates. -----------------------------------------------------------------------------------------------*/ -bool GrCharStream::AtUnicodeCharBoundary(ITextSource * pgts, int ichr) -{ - int cchr = pgts->getLength(); - if (ichr <= 0 || ichr >= cchr) - return true; - - UtfType utf = pgts->utfEncodingForm(); - - // Note that we never need more than a handful of characters. - int ichrMinGet = max(0, ichr - 1); - int ichrLimGet = ichr + 1; - utf16 rgchwText16[3]; - utf8 rgchsText8[3]; - bool fRet; - switch (utf) - { - case kutf8: - pgts->fetch(ichrMinGet, ichrLimGet - ichrMinGet, rgchsText8); - fRet = AtUnicodeCharBoundary(rgchsText8, ichrLimGet - ichrMinGet, - ichr - ichrMinGet, utf); - break; - case kutf16: - pgts->fetch(ichrMinGet, ichrLimGet - ichrMinGet, rgchwText16); - fRet = AtUnicodeCharBoundary(rgchwText16, ichrLimGet - ichrMinGet, - ichr - ichrMinGet, utf); - break; - default: - Assert(false); - case kutf32: - fRet = true; - break; - } - - return fRet; -} - -/*---------------------------------------------------------------------------------------------- - Return true if the given position is at the boundary of a Unicode character; return false - if it is between two parts of pair of surrogates. -----------------------------------------------------------------------------------------------*/ -bool GrCharStream::AtUnicodeCharBoundary(utf16 * prgchw, int cchw, int ichr, UtfType utf) -{ - Assert(ichr >= 0); - Assert(ichr <= cchw); - - if (ichr == 0) - return true; - if (ichr >= cchw) - return true; - - switch (utf) - { - case kutf16: - { - unsigned int nUtf32; - bool fMiddleOfPair = FromSurrogatePair(prgchw[ichr - 1], prgchw[ichr], &nUtf32); - return !fMiddleOfPair; - } - case kutf8: - { - // 16-bit buffer being treated like UTF-8. - utf8 rgchs[2]; - rgchs[1] = (utf8)prgchw[ichr]; - return AtUnicodeCharBoundary(rgchs, 2, 1, kutf8); - } - case kutf32: - default: - return true; - } - -/* - // temp stuff for debugging: - if (ichr > 0 && cchw >= 1 && prgchw[ichr-1] == '^' && prgchw[ichr] == 'a') - { - return false; - } - if (ichr > 0 && cchw >= 2 && prgchw[ichr-1] == '#' && prgchw[ichr] == '#' && - prgchw[ichr+1] == 'B') - { - return false; - } - if (ichr > 1 && cchw >= 1 && prgchw[ichr-2] == '#' && prgchw[ichr-1] == '#' && - prgchw[ichr] == 'B') - { - return false; - } - - return true; -*/ -} - -bool GrCharStream::AtUnicodeCharBoundary(utf8 * prgchs, int cchs, int ichs, UtfType utf) -{ - Assert(ichs >= 0); - Assert(ichs <= cchs); - - Assert(utf == kutf8); - - if (ichs == 0) - return true; - if (ichs >= cchs) - return true; - - if (cchs == 0) - return true; - - // A bit pattern of 10xxxxxx indicates a continuation of a sequence - // (11xxxxxx means the first byte of a sequence, 0xxxxxxx means a single character). - - utf8 chsTest = prgchs[ichs] & 0xC0; - return (chsTest != 0x80); -} - -/*---------------------------------------------------------------------------------------------- - Convert the given pair of characters into a single 32-bit Unicode character. Return - true if they are a legitimate surrogate pair. If not, just return the first of the - two 16-bit characters. -----------------------------------------------------------------------------------------------*/ -bool GrCharStream::FromSurrogatePair(utf16 chwIn1, utf16 chwIn2, unsigned int * pchlOut) -{ - if ((chwIn1 < kzUtf16HighFirst) || (chwIn1 > kzUtf16HighLast) - || (chwIn2 < kzUtf16LowFirst) || (chwIn2 > kzUtf16LowLast)) - { - // Not a surrogate - *pchlOut = (unsigned int)chwIn1; - return false; - } - else - { - *pchlOut = ((chwIn1 - kzUtf16HighFirst) << kzUtf16Shift) + chwIn2 + kzUtf16Inc; - return true; - } -} - -/*---------------------------------------------------------------------------------------------- - Decode 1-6 bytes in the character string from UTF-8 format to Unicode (UCS-4). - As a side-effect, cbOut is set to the number of UTF-8 bytes consumed. - - @param rgchUtf8 Pointer to a a character array containing UTF-8 data. - @param cchUtf8 Number of characters in the array. - @param cbOut Reference to an integer for holding the number of input (8-bit) characters - consumed to produce the single output Unicode character. - - @return A single Unicode (UCS-4) character. If an error occurs, return -1. -----------------------------------------------------------------------------------------------*/ -long GrCharStream::DecodeUtf8(const utf8 * rgchUtf8, int cchUtf8, int * pcbOut) -{ - // check for valid input - AssertArray(rgchUtf8, cchUtf8); - if ((cchUtf8 == 0) || (rgchUtf8[0] == '\0')) - { - *pcbOut = (cchUtf8) ? 1 : 0; - return 0; - } - // - // decode the first byte of the UTF-8 sequence - // - long lnUnicode; - int cbExtra; - int chsUtf8 = *rgchUtf8++ & 0xFF; - if (chsUtf8 >= kzUtf8Flag6) // 0xFC - { - lnUnicode = chsUtf8 & kzUtf8Mask6; - cbExtra = 5; - } - else if (chsUtf8 >= kzUtf8Flag5) // 0xF8 - { - lnUnicode = chsUtf8 & kzUtf8Mask5; - cbExtra = 4; - } - else if (chsUtf8 >= kzUtf8Flag4) // 0xF0 - { - lnUnicode = chsUtf8 & kzUtf8Mask4; - cbExtra = 3; - } - else if (chsUtf8 >= kzUtf8Flag3) // 0xE0 - { - lnUnicode = chsUtf8 & kzUtf8Mask3; - cbExtra = 2; - } - else if (chsUtf8 >= kzUtf8Flag2) // 0xC0 - { - lnUnicode = chsUtf8 & kzUtf8Mask2; - cbExtra = 1; - } - else // 0x00 - { - lnUnicode = chsUtf8; - cbExtra = 0; - } - if (cbExtra >= cchUtf8) - { - return -1; - } - - switch (cbExtra) - { - case 5: - lnUnicode <<= kzUtf8ByteShift; - chsUtf8 = *rgchUtf8++ & 0xFF; - if ((chsUtf8 & ~kzByteMask) != 0x80) - return -1; - lnUnicode += chsUtf8 & kzByteMask; - // fall through - case 4: - lnUnicode <<= kzUtf8ByteShift; - chsUtf8 = *rgchUtf8++ & 0xFF; - if ((chsUtf8 & ~kzByteMask) != 0x80) - return -1; - lnUnicode += chsUtf8 & kzByteMask; - // fall through - case 3: - lnUnicode <<= kzUtf8ByteShift; - chsUtf8 = *rgchUtf8++ & 0xFF; - if ((chsUtf8 & ~kzByteMask) != 0x80) - return -1; - lnUnicode += chsUtf8 & kzByteMask; - // fall through - case 2: - lnUnicode <<= kzUtf8ByteShift; - chsUtf8 = *rgchUtf8++ & 0xFF; - if ((chsUtf8 & ~kzByteMask) != 0x80) - return -1; - lnUnicode += chsUtf8 & kzByteMask; - // fall through - case 1: - lnUnicode <<= kzUtf8ByteShift; - chsUtf8 = *rgchUtf8++ & 0xFF; - if ((chsUtf8 & ~kzByteMask) != 0x80) - return -1; - lnUnicode += chsUtf8 & kzByteMask; - break; - case 0: - // already handled - break; - default: - Assert(false); - } - if ((unsigned long)lnUnicode > kzUnicodeMax) - { - return -1; - } - *pcbOut = cbExtra + 1; - return lnUnicode; -} - -/*---------------------------------------------------------------------------------------------- - Get the current feature values and character properties from the stream. -----------------------------------------------------------------------------------------------*/ -void GrCharStream::CurrentFeatures(GrTableManager * ptman, GrFeatureValues * pfval) -{ - if (m_ichrRunOffset == kPosInfinity) - { - // Not yet set up. - if (AtEnd()) - { - // Empty stream; no valid values. - Assert(false); - return; - } - - // Get the settings from the first character. - int ichrSegOffset; - int ichrPosSave = m_ichrPos; - int ichrRunOffsetSave = m_ichrRunOffset; - int ichlRunOffsetSave = m_ichlRunOffset; - int cMapSize = m_vislotNextChunkMap.size(); - int cchrConsumed; - NextGet(ptman, pfval, &ichrSegOffset, &cchrConsumed); - // Put the character back. - m_ichrPos = ichrPosSave; - m_ichrRunOffset = ichrRunOffsetSave; - m_ichlRunOffset = ichlRunOffsetSave; - while (signed(m_vislotNextChunkMap.size()) > cMapSize) - m_vislotNextChunkMap.pop_back(); - } - else - { - *pfval = m_fvalRunFeats; - //*ppchrp = &m_chrpRun; - } -} - -/*---------------------------------------------------------------------------------------------- - Read the feature settings from the text properties. - - Eventually, handle style index here? -----------------------------------------------------------------------------------------------*/ -void GrCharStream::SetUpFeatureValues(GrTableManager * ptman, int ichr) -{ - // Set all the features to their default values. - for (int i = 0; i < kMaxFeatures; ++i) - { - m_fvalRunFeats.m_rgnFValues[i] = ptman->DefaultForFeatureAt(i); - } - m_fvalRunFeats.m_nStyleIndex = 0; - - // Add in the defaults for the language of the text. - std::vector<featid> vnFeats; - std::vector<int> vnValues; - isocode lgcode = m_pgts->getLanguage(ichr); - ptman->DefaultsForLanguage(lgcode, vnFeats, vnValues); - size_t ifeatLp; - int ifeat; - for (ifeatLp = 0; ifeatLp < vnFeats.size(); ifeatLp++) - { - ptman->FeatureWithID(vnFeats[ifeatLp], &ifeat); - m_fvalRunFeats.m_rgnFValues[ifeat] = vnValues[ifeatLp]; - } - - // Add in the explicit feature settings. - FeatureSetting rgfset[kMaxFeatures]; - int cfeat = m_pgts->getFontFeatures(ichr, rgfset); - - for (ifeatLp = 0; ifeatLp < (size_t)cfeat; ifeatLp++) - { - ptman->FeatureWithID(rgfset[ifeatLp].id, &ifeat); - if (ifeat >= 0) - m_fvalRunFeats.m_rgnFValues[ifeat] = rgfset[ifeatLp].value; - } -} - -} // namespace gr diff --git a/Build/source/libs/graphite-engine/src/segment/GrCharStream.h b/Build/source/libs/graphite-engine/src/segment/GrCharStream.h deleted file mode 100644 index 892435d376e..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrCharStream.h +++ /dev/null @@ -1,183 +0,0 @@ -/*--------------------------------------------------------------------*//*:Ignore this sentence. -Copyright (C) 1999 - 2008 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: GrCharStream.h -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - - -----------------------------------------------------------------------------------------------*/ -#ifdef _MSC_VER -#pragma once -#endif -#ifndef GR_CHARSTREAM_INCLUDED -#define GR_CHARSTREAM_INCLUDED - -//:End Ignore - -namespace gr -{ - -/*---------------------------------------------------------------------------------------------- - Makes a stream out of a text string that is serving as input to the process. - - Hungarian: chstrm -----------------------------------------------------------------------------------------------*/ -class GrCharStream -{ -public: - // Constructor and destructor: - GrCharStream(ITextSource * pgts, int ichrMin, int ichrLim, - bool fStartLine, bool fEndLine); - - ~GrCharStream() - { - if (m_cchlRunMax >= 0) - delete[] m_prgchlRunText; - } - - // Getters: - ITextSource * TextSrc() { return m_pgts; } - int Min() { return m_ichrMin; } - int Pos() { return m_ichrPos; } - int Lim() { return m_ichrLim; } - bool StartLine() { return m_fStartLine; } - bool EndLine() { return m_fEndLine; } - - // offset from the beginning of the segment - int SegOffset() { return m_ichrPos - m_ichrMin; } - int SegOffset(int ichr) { return ichr - m_ichrMin; } - - bool AtEnd() - { - return (m_ichrPos >= m_ichrLim); - } - - // The input string is empty. - bool IsEmpty() - { - return (m_ichrLim - m_ichrMin == 0); - } - - // When we are restarting in order to create a segment other than the first, - // back up the position in the stream slightly in order to reprocess a few characters - // before the line-break. - void Backup(int cchrToReprocess) - { - Assert(m_ichrPos >= cchrToReprocess); - m_ichrPos -= cchrToReprocess; - m_ichrRunOffset = kPosInfinity; - m_cchrBackedUp = cchrToReprocess; - } - - // When we found a hard-break in the input stream, we need to put it back, and since - // we're done, we set the end of the stream to that position. - void HitHardBreak() - { - m_ichrPos -= 1; - m_ichrRunOffset -= 1; - m_ichrLim = m_ichrPos; - } - - void Restart(); - - int NextGet(GrTableManager *, GrFeatureValues * pfval, int * ichrSegOffset, int * pcchr); - - void CurrentFeatures(GrTableManager * ptman, GrFeatureValues * pfval); - - // For transduction logging: - int GetLogData(GrTableManager * ptman, int * rgnChars, bool * rgfNewRun, - GrFeatureValues * rgfval, int cchwBackup, - int * pcchwMaxRaw); - void GetLogDataRaw(GrTableManager * ptman, int cchw, int cchwBackup, - int cchwMax16bit, int * prgnChars, - utf16 * prgchw2, utf16 * prgchw3, utf16 * prgchw4, utf16 * prgchw5, utf16 * prgchw6, - int * prgichwRaw); - -protected: - void SetUpFeatureValues(GrTableManager * ptman, int ichr); -public: - static utf32 Utf8ToUtf32(utf8 * prgchs8bit, int cchs, int * pcchsUsed); - static utf32 Utf16ToUtf32(utf16 * prgchw16bit, int cchw, int * pcchwUsed); - bool AtUnicodeCharBoundary(int cchr) - { - return AtUnicodeCharBoundary(m_pgts, cchr); - } - static bool AtUnicodeCharBoundary(ITextSource * pgts, int ichr); - static bool AtUnicodeCharBoundary(utf8 * prgchs, int cchs, int ichs, UtfType utf); - static bool AtUnicodeCharBoundary(utf16 * prgchw, int cchw, int ichr, UtfType utf); - static bool FromSurrogatePair(utf16 chwIn1, utf16 chwIn2, unsigned int * pch32Out); - static long DecodeUtf8(const utf8 * rgchUtf8, int cchUtf8, int * pcbOut); - -protected: - // Instance variables: - // Hungarian note: chr = raw characters, chl = long characters (UTF-32) - // chs = short characters (UTF-8), chw = wide characters (UTF-16) - ITextSource * m_pgts; // string to render - UtfType m_utf; // what encoding form the text-source uses - int m_ichrMin; // official start of segment relative to beginning of string - int m_ichrLim; // end of stream (potential end of seg) relative to beginning of string - int m_ichrPos; // stream position (0 = start of string) - bool m_fStartLine; // true if a line-break character should be prepended - bool m_fEndLine; // true if a line-break character should be appended - int m_cchrBackedUp; // number of characters backed up before beginning of segment - - // We read a run's worth of data at a time and cache it in the following variables: - int m_cchlRunMax; // size of buffer allocated - int * m_prgchlRunText; // buffer containing current run - int m_ichrRunMin; // start of run relative to beginning of string - int m_ichrRunLim; // end of run relative to beginning of string - int m_ichlRunOffset; // index into m_prgchlRunText; kPosInfinity if nothing set up - int m_ichrRunOffset; // corresponding index into text source - GrFeatureValues m_fvalRunFeats; - - std::vector<int> m_vislotNextChunkMap; // maps from 16-bit chars to 32-bit chars & glyphs - - enum - { - kzUtf8Mask1 = 0x7F, - kzUtf8Mask2 = 0x1F, - kzUtf8Mask3 = 0x0F, - kzUtf8Mask4 = 0x07, - kzUtf8Mask5 = 0x03, - kzUtf8Mask6 = 0x01 - }; - - enum - { - kzUtf8Flag1 = 0x00, - kzUtf8Flag2 = 0xC0, - kzUtf8Flag3 = 0xE0, - kzUtf8Flag4 = 0xF0, - kzUtf8Flag5 = 0xF8, - kzUtf8Flag6 = 0xFC - }; - - enum - { - kzByteMask = 0x3F, - kzByteMark = 0x80, - kzUtf8ByteShift = 6, - kzUnicodeMax = 0x7FFFFFFF - }; - - enum - { - kzUtf16Shift = 10, - kzUtf16Inc = 0x2400, - kzUtf16HighFirst = 0xD800, - kzUtf16HighLast = 0xDBFF, - kzUtf16LowFirst = 0xDC00, - kzUtf16LowLast = 0xDFFF - }; -}; - -} // namespace gr - -#endif // !GR_CHARSTREAM_INCLUDED - diff --git a/Build/source/libs/graphite-engine/src/segment/GrClassTable.cpp b/Build/source/libs/graphite-engine/src/segment/GrClassTable.cpp deleted file mode 100644 index 43316fdc04a..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrClassTable.cpp +++ /dev/null @@ -1,382 +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: GrClassTable.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Implements the GrClassTable class and related classes. -----------------------------------------------------------------------------------------------*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" - -#ifdef _MSC_VER -#pragma hdrstop -#endif -#undef THIS_FILE -DEFINE_THIS_FILE - -//:End Ignore - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -namespace gr -{ - -//:>******************************************************************************************** -//:> Methods -//:>******************************************************************************************** - -/*---------------------------------------------------------------------------------------------- - Fill in by reading from the file stream. -----------------------------------------------------------------------------------------------*/ -bool GrClassTable::ReadFromFont(GrIStream & grstrm, int fxdVersion) -{ - long lClassMapStart; - grstrm.GetPositionInFont(&lClassMapStart); - - // number of classes - m_ccls = grstrm.ReadUShortFromFont(); - if (m_ccls >= kMaxReplcmtClasses) - return false; // bad table - if (fxdVersion < 0x00030000 && m_ccls > kMaxReplcmtClassesV1_2) - return false; // bad table - - // number of linear classes - m_cclsLinear = grstrm.ReadUShortFromFont(); - if (m_cclsLinear > m_ccls) - return false; // bad table - - // class offsets - m_prgichwOffsets = new data16[m_ccls + 1]; - gAssert(m_prgichwOffsets); - if (!m_prgichwOffsets) - return false; // bad table - - data16 * pchw = m_prgichwOffsets; - int icls; - for (icls = 0; icls <= m_ccls; icls++, pchw++) - { - *pchw = grstrm.ReadUShortFromFont(); - } - - // Offsets are relative to the start class map; make them relative to the class list - // itself, and in terms of utf16s, not bytes. - long lClassesPos; - grstrm.GetPositionInFont(&lClassesPos); - int cbDiff = lClassesPos - lClassMapStart; - for (icls = 0; icls <= m_ccls; icls++) - { - m_prgichwOffsets[icls] = data16(int(m_prgichwOffsets[icls]) - cbDiff); - gAssert((m_prgichwOffsets[icls] & 0x00000001) == 0); - if ((m_prgichwOffsets[icls] & 0x00000001) != 0) - return false; // bad table - m_prgichwOffsets[icls] >>= 1; // divide by 2 - } - - // classes - slurp entire block (data remains in big-endian format) - m_prgchwBIGGlyphList = new data16[m_prgichwOffsets[m_ccls]]; - gAssert(m_prgchwBIGGlyphList); - if (!m_prgchwBIGGlyphList) - return false; // bad table - grstrm.ReadBlockFromFont(m_prgchwBIGGlyphList, - m_prgichwOffsets[m_ccls] * isizeof(data16)); - - return true; -} - -/*---------------------------------------------------------------------------------------------- - Set up an empty class table. -----------------------------------------------------------------------------------------------*/ -void GrClassTable::CreateEmpty() -{ - // number of classes - m_ccls = 0; - // number of linear classes - m_cclsLinear = 0; -} - -/*---------------------------------------------------------------------------------------------- - Search for the glyph ID using a fast binary search, and return the matching index. -----------------------------------------------------------------------------------------------*/ -int GrInputClass::FindIndex(gid16 gid) -{ - int digixInit = InitialSearchRange(); - int igixStart = StartSearch(); -#ifdef _DEBUG - int cgix = NumberOfGlyphs(); - int nPowerOf2 = 1; - while (nPowerOf2 <= cgix) - nPowerOf2 <<= 1; - nPowerOf2 >>= 1; - // Now nPowerOf2 is the max power of 2 <= cgix - gAssert((1 << LoopCount()) == nPowerOf2); // LoopCount() == log2(nPowerOf2) - gAssert(digixInit == nPowerOf2); - gAssert(igixStart == cgix - digixInit); -#endif // _DEBUG - - int digixCurr = digixInit; - - GrGlyphIndexPair * pgixCurr = m_pgixFirst + igixStart; - while (digixCurr > 0) - { - int nTest; - if (pgixCurr < m_pgixFirst) - nTest = -1; - else - nTest = pgixCurr->GlyphID() - gid; - - if (nTest == 0) - return pgixCurr->Index(); - - digixCurr >>= 1; // divide by 2 - if (nTest < 0) - pgixCurr += digixCurr; - else // (nTest > 0) - pgixCurr -= digixCurr; - } - - return -1; -} - -/*---------------------------------------------------------------------------------------------- - Return the selector index for the given glyph ID. -----------------------------------------------------------------------------------------------*/ -int GrClassTable::FindIndex(int icls, gid16 chwGlyphID) -{ - if (icls >= m_ccls) - { - gAssert(false); // bad compiler problem - return 0; - } - - if (icls < m_cclsLinear) - { - // The class is an output class--uses linear format--and is being used as an - // input class. Shouldn't happen if the compiler is working right. - gAssert(false); // comment out for test procedures - - // Do a slow linear search to find the glyph ID. - int ichwMin = m_prgichwOffsets[icls]; - int ichwLim = m_prgichwOffsets[icls+1]; - int cchw = ichwLim - ichwMin; - - for (int ichw = 0; ichw < cchw; ichw++) - { - if (GlyphAt(ichwMin + ichw) == chwGlyphID) - return ichw; - } - return -1; - } - - // Slurp the class into an instance so we can see what's there. - GrInputClass clsin; - int ichwMin = m_prgichwOffsets[icls]; - int ichwLim = m_prgichwOffsets[icls+1]; - clsin.CopyFrom(GlyphListLoc(ichwMin), (ichwLim - ichwMin)); - - // Do a fast binary search to find our glyph. - int iRet = clsin.FindIndex(chwGlyphID); - return iRet; -} - -/*---------------------------------------------------------------------------------------------- - Return the glyph ID at the selector index. -----------------------------------------------------------------------------------------------*/ -gid16 GrClassTable::GetGlyphID(int icls, int ichw) -{ - if (ichw < 0) - { - gAssert(false); - return 0; - } - - if (icls >= m_cclsLinear) - { - // The class is an input class--sorted by glyph ID--and is being used as an - // output class. Shouldn't happen if the compiler is working right. - gAssert(false); // comment out for test procedures - - if (icls >= m_ccls) // bad compiler problem - return 0; - - // Do a slow linear search to find the index and answer the matching glyph. - // Slurp the class into an instance so we can see what's there. - GrInputClass clsin; - int ichwMin = m_prgichwOffsets[icls]; - int ichwLim = m_prgichwOffsets[icls+1]; - clsin.CopyFrom(GlyphListLoc(ichwMin), (ichwLim - ichwMin)); - - int cgix = clsin.NumberOfGlyphs(); - for (int igix = 0; igix < cgix; igix++) - { - GrGlyphIndexPair * m_pgix = clsin.m_pgixFirst + igix; - if (m_pgix->Index() == ichw) - return m_pgix->GlyphID(); - } - return 0; - } - - int ichwMin = m_prgichwOffsets[icls]; - int ichwLim = m_prgichwOffsets[icls+1]; - - if (ichw >= ichwLim - ichwMin) - return 0; - else - return GlyphAt(ichwMin + ichw); -} - -/*---------------------------------------------------------------------------------------------- - Return the number of glyphs in the class. -----------------------------------------------------------------------------------------------*/ -int GrClassTable::NumberOfGlyphsInClass(int icls) -{ - int ichwMin = m_prgichwOffsets[icls]; - int ichwLim = m_prgichwOffsets[icls+1]; - - if (icls >= m_cclsLinear) - { - if (icls >= m_ccls) // bad compiler problem - return 0; - - GrInputClass clsin; - clsin.CopyFrom(GlyphListLoc(ichwMin), (ichwLim - ichwMin)); - - int cgix = clsin.NumberOfGlyphs(); - return cgix; - } - else - { - gAssert(false); // this method should not be used for output classes. - return ichwLim - ichwMin; - } -} - -//:>******************************************************************************************** -//:> For test procedures -//:>******************************************************************************************** - -//:Ignore - -#ifdef OLD_TEST_STUFF -/*---------------------------------------------------------------------------------------------- - General test of class table. -----------------------------------------------------------------------------------------------*/ -void GrClassTable::SetUpTestData() -{ - m_ccls = 7; // number of classes - m_cclsLinear = 4; // number of classes in linear format - - m_prgchwBIGGlyphList = new gid16[100]; - - m_prgichwOffsets = new data16[7+1]; - - gid16 * pchw = m_prgchwBIGGlyphList; - - // Output class 0: uppercase consonants B - H - m_prgichwOffsets[0] = 0; - *pchw++ = msbf(gid16(66)); *pchw++ = msbf(utf16(67)); *pchw++ = msbf(utf16(68)); - *pchw++ = msbf(gid16(70)); *pchw++ = msbf(utf16(71)); *pchw++ = msbf(utf16(72)); - - // Output class 1: grave vowels - m_prgichwOffsets[1] = 6; - *pchw++ = msbf(gid16(192)); // A - *pchw++ = msbf(gid16(224)); // a - *pchw++ = msbf(gid16(200)); // E - *pchw++ = msbf(gid16(232)); // e - *pchw++ = msbf(gid16(204)); // I - *pchw++ = msbf(gid16(236)); // i - *pchw++ = msbf(gid16(210)); // O - *pchw++ = msbf(gid16(243)); // o - *pchw++ = msbf(gid16(217)); // U - *pchw++ = msbf(gid16(249)); // u - - // Output class 2: circumflex vowels - m_prgichwOffsets[2] = 6 + 10; - *pchw++ = msbf(gid16(194)); // A - *pchw++ = msbf(gid16(226)); // a - *pchw++ = msbf(gid16(202)); // E - *pchw++ = msbf(gid16(234)); // e - *pchw++ = msbf(gid16(206)); // I - *pchw++ = msbf(gid16(238)); // i - *pchw++ = msbf(gid16(212)); // O - *pchw++ = msbf(gid16(244)); // o - *pchw++ = msbf(gid16(219)); // U - *pchw++ = msbf(gid16(251)); // u - - // Output class 3: diaeresis vowels, uppercase - m_prgichwOffsets[3] = 16 + 10; - *pchw++ = msbf(gid16(196)); // A - *pchw++ = msbf(gid16(196)); // A - *pchw++ = msbf(gid16(203)); // E - *pchw++ = msbf(gid16(203)); // E - *pchw++ = msbf(gid16(207)); // I - *pchw++ = msbf(gid16(207)); // I - *pchw++ = msbf(gid16(214)); // O - *pchw++ = msbf(gid16(214)); // O - *pchw++ = msbf(gid16(220)); // U - *pchw++ = msbf(gid16(220)); // U - - // Input class 4: lowercase consonants b - h - m_prgichwOffsets[4] = 26 + 10; // = 36 - *pchw++ = msbf(gid16(6)); - *pchw++ = msbf(gid16(4)); *pchw++ = msbf(gid16(2)); *pchw++ = msbf(gid16(6-4)); - *pchw++ = msbf(gid16(98)); *pchw++ = msbf(gid16(0)); - *pchw++ = msbf(gid16(99)); *pchw++ = msbf(gid16(1)); - *pchw++ = msbf(gid16(100)); *pchw++ = msbf(gid16(2)); - *pchw++ = msbf(gid16(102)); *pchw++ = msbf(gid16(3)); - *pchw++ = msbf(gid16(103)); *pchw++ = msbf(gid16(4)); - *pchw++ = msbf(gid16(104)); *pchw++ = msbf(gid16(5)); - - // Input class 5: vowels - m_prgichwOffsets[5] = 36 + 4 + 6*2; // = 52 - *pchw++ = msbf(gid16(10)); - *pchw++ = msbf(gid16(8)); *pchw++ = msbf(utf16(3)); *pchw++ = msbf(utf16(10-8)); - *pchw++ = msbf(gid16(65)); *pchw++ = msbf(gid16(0)); // A - *pchw++ = msbf(gid16(69)); *pchw++ = msbf(gid16(2)); // E - *pchw++ = msbf(gid16(73)); *pchw++ = msbf(gid16(4)); // I - *pchw++ = msbf(gid16(79)); *pchw++ = msbf(gid16(6)); // O - *pchw++ = msbf(gid16(85)); *pchw++ = msbf(gid16(8)); // U - *pchw++ = msbf(gid16(97)); *pchw++ = msbf(gid16(1)); // a - *pchw++ = msbf(gid16(101)); *pchw++ = msbf(gid16(3)); // e - *pchw++ = msbf(gid16(105)); *pchw++ = msbf(gid16(5)); // i - *pchw++ = msbf(gid16(111)); *pchw++ = msbf(gid16(7)); // o - *pchw++ = msbf(gid16(117)); *pchw++ = msbf(gid16(9)); // u - - // Input class 6: acute vowels - m_prgichwOffsets[6] = 52 + 4 + 10*2; // = 76 - *pchw++ = msbf(gid16(10)); - *pchw++ = msbf(gid16(8)); *pchw++ = msbf(gid16(3)); *pchw++ = msbf(gid16(10-8)); - *pchw++ = msbf(gid16(193)); *pchw++ = msbf(gid16(0)); // A - *pchw++ = msbf(gid16(201)); *pchw++ = msbf(gid16(2)); // E - *pchw++ = msbf(gid16(205)); *pchw++ = msbf(gid16(4)); // I - *pchw++ = msbf(gid16(211)); *pchw++ = msbf(gid16(6)); // O - *pchw++ = msbf(gid16(218)); *pchw++ = msbf(gid16(8)); // U - *pchw++ = msbf(gid16(225)); *pchw++ = msbf(gid16(1)); // a - *pchw++ = msbf(gid16(233)); *pchw++ = msbf(gid16(3)); // e - *pchw++ = msbf(gid16(237)); *pchw++ = msbf(gid16(5)); // i - *pchw++ = msbf(gid16(243)); *pchw++ = msbf(gid16(7)); // o - *pchw++ = msbf(gid16(250)); *pchw++ = msbf(gid16(9)); // u - - m_prgichwOffsets[7] = 76 + 4 + 10*2; // = 100 -}; - -#endif // OLD_TEST_STUFF - -} // namespace gr - -//:End Ignore - diff --git a/Build/source/libs/graphite-engine/src/segment/GrClassTable.h b/Build/source/libs/graphite-engine/src/segment/GrClassTable.h deleted file mode 100644 index 67d6940862c..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrClassTable.h +++ /dev/null @@ -1,188 +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: GrClassTable.h -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - The GrClassTable and related classes that store the classes that are used in substitutions. -----------------------------------------------------------------------------------------------*/ -#ifdef _MSC_VER -#pragma once -#endif -#ifndef GR_CTABLE_INCLUDED -#define GR_CTABLE_INCLUDED - -//:End Ignore - -namespace gr -{ - -/*---------------------------------------------------------------------------------------------- - A glyph ID / index pair, a member of the GrInputClass where the items are sorted - by glyph ID. - - Hungarian: gix -----------------------------------------------------------------------------------------------*/ -class GrGlyphIndexPair -{ - friend class GrInputClass; - friend class GrClassTable; - - gid16 GlyphID() { return lsbf(m_gidBIG); } - data16 Index() { return lsbf(m_nBIGIndex); } - - gid16 m_gidBIG; - data16 m_nBIGIndex; -}; - -/*---------------------------------------------------------------------------------------------- - A class consisting of a mapping from glyph ID to index, used for classes that - function as input classes (eg, occurrng in the left-hand side of a rule). - - Hungarian: clsin -----------------------------------------------------------------------------------------------*/ -class GrInputClass -{ - friend class GrClassTable; - -protected: - /*------------------------------------------------------------------------------------------ - Copy the raw memory into the instance. - ------------------------------------------------------------------------------------------*/ - void CopyFrom(data16 * pchwStart, int cchw) - { - m_cgixBIG = pchwStart[0]; - m_digixBIGInit = pchwStart[1]; - m_cBIGLoop = pchwStart[2]; - m_igixBIGStart = pchwStart[3]; - - int cgix = NumberOfGlyphs(); - m_pgixFirst = m_prggixBuffer; - if (cgix > 64) - { - m_vgix.resize(cgix); - m_pgixFirst = &m_vgix[0]; - } - gAssert((4 + (cgix * 2)) == cchw); - #ifdef _DEBUG - memset(m_pgixFirst, 0, cgix * isizeof(GrGlyphIndexPair)); - #endif - Assert(sizeof(GrGlyphIndexPair) == sizeof(gid16) + sizeof(data16)); - GrGlyphIndexPair * pgixStart = reinterpret_cast<GrGlyphIndexPair*>(pchwStart + 4); - std::copy(pgixStart, pgixStart + cgix, m_pgixFirst); - } - - int NumberOfGlyphs() { return lsbf(m_cgixBIG); } - int LoopCount() { return lsbf(m_cBIGLoop); } - int InitialSearchRange() { return lsbf(m_digixBIGInit); } - int StartSearch() { return lsbf(m_igixBIGStart); } - - int FindIndex(gid16 gid); - -protected: - // Instance variables: - data16 m_cgixBIG; // number of glyphs in the class - - // constants for fast binary search - data16 m_digixBIGInit; // (max power of 2 <= m_cgix); - // size of initial range to consider - data16 m_cBIGLoop; // log2(max power of 2 <= m_cgix); - // indicates how many iterations are necessary - data16 m_igixBIGStart; // m_cgix - m_digixInit; - // where to start search - - GrGlyphIndexPair m_prggixBuffer[64]; - std::vector<GrGlyphIndexPair> m_vgix; - GrGlyphIndexPair * m_pgixFirst; -}; - - -/*---------------------------------------------------------------------------------------------- - Contains all the classes used for substitution rules. - - Hungarian: ctbl -----------------------------------------------------------------------------------------------*/ - -class GrClassTable -{ - friend class FontMemoryUsage; - -public: - // Constructor & destructor: - GrClassTable() - : m_prgichwOffsets(NULL), - m_prgchwBIGGlyphList(NULL) - { - } - - ~GrClassTable() - { - delete[] m_prgichwOffsets; - delete[] m_prgchwBIGGlyphList; - } - - int NumberOfClasses() { return m_ccls; } - int NumberOfInputClasses() { return m_ccls - m_cclsLinear; } - int NumberOfOutputClasses() { return m_cclsLinear; } - - bool ReadFromFont(GrIStream & grstrm, int fxdVersion); - void CreateEmpty(); - - int FindIndex(int icls, gid16 chwGlyphID); - gid16 GetGlyphID(int icls, int ichw); - int NumberOfGlyphsInClass(int icls); - - gid16 GlyphAt(int ichw) - { - return lsbf(m_prgchwBIGGlyphList[ichw]); - } - data16 * GlyphListLoc(int ichw) - { - return m_prgchwBIGGlyphList + ichw; - } - -protected: - // Instance variables: - int m_ccls; // number of classes - int m_cclsLinear; // number of classes in linear format - - data16 * m_prgichwOffsets; - - // Two formats are included in the following array: the first section consists of - // flat ordered lists of glyphs, used for the "output" classes that use linear format. - // This provides an index-to-glyph mapping. - // The second section contains data in the format of GrInputClasses, used for "input" - // classes that need a binary-search format. This provides a glyph-to-index mapping. - // We don't create instances of GrInputClasses, because that would make reading - // from the ECF file slow. Instead we just set up a single instance at the time - // we're interested in it. - // NOTE that all this data has been slurped directly from the ECF file and therefore - // uses BIG-ENDIAN format. - gid16 * m_prgchwBIGGlyphList; - -//:Ignore -#ifdef OLD_TEST_STUFF -public: - // For test procedures: - void SetUpTestData(); - void SetUpRuleActionTest(); - void SetUpRuleAction2Test(); - void SetUpAssocTest(); - void SetUpAssoc2Test(); - void SetUpDefaultAssocTest(); - void SetUpFeatureTest(); - void SetUpLigatureTest(); - void SetUpLigature2Test(); -#endif // OLD_TEST_STUFF -//:End Ignore -}; - -} // namespace gr - -#endif // !GR_CTABLE_INCLUDED - diff --git a/Build/source/libs/graphite-engine/src/segment/GrEngine.cpp b/Build/source/libs/graphite-engine/src/segment/GrEngine.cpp deleted file mode 100644 index 0fda68df880..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrEngine.cpp +++ /dev/null @@ -1,2030 +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, - byte *pSilfTbl, int lSilfStart, - byte *pGlobTbl, int lGlocStart, - 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(); - data16 chwBehaviors[kMaxRenderingBehavior]; - for (i = 0; i < cBehaviors; i++) - { - chwBehaviors[i] = grstrm.ReadUShortFromFont(); - } - - // 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, 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 - diff --git a/Build/source/libs/graphite-engine/src/segment/GrEngine.h b/Build/source/libs/graphite-engine/src/segment/GrEngine.h deleted file mode 100644 index 81b54e805bc..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrEngine.h +++ /dev/null @@ -1,622 +0,0 @@ -/*-------------------------------------------------------------------- -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.h -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Contains the definition of the GrEngine class. -----------------------------------------------------------------------------------------------*/ -#ifdef _MSC_VER -#pragma once -#endif -#ifndef GR_ENGINE_INCLUDED -#define GR_ENGINE_INCLUDED -#include <limits> - -#ifdef _MSC_VER -#include <crtdbg.h> -#endif - -namespace gr -{ -class IGrJustifier; -class Segment; - - -/*---------------------------------------------------------------------------------------------- - The GrEngine serves as the top level object that knows how to run Graphite tables - and generate Graphite segments. - - Primarily, this class implements IRenderEngine, which allows it to serve as a FW - rendering engine. It also implements ISimpleInit, a general interface for initializing - using a string. Finally, it implements ITraceControl, a very simple interface which - allows a client to flip a flag indicating whether or not we want to output a log of - the Graphite transduction process. - - Hungarian: greng -----------------------------------------------------------------------------------------------*/ -class GrEngine : public GraphiteProcess -{ - friend class FontFace; - friend class FontMemoryUsage; - -public: - // Constructors & destructors: - GrEngine(); - void BasicInit(); - virtual ~GrEngine(); - void DestroyContents(bool fDestroyCmap = true); - - // ISimpleInit methods: - ////GrResult InitNew(const byte * prgb, int cb); -- obsolete - ////GrResult get_InitializationData(int cchMax, OLECHAR * rgchw, int * pcch); -- obsolete - - // ITraceControl methods: - //GrResult SetTracing(int n); - //GrResult GetTracing(int * pnOptions); - - // IRenderingFeatures methods: - //GrResult GetFeatureIDs(int cMax, int * prgFids, int * pcfid); - //GrResult GetFeatureLabel(int fid, int nLanguage, int cchMax, OLECHAR * rgchw, int * pcch); - //GrResult GetFeatureValues(int fid, int cfvalMax, - // int * prgfval, int * pcfval, int * pfvalDefault); - //GrResult GetFeatureValueLabel(int fid, int fval, int nLanguage, - // int cchMax, OLECHAR * rgchw, int * pcch); - - // IRenderEngine methods: - ////GrResult InitRenderer(IGrGraphics * pgg, OLECHAR * prgchData, int cchData); -- obsolete - ////GrResult FontIsValid(OLECHAR * prgchwErrMsg, int cchMaxErrMsg); - - GrResult get_SegDatMaxLength(int * pcb); - - //GrResult FindBreakPoint(Font * pfont, ITextSource * pgts, DELETE - // int ichMin, int ichLim, int ichLimBacktrack, - // bool fNeedFinalBreak, - // bool fStartLine, - // float dxMaxWidth, - // LineBrk lbPref, LineBrk lbMax, - // TrWsHandling twsh, bool fParaRtoL, - // Segment ** ppsegRet, - // int * pdichwLimSeg, float * pdxWidth, SegEnd * pest, - // int cbPrev, byte * pbPrevSegDat, - // int cbNextMax, byte * pbNextSegDat, int * pcbNextSegDat, - // int * pdichwContext, - // std::ostream * pstrmLog, - // OLECHAR * prgchwErrMsg, int cchMaxErrMsg); - - //GrResult FindBreakPointWJust(Font * pfont, ITextSource * pgts, IGrJustifier * pgjus, - // int ichMin, int ichLim, int ichLimBacktrack, DELETE - // bool fNeedFinalBreak, - // bool fStartLine, - // float dxMaxWidth, - // LineBrk lbPref, LineBrk lbMax, - // TrWsHandling twsh, bool fParaRtoL, - // Segment ** ppsegRet, - // int * pdichwLimSeg, float * pdxWidth, SegEnd * pest, - // int cbPrev, byte * pbPrevSegDat, - // int cbNextMax, byte * pbNextSegDat, int * pcbNextSegDat, - // int * pdichwContext, - // std::ostream * pstrmLog, - // OLECHAR * prgchwErrMsg, int cchMaxErrMsg); - - GrResult get_ScriptDirection(unsigned int * pgrfsdc, OLECHAR * prgchwErrMsg, int cchMaxErrMsg); - - // DELETE - //GrResult MakeJustifiedSegment(Font * pfont, ITextSource * pgts, IGrJustifier * pgj, - // int ichMin, int ichLim, - // bool fStartLine, bool fEndLine, - // float dxUnjustifiedWidth, float dxJustifiedWidth, - // TrWsHandling twsh, SegEnd est, LineBrk lb, - // bool fParaRtl, - // Segment ** ppsegRet, float * pdxWidth, - // //int cbPrev, byte * pbPrevSegDat, int cbNextMax, byte * pbNextSegDat, int * pcbNextSegDat, int * pdichwContext, - // std::ostream * pstrmLog, - // OLECHAR * prgchwErrMsg, int cchwMaxErrMsg); - - // IJustifyingRenderer methods: - // These methods return kresInvalidArg if the attribute ID is invalid or inappropriate; - // kresFail if the engine is not in an appropriate state to return the information. - virtual GrResult getGlyphAttribute(int iGlyph, int jgat, int nLevel, float * pValueRet); - virtual GrResult getGlyphAttribute(int iGlyph, int jgat, int nLevel, int * pValueRet); - virtual GrResult setGlyphAttribute(int iGlyph, int jgat, int nLevel, float value); - virtual GrResult setGlyphAttribute(int iGlyph, int jgat, int nLevel, int value); - - // Interface methods not used by FW: - - ////GrResult IsGraphiteFont(IGrGraphics * pgg); -- obsolete - - ////GrResult FontAscentAndDescent(IGrGraphics * pgg, int * pysAscent, int * pysDescent); -- obsolete - - //GrResult MakeMeasuredSegment( - // Font * pfont, ITextSource * pgts, - // int ichMin, int ichLim, - // bool fParaRtl, - // Segment ** ppsegRet, SegEnd * pest, - // std::ostream * pstrmLog, - // OLECHAR * prgchwErrMsg, int cchMaxErrMsg); - - //GrResult 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); - - // NEW interface - - GrResult ReadFontTables(Font * pfont, bool fItalic); - - FontErrorCode IsValidForGraphite(int * pnVersion, int * pnSubVersion); - - // Other public methods - - GrResult FindBreakPointAux(Font * pfont, ITextSource * pgts, IGrJustifier * pgjus, - int ichwMin, int ichwLim, int ichwLimBacktrack, - bool fNeedFinalBreakArg, bool fStartLine, bool fEndLine, - float dxMaxWidth, bool fWidthIsCharCount, - LineBrk lbPref, LineBrk lbMax, TrWsHandling twsh, bool fParaRtl, - Segment ** ppsegRet, - int * pdichwLimSeg, - float * pdxWidth, SegEnd * pest, - int cbPrev, byte * pbPrevSegDat, - int cbNextMax, byte * pbNextSegDat, int * pcbNextSegDat, - int * pdichwContext, - std::ostream * pstrmLog, - OLECHAR * prgchwErrMsg, int cchMaxErrMsg); - - gid16 GetGlyphIDFromUnicode(int nUnicode); - gid16 ActualGlyphForOutput(utf16 chwGlyphID); - - int GetFontEmUnits() - { - return m_mFontEmUnits; - } - - gid16 LBGlyphID() - { - return m_chwLBGlyphID; - } - - gid16 GetClassGlyphIDAt(int nClass, int nIndex); - int GetIndexInGlyphClass(int nClass, gid16 chwGlyphID); - size_t NumberOfGlyphsInClass(int nClass); - int GlyphAttrValue(gid16 chwGlyphID, int nAttrID); - int ComponentIndexForGlyph(gid16 chwGlyphID, int nCompID); - - ////void InitFontName(std::wstring stuInitialize, std::wstring & stuFaceName, std::wstring & stuFeatures); -- obsolete - void RecordFontLoadError(OLECHAR * prgchwErrMsg, int cchMaxErrMsg); - void RecordFontRunError(OLECHAR * prgchwErrMsg, int cchMaxErrMsg, GrResult res); - void ClearFontError(OLECHAR * prgchwErrMsg, int cchMaxErrMsg); - void GetWritingSystemDirection(ITextSource * pgts, int ichwMin); - ////GrResult SetUp(IGrGraphics * pgg, std::wstring stuFeatures); -- obsolete - ////GrResult SetUp(IGrGraphics * pgg, std::wstring stuFeaturesArg, bool fBold, bool fItalic); -- obsolete - - GrResult 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); - bool InErrorState() - { - return m_fInErrorState; - } - - std::wstring FaceName() - { - return m_stuFaceName; - } - std::wstring BaseFaceName() - { - Assert(m_stuBaseFaceName.size() == 0 || m_fUseSepBase); - return m_stuBaseFaceName; // empty if not using separate base font - } - bool Bold() - { - return m_fBold; - } - bool Italic() - { - return m_fItalic; - } - - void GetStyles(Font * pfont, int ichwMin, bool * pfBold, bool * pfItalic); - void SwitchGraphicsFont(bool fBase); - - void AddFeature(featid nID, int nNameId, int cfset, int nDefault = 0); - GrFeature * FeatureWithID(featid nID, int * pifeat); - int DefaultForFeatureAt(int ifeat); - void SetDefaultForFeatureAt(int ifeat, int nValue); - GrFeature * Feature(int ifeat) - { - if (ifeat >= kMaxFeatures) - return NULL; - return m_rgfeat + ifeat; - } - void DefaultsForLanguage(isocode lgcode, - std::vector<featid> & vnFeats, std::vector<int> & vnValues); - std::wstring StringFromNameTable(int nNameId, int nLang); - - void InitSlot(GrSlotState *, int nUnicode = -1); - void SetSlotAttrsFromGlyphAttrs(GrSlotState *); - - bool RightToLeft() - { - return m_fRightToLeft; - } - int TopDirectionLevel() - { - return (m_fRightToLeft) ? 1 : 0; - } - - GrGlyphTable * GlyphTable() - { - return m_pgtbl; - } - - GrClassTable * ClassTable() - { - return m_pctbl; - } - - int NumFeat() - { - return m_cfeat; - } - - bool LineBreakFlag() - { - return m_fLineBreak; - } - - int PreXlbContext() - { - return m_cchwPreXlbContext; - } - - int PostXlbContext() - { - return m_cchwPostXlbContext; - } - - int ExtraAscent() - { - return m_mXAscent; - } - - int ExtraDescent() - { - return m_mXDescent; - } - - float VerticalOffset() - { - return m_dysOffset; - } - - int NumUserDefn() - { - return m_cnUserDefn; - } - - int NumCompPerLig() - { - return m_cnCompPerLig; - } - - bool BasicJustification() - { - return m_fBasicJust; - } - - bool LoggingTransduction(); - //{ - // return m_pfface->getLogging(); - // //return m_fLogXductn; - //} - - bool FakeItalic() - { - return m_fFakeItalic; - } - - void NewSegment(Segment ** ppseg); - - static int ReadVersion(GrIStream & grstrm); - - /*---------------------------------------------------------------------------------------------- - Function to convert between coordinate systems. - This is identical to the built-in MulDiv function except that it rounds with better - precision. - - TODO: move these out of GrEngine to someplace more general. - ----------------------------------------------------------------------------------------------*/ - inline static int GrIntMulDiv(const int v, const int n, const int d) - { - return int(n < 0 ? - (double(v * n)/double(d)) - 0.5 : - (double(v * n)/double(d)) + 0.5); - } - inline static float GrFloatMulDiv(const float v, const float n, const float d) - { - return v * n / d; - } - inline static float GrIFIMulDiv(const int v, const float n, const int d) - { - return float(double(v) * n / double(d)); - } - inline static int GrFIFMulDiv(const float v, const int n, const float d) - { - return int(n < 0 ? - (v * double(n) / double(d)) - 0.5 : - (v * double(n) / double(d)) + 0.5); - } - inline static int RoundFloat(const float n) - { - return int(n < 0 ? n - 0.5 : n + 0.5); - } - -protected: - // Member variables: - - long m_cref; - - //////////// Font information //////////// - - bool m_fBold; - bool m_fItalic; - - // do we have the capacity to perform smart rendering for the various styles? - bool m_fSmartReg; - bool m_fSmartBold; - bool m_fSmartItalic; - bool m_fSmartBI; - // are the italics faked using a slant? - bool m_fFakeItalicCache; - bool m_fFakeBICache; - // control files for styled text; empty means not yet determined - std::wstring m_strCtrlFileReg; // regular - std::wstring m_strCtrlFileBold; // bold - std::wstring m_strCtrlFileItalic; // italic - std::wstring m_strCtrlFileBI; // bold-italic - - bool m_fFakeItalic; // true if we are simulating an italic slant in positioning - - std::wstring m_stuCtrlFile; // control file (.ttf file) from which we got - // currently loaded files - - std::wstring m_stuInitError; // description of any error that happened while initializing - // the engine - std::wstring m_stuErrCtrlFile; // file for which the error occurred - - std::wstring m_stuFaceName; // eg, "Times New Roman" - std::wstring m_stuFeatures; - - bool m_fUseSepBase; - std::wstring m_stuBaseFaceName; // from Sile table; empty if we are not using a separate - // control file - - GrResult m_resFontRead; // kresOk if the Graphite font was loaded successfully; - // kresFail if the font could not be found or basic tables couldn't be read; - // kresFalse if the Silf table is not present; - // kresUnexpected if the Graphite tables could not be loaded - - GrResult m_resFontValid; // kresInvalidArg if the engine is not yet initialized - // Originally: - // kresOk if Graphite font & dc font match cmaps - // kresUnexpected/kresFalse if dumb rendering - // kresFail if dumb rendering with no cmap - // But now it is apparently just = to m_resFontRead otherwise. - FontErrorCode m_ferr; - int m_fxdBadVersion; - - int m_nFontCheckSum; // when loading a font using the GrGraphics, remember the - // check sum as a unique identifer - - int m_nScriptTag; // from the pertinent writing system; currently not used - unsigned int m_grfsdc; // supported script directions - - bool m_fRightToLeft; // overall writing-system direction - - int m_mXAscent; // extra ascent, in font's em-units - int m_mXDescent; // extra descent, in font's em_units - - float m_dysOffset; // vertical offset, in logical units (eg, for super/subscript) - - bool m_fBasicJust; // true if there are no complex justification tables/rules in the - // font, so we use basic whitespace justification - int m_cJLevels; // number of justification levels - - GrTableManager * m_ptman; - GrClassTable * m_pctbl; - GrGlyphTable * m_pgtbl; - - FontFace * m_pfface; - - GrFeature m_rgfeat[kMaxFeatures]; -// HashMap<int, int> m_hmnifeat; // maps from feature IDs to indices in the array -// // Review: do we need this, or is a linear search adequate? - int m_cfeat; // number of features present - - short * m_rglcidFeatLabelLangs; // LCIDs (language IDs) for all the labels in the feature table - size_t m_clcidFeatLabelLangs; - - GrLangTable m_langtbl; - - // are line-breaks relevant at all? - bool m_fLineBreak; - // ranges for possible cross-line-boundary contextualization - int m_cchwPreXlbContext; - int m_cchwPostXlbContext; - - // magic glyph attribute numbers - data16 m_chwPseudoAttr; // actual-for-pseudo fake glyph attribute - data16 m_chwBWAttr; // break-weight - data16 m_chwDirAttr; // directionality - data16 m_chwJStretch0; // justify.0.stretch - data16 m_chwJShrink0; // justify.0.shrink - data16 m_chwJStep0; // justify.0.step - data16 m_chwJWeight0; // justify.0.weight - - gid16 m_chwLBGlyphID; // magic line-break glyph ID - - int m_cComponents; // number of glyph attributes at the beginning of the glyph table - // that actually represent ligature components - - int m_cnUserDefn; // number of user-defined slot attributes - int m_cnCompPerLig; // max number of components needed per ligature - - int m_mFontEmUnits; // number of design units in the Em square for the font - - // for pseudo-glyph mappings - int m_cpsd; // number of psuedo-glyphs - GrPseudoMap * m_prgpsd; - int m_dipsdInit; // (max power of 2 <= m_cpsd); - // size of initial range to consider - int m_cPsdLoop; // log2(max power of 2 <= m_cpsd); - // indicates how many iterations are necessary - int m_ipsdStart; // m_cpsd - m_dipsdInit; - // where to start search - - // for Unicode to glyph ID mapping - ////TableBuffer m_tbufCmap; // hold the full cmap table - void * m_pCmap_3_1; // point to the MS Unicode cmap subtable - // uses platform 3 writing system 1 or 0, preferably 1 - // use for Unicode to Glyph ID conversion - void * m_pCmap_3_10; - byte * m_pCmapTbl; - bool m_fCmapTblCopy; - int m_cbCmapTbl; // needed only for memory instrumentation - - // for feature names and maybe other strings from font later - ////TableBuffer m_tbufNameTbl; // hold full name table; use Name() method to access - byte * m_pNameTbl; - bool m_fNameTblCopy; - int m_cbNameTbl; // needed only for memory instrumentation - - bool m_fLogXductn; // true if we want to log the transduction process - - bool m_fInErrorState; // true if we are handling a rendering error - - // Other protected methods: - - enum { - ksegmodeBreak = 0, // FindBreakPoint - ksegmodeJust, // MakeJustifiedSegment - //ksegmodeMms, // MakeMeasuredSegment - ksegmodeRange // MakeSegmentFromRange - }; - - void MakeSegment( - // Common parameters - Segment * psegRet, - Font * pfont, ITextSource * pgts, IGrJustifier * pjus, - LayoutEnvironment & layout, - int ichMin, int ichLim, - // for finding a line break - float dxMaxWidth, - bool fBacktracking, - // for making a justified segment - bool fJust, float dxJustifiedWidthJ, SegEnd estJ); - - int FindFontLim(ITextSource * pgts, int ichFontMin, int * pnDirDepth); - -#ifdef GR_FW - ////GrResult InitFromControlFile(IGrGraphics * pgg, std::wstring stuFaceName, - //// bool fBold, bool fItalic); -- obsolete - ////GrResult ReadFromControlFile(std::wstring stuFontFile); -- obsolete -// GrResult GetFallBackFont(std::wstring * pstu); -#endif - - ////GrResult ReadFromGraphicsFont(IGrGraphics * pgg, bool fItalic); -- obsolete - void DestroyEverything(); - - bool CheckTableVersions(GrIStream * pgrstrm, - byte *silf_tbl, int lSilfStart, - byte *gloc_tbl, int lGlocStart, - byte *feat_tbl, int lFeatStart, - int * pfxdBadVersion); - //bool ReadSileTable(GrIStream & grstrm, long lTableSTart, - // int * pmFontEmUnits, bool * pfMismatchedBase); - bool ReadSilfTable(GrIStream & grstrm, long lTableStart, int iSubTable, - int * pchwMaxGlyphID, int * pfxdVersion); - bool ReadGlocAndGlatTables(GrIStream & grstrm, long lGlocStart, GrIStream & glat_strm, long lGlatStart, - int chwMaxGlyphID, int fxdSilfVersion); - bool ReadFeatTable(GrIStream & grstrm, long lTableStart); - bool ReadSillTable(GrIStream & grstrm, long lTableStart); - bool SetCmapAndNameTables(Font * pfont); - - void CreateEmpty(); - - bool BadFont(FontErrorCode * pferr = NULL) - { - if (pferr) - *pferr = m_ferr; - return (m_resFontValid == kresFail || m_resFontRead == kresFail); - } - bool DumbFallback(FontErrorCode * pferr = NULL) - { - if (pferr) - *pferr = m_ferr; - return (m_resFontValid != kresOk || m_resFontRead != kresOk); - } - - gid16 MapToPseudo(int nUnicode); - - // NEW interface - void AssignDefaultFeatures(int cfeat, FeatureSetting * prgfset); - - // Feature access for FontFace: - size_t NumberOfFeatures_ff(); - featid FeatureID_ff(size_t ifeat); - size_t FeatureWithID_ff(featid id); - bool GetFeatureLabel_ff(size_t ifeat, lgid language, utf16 * label); - int GetFeatureDefault_ff(size_t ifeat); - size_t NumberOfSettings_ff(size_t ifeat); - int GetFeatureSettingValue_ff(size_t ifeat, size_t ifset); - bool GetFeatureSettingLabel_ff(size_t ifeat, size_t ifset, lgid language, utf16 * label); - // Feature-label languages: - size_t NumberOfFeatLangs_ff(); - short GetFeatLabelLang_ff(size_t ilang); - // Language access for FontFace: - size_t NumberOfLanguages_ff(); - isocode GetLanguageCode_ff(size_t ilang); - - void SetUpFeatLangList(); - -//:Ignore -#ifdef OLD_TEST_STUFF - // For test procedures: - void SetUpCrossLineContextTest(); - void SetUpPseudoGlyphTest(); - void SetUpRuleActionTest(); - void SetUpRuleAction2Test(); - void SetUpAssocTest(); - void SetUpAssoc2Test(); - void SetUpDefaultAssocTest(); - void SetUpFeatureTest(); - void SetUpLigatureTest(); - void SetUpLigature2Test(); - - void InitFromControlFileTest(); -#endif // OLD_TEST_STUFF -//:End Ignore -}; - -} // namespace gr - -#if defined(GR_NO_NAMESPACE) -using namespace gr; -#endif - - -#endif // !GR_ENGINE_INCLUDED diff --git a/Build/source/libs/graphite-engine/src/segment/GrFSM.cpp b/Build/source/libs/graphite-engine/src/segment/GrFSM.cpp deleted file mode 100644 index 53182edab0d..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrFSM.cpp +++ /dev/null @@ -1,526 +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: GrFSM.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Implements the finite state machine. -----------------------------------------------------------------------------------------------*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" -#include <cstring> -#ifdef _MSC_VER -#pragma hdrstop -#endif -// any other headers (not precompiled) - -#undef THIS_FILE -DEFINE_THIS_FILE - -//:End Ignore - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -namespace gr -{ - -//:>******************************************************************************************** -//:> Methods -//:>******************************************************************************************** - -/*---------------------------------------------------------------------------------------------- - Fill in the FSM by reading from the font stream. - Assumes the stream is in the correct position. -----------------------------------------------------------------------------------------------*/ -bool GrFSM::ReadFromFont(GrIStream & grstrm, int fxdVersion) -{ - short snTmp; - - // number of FSM states - snTmp = grstrm.ReadShortFromFont(); - m_crow = snTmp; - // number of transitional states - snTmp = grstrm.ReadShortFromFont(); - int crowTransitional = snTmp; - // number of success states - snTmp = grstrm.ReadShortFromFont(); - int crowSuccess = snTmp; - m_crowFinal = m_crow - crowTransitional; - m_crowNonAcpt = m_crow - crowSuccess; - m_rowFinalMin = crowTransitional; - // number of columns - snTmp = grstrm.ReadShortFromFont(); - m_ccol = snTmp; - - // Sanity checks. - if (crowTransitional > m_crow || crowSuccess > m_crow) - return false; // bad table - // TODO: add a sanity check for m_ccol. - - // number of FSM glyph ranges and search constants - snTmp = grstrm.ReadShortFromFont(); - m_cmcr = snTmp; - snTmp = grstrm.ReadShortFromFont(); - m_dimcrInit = snTmp; - snTmp = grstrm.ReadShortFromFont(); - m_cLoop = snTmp; - snTmp = grstrm.ReadShortFromFont(); - m_imcrStart = snTmp; - - m_prgmcr = new GrFSMClassRange[m_cmcr]; - for (int imcr = 0; imcr < m_cmcr; imcr++) - { - m_prgmcr[imcr].m_chwFirst = grstrm.ReadUShortFromFont(); - m_prgmcr[imcr].m_chwLast = grstrm.ReadUShortFromFont(); - m_prgmcr[imcr].m_col = grstrm.ReadUShortFromFont(); - } - - // rule map and offsets (extra item at end gives final offset, ie, total) - m_prgirulnMin = new data16[crowSuccess + 1]; - data16 * pchw = m_prgirulnMin; - int i; - for (i = 0; i < (crowSuccess + 1); i++, pchw++) - { - *pchw = grstrm.ReadUShortFromFont(); - } - - // Last offset functions as the total length of the rule list. - // Note that the number of rules in the map is not necessarily equal to the number of - // rules in the pass; some rules may be listed multiply, if they are matched by more - // than one state. - int crulInMap = m_prgirulnMin[crowSuccess]; - m_prgrulnMatched = new data16[crulInMap]; - m_crulnMatched = crulInMap; - pchw = m_prgrulnMatched; - for (i = 0; i < crulInMap; i++, pchw++) - { - *pchw = grstrm.ReadUShortFromFont(); - } - - // min rule pre-context number of items - byte bTmp = grstrm.ReadByteFromFont(); - m_critMinRulePreContext = bTmp; - // max rule pre-context number of items - bTmp = grstrm.ReadByteFromFont(); - m_critMaxRulePreContext = bTmp; - - if (m_critMinRulePreContext > kMaxSlotsPerRule || m_critMaxRulePreContext > kMaxSlotsPerRule) - return false; // bad table - - int cStartStates = m_critMaxRulePreContext - m_critMinRulePreContext + 1; - - // start states - m_prgrowStartStates = new short[cStartStates]; - short * psn = m_prgrowStartStates; - for (int ic = 0; ic < cStartStates; ic++, psn++) - { - *psn = grstrm.ReadShortFromFont(); - } - - return true; -} - -/*---------------------------------------------------------------------------------------------- - Fill in the FSM's state table by reading from the font stream. - Assumes the stream is in the correct position. -----------------------------------------------------------------------------------------------*/ -bool GrFSM::ReadStateTableFromFont(GrIStream & grstrm, int fxdVersion) -{ - int cCells = ((m_crow - m_crowFinal) * m_ccol); - m_prgrowTransitions = new short[cCells]; - short * psn = m_prgrowTransitions; - for (int iCell = 0; iCell < cCells; iCell++, psn++) - { - *psn = grstrm.ReadShortFromFont(); - } - - return true; -} - -/*---------------------------------------------------------------------------------------------- - Use the transition table to find a rule or rules that match; then run the contraint - code to see if the rule is active. Return the rule number of the rule to be applied. - - @param ppass - pass, which knows how to run constraint code - @param psstrmIn - input stream - @param psstrmOut - output stream (from which to get recently output slots) -----------------------------------------------------------------------------------------------*/ -int GrFSM::GetRuleToApply(GrTableManager * ptman, GrPass * ppass, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - // List of accepting states and corresponding count of slots that were - // matched by each. - int prgrowAccepting[kMaxSlotsPerRule]; - int prgcslotMatched[kMaxSlotsPerRule]; - - // Run the transition table until it jams. - int crowAccepting = RunTransitionTable(ppass, psstrmIn, psstrmOut, - prgrowAccepting, prgcslotMatched); - - // Nothing matched; fail quickly. - if (crowAccepting == 0) - return -1; - - int * prow = prgrowAccepting + crowAccepting - 1; - int * pcslot = prgcslotMatched + crowAccepting - 1; // # of slots matched AFTER the curr pos - - // Quick test for common case of exactly one rule matched. - if (crowAccepting == 1 && - (m_prgirulnMin[*prow - m_crowNonAcpt + 1] - m_prgirulnMin[*prow - m_crowNonAcpt]) == 1) - { - int iruln = m_prgirulnMin[*prow - m_crowNonAcpt]; - int ruln = m_prgrulnMatched[iruln]; - if (RunConstraintAndRecordLog(ptman, ppass, ruln, psstrmIn, psstrmOut, - ppass->PreModContextForRule(ruln), *pcslot)) - { - return ruln; - } - else - return -1; - } - - // Several rules were matched. We need to sort them and then run the constraints - // for each rule, accepting the first one whose constraints succeed. - - // Count up the number of rules that matched and allocate a buffer of the right size. - int crulMatched = 0; - while (prow >= prgrowAccepting) - { - crulMatched += - m_prgirulnMin[*prow - m_crowNonAcpt + 1] - m_prgirulnMin[*prow - m_crowNonAcpt]; - --prow; - } - MatchedRule * prgmr = new MatchedRule[crulMatched]; - - prow = prgrowAccepting + crowAccepting - 1; - - // Do a dumb insertion sort, ordering primarily by sort key (largest first) - // and secondarily by the order in the original file (rule number). - // Review: is this kind of sort fast enough? We assuming that we usually only - // have a handful of matched rules. - int cmr = 0; - while (prow >= prgrowAccepting) - { - int iruln = m_prgirulnMin[*prow - m_crowNonAcpt]; - // Get all the rules matches by a single state. - while (iruln < m_prgirulnMin[*prow - m_crowNonAcpt + 1]) - { - int ruln = m_prgrulnMatched[iruln]; - int nSortKey = ppass->SortKeyForRule(ruln); - int cslot = *pcslot; - int imr; - for (imr = 0; imr < cmr; imr++) - { - if (nSortKey > prgmr[imr].nSortKey || - (nSortKey == prgmr[imr].nSortKey && ruln < prgmr[imr].ruln)) - { - // Insert here. - memmove(prgmr+imr+1, prgmr+imr, (isizeof(MatchedRule) * (cmr - imr))); - prgmr[imr].ruln = ruln; - prgmr[imr].nSortKey = nSortKey; - prgmr[imr].cslot = cslot; - break; - } - } - if (imr >= cmr) - { - prgmr[cmr].ruln = ruln; - prgmr[cmr].nSortKey = nSortKey; - prgmr[cmr].cslot = cslot; - } - cmr++; - - iruln++; - } - --prow; - --pcslot; - } - - - for (int imr = 0; imr < cmr; imr++) - { - int ruln = prgmr[imr].ruln; - if (RunConstraintAndRecordLog(ptman, ppass, ruln, psstrmIn, psstrmOut, - ppass->PreModContextForRule(ruln), prgmr[imr].cslot)) - { - // Success! - delete[] prgmr; - return ruln; - } - } - - // No rule matched or the constraints failed. - delete[] prgmr; - return -1; -} - -/*---------------------------------------------------------------------------------------------- - Run the transition table, generating a list of rows corresponding to accepting states. - - @param psstrmIn - input stream - @param prgrowAccepting - array to fill in with accepting rows - @param prgcslotMatched - corresponding array with number of slots matched -----------------------------------------------------------------------------------------------*/ -int GrFSM::RunTransitionTable(GrPass * ppass, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, - int * prgrowAccepting, int * prgcslotMatched) -{ - int ipass = ppass->PassNumber(); - - // Remember we're reading the pre-context items from the output stream, not the input. - int cslotPreContextAvail = psstrmOut->WritePos(); - - if (cslotPreContextAvail < m_critMinRulePreContext) - return 0; // not enough input to match any rule - - // Look backwards by the number of pre-context items for this pass, but not earlier - // than the beginning of the stream. - int cslot = -1 * min(cslotPreContextAvail, m_critMaxRulePreContext); - - // Normally the start state is state 0. But if we are near the beginning of the stream, - // we may need to adjust due to the fact that we don't have enough input yet to - // match the pre-context items in all the rules. So in effect we skip some states - // corresponding to the earlier items that aren't present. - int row = m_prgrowStartStates[max(0, m_critMaxRulePreContext - cslotPreContextAvail)]; - - int * prowTop = prgrowAccepting; - int * pcslotTop = prgcslotMatched; - while (true) - { - if (row >= m_rowFinalMin) - // final state--jammed - return (prowTop - prgrowAccepting); - - if (psstrmIn->SlotsPendingInContext() <= cslot) - // no more input - return (prowTop - prgrowAccepting); - - // Figure out what column the input glyph belong in. - // Since this is a time-critical routine, we cache the results for the current pass. - GrSlotState * pslot = (cslot < 0) ? - psstrmOut->PeekBack(cslot) : - psstrmIn->Peek(cslot); - int col; - if (pslot->PassNumberForColumn() == ipass) - { - col = pslot->FsmColumn(); - } - else - { - gid16 chwGlyphID = (cslot < 0) ? - psstrmOut->PeekBack(cslot)->GlyphID() : - psstrmIn->Peek(cslot)->GlyphID(); - col = FindColumn(chwGlyphID); - pslot->CacheFsmColumn(ipass, col); - } - int rowNext; - if (col < 0) - rowNext = 0; - else - rowNext = m_prgrowTransitions[(row * m_ccol) + col]; - - if (rowNext == 0) // jammed - return (prowTop - prgrowAccepting); - - cslot++; - if (rowNext >= m_crowNonAcpt) // or (rowNext < 0) - { - // Accepting state--push it on the stack. - //rowNext *= -1; - gAssert((prowTop - prgrowAccepting) < kMaxSlotsPerRule); - *prowTop++ = rowNext; - *pcslotTop++ = cslot; - } - row = rowNext; - - gAssert((prowTop - prgrowAccepting) == (pcslotTop - prgcslotMatched)); - } -} - -/*---------------------------------------------------------------------------------------------- - Run the transition table, generating a list of rows corresponding to accepting states. - Optimized to avoid matrix arithmetic for non-accepting states. - - Review: do we need to use this version? - - @param psstrmIn - input stream - @param prgrowAccepting - array to fill in with accepting rows - @param prgcslotMatched - corresponding array with number of slots matched -----------------------------------------------------------------------------------------------*/ -#if 0 - -int GrFSM::RunTransitionTableOptimized(GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, - int * prgrowAccepting, int * prgcslotMatched) -{ - int cslot = 0; - int ichwRowOffset = 0; - int ichwRowOffsetLim = m_crowFinal * m_ccol; // number of cells - int * prowTop = prgrowAccepting; - int * pcslotTop = prgcslotMatched; - while (true) - { - if (ichwRowOffset >= ichwRowOffsetLim) - // final state--jammed - return (prowTop - prgrowAccepting); - - if (psstrmIn->SlotsPendingInContext() < cslot) - // no more input - return (prowTop - prgrowAccepting); - - gid16 chwGlyphID = psstrmIn->Peek(cslot)->GlyphID(); - int col = FindColumn(chwGlyphID); - short cellValue = *(m_prgprgrowXitions + ichwRowOffset + col); - - if (cellValue == 0) // jammed - return (prowTop - prgrowAccepting); - - cslot++; - if (cellValue < 0) - { - // Accepting state--push it on the stack. - int rowNext = cellValue * -1; - gAssert((prowTop - prgrowAccepting) < kMaxSlotsPerRule); - *prowTop++ = rowNext; - *pcslotTop++ = cslot; - ichwRowOffset = rowNext * m_ccol; - } - else - ichwRowOffset = cellValue; - - gAssert((prowTop - prgrowAccepting) == (pcslotTop - prgcslotMatched)); - } -} - -#endif // 0 - - -/*---------------------------------------------------------------------------------------------- - Run all the constraints for the rules matched by the state that we have reached. - The rules are ordered as they were in the GDL file. When we hit a constraint that - matches, return the corresponding rule number. Return -1 if no rule passed. - - @param ppass - pass, which knows how to actually run the constraints - @param psstrmIn - input stream - @param cslotMatched - number of slots matched; constraints must be run for each of these -----------------------------------------------------------------------------------------------*/ -//:Ignore -int GrFSM::RunConstraints_Obsolete(GrTableManager * ptman, GrPass * ppass, int row, - GrSlotStream * psstrmIn, int cslotMatched) -{ - int iruln = m_prgirulnMin[row - m_crowNonAcpt]; - while (iruln < m_prgirulnMin[row - m_crowNonAcpt + 1]) - { - int ruln = m_prgrulnMatched[iruln]; - bool fSuccess = ppass->RunConstraint(ptman, ruln, psstrmIn, NULL, 0, cslotMatched); - if (fSuccess) - { - if (ptman->LoggingTransduction()) - ppass->RecordRuleFired(psstrmIn->ReadPosForNextGet(), ruln); - return ruln; - } - else - { - if (ptman->LoggingTransduction()) - ppass->RecordRuleFailed(psstrmIn->ReadPosForNextGet(), ruln); - } - - iruln++; - } - return -1; // no rule succeeded -} -//:End Ignore - -/*---------------------------------------------------------------------------------------------- - Run the constraints for the given rule, and record whether it failed or succeeded in the - transduction log. - - @param ppass - pass, which knows how to actually run the constraints - @param psstrmIn - input stream - @param cslotPreModContext - number of slots before the current position that must be tested - @param islotLimMatched - number of slots matched AFTER the current position - - @return True if the constraints succeeded. -----------------------------------------------------------------------------------------------*/ -bool GrFSM::RunConstraintAndRecordLog(GrTableManager * ptman, GrPass * ppass, int ruln, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, - int cslotPreModContext, int islotLimMatched) -{ - bool fSuccess = ppass->RunConstraint(ptman, ruln, psstrmIn, psstrmOut, - cslotPreModContext, islotLimMatched); - - if (ptman->LoggingTransduction()) - { - if (fSuccess) - ppass->RecordRuleFired(psstrmIn->ReadPosForNextGet(), ruln); - else - ppass->RecordRuleFailed(psstrmIn->ReadPosForNextGet(), ruln); - } - - return fSuccess; -} - -/*---------------------------------------------------------------------------------------------- - Search for the class range containing the glyph ID, and return the matching FSM column. - Does a fast binary search that uses only shifts, no division. -----------------------------------------------------------------------------------------------*/ -int GrFSM::FindColumn(gid16 chwGlyphID) -{ - #ifdef _DEBUG - // Check that the pre-calculated constants are correct. - int nPowerOf2 = 1; - while (nPowerOf2 <= m_cmcr) - nPowerOf2 <<= 1; - nPowerOf2 >>= 1; - // Now nPowerOf2 is the max power of 2 <= m_cclsrg. - // m_cLoop is not needed for our purposes, but it is included because it is part of - // the TrueType standard. - gAssert(1 << m_cLoop == nPowerOf2); // m_cloop == log2(nPowerOf2) - gAssert(m_dimcrInit == nPowerOf2); - gAssert(m_imcrStart == m_cmcr - m_dimcrInit); - #endif - - int dimcrCurr = m_dimcrInit; - - GrFSMClassRange * pmcrCurr = m_prgmcr + m_imcrStart; - while (dimcrCurr > 0) - { - int nTest; - if (pmcrCurr < m_prgmcr) - nTest = -1; - else - { - nTest = pmcrCurr->m_chwFirst - chwGlyphID; - if (nTest < 0 && chwGlyphID <= pmcrCurr->m_chwLast) - //nTest = 0; - // This is a tiny bit more efficient: - return pmcrCurr->m_col; - } - - if (nTest == 0) - // found it - return pmcrCurr->m_col; - - dimcrCurr >>= 1; // divide by 2 - if (nTest < 0) - pmcrCurr += dimcrCurr; - else // (nTest > 0) - pmcrCurr -= dimcrCurr; - } - - return -1; -} - -} // namespace gr diff --git a/Build/source/libs/graphite-engine/src/segment/GrFSM.h b/Build/source/libs/graphite-engine/src/segment/GrFSM.h deleted file mode 100644 index b1909553daa..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrFSM.h +++ /dev/null @@ -1,245 +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: GrFSM.h -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - The GrFSM class, which is the mechanism that examines input in a glyph stream and - determines which rule matches and should be run. -----------------------------------------------------------------------------------------------*/ -#ifdef _MSC_VER -#pragma once -#endif -#ifndef FSM_INCLUDED -#define FSM_INCLUDED - -//:End Ignore - -namespace gr -{ - -class GrPass; - -/*---------------------------------------------------------------------------------------------- - A machine class range consists of a range of contiguous glyph IDs that map to - a single column in the FSM (a machine class). (Note that there might be more than one - range mapping to a given column.) - - Keep in mind that these "classes" are completely different from the classes that - are used for substitution. These are used only for matching by the FSM. - - Hungarian: mcr -----------------------------------------------------------------------------------------------*/ -class GrFSMClassRange -{ - friend class GrFSM; - -protected: - gid16 m_chwFirst; // first glyph ID in range - gid16 m_chwLast; // last glyph ID in range - data16 m_col; // column (machine class) to which this range maps -}; - -/*---------------------------------------------------------------------------------------------- - The finite state machine that is used to match sequences of glyphs and - determine which rule to apply. There is one FSM per pass. - - The states in the FSM are grouped and ordered in the following way: - - non-accepting states (no rule completely matched) - - accepting non-final states (a rule matched, but a longer rule is possible) - - final states (a rule matched and no longer rule is possible) - In other words, we have: - - transition, non-accepting - - transition, accepting - - non-transition, accepting - The transition states have information about the next state to transition to; - the accepting states have information about the rule(s) that matched. - - There are three main data structures that are part of the finite state machine: - - (1) the transition matrix: m_prgprgrowXitions. It contains a row for each transition - state (non-accepting states plus accepting non-final states), and a column for each - machine class. The cell values indicate the next state to transition to for the - matched input. A positive number indicates that the next state is a non-accepting state; - a negative value indicates an accepting state. Zero means there is no next state; - no more matches are possible; machine has "jammed." - - (2) the matched-rule list: m_prgrulnMatched. This is a list of rule numbers, - which are indices into the pass's action- and constraint-code arrays. - It contains the numbers of the rules matched by the first accepting state, - followed by those matched by the second accepting state, etc. For each state, - the rules must be ordered using the same order of the rules in the RDL file. - - (3) the matched-rule-offsets list: m_prgirulnMin. This gives the starting index into - the matched-rule list for each accepting state. (Non-accepting states are not included, - so the first item is for state m_crowNonAcpt.) - - In addition, the FSM interacts with the action- and constraint-code lists in the pass - itself. These lists are indexed by rule number (the values of m_prgrulnMatched). - When some input matches the rule, the constraint-code is run; if it succeeds, - the rule number is returned to the caller and that rule is applied (ie, the action-code - is run). - - Hungarian: fsm - - Other hungarian: - row - row (state) - col - column (machine class) - ruln - rule number - - REVIEW: This is quite a time-critical class, and there are two potential optimizations - that have been proposed for the value of a cell: - - (1) use a negative cell number to indicate an accepting state and a positive number - to indicate a non-accepting state. So this gives a comparison with zero rather than - some arbitrary number - - (2) have the positive numbers--the most common case--be the actual byte offset into the - table rather than the row number. This saves matrix multiplication at each step, - ie, "m_prgsnTransitions[(row * m_ccol) + col]". - - The two versions are implemented in RunTransitionTable and RunTransitionTableOptimized. - Do these seem to be worth the inconvenience of added complexity in understanding - and debugging? -----------------------------------------------------------------------------------------------*/ -class GrFSM -{ - friend class FontMemoryUsage; - -public: - GrFSM() : - m_prgirulnMin(NULL), - m_prgrulnMatched(NULL), - m_prgrowTransitions(NULL), - m_prgibStateDebug(NULL), - m_prgmcr(NULL), - m_prgrowStartStates(NULL) - { - } - - ~GrFSM() - { - delete[] m_prgirulnMin; - delete[] m_prgrulnMatched; - - delete[] m_prgrowTransitions; - - delete[] m_prgibStateDebug; - - delete[] m_prgmcr; - - delete[] m_prgrowStartStates; - } - - bool ReadFromFont(GrIStream & grstrm, int fxdVersion); - bool ReadStateTableFromFont(GrIStream & grstrm, int fxdVersion); - - int GetRuleToApply(GrTableManager *, GrPass * ppass, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - - int RunTransitionTable(GrPass * ppass, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, - int * prgrowAccepting, int * prgcslotMatched); - int RunTransitionTableOptimized(GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, - int * prgrowAccepting, int * prgcslotMatched); - bool RunConstraintAndRecordLog(GrTableManager *, GrPass * ppass, int ruln, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, - int cslotPreModContext, int cslotMatched); - - int RunConstraints_Obsolete(GrTableManager *, GrPass * ppass, int row, GrSlotStream * psstrmIn, - int cslotMatched); - - // For sorting matched rules - struct MatchedRule // mr - { - int ruln; - int nSortKey; - int cslot; // number of slots matched AFTER the current stream position - }; - - int MaxRulePreContext() - { - return m_critMaxRulePreContext; - } - -protected: - int FindColumn(gid16 chwGlyphID); -protected: - // Instance variables: - int m_crow; // number of rows (states) - int m_crowFinal; // number of final states; no transitions for these - int m_rowFinalMin; // index of first final row - int m_crowNonAcpt; // number of non-accepting states; no rule indices for these - - int m_ccol; // number of columns (machine classes) - - data16 * m_prgirulnMin; // m_crow-m_crowNonAcpt+1 of these; - // index within m_prgrulnMatched, start of matched - // rules for each accepting state - - data16 * m_prgrulnMatched; // long ordered list of rule indices matched by - // subsequent states; total length is sum of number - // of rules matched for each accepting state - int m_crulnMatched; // needed only for memory instrumentation - - // Transition matrix--for optimized version: -// short ** m_prgprgrowXitions; // ((m_crow-m_crowFinal) * m_ccol) of these; - // positive number indicates - // next state is non-accepting; negative number is - // negative of accepting state. - - // Transition matrix--for current version: - short * m_prgrowTransitions; // ((m_crow-m_crowFinal) * m_ccol) of these - - // debugger string offsets - data16 * m_prgibStateDebug; // for transition states; (m_crow-m_crul+1) of these - - // constants for fast binary search; these are generated by the compiler so that the - // engine doesn't have to take time to do it - data16 m_dimcrInit; // (max power of 2 <= m_cmcr); - // size of initial range to consider - data16 m_cLoop; // log2(max power of 2 <= m_cmcr); - // indicates how many iterations are necessary - data16 m_imcrStart; // m_cmcr - m_dimcrInit; - // where to start search - - int m_cmcr; // number of machine-class-ranges - GrFSMClassRange * m_prgmcr; // array of class ranges; we search these to find the - // mapping to the machine-class-column - - // minimum and maximum number of items in the rule contexts before the first modified - // item. - int m_critMinRulePreContext; - int m_critMaxRulePreContext; - - // start states--row in the FSM to start on depending on how many bogus slots we - // are skipping; (max rule-precontext - min rule-precontext + 1) of these; - // first always = zero - short * m_prgrowStartStates; - -//:Ignore -#if OLD_TEST_STUFF -public: - // For test procedures: - void SetUpSimpleFSMTest(); - void SetUpRuleActionTest(); - void SetUpRuleAction2Test(int); - void SetUpAssocTest(int); - void SetUpAssoc2Test(int); - void SetUpDefaultAssocTest(); - void SetUpFeatureTest(); - void SetUpLigatureTest(int); - void SetUpLigature2Test(int); -#endif // OLD_TEST_STUFF -//:End Ignore - -}; - -} // namespace gr - - -#endif // !FSM_INCLUDED diff --git a/Build/source/libs/graphite-engine/src/segment/GrFeature.cpp b/Build/source/libs/graphite-engine/src/segment/GrFeature.cpp deleted file mode 100644 index 61970d56949..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrFeature.cpp +++ /dev/null @@ -1,321 +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: GrFeature.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Implements the GrFeature class. --------------------------------------------------------------------------------*//*:End Ignore*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" -#include <cstring> - -#ifdef _MSC_VER -#pragma hdrstop -#endif -#undef THIS_FILE -DEFINE_THIS_FILE - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -namespace gr -{ - -//:>******************************************************************************************** -//:> GrFeature Methods -//:>******************************************************************************************** - -/*---------------------------------------------------------------------------------------------- - Initialize the feature. -----------------------------------------------------------------------------------------------*/ -void GrFeature::Initialize(featid nID, int nNameId, int cfset, int nDefault) -{ - m_nID = nID; - m_nNameId = nNameId; - m_nDefault = nDefault; - - m_vnVal.resize(cfset); - for (unsigned int ifset = 0; ifset < m_vnVal.size(); ifset++) - m_vnVal[ifset] = INT_MAX; - m_vnNameId.resize(cfset); -} - -/*---------------------------------------------------------------------------------------------- - Return the feature settings. -----------------------------------------------------------------------------------------------*/ -int GrFeature::Settings(int cMax, int * prgnVal) -{ - int cRet = min(cMax, signed(m_vnVal.size())); - for (int ifset = 0; ifset < cRet; ifset++) - prgnVal[ifset] = m_vnVal[ifset]; - return cRet; -} - -/*---------------------------------------------------------------------------------------------- - Add a feature setting. -----------------------------------------------------------------------------------------------*/ -void GrFeature::AddSetting(int nVal, int nNameId) -{ - Assert(nVal != INT_MAX); - unsigned int ifset; - for (ifset = 0; ifset < m_vnVal.size(); ifset++) - { - if (m_vnVal[ifset] == nVal) - return; // already there - } - for (ifset = 0; ifset < m_vnVal.size(); ifset++) - { - if (m_vnVal[ifset] == INT_MAX) - { - m_vnVal[ifset] = nVal; - m_vnNameId[ifset] = nNameId; - return; - } - } - m_vnVal.push_back(nVal); - m_vnNameId.push_back(nNameId); -} - -/*---------------------------------------------------------------------------------------------- - Return true if the given setting is valid according to the font's feature table. -----------------------------------------------------------------------------------------------*/ -bool GrFeature::IsValidSetting(int nVal) -{ - for (unsigned int ifset = 0; ifset < m_vnVal.size(); ifset++) - { - if (m_vnVal[ifset] == nVal) - return true; - } - return false; -} - -/*---------------------------------------------------------------------------------------------- - Read the feature label from the name table. -----------------------------------------------------------------------------------------------*/ -std::wstring GrFeature::Label(GrEngine * pgreng, int nLang) -{ - std::wstring stu = pgreng->StringFromNameTable(nLang, m_nNameId); - if (stu == L"NoName") - stu.erase(); - return stu; -} - -/*---------------------------------------------------------------------------------------------- - Read the feature value label from the name table. -----------------------------------------------------------------------------------------------*/ -std::wstring GrFeature::SettingLabel(GrEngine * pgreng, int nVal, int nLang) -{ - for (unsigned int ifset = 0; ifset < m_vnVal.size(); ifset++) - { - if (m_vnVal[ifset] == nVal) - { - std::wstring stu = pgreng->StringFromNameTable(nLang, m_vnNameId[ifset]); - if (stu == L"NoName") - stu.erase(); - return stu; - } - } - Assert(false); // setting is not valid - return L""; -} - -/*---------------------------------------------------------------------------------------------- - Return the given setting value. -----------------------------------------------------------------------------------------------*/ -int GrFeature::NthSetting(int ifset) -{ - if (ifset >= (int)m_vnVal.size()) - return -1; - else - return m_vnVal[ifset]; -} - -/*---------------------------------------------------------------------------------------------- - Read the feature value label for the given index. -----------------------------------------------------------------------------------------------*/ -std::wstring GrFeature::NthSettingLabel(GrEngine * pgreng, int ifset, int nLang) -{ - std::wstring stu; - - if (ifset >= (int)m_vnVal.size()) - stu.erase(); - else - { - stu = pgreng->StringFromNameTable(nLang, m_vnNameId[ifset]); - if (stu == L"NoName") - stu.erase(); - } - return stu; -} - -/*---------------------------------------------------------------------------------------------- - Return the feature setting label. -----------------------------------------------------------------------------------------------*/ -// void GrFeature::SetSettingLabel(int nVal, std::wstring stuLabel, int nLang) -// { -// for (int ifset = 0; ifset < m_vfset.size(); ifset++) -// { -// if (m_vfset[ifset].m_nVal == nVal) -// { -// m_vfset[ifset].m_hmnstuLabels.Insert(nLang, stuLabel, true); -// return; -// } -// } -// Assert(false); // setting is not valid -// } - - -//:>******************************************************************************************** -//:> GrLangTable Methods -//:>******************************************************************************************** - -/*---------------------------------------------------------------------------------------------- - Read the languages from the font. -----------------------------------------------------------------------------------------------*/ -bool GrLangTable::ReadFromFont(GrIStream * pgrstrm, int fxdVersion) -{ - GrIStream & grstrm = *pgrstrm; - - // number of languages - m_clang = (size_t)grstrm.ReadUShortFromFont(); - - // search constants - m_dilangInit = grstrm.ReadUShortFromFont(); - m_cLoop = grstrm.ReadUShortFromFont(); - m_ilangStart = grstrm.ReadUShortFromFont(); - - // Slurp the data into the buffers. The "+1" represents a bogus ending entry that quickly - // gives us the size of the feature list. Note that the resulting data is all big-endian. - int cb = (m_clang + 1) * sizeof(LangEntry); - m_prglang = new LangEntry[m_clang + 1]; - grstrm.ReadBlockFromFont(m_prglang, cb); - - m_cbOffset0 = (lsbf)(m_prglang[0].cbOffsetBIG); - - Assert((lsbf)(m_prglang[m_clang].cFeaturesBIG) == 0); // bogus entry has no settings - cb = (lsbf)(m_prglang[m_clang].cbOffsetBIG) - m_cbOffset0; - Assert(cb % sizeof(FeatSet) == 0); // # of bytes fits nicely into FeatSet class - int cfset = cb / sizeof(FeatSet); - m_prgfset = new FeatSet[cfset]; - m_cfset = cfset; - grstrm.ReadBlockFromFont(m_prgfset, cb); - - return true; -} - -/*---------------------------------------------------------------------------------------------- - Create an empty language table to use for dumb rendering, or when there is no valid - Sill table. -----------------------------------------------------------------------------------------------*/ -void GrLangTable::CreateEmpty() -{ - m_prglang = NULL; - m_prgfset = NULL; - m_clang = 0; - m_dilangInit = 0; - m_cLoop = 0; - m_ilangStart = 0; -} - -/*---------------------------------------------------------------------------------------------- - Return information about the language with the given ID by filling in the given vectors - with the feature ids and values. Will wipe out any data in the vectors already. -----------------------------------------------------------------------------------------------*/ -void GrLangTable::LanguageFeatureSettings(isocode lgcode, - std::vector<featid> & vnFeatId, std::vector<int> & vnValues) -{ - vnFeatId.clear(); - vnValues.clear(); - - int ilang = FindIndex(lgcode); - if (ilang == -1) - return; // no such language: leave vectors empty - - LangEntry * plang = m_prglang + ilang; - int cbOffset = lsbf(plang->cbOffsetBIG) - m_cbOffset0; - Assert(cbOffset % sizeof(FeatSet) == 0); - byte * pbFeatSet = reinterpret_cast<byte*>(m_prgfset) + cbOffset; - FeatSet * pfset = reinterpret_cast<FeatSet*>(pbFeatSet); - for (int ifset = 0; ifset < lsbf(plang->cFeaturesBIG); ifset++) - { - vnFeatId.push_back(lsbf(pfset[ifset].featidBIG)); - vnValues.push_back(lsbf(pfset[ifset].valueBIG)); - } -} - -/*---------------------------------------------------------------------------------------------- - Return the code for the language at the given index. -----------------------------------------------------------------------------------------------*/ -isocode GrLangTable::LanguageCode(size_t ilang) -{ - isocode lgcodeRet; - if (ilang > m_clang) - { - std::fill_n(lgcodeRet.rgch, 4, '\0'); - return lgcodeRet; - } - LangEntry * plang = m_prglang + ilang; - std::copy(plang->rgchCode, plang->rgchCode + 4, lgcodeRet.rgch); - return lgcodeRet; -} - -/*---------------------------------------------------------------------------------------------- - Return the index of the language in the list. -----------------------------------------------------------------------------------------------*/ -int GrLangTable::FindIndex(isocode lgcode) -{ - if (m_clang == 0) - return -1; -#ifdef _DEBUG - int nPowerOf2 = 1; - while (nPowerOf2 <= signed(m_clang)) - nPowerOf2 <<= 1; - nPowerOf2 >>= 1; - // Now nPowerOf2 is the max power of 2 <= m_clang - gAssert((1 << m_cLoop) == nPowerOf2); // m_cLoop == log2(nPowerOf2) - gAssert(m_dilangInit == nPowerOf2); - gAssert(m_ilangStart == m_clang - m_dilangInit); -#endif // _DEBUG - - int dilangCurr = m_dilangInit; - - int ilangCurr = m_ilangStart; // may become < 0 - while (dilangCurr > 0) - { - int nTest; - if (ilangCurr < 0) - nTest = -1; - else - { - LangEntry * plangCurr = m_prglang + ilangCurr; - nTest = strcmp(plangCurr->rgchCode, lgcode.rgch); - } - - if (nTest == 0) - return ilangCurr; - - dilangCurr >>= 1; // divide by 2 - if (nTest < 0) - ilangCurr += dilangCurr; - else // (nTest > 0) - ilangCurr -= dilangCurr; - } - - return -1; -} - -} // namespace gr diff --git a/Build/source/libs/graphite-engine/src/segment/GrFeatureValues.h b/Build/source/libs/graphite-engine/src/segment/GrFeatureValues.h deleted file mode 100644 index de9eda0f03f..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrFeatureValues.h +++ /dev/null @@ -1,71 +0,0 @@ -/*--------------------------------------------------------------------*//*:Ignore this sentence. -Copyright (C) 1999 - 2008 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: GrFeatureValues.h -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - - -----------------------------------------------------------------------------------------------*/ -#ifdef _MSC_VER -#pragma once -#endif -#ifndef GR_FEATVAL_INCLUDED -#define GR_FEATVAL_INCLUDED - -//:End Ignore - -namespace gr -{ - -/*---------------------------------------------------------------------------------------------- - A convenient way to group together style and feature information that interacts - with the rules. - - Hungarian: fval -----------------------------------------------------------------------------------------------*/ -class GrFeatureValues -{ - friend class GrCharStream; - friend class GrSlotAbstract; - friend class GrSlotState; - -public: - // Standard constructor: - GrFeatureValues() - { - m_nStyleIndex = 0; - std::fill(m_rgnFValues, m_rgnFValues + kMaxFeatures, 0); - } - - // Copy constructor: - GrFeatureValues(const GrFeatureValues & fval) - { - m_nStyleIndex = fval.m_nStyleIndex; - std::copy(fval.m_rgnFValues, fval.m_rgnFValues + kMaxFeatures, m_rgnFValues); - } - - bool FeatureValue(size_t ifeat) - { - return m_rgnFValues[ifeat]; - } - - // For transduction logging: -#ifdef TRACING - void WriteXductnLog(GrTableManager * ptman, std::ostream &); -#endif // TRACING - -protected: - int m_nStyleIndex; - int m_rgnFValues[kMaxFeatures]; -}; - -} // namespace gr - - -#endif // !GR_FEATVAL_INCLUDED diff --git a/Build/source/libs/graphite-engine/src/segment/GrGlyphTable.cpp b/Build/source/libs/graphite-engine/src/segment/GrGlyphTable.cpp deleted file mode 100644 index 8643eae8cb8..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrGlyphTable.cpp +++ /dev/null @@ -1,650 +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: GrGlyphTable.cpp -Responsibility: Sharon Correll -Last reviewed: 10Aug99, JT, quick look over - -Description: - Implements the GrGlyphTable class and related classes. -----------------------------------------------------------------------------------------------*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" - -#ifdef _MSC_VER -#pragma hdrstop -#endif -#undef THIS_FILE -DEFINE_THIS_FILE - -//:End Ignore - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -namespace gr -{ - -//:>******************************************************************************************** -//:> Methods -//:>******************************************************************************************** - -/*---------------------------------------------------------------------------------------------- - Fill in the glyph table from the font stream. -----------------------------------------------------------------------------------------------*/ -bool GrGlyphTable::ReadFromFont(GrIStream & grstrmGloc, long lGlocStart, - GrIStream & grstrmGlat, long lGlatStart, - data16 chwBWAttr, data16 chwJStrAttr, int cJLevels, int cnCompPerLig, - int fxdSilfVersion) -{ - // Create the glyph sub-table for the single style. - GrGlyphSubTable * pgstbl = new GrGlyphSubTable(); - - // Gloc table--offsets into Glat table - grstrmGloc.SetPositionInFont(lGlocStart); - - // version - int fxdGlocVersion = GrEngine::ReadVersion(grstrmGloc); - if (fxdGlocVersion > kGlocVersion) - return false; - - // flags - short snFlags = grstrmGloc.ReadShortFromFont(); - - // number of attributes - unsigned short cAttrs = grstrmGloc.ReadUShortFromFont(); - - // Create a single sub-table for the single style. - pgstbl->Initialize(fxdSilfVersion, snFlags, chwBWAttr, chwJStrAttr, data16(chwJStrAttr + cJLevels), - m_cglf, cAttrs, cnCompPerLig); - - SetSubTable(0, pgstbl); - - return pgstbl->ReadFromFont(grstrmGloc, m_cglf, grstrmGlat, lGlatStart); -} - -bool GrGlyphSubTable::ReadFromFont(GrIStream & grstrmGloc, int cGlyphs, - GrIStream & grstrmGlat, long lGlatStart) -{ - // attribute value offsets--slurp - if (m_fGlocShort) - { - grstrmGloc.ReadBlockFromFont(m_prgibBIGAttrValues, ((cGlyphs + 1) * sizeof(data16))); - } - else - { - grstrmGloc.ReadBlockFromFont(m_prgibBIGAttrValues, ((cGlyphs + 1) * sizeof(data32))); - } - - // length of buffer needed for glyph attribute values: - int cbBufLen = GlocLookup(data16(cGlyphs)); - - // TODO: slurp debugger offsets: 'm_prgibBIGGlyphAttrDebug' - - m_pgatbl = new GrGlyphAttrTable(); - m_pgatbl->Initialize(m_fxdSilfVersion, cbBufLen); - - // Glat table - grstrmGlat.SetPositionInFont(lGlatStart); - - // version - int fxdGlatVersion = grstrmGlat.ReadIntFromFont(); - if (fxdGlatVersion > kGlatVersion) - return false; - - // Back up over the version number and include it right in the attribute value entry - // buffer, since the offsets take it into account. - grstrmGlat.SetPositionInFont(lGlatStart); - - // Slurp the entire block of entries. - grstrmGlat.ReadBlockFromFont(m_pgatbl->m_prgbBIGEntries, cbBufLen); - - return true; -} - -/*---------------------------------------------------------------------------------------------- - Create an empty glyph table with no glyph attributes. -----------------------------------------------------------------------------------------------*/ -void GrGlyphTable::CreateEmpty() -{ - // Create the glyph sub-table for the single style. - GrGlyphSubTable * pgstbl = new GrGlyphSubTable(); - - // Create a single sub-table for the single style. - pgstbl->Initialize(0, 0, 0, 0, 0, m_cglf, 0, 0); - - SetSubTable(0, pgstbl); - - pgstbl->CreateEmpty(); -} - -void GrGlyphSubTable::CreateEmpty() -{ - m_pgatbl = new GrGlyphAttrTable(); - m_pgatbl->Initialize(0, 0); -} - -/*---------------------------------------------------------------------------------------------- - Initialization. -----------------------------------------------------------------------------------------------*/ -void GrGlyphSubTable::Initialize(int fxdSilfVersion, utf16 chwFlags, - data16 chwBWAttr, data16 chwJStrAttr, data16 chwJStrHWAttr, - int cGlyphs, int cAttrs, int cnCompPerLig) -{ - m_fxdSilfVersion = fxdSilfVersion; - m_fHasDebugStrings = HasAttrNames(chwFlags); - m_nAttrIDLim = cAttrs; - m_chwBWAttr = chwBWAttr; - m_chwJStrAttr = chwJStrAttr; - m_chwJStrHWAttr = chwJStrHWAttr; - m_fGlocShort = !LongFormat(chwFlags); - - if (m_fGlocShort) - { // item # cGlyphs holds length, which is convenient for dealing with last item - m_prgibBIGAttrValues = new byte[(cGlyphs + 1) * sizeof(data16)]; - } - else - { - m_prgibBIGAttrValues = new byte[(cGlyphs + 1) * sizeof(data32)]; - } - - - if (m_fHasDebugStrings) - { - m_prgibBIGGlyphAttrDebug = new data16[cAttrs + 1]; - } - - // Make a cache to hold a list of defined components for each glyph. This is - // calculated lazily, as needed, so we also include (as the first item) a flag to - // indicate whether or not it has been calculated; hence the "+1". - m_cnCompPerLig = cnCompPerLig; - m_prgnDefinedComponents = new int[(m_cnCompPerLig + 1) * cGlyphs]; - std::fill_n(m_prgnDefinedComponents, (m_cnCompPerLig + 1) * cGlyphs, 0); - - // Now the instance is ready to have the locations and the debug strings - // read from the file. -} - -/*---------------------------------------------------------------------------------------------- - Return the attribute value for the given glyph. -----------------------------------------------------------------------------------------------*/ -int GrGlyphSubTable::GlyphAttrValue(gid16 chwGlyphID, int nAttrID) -{ - if (m_nAttrIDLim == 0) - { - // No attributes defined (eg, invalid font) - return 0; - } - if (nAttrID >= m_nAttrIDLim || nAttrID >= 0xFF) - { - gAssert(false); - return 0; - } - int ibMin = GlocLookup(chwGlyphID); // where this glyph's attrs start - int ibLim = GlocLookup(chwGlyphID + 1); // where next glyph starts - - int nRet = m_pgatbl->GlyphAttr16BitValue(ibMin, ibLim, byte(nAttrID)); - if ((data16)nAttrID == m_chwJStrAttr) - { - // For justify.stretch, which can be a 32-bit value, add on the high word. - unsigned int nRetHW = m_pgatbl->GlyphAttr16BitValue(ibMin, ibLim, byte(m_chwJStrHWAttr)); - nRet = (nRetHW << 16) | nRet; - } - return ConvertValueForVersion(nRet, nAttrID); -} - -/*---------------------------------------------------------------------------------------------- - Convert the glyph attribute value from the version of the font table to what is - expected by the engine. -----------------------------------------------------------------------------------------------*/ -int GrGlyphSubTable::ConvertValueForVersion(int nValue, int nAttrID) -{ - return ConvertValueForVersion(nValue, nAttrID, (int)m_chwBWAttr, m_fxdSilfVersion); -} - -int GrGlyphSubTable::ConvertValueForVersion(int nValue, int nAttrID, int nBWAttr, int fxdVersion) -{ - if ((nBWAttr >= 0 && nAttrID == (int)nBWAttr) || - (nBWAttr == -1 && nAttrID == (int)kslatBreak)) - { - if (fxdVersion < 0x00020000) - { - //switch (nValue) - //{ - //case klbv1WordBreak: return klbWordBreak; - //case klbv1HyphenBreak: return klbHyphenBreak; - //case klbv1LetterBreak: return klbLetterBreak; - //case klbv1ClipBreak: return klbClipBreak; - //default: - // break; - //} - //switch (nValue * -1) - //{ - //case klbv1WordBreak: return (klbWordBreak * -1); - //case klbv1HyphenBreak: return (klbHyphenBreak * -1); - //case klbv1LetterBreak: return (klbLetterBreak * -1); - //case klbv1ClipBreak: return (klbClipBreak * -1); - //default: - // break; - //} - - // Breakweight values in version 2 are 10 times what they were in version 1. - if (abs(nValue) <= 7) - return nValue * 10; - } - } - return nValue; -} - -/*---------------------------------------------------------------------------------------------- - Return the attribute value a glyph. Loop through the attribute runs, looking - for the one containing the given attribute. Assume the value is 0 if not found. - - @param ibMin - byte offset of first run for the glyph of interest - @param ibLim - byte offset of first run for the following glyph - @param bAttrID - attribute to find -----------------------------------------------------------------------------------------------*/ -int GrGlyphAttrTable::GlyphAttr16BitValue(int ibMin, int ibLim, byte bAttrID) -{ - GrGlyphAttrRun gatrun; - byte * pbBIGEnt = m_prgbBIGEntries + ibMin; - - while (pbBIGEnt < m_prgbBIGEntries + ibLim) - { - // Suck the run of attribute values into the instance, so we can see - // what's there. - gatrun.CopyFrom(pbBIGEnt); - - if (bAttrID < gatrun.m_bMinAttrID) - // Attribute not found--assume value is 0. - return 0; - else if (gatrun.m_bMinAttrID + gatrun.m_cAttrs > bAttrID) - { - // Found the value in this run. - data16 chw = lsbf(gatrun.m_rgchwBIGValues[bAttrID - gatrun.m_bMinAttrID]); - if ((chw & 0x8000) == 0) - return (int)chw; - else - return 0xFFFF0000 | chw; // sign extension - } - else - // Go to next run. - pbBIGEnt += gatrun.ByteCount(); - } - - // Attribute not found--assume value is 0; - return 0; -} - -/*---------------------------------------------------------------------------------------------- - Given a point on the glyph, determine which component (if any) the point is in, and return - its index relative to the components that are defined for this glyph; ie, the index within - the compRef array. - Return -1 if the click with not inside any component, or if there are no components - defined for this glyph. - CURRENTLY NOT USED - if ever used, need to incorporate floating point -----------------------------------------------------------------------------------------------*/ -int GrGlyphSubTable::ComponentContainingPoint(gid16 chwGlyphID, int x, int y) -{ - int i = CalculateDefinedComponents(chwGlyphID); - for (int inComp = 0; inComp < m_cnCompPerLig; inComp++) - { - // The m_pnComponents list holds a list of the component attributes that are defined - // for this glyph, padded with -1's. - int nCompID = m_prgnDefinedComponents[i + inComp]; - if (nCompID == -1) - break; // hit the end of the list - - // The value of the component attribute is actually the attribute ID for the - // first of the component box fields--the top. There should a contiguous group of - // four fields: top, bottom, left, right. - int nFieldIDMin = GlyphAttrValue(chwGlyphID, nCompID); - gAssert(nFieldIDMin != 0); - int nTop = GlyphAttrValue(chwGlyphID, nFieldIDMin); - int nBottom = GlyphAttrValue(chwGlyphID, nFieldIDMin + 1); - int nLeft = GlyphAttrValue(chwGlyphID, nFieldIDMin + 2); - int nRight = GlyphAttrValue(chwGlyphID, nFieldIDMin + 3); - - if (nLeft <= x && x < nRight && - nBottom <= y && y < nTop) - { - return inComp; - } - } - return -1; -} - -/*---------------------------------------------------------------------------------------------- - Fill in the box with the source-device coordinates corresponding to the given component. - The rectangle is relative to the top-left of the glyph. - Return false if the component is not defined. - - @param xysEmSquare - of the font, in logical units - @param chwGlyphID - the glyph of interest - @param icomp - the component of interest (eg, for the "oe" ligature, - the index for component.o would be 0, - and the index for component.e would be 1); - these is as defined by the glyph, not as used in the rules - @param mFontEmUnits - the number of em-units in the font, for scaling - @param dysFontAscent - ascent of the font, for adjusting coordinate systems - @param pxsLeft, pxsRight, pysTop, pysBottom - - return values, in source device coordinates - @param fTopOrigin - convert values to a coordinate system where the origin is the - top of the line, not the baseline -----------------------------------------------------------------------------------------------*/ -bool GrGlyphSubTable::ComponentBoxLogUnits(float xysEmSquare, - gid16 chwGlyphID, int icomp, int mFontEmUnits, float dysFontAscent, - float * pxsLeft, float * pysTop, float * pxsRight, float * pysBottom, - bool fTopOrigin) -{ - int i = CalculateDefinedComponents(chwGlyphID); - - // The m_pnComponents list holds a list of the component attributes that are defined - // for this glyph, padded with -1's. - int nCompID = m_prgnDefinedComponents[i + icomp]; - if (nCompID == -1) - { - // Ooops, the component is undefined for this glyph. - *pxsLeft = 0; - *pxsRight = 0; - *pysTop = 0; - *pysBottom = 0; - return false; - } - - // The value of the component attribute is actually the attribute ID for the - // first of the component box fields--the top. There should a contiguous group of - // four fields: top, bottom, left, right. - int nFieldIDMin = GlyphAttrValue(chwGlyphID, nCompID); - if (nFieldIDMin == 0) - { - // Component inadequately defined. This can happen when we defined components - // for a glyph and then substituted another glyph for it. - *pxsLeft = 0; - *pxsRight = 0; - *pysTop = 0; - *pysBottom = 0; - return false; - } - int mTop = GlyphAttrValue(chwGlyphID, nFieldIDMin); - int mBottom = GlyphAttrValue(chwGlyphID, nFieldIDMin + 1); - int mLeft = GlyphAttrValue(chwGlyphID, nFieldIDMin + 2); - int mRight = GlyphAttrValue(chwGlyphID, nFieldIDMin + 3); - - ////int xysFontEmUnits; - ////// ysHeight should correspond to the pixels in the font's em square - ////GrResult res = pgg->GetFontEmSquare(&xysFontEmUnits); - ////if (ResultFailed(res)) - //// return false; - - *pxsLeft = GrEngine::GrIFIMulDiv(mLeft, xysEmSquare, mFontEmUnits); - *pxsRight = GrEngine::GrIFIMulDiv(mRight, xysEmSquare, mFontEmUnits); - *pysTop = GrEngine::GrIFIMulDiv(mTop, xysEmSquare, mFontEmUnits); - *pysBottom = GrEngine::GrIFIMulDiv(mBottom, xysEmSquare, mFontEmUnits); - - if (*pxsLeft > *pxsRight) - { - float xsTmp = *pxsLeft; - *pxsLeft = *pxsRight; - *pxsRight = xsTmp; - } - if (*pysTop < *pysBottom) - { - float ysTmp = *pysTop; - *pysTop = *pysBottom; - *pysBottom = ysTmp; - } - - if (fTopOrigin) - { - // Currently top and bottom coordinates are such that 0 is the baseline and positive is - // upwards, while for the box we want to return, 0 is the top of the glyph and positive - // is downwards. So switch systems. - *pysTop = (dysFontAscent - *pysTop); - *pysBottom = (dysFontAscent - *pysBottom); - } - - return true; -} - -/*---------------------------------------------------------------------------------------------- - Calculate the list of defined components for the given glyph, if any. - Return the index to the first relevant item in the array. - Private. - TODO: With the current implementation that stores the glyph ids in each slot, this - mechanism is redundant and obsolete, and should be removed. -----------------------------------------------------------------------------------------------*/ -int GrGlyphSubTable::CalculateDefinedComponents(gid16 chwGlyphID) -{ - // The first item is a flag indicating whether the list has been calculated. - int iFlag = chwGlyphID * (m_cnCompPerLig + 1); // index of has-been-calculated flag - int iMin = iFlag + 1; // first actual value; +1 in order to skip the flag - if (m_prgnDefinedComponents[iFlag] == 0) - { - int iTmp = iMin; - for (int nCompID = 0; nCompID < m_cComponents; nCompID++) - { - if (ComponentIsDefined(chwGlyphID, nCompID)) - m_prgnDefinedComponents[iTmp++] = nCompID; - if (iTmp - iMin >= m_cnCompPerLig) - break; // ignore any components beyond the maximum allowed - } - // Fill in the rest of the list with -1. - for( ; iTmp < iMin + m_cnCompPerLig; iTmp++) - m_prgnDefinedComponents[iTmp] = -1; - - m_prgnDefinedComponents[iFlag] = 1; // has been calculated - } - return iMin; -} - -/*---------------------------------------------------------------------------------------------- - Return true if the given attr ID, which is a component definition attribute, indicates - that that component is defined for the given glyph. - - @param chwGlyphID - the glyph of interest - @param nAttrID - the attribute of interest, assumed to be a component glyph - attribute (eg. component.e.top) -----------------------------------------------------------------------------------------------*/ -bool GrGlyphSubTable::ComponentIsDefined(gid16 chwGlyphID, int nAttrID) -{ - gAssert(nAttrID < m_cComponents); - if (nAttrID >= m_cComponents) - return false; - - return (GlyphAttrValue(chwGlyphID, nAttrID) != 0); -} - -/*---------------------------------------------------------------------------------------------- - Return the index of the given component as defined for the given glyph ID. that is, - convert the global ID for the component to the one within this glyph. Return -1 - if the component is not defined for the given glyph. - For instance, given the glyph ID "oe" (the oe ligature) and the attr ID for component.o, - the result would be 0; for component.e the result would be 1. -----------------------------------------------------------------------------------------------*/ -int GrGlyphSubTable::ComponentIndexForGlyph(gid16 chwGlyphID, int nCompID) -{ - int i = CalculateDefinedComponents(chwGlyphID); - - for (int iLp = 0; iLp < m_cnCompPerLig; iLp++) - { - if (m_prgnDefinedComponents[i + iLp] == nCompID) - return iLp; - } - return -1; -} - -/*---------------------------------------------------------------------------------------------- - Return the ID of the nth defined component attribute for the given glyph. -----------------------------------------------------------------------------------------------*/ -//int GrGlyphSubTable::NthComponentID(gid16 chwGlyphID, int n) -//{ -// int i = CalculateDefinedComponents(chwGlyphID); -// return m_pnComponents[i + 1 + n]; -//} - - -//:>******************************************************************************************** -//:> For test procedures -//:>******************************************************************************************** - -//:Ignore -#ifdef OLD_TEST_STUFF - -void GrGlyphTable::SetUpTestData() -{ - SetNumberOfGlyphs(5); - SetNumberOfStyles(1); - - GrGlyphSubTable * pgstbl = new GrGlyphSubTable(); - gAssert(pgstbl); - - pgstbl->Initialize(1, 0, 5, 10, 4); - SetSubTable(0, pgstbl); - - pgstbl->SetUpTestData(); -} - -/*********************************************************************************************** - TODO: This method is BROKEN because m_prgibBIGAttrValues has been changed. It is no - longer a utf16 *. The Gloc table can contain 16-bit or 32-bit entries and must be - accessed accordingly. -***********************************************************************************************/ -void GrGlyphSubTable::SetUpTestData() -{ - m_pgatbl = new GrGlyphAttrTable(); - m_pgatbl->Initialize(0, 48); - - m_prgibBIGAttrValues[0] = byte(msbf(data16(0))); - m_prgibBIGAttrValues[1] = byte(msbf(data16(6)))); - m_prgibBIGAttrValues[2] = byte(msbf(data16(20))); - m_prgibBIGAttrValues[3] = byte(msbf(data16(20))); - m_prgibBIGAttrValues[4] = byte(msbf(data16(40))); - m_prgibBIGAttrValues[5] = byte(msbf(data16(48))); - - m_pgatbl->SetUpTestData(); -} - -void GrGlyphAttrTable::SetUpTestData() -{ - // Glyph 0 (1 run; offset = 0): - // 1 = 11 = 0x0B - // 2 = 22 = 0x16 - // 0102 000B 0016 - // - // Glyph 1 (2 runs; offset = 3*2 = 6): - // 0 = 5 - // 1 = 6 - // 2 = 7 - // 8 = 8 - // 9 = 9 - // 0003 0005 0006 0007 - // 0802 0008 0009 - // - // Glyph 2 (0 runs; offset = 6 + 7*2 = 20): - // all values = 0 - // - // Glyph 3 (5 runs; offset = 20): - // 1 = 111 = 0x006F - // 3 = 333 = 0x00DE - // 5 = 555 = 0x022B - // 7 = 777 = 0x0309 - // 9 = 999 = 0x03E7 - // 0101 006F - // 0301 00DE - // 0501 022B - // 0701 0309 - // 0901 03E7 - // - // Glyph 4 (1 run; offset = 20 + 10*2 = 40): - // 5 = 4 - // 6 = 4 - // 7 = 4 - // 0503 0004 0004 0004 - // - // Glyph 5 (offset = 40 + 4*2 = 48) - - byte * pbBIG = m_prgbBIGEntries; - - GrGlyphAttrRun gatrun; - - // Glyph 0 - gatrun.m_bMinAttrID = 1; - gatrun.m_cAttrs = 2; - gatrun.m_rgchwBIGValues[0] = msbf(data16(11)); - gatrun.m_rgchwBIGValues[1] = msbf(data16(22)); - memcpy(pbBIG, &gatrun, 6); - pbBIG += 6; - - // Glyph 1 - gatrun.m_bMinAttrID = 0; - gatrun.m_cAttrs = 3; - gatrun.m_rgchwBIGValues[0] = msbf(data16(5)); - gatrun.m_rgchwBIGValues[1] = msbf(data16(6)); - gatrun.m_rgchwBIGValues[2] = msbf(data16(7)); - memcpy(pbBIG, &gatrun, 8); - pbBIG += 8; - gatrun.m_bMinAttrID = 8; - gatrun.m_cAttrs = 2; - gatrun.m_rgchwBIGValues[0] = msbf(data16(8)); - gatrun.m_rgchwBIGValues[1] = msbf(data16(9)); - memcpy(pbBIG, &gatrun, 6); - pbBIG += 6; - - // Glyph 2: no data - - // Glyph 3 - gatrun.m_bMinAttrID = 1; - gatrun.m_cAttrs = 1; - gatrun.m_rgchwBIGValues[0] = msbf(data16(111)); - memcpy(pbBIG, &gatrun, 4); - pbBIG += 4; - gatrun.m_bMinAttrID = 3; - gatrun.m_cAttrs = 1; - gatrun.m_rgchwBIGValues[0] = msbf(data16(333)); - memcpy(pbBIG, &gatrun, 4); - pbBIG += 4; - gatrun.m_bMinAttrID = 5; - gatrun.m_cAttrs = 1; - gatrun.m_rgchwBIGValues[0] = msbf(data16(555)); - memcpy(pbBIG, &gatrun, 4); - pbBIG += 4; - gatrun.m_bMinAttrID = 7; - gatrun.m_cAttrs = 1; - gatrun.m_rgchwBIGValues[0] = msbf(data16(777)); - memcpy(pbBIG, &gatrun, 4); - pbBIG += 4; - gatrun.m_bMinAttrID = 9; - gatrun.m_cAttrs = 1; - gatrun.m_rgchwBIGValues[0] = msbf(data16(999)); - memcpy(pbBIG, &gatrun, 4); - pbBIG += 4; - - // Glyph 4 - gatrun.m_bMinAttrID = 5; - gatrun.m_cAttrs = 3; - gatrun.m_rgchwBIGValues[0] = msbf(data16(4)); - gatrun.m_rgchwBIGValues[1] = msbf(data16(4)); - gatrun.m_rgchwBIGValues[2] = msbf(data16(4)); - memcpy(pbBIG, &gatrun, 8); - pbBIG += 8; - - gAssert(pbBIG == m_prgbBIGEntries + 48); -} - -#endif // OLD_TEST_STUFF - -} // namespace gr - -//:End Ignore diff --git a/Build/source/libs/graphite-engine/src/segment/GrGlyphTable.h b/Build/source/libs/graphite-engine/src/segment/GrGlyphTable.h deleted file mode 100644 index bec0e518dee..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrGlyphTable.h +++ /dev/null @@ -1,429 +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: GrGlyphTable.h -Responsibility: Sharon Correll -Last reviewed: 10Aug99, JT, quick look over - -Description: - The GrGlyphTable and related classes that store the values of glyph attributes. - - For each glyph in a TrueType font, Graphite has a list of glyph attributes (which - are defined in the GDL script file). Since most of the values will be zero, we save space - by only storing the non-zero values. - - Eventually it may be possible to have more than one TrueType font compiled into a single - glyph table, hence the need for multiple sub-tables. For now we assume that there is only - one font file and only one sub-table. - - Note that BIG in a variable name means that the data is in big-endian format, or is a range - of bytes that must be interpreted as a run of wide chars or ints in big-endian format. --------------------------------------------------------------------------------*//*:End Ignore*/ - -//:Ignore -#ifdef _MSC_VER -#pragma once -#endif -#ifndef GR_GTABLE_INCLUDED -#define GR_GTABLE_INCLUDED -//:End Ignore - -namespace gr -{ - -class Font; - -/*---------------------------------------------------------------------------------------------- - A run of non-zero attribute values for a single glyph, where the attribute IDs - are contiguous. - - NOTE: it is assumed that the format of this class matches the byte order of the data as it - is read directly from the TTF/ECF file--that is, it is big-endian. - - Hungarian: gatrun -----------------------------------------------------------------------------------------------*/ - -class GrGlyphAttrRun -{ - friend class GrGlyphTable; - friend class GrGlyphSubTable; - friend class GrGlyphAttrTable; - - enum { - kMaxAttrsPerRun = 255 - }; - - /*------------------------------------------------------------------------------------------ - Copy the raw memory (starting at the given byte) into the instance. This method must - reflect the format of the "Glat_entry" as it is stored in the file and slurped into - memory. - ------------------------------------------------------------------------------------------*/ - void CopyFrom(byte * pbBIGEnt) - { - m_bMinAttrID = *pbBIGEnt; - m_cAttrs = *(pbBIGEnt + 1); - if (m_cAttrs >= kMaxAttrsPerRun) - { - gAssert(false); - m_cAttrs = kMaxAttrsPerRun; - } - #ifdef _DEBUG - // Probably not strictly necessary to zero the array, but convenient for debugging. - // Removed from release build for optimization - std::fill(m_rgchwBIGValues, m_rgchwBIGValues + kMaxAttrsPerRun, 0); - #endif - // this is mixing types of data16 and byte pointers! - const data16 * prgchw = reinterpret_cast<const data16*>(pbBIGEnt + 2); - std::copy(prgchw, prgchw + m_cAttrs, m_rgchwBIGValues); - } - - int ByteCount() - { - return (2 + (m_cAttrs * isizeof(data16))); - } - -protected: - byte m_bMinAttrID; // ID of first attribute in the run - byte m_cAttrs; // number of attributes in the run - data16 m_rgchwBIGValues[kMaxAttrsPerRun]; -}; - -/*---------------------------------------------------------------------------------------------- - Contains runs of attribute values for all the glyphs in the font; corresponds to - the "Glat" table in the font. - - Hungarian: gatbl -----------------------------------------------------------------------------------------------*/ - -class GrGlyphAttrTable -{ - friend class GrGlyphTable; - friend class GrGlyphSubTable; - friend class FontMemoryUsage; - -protected: - // Constructor: - GrGlyphAttrTable() - { - m_prgbBIGEntries = NULL; - } - - // Destructor: - ~GrGlyphAttrTable() - { - delete[] m_prgbBIGEntries; - } - - // Initialization: - void Initialize(int fxdSilfVersion, int cbBufLen) - { - m_fxdSilfVersion = fxdSilfVersion; - m_cbEntryBufLen = cbBufLen; - m_prgbBIGEntries = new byte[cbBufLen]; - // Now the instance is ready to have all the glyph attr entries slurped into - // the byte array from the file. - } - - int GlyphAttr16BitValue(int ibMin, int ibLim, byte bAttrID); - -protected: - int m_fxdSilfVersion; // version number of the Silf table, which is used - // to interpret the attribute values - - // Block of variable-length glyph attribute runs, matching the format of - // GrGlyphAttrRun. We don't store instances of that class here because they - // are variable length, and it would be too slow to read them individually from the - // font. Instead, we set up a single instance in the method that accesses the values; - // having this instance will help debugging. Eventually we may want to do without it, - // if it would help efficiency. - int m_cbEntryBufLen; // needed only for memory instrumentation - byte * m_prgbBIGEntries; - -//:Ignore -#ifdef OLD_TEST_STUFF -public: - // For test procedures: - void SetUpTestData(); - void SetUpLigatureTest(); - void SetUpLigature2Test(); -#endif // OLD_TEST_STUFF - -//:End Ignore - -}; - -/*---------------------------------------------------------------------------------------------- - One glyph table per font (style) file; corresponds to the "Gloc" table in the font. - Currently there is only considered to be one style per file, so there is only one of - these. It holds the (non-zero) glyph attribute values for every glyph in the font. - - Hungarian: gstbl - - Review: Eventually we may need to make a subclass that uses 32-bit values for the offsets, - or just use a separate array pointer in this class. Which would be preferable? -----------------------------------------------------------------------------------------------*/ - -class GrGlyphSubTable -{ - friend class GrGlyphTable; - friend class FontMemoryUsage; - -public: - // Constructor: - GrGlyphSubTable() : - m_pgatbl(NULL), - m_prgibBIGAttrValues(NULL), - m_prgibBIGGlyphAttrDebug(NULL), - m_prgnDefinedComponents(NULL) - { - } - // Destructor: - ~GrGlyphSubTable() - { - delete m_pgatbl; - delete[] m_prgibBIGAttrValues; - if (m_fHasDebugStrings) - delete[] m_prgibBIGGlyphAttrDebug; - delete[] m_prgnDefinedComponents; - } - - // Initialization: - bool ReadFromFont(GrIStream & gloc_strm, int cGlyphs, - GrIStream & glat_strm, long lGlatStart); - void Initialize(int fxdSilfVersion, data16 chwFlags, - data16 chwBWAttr, data16 chwJStrAttr, data16 chwJStrHWAttr, - int cGlyphs, int cAttrs, int cnCompPerLig); - - void CreateEmpty(); - - void SetNumberOfComponents(int c) - { - m_cComponents = c; - } - - // General: - int NumberOfGlyphAttrs() { return m_nAttrIDLim; } // 0..(m_nAttrIDLim-1) - - int GlyphAttrValue(gid16 chwGlyphID, int nAttrID); - - // Ligatures: - int ComponentContainingPoint(gid16 chwGlyphID, int x, int y); - bool ComponentBoxLogUnits(float xysEmSquare, gid16 chwGlyphID, int icomp, - int mFontEmUnits, float dysAscent, - float * pxsLeft, float * pysTop, float * pxsRight, float * pysBottom, - bool fTopOrigin = true); -protected: - int CalculateDefinedComponents(gid16 chwGlyphID); - bool ComponentIsDefined(gid16 chwGlyphID, int nAttrID); - int ComponentIndexForGlyph(gid16 chwGlyphID, int nCompID); -// int NthComponentID(gid16 chwGlyphID, int n); - int ConvertValueForVersion(int nRet, int nAttrID); - -public: - static int ConvertValueForVersion(int nRet, int nAttrID, int nBWAttr, int fxdVersion); - - // Flags: - bool LongFormat(data16 chwFlags) // 32-bit values? - { - return ((chwFlags & 0x01) == 0x01); // bit 0 - } - bool HasAttrNames(data16 chwFlags) - { - return ((chwFlags & 0x02) == 0x02); // bit 1 - } - int GlocLookup(data16 chwGlyphId) - { - if (m_fGlocShort) - { - unsigned short su = ((unsigned short *)m_prgibBIGAttrValues)[chwGlyphId]; - return lsbf(su); - } - else - { unsigned int u = ((unsigned int *)m_prgibBIGAttrValues)[chwGlyphId]; - return lsbf((int)u); - } - } - -protected: - int m_fxdSilfVersion; // version number of the Silf table, which is used - // to interpret the attribute values - bool m_fHasDebugStrings; // are debugging strings loaded into memory? - - int m_nAttrIDLim; // number of glyph attributes - int m_cComponents; // number of initial glyph attributes that - // represent ligature components - int m_cnCompPerLig; - - GrGlyphAttrTable * m_pgatbl; - byte * m_prgibBIGAttrValues; // byte offsets for glyph attr values - BIG endian - bool m_fGlocShort; // flag for Gloc table format - data16 * m_prgibBIGGlyphAttrDebug; // byte offsets for glyph attr debug strings - BIG endian - - data16 m_chwBWAttr; // breakweight attr ID; needed for converting - // between versions - - // Attr IDs for justify.0.stretch and justify.0.stretchHW; these must always be looked - // up in tandem. - data16 m_chwJStrAttr; - data16 m_chwJStrHWAttr; - - int * m_prgnDefinedComponents; // for each glyph, cache list of component attributes that - // are defined - -//:Ignore -#ifdef OLD_TEST_STUFF -public: - // For test procedures: - void SetUpTestData(); - void SetUpLigatureTest(); - void SetUpLigature2Test(); -#endif // OLD_TEST_STUFF - -//:End Ignore -}; - -/*---------------------------------------------------------------------------------------------- - Holds all the information about glyph attributes. - - Hungarian: gtbl -----------------------------------------------------------------------------------------------*/ - -class GrGlyphTable -{ - friend class GrGlyphSubTable; - friend class FontMemoryUsage; - -public: - // Constructor: - GrGlyphTable() - { - m_cglf = 0; - m_cComponents = 0; - m_cgstbl = 0; - m_vpgstbl.clear(); - } - - // Destructor: - ~GrGlyphTable() - { - for (int i = 0; i < m_cgstbl; ++i) - delete m_vpgstbl[i]; - } - - bool ReadFromFont(GrIStream & gloc_strm, long lGlocStart, - GrIStream & glat_strm, long lGlatStart, - data16 chwBWAttr, data16 chwJStrAttr, int cJLevels, int cnCompPerLig, - int fxdSilfVersion); - - void CreateEmpty(); - - // Setters: - void SetNumberOfGlyphs(int c) - { - m_cglf = c; - } - void SetNumberOfStyles(int c) - { - m_cgstbl = c; - m_vpgstbl.resize(c); - } - void SetNumberOfComponents(int c) - { - m_cComponents = c; - for (unsigned int ipgstbl = 0; ipgstbl < m_vpgstbl.size(); ipgstbl++) - m_vpgstbl[ipgstbl]->SetNumberOfComponents(c); - } - void SetSubTable(int i, GrGlyphSubTable * pgstbl) - { - if (signed(m_vpgstbl.size()) <= i) - { - gAssert(false); - m_vpgstbl.resize(i+1); - } - m_vpgstbl[i] = pgstbl; - m_vpgstbl[i]->SetNumberOfComponents(m_cComponents); - } - - // Getters: - int NumberOfGlyphs() { return m_cglf; } - int NumberOfStyles() { return m_cgstbl; } - - int NumberOfGlyphAttrs() - { - // All of the sub-tables should have the same number of glyph attributes, - // so just ask the first. - return m_vpgstbl[0]->NumberOfGlyphAttrs(); - } - - int GlyphAttrValue(gid16 chwGlyphID, int nAttrID) - { - gAssert(m_cgstbl == 1); - return m_vpgstbl[0]->GlyphAttrValue(chwGlyphID, nAttrID); - } - // Eventually: - //int GlyphAttrValue(gid16 chwGlyphID, int nAttrID, int nStyleIndex) - //{ - // return m_vpgstbl[nStyleIndex]->GlyphAttrValue(chwGlyphID, nAttrID); - //} - - int ComponentContainingPoint(gid16 chwGlyphID, int x, int y) - { - gAssert(m_cgstbl == 1); - return m_vpgstbl[0]->ComponentContainingPoint(chwGlyphID, x, y); - } - // Eventually: - //int ComponentContainingPoint(gid16 chwGlyphID, int nStyleIndex, int x, int y) - //{ - // gAssert(m_cgstbl == 1); - // return m_vpgstbl[nStyleIndex]->ComponentContainingPoint(chwGlyphID, nAttrID); - //} - - bool ComponentBoxLogUnits(float xysEmSquare, gid16 chwGlyphID, int icomp, - int mFontEmUnits, float dysAscent, - float * pxsLeft, float * pysTop, float * pxsRight, float * pysBottom, - bool fTopOrigin = true) - { - gAssert(m_cgstbl == 1); - return m_vpgstbl[0]->ComponentBoxLogUnits(xysEmSquare, - chwGlyphID, icomp, mFontEmUnits, dysAscent, - pxsLeft, pysTop, pxsRight, pysBottom, - fTopOrigin); - } - - int ComponentIndexForGlyph(gid16 chwGlyphID, int nCompID) - { - gAssert(m_cgstbl == 1); - return m_vpgstbl[0]->ComponentIndexForGlyph(chwGlyphID, nCompID); - } - - bool IsEmpty() - { - return (m_cglf == 0); - } - -protected: - int m_cglf; // number of glyphs - int m_cComponents; // number of defined components - int m_cgstbl; // number of sub-tables, corresponding to font files; - // for now there is only one - - std::vector<GrGlyphSubTable *> m_vpgstbl; - -//:Ignore -#ifdef OLD_TEST_STUFF -public: - // For test procedures: - void SetUpTestData(); - void SetUpLigatureTest(); - void SetUpLigature2Test(); -#endif // OLD_TEST_STUFF -//:End Ignore - -}; - -} // namespace gr - -#endif // !GR_GTABLE_INCLUDED diff --git a/Build/source/libs/graphite-engine/src/segment/GrPass.cpp b/Build/source/libs/graphite-engine/src/segment/GrPass.cpp deleted file mode 100644 index 26eb3a3deb6..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrPass.cpp +++ /dev/null @@ -1,1995 +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: GrPass.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Implements the GrPass class and subclasses. -----------------------------------------------------------------------------------------------*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" - -#ifdef _MSC_VER -#pragma hdrstop -#endif -#undef THIS_FILE -DEFINE_THIS_FILE - -//:End Ignore - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -namespace gr -{ - -//:>******************************************************************************************** -//:> Methods -//:>******************************************************************************************** -/*---------------------------------------------------------------------------------------------- - Constructors and initializers -----------------------------------------------------------------------------------------------*/ -GrPass::GrPass(int i) - : m_ipass(i), - m_fxdVersion(0), - m_nMaxRuleContext(0), - m_pfsm(NULL), - m_nMaxRuleLoop(0), - m_nMaxBackup(0), - m_crul(0), - m_prgchwRuleSortKeys(NULL), - m_prgcritRulePreModContext(NULL), - m_cbPassConstraint(0), - m_prgibConstraintStart(NULL), - m_prgibActionStart(NULL), - m_prgbPConstraintBlock(NULL), - m_prgbConstraintBlock(NULL), - m_prgbActionBlock(NULL), - m_cbConstraints(0), - m_cbActions(0), - m_prgibConstraintDebug(NULL), - m_prgibRuleDebug(NULL), - m_fCheckRules(false), - m_prgfRuleOkay(NULL), - m_vnStack(128), - m_pzpst(NULL) -{ -} - -void PassState::InitForNewSegment(int ipass, int nMaxChunk) -{ - m_ipass = ipass; - m_nRulesSinceAdvance = 0; - m_nMaxChunk = nMaxChunk; - m_cslotSkipToResync = 0; - m_fDidResyncSkip = false; - InitializeLogInfo(); -} - -void PassState::InitializeLogInfo() -{ - m_crulrec = 0; - std::fill_n(m_rgcslotDeletions, 128, 0); - std::fill_n(m_rgfInsertion, 128, false); -} - -/*---------------------------------------------------------------------------------------------- - Destructors -----------------------------------------------------------------------------------------------*/ -GrPass::~GrPass() -{ - delete m_pfsm; - - delete[] m_prgchwRuleSortKeys; - - delete[] m_prgcritRulePreModContext; - - delete[] m_prgibConstraintStart; - delete[] m_prgibActionStart; - - delete[] m_prgbPConstraintBlock; - delete[] m_prgbConstraintBlock; - delete[] m_prgbActionBlock; - - delete[] m_prgfRuleOkay; - - delete[] m_prgibConstraintDebug; - delete[] m_prgibRuleDebug; -} - -/*---------------------------------------------------------------------------------------------- - Fill in the pass by reading from the font stream. -----------------------------------------------------------------------------------------------*/ -bool GrPass::ReadFromFont(GrIStream & grstrm, int fxdSilfVersion, int fxdRuleVersion, - int nOffset) -{ - long lPassInfoStart; - grstrm.GetPositionInFont(&lPassInfoStart); - - m_fxdVersion = fxdSilfVersion; - - m_fCheckRules = (fxdRuleVersion > kRuleVersion); - -// Assert(nOffset == lPassInfoStart); - if (lPassInfoStart != nOffset) - { - grstrm.SetPositionInFont(nOffset); - } - - // flags - ignore for now - //byte bTmp = grstrm.ReadByteFromFont(); - grstrm.ReadByteFromFont(); - - // MaxRuleLoop - m_nMaxRuleLoop = grstrm.ReadByteFromFont(); - - // max rule context - m_nMaxRuleContext = grstrm.ReadByteFromFont(); - - // MaxBackup - m_nMaxBackup = grstrm.ReadByteFromFont(); - - // number of rules - m_crul = grstrm.ReadShortFromFont(); - // TODO: add a sanity check for the number of rules. - - // offset to pass constraint code, relative to start of subtable - int nPConstraintOffset = 0; - long lFsmPos = -1; - if (fxdSilfVersion >= 0x00020000) - { - if (fxdSilfVersion >= 0x00030000) - lFsmPos = grstrm.ReadUShortFromFont() + nOffset; // offset to row info - else - grstrm.ReadShortFromFont(); // pad bytes - nPConstraintOffset = grstrm.ReadIntFromFont(); - } - // offset to rule constraint code, relative to start of subtable - //int nConstraintOffset = grstrm.ReadIntFromFont(); - grstrm.ReadIntFromFont(); - // offset to action code, relative to start of subtable - //int nActionOffset = grstrm.ReadIntFromFont(); - grstrm.ReadIntFromFont(); - // offset to debug strings; 0 if stripped - //int nDebugOffset = grstrm.ReadIntFromFont(); - grstrm.ReadIntFromFont(); - - // Jump to beginning of FSM, if we have this information. - if (fxdSilfVersion >= 0x00030000) - grstrm.SetPositionInFont(lFsmPos); - else - // Otherwise assume that's where we are! - Assert(lFsmPos == -1); - - m_pfsm = new GrFSM(); - - m_pfsm->ReadFromFont(grstrm, fxdSilfVersion); - - // rule sort keys - m_prgchwRuleSortKeys = new data16[m_crul]; - data16 * pchw = m_prgchwRuleSortKeys; - int irul; - for (irul = 0; irul < m_crul; irul++, pchw++) - { - *pchw = grstrm.ReadUShortFromFont(); - } - - // rule pre-mod-context item counts - m_prgcritRulePreModContext = new byte[m_crul]; - byte * pb = m_prgcritRulePreModContext; - for (irul = 0; irul < m_crul; irul++, pb++) - { - *pb = grstrm.ReadByteFromFont(); - } - - // constraint offset for pass-level constraints - if (fxdSilfVersion >= 0x00020000) - { - // reserved - pad byte - grstrm.ReadByteFromFont(); - // Note: pass constraints have not been fully implemented. - m_cbPassConstraint = grstrm.ReadUShortFromFont(); - } - else - m_cbPassConstraint = 0; - - // constraint and action offsets for rules - m_prgibConstraintStart = new data16[m_crul + 1]; - pchw = m_prgibConstraintStart; - for (irul = 0; irul <= m_crul; irul++, pchw++) - { - *pchw = grstrm.ReadUShortFromFont(); - } - - m_prgibActionStart = new data16[m_crul + 1]; - pchw = m_prgibActionStart; - for (irul = 0; irul <= m_crul; irul++, pchw++) - { - *pchw = grstrm.ReadUShortFromFont(); - } - - // FSM state table - m_pfsm->ReadStateTableFromFont(grstrm, fxdSilfVersion); - - if (fxdSilfVersion >= 0x00020000) - // reserved - pad byte - grstrm.ReadByteFromFont(); - - // Constraint and action blocks - int cb = m_cbPassConstraint; - m_prgbPConstraintBlock = new byte[cb]; - grstrm.ReadBlockFromFont(m_prgbPConstraintBlock, cb); - m_cbConstraints = cb; - - cb = m_prgibConstraintStart[m_crul]; - m_prgbConstraintBlock = new byte[cb]; - grstrm.ReadBlockFromFont(m_prgbConstraintBlock, cb); - m_cbConstraints += cb; - - cb = m_prgibActionStart[m_crul]; - m_prgbActionBlock = new byte[cb]; - grstrm.ReadBlockFromFont(m_prgbActionBlock, cb); - m_cbActions = cb; - - // Rule-validity flags - m_prgfRuleOkay = new bool[m_crul]; - for (irul = 0; irul < m_crul; irul++) - m_prgfRuleOkay[irul] = !m_fCheckRules; - - // TODO SharonC/AlanW: debuggers - - return true; -} - -/*---------------------------------------------------------------------------------------------- - Initialize a bogus pass with no rules. Currently this is used to make a single positioning - pass if there was none in the font. -----------------------------------------------------------------------------------------------*/ -void GrPass::InitializeWithNoRules() -{ - m_crul = 0; - m_nMaxRuleContext = 1; - m_nMaxRuleLoop = 1; - m_nMaxBackup = 0; - m_pfsm = NULL; - m_prgchwRuleSortKeys = NULL; - m_prgcritRulePreModContext = NULL; -} - -/*---------------------------------------------------------------------------------------------- - Extend the output stream by the given number of characters. - (Overridden by GrBidiPass.) - - @param ptman - table manager - @param psstrmIn/Out - streams being processed - @param cslotNeededByNext - the number of slots being requested by the following pass - @param twsh - how we are handling trailing white-space - @param pnRet - return value - @param pcslotGot - return the number of slots gotten - @param pislotFinalBreak - return the index of the final slot, when we are removing - the trailing white-space and so the end of the segment - will be before the any actual line-break slot - - @return kNextPass if we were able to generated the number requested, or processing is - complete; otherwise return the number of slots needed from the previous pass. -----------------------------------------------------------------------------------------------*/ -void GrPass::ExtendOutput(GrTableManager * ptman, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, - int cslotNeededByNext, TrWsHandling twsh, - int * pnRet, int * pcslotGot, int * pislotFinalBreak) -{ - // Kludge to generate an error in rendering: - //int z = 50; - //int t = ((5 * 10) / z) - 1; - //if (this->m_ipass == 4) - //{ - // int x; x = z / t; - //} - - int islotInitReadPos = psstrmIn->ReadPos(); - int islotInitWritePos = psstrmOut->WritePos(); - - int cslotToGet = max(cslotNeededByNext, - m_pzpst->NeededToResync() - psstrmOut->WritePos()); - int cslotGot = 0; - - gid16 chwLB = ptman->LBGlyphID(); - - // While we haven't got the number of slot we've been asked for, and there is enough - // available in the input, run rules, filling up the output. - - while ((cslotToGet > 0 && cslotGot < cslotToGet) - // Don't leave this pass until we've got the index offset. This is especially - // needed for input to the positioning pass, but it doesn't hurt to make it a - // general rule. - || !psstrmOut->GotIndexOffset() - // Don't leave this pass until all the slots to reprocess have been - // completely handled. - || (psstrmIn->SlotsToReprocess() > 0) - // Don't leave this pass until there is a complete cluster in the output - || (islotInitWritePos == psstrmOut->WritePos()) - || (psstrmOut->MaxClusterSlot(islotInitWritePos, psstrmOut->WritePos()) > 0)) - { - int cslotAvailable = psstrmIn->TotalSlotsPending(); - int cslotNeedMore = MaxRuleContext() - cslotAvailable + ptman->PrevPassMaxBackup(m_ipass); - - // This test should not be necessary, but just in case. - if (psstrmIn->PastEndOfPositioning(false)) - cslotNeedMore = 0; // the input stream is done - - if (// Not enough available in the input: - (cslotNeedMore > 0 && !psstrmIn->FullyWritten()) - - // && psstrmIn->SegLimIfKnown() == -1) && -- no, because substitution passes may need - // to consider slots beyond the seg limit - - // Positioning passes need to know where they are in relation to the initial - // line-break. - || (IsPosPass() && !psstrmIn->GotIndexOffset()) - - // The following can happen on backtracking, when we undo stuff before the - // beginning of the segment: - || !ptman->Pass(m_ipass - 1)->DidResyncSkip()) - { - // Ask previous pass for more input. - *pnRet = max(cslotNeedMore, 1); - *pnRet = max(*pnRet, cslotNeededByNext - cslotGot); - *pcslotGot = cslotGot; - return; - } - - Assert(ptman->Pass(m_ipass - 1)->DidResyncSkip()); - - bool fDoneThisPass = (cslotAvailable == 0); - if (psstrmIn->SlotsToReprocess() == 0) - { - fDoneThisPass = fDoneThisPass || - psstrmIn->PastEndOfPositioning(false) || - psstrmOut->PastEndOfPositioning(true); - } - - if (fDoneThisPass) - { - // No more input to process--this pass is done. - Assert(psstrmIn->SlotsToReprocess() == 0); - psstrmIn->ClearReprocBuffer(); - - if (twsh == ktwshNoWs && m_ipass == ptman->NumberOfLbPasses()) - { - *pnRet = RemoveTrailingWhiteSpace(ptman, psstrmOut, twsh, pislotFinalBreak); - if (*pnRet == kBacktrack) // entire segment was white-space: - return; // backtrack, which will fail - } - DoResyncSkip(psstrmOut); - DoCleanUpSegMin(ptman, psstrmIn, islotInitReadPos, psstrmOut); - psstrmOut->MarkFullyWritten(); - *pnRet = kNextPass; - *pcslotGot = cslotGot; - return; - } - - if (twsh == ktwshOnlyWs && m_ipass == ptman->NumberOfLbPasses() + 1) - { - // Note that this is the first pass after the linebreak pass, so psstrmInput - // is the output of the linebreak pass. - GrSlotState * pslotNext = psstrmIn->Peek(); - if (!pslotNext->IsLineBreak(chwLB) && - pslotNext->Directionality() != kdircWhiteSpace && - psstrmIn->SegMin() > -1 && psstrmIn->SegMin() <= psstrmIn->ReadPos()) - { - // We are only allowing white-space in this segment and we hit - // something else. Don't process any further. - if (psstrmIn->SegLimIfKnown() > -1 && - psstrmIn->SegLimIfKnown() <= psstrmIn->ReadPos()) - { - // Already inserted a line-break; we're done. - DoResyncSkip(psstrmOut); - psstrmOut->MarkFullyWritten(); - *pnRet = kNextPass; - *pcslotGot = cslotGot; - return; - } - while (psstrmIn->SlotsToReprocess() > 0) - { - psstrmOut->CopyOneSlotFrom(psstrmIn); - psstrmOut->SetPosForNextRule(0, psstrmIn, IsPosPass()); - } - psstrmIn->ClearReprocBuffer(); - *pnRet = kBacktrack; - return; - } - } - - // Otherwise, we have enough input to run a rule. - - psstrmIn->SetRuleStartReadPos(); - psstrmOut->SetRuleStartWritePos(); - - int ruln = -1; - if (m_pfsm) - ruln = m_pfsm->GetRuleToApply(ptman, this, psstrmIn, psstrmOut); - ruln = CheckRuleValidity(ruln); - RunRule(ptman, ruln, psstrmIn, psstrmOut); - - cslotGot = psstrmOut->WritePos() - islotInitWritePos; - psstrmOut->CalcIndexOffset(ptman); - } - - DoResyncSkip(psstrmOut); - DoCleanUpSegMin(ptman, psstrmIn, islotInitReadPos, psstrmOut); - - // We're past the point where we care about anything in the reprocessing buffer. - Assert(psstrmIn->NoReproc()); - psstrmIn->ClearReprocBuffer(); - - if (psstrmOut->PastEndOfPositioning(true)) - psstrmOut->MarkFullyWritten(); - - *pnRet = kNextPass; - *pcslotGot = cslotGot; -} - -/*---------------------------------------------------------------------------------------------- - Extend the output stream by the given number of characters. - For a GrBidiPass, if we are at a direction change, get the entire - range of upstream glyphs, reverse them, and treat them as one chunk. - Otherwise just pass one slot through. - - @param ptman - table manager - @param psstrmInput/Output - streams being processed - @param cslotNeededByNext - the number of slots being requested by the following pass - @param twsh - how we are handling trailing white-space - @param pnRet - return value - @param pcslotGot - return the number of slots gotten - @param pislotFinalBreak - not used in this version - - @return 1 if we need more glyphs from the previous pass -----------------------------------------------------------------------------------------------*/ -void GrBidiPass::ExtendOutput(GrTableManager * ptman, - GrSlotStream* psstrmIn, GrSlotStream* psstrmOut, - int cslotNeededByNext, TrWsHandling twsh, - int * pnRet, int * pcslotGot, int * pislotFinalBreak) -{ - Assert(psstrmIn->SlotsToReprocess() == 0); - - int islotInitReadPos = psstrmIn->ReadPos(); - int islotInitWritePos = psstrmOut->WritePos(); - - Assert(m_pzpst->NeededToResync() == 0); - - int cslotToGet = max(cslotNeededByNext, - m_pzpst->NeededToResync() - psstrmOut->WritePos()); - int cslotGot = 0; - int nTopDir; - if (twsh == ktwshOnlyWs) - nTopDir = (ptman->State()->ParaRightToLeft()) ? 1 : 0; - else - nTopDir = ptman->TopDirectionLevel(); - - while (cslotToGet > 0 && cslotGot < cslotToGet) - { - int islotChunkO = psstrmOut->WritePos(); - int islotChunkI = psstrmIn->ReadPos(); - - // Need at least one character to test. - if (psstrmIn->SlotsPending() < 1 || !ptman->Pass(m_ipass-1)->DidResyncSkip()) - { - if (!psstrmIn->FullyWritten()) - { - // Ask previous pass for more input. - *pnRet = max(cslotToGet - psstrmIn->SlotsPending(), 1); - *pnRet = max(*pnRet, cslotNeededByNext - cslotGot); - *pcslotGot = cslotGot; - return; - } - else - { - Assert(ptman->Pass(m_ipass-1)->DidResyncSkip()); - Assert(psstrmIn->SlotsToReprocess() == 0); - psstrmIn->ClearReprocBuffer(); - DoResyncSkip(psstrmOut); - DoCleanUpSegMin(ptman, psstrmIn, islotInitReadPos, psstrmOut); - psstrmOut->MarkFullyWritten(); - *pnRet = kNextPass; - *pcslotGot = cslotGot; - return; - } - } - - std::vector<int> vislotStarts; - std::vector<int> vislotStops; - int islotReverseLim = psstrmIn->DirLevelRange(ptman->State(), - psstrmIn->ReadPos(), nTopDir, - vislotStarts, vislotStops); - //int islotReverseLim = psstrmIn->OldDirLevelRange(pengst, psstrmIn->ReadPos(), nTopDir); - if (islotReverseLim == -1) - { - // We haven't got the full range of reversed text yet-- - // ask for more input. - *pnRet = max(1, cslotNeededByNext - cslotGot); - *pcslotGot = cslotGot; - return; - } - - // Okay, we have enough input to do the reversal, if any. - - int cslotToReverse = islotReverseLim - psstrmIn->ReadPos(); - - // Never reverse the final linebreak; leave it at the end. - if (cslotToReverse > 0 && islotReverseLim > 0) - { - GrSlotState * pslotLast = psstrmIn->SlotAt(islotReverseLim - 1); - if (pslotLast->IsFinalLineBreak(ptman->LBGlyphID())) - { - for (size_t i = 0; i < vislotStops.size(); i++) - if (vislotStops.back() == islotReverseLim - 1) - vislotStops.back() = islotReverseLim - 2; - islotReverseLim--; - cslotToReverse--; - } - } - - psstrmIn->SetRuleStartReadPos(); - psstrmOut->SetRuleStartWritePos(); - - if (cslotToReverse == 0) - { - psstrmOut->CopyOneSlotFrom(psstrmIn); - } - else - { - int islotNextWritePos = psstrmOut->WritePos() + cslotToReverse; - int islotNextReadPos = psstrmIn->ReadPos() + cslotToReverse; - if (vislotStarts.size() == 0) - { - Assert(false); // this should have been done by DirLevelRange - vislotStarts.push_back(psstrmIn->ReadPos()); - vislotStops.push_back(islotNextReadPos - 1); - } - Assert(vislotStarts.back() == psstrmIn->ReadPos()); - Assert(vislotStops.back() == islotNextReadPos - 1); - int cslotNotCopied = Reverse(ptman, psstrmIn, psstrmOut, vislotStarts, vislotStops); - //Reverse(nTopDir + 1, - // psstrmIn, psstrmIn->ReadPos(), islotReverseLim, - // psstrmOut, psstrmOut->WritePos() + cslotToReverse - 1, psstrmOut->WritePos()-1); - - islotNextWritePos -= cslotNotCopied; // bidi markers that are not passed through - - psstrmIn->SetReadPos(islotNextReadPos); - psstrmOut->SetWritePos(islotNextWritePos); - - // It's quite strange to have the segment start or end in the middle of stuff to - // reverse (because the LB forms a natural terminator), but at any rate, - // if that happens, record the segment lim at the corresponding place in the - // output stream. - int islotSegMinIn = psstrmIn->SegMin(); - if (islotSegMinIn > -1 && - psstrmIn->ReadPos() - cslotToReverse <= islotSegMinIn && - islotSegMinIn < psstrmIn->ReadPos()) - { - Assert(islotSegMinIn == psstrmIn->ReadPos() - cslotToReverse); // normal situation - psstrmOut->SetSegMin( - psstrmOut->WritePos() - (psstrmIn->ReadPos() - islotSegMinIn)); - } - int islotSegLimIn = psstrmIn->SegLimIfKnown(); - if (islotSegLimIn > -1 && - psstrmIn->ReadPos() - cslotToReverse <= islotSegLimIn && - islotSegLimIn < psstrmIn->ReadPos()) - { - Assert(islotSegLimIn == psstrmIn->ReadPos() - cslotToReverse); // normal situation - psstrmOut->SetSegLim( - psstrmOut->WritePos() - (psstrmIn->ReadPos() - islotSegLimIn)); - } - } - - psstrmOut->SetPosForNextRule(0, psstrmIn, false); - - // Record the chunk mappings: - MapChunks(psstrmIn, psstrmOut, islotChunkI, islotChunkO, 0); - - cslotGot = psstrmOut->WritePos() - islotInitWritePos; - psstrmOut->CalcIndexOffset(ptman); - } - - DoResyncSkip(psstrmOut); - DoCleanUpSegMin(ptman, psstrmIn, islotInitReadPos, psstrmOut); - - // We're past the point where we care about anything in the reprocessing buffer. - Assert(psstrmIn->NoReproc()); - psstrmIn->ClearReprocBuffer(); - - Assert(psstrmIn->SlotsToReprocess() == 0); - - if (psstrmOut->PastEndOfPositioning(true)) - psstrmOut->MarkFullyWritten(); - - *pnRet = kNextPass; - *pcslotGot = cslotGot; -} - -/*---------------------------------------------------------------------------------------------- - Generate slots containing glyph IDs for the underlying character data, - incrementing the input pointer as we go. - - @param ptman - table manager - @param pchstrm - input character stream - @param psstrmOutput - output slot stream - @param ichSegLim - known end of segment, index into the text; or -1; - the lim of the of char-stream itself represents - the end of the text-source; this lim is the - known desired end of the segment - @param cchwPostXlbContext - number of characters that may be needed from the following line; - valid when ichSegLim > -1 - @param lb - breakweight to use for inserted LB - @param cslotToGet - the number of slots being requested by the following pass - @param fNeedFinalBreak - true if the end of the segment needs to be a valid break point - @param pislotFinalBreak - the end of this segment -----------------------------------------------------------------------------------------------*/ -int GrPass::ExtendGlyphIDOutput(GrTableManager * ptman, - GrCharStream * pchstrm, GrSlotStream * psstrmOut, int ichSegLim, int cchwPostXlbContext, - LineBrk lb, int cslotToGet, bool fNeedFinalBreak, TrWsHandling twsh, - int * pislotFinalBreak) -{ - EngineState * pengst = ptman->State(); - - // This pass should be the glyph-generation pass. - Assert(dynamic_cast<GrGlyphGenPass*>(this)); - Assert(m_pzpst->m_cslotSkipToResync == 0); - m_pzpst->m_fDidResyncSkip = true; - - for (int islot = 0; islot < cslotToGet; ++islot) - { - int islotChunkO = psstrmOut->WritePos(); - int islotChunkI = pchstrm->SegOffset(); - - if (pchstrm->AtEnd() - || (ichSegLim > -1 && pchstrm->Pos() == ichSegLim)) - { - if (psstrmOut->SegLimIfKnown() > -1 && - psstrmOut->SegLimIfKnown() <= psstrmOut->WritePos()) - { - // Already found the end of this stream. - } - else - { - if (pchstrm->EndLine() && !fNeedFinalBreak) - // (if we need a good final break, don't just append an LB; - // make it backtrack and find a valid break point) - { - // Only need to get a good break when we're backtracking; otherwise we - // already know it. - Assert(ichSegLim == -1 || !fNeedFinalBreak); - // Notice that we're cheating here: we're putting the LB in the zeroth - // stream instead of in the output of the linebreak table. - psstrmOut->AppendLineBreak(ptman, pchstrm, - (pchstrm->AtEnd() ? klbWordBreak : lb), - ((ptman->RightToLeft()) ? kdircRlb : kdircLlb), -1, false, - pchstrm->SegOffset()); - if (pchstrm->AtEnd()) - pengst->SetFinalLB(); - else - pengst->SetInsertedLB(true); - } - else - { - // Don't actually insert a line-break glyph. - psstrmOut->SetSegLimToWritePos(); - } - *pislotFinalBreak = psstrmOut->WritePos() - 1; - if (ptman->NumberOfLbPasses() > 0 && pengst->HasInitialLB()) - { - // Because we cheated above: the output stream of the linekbreak table - // has an initial LB, which this stream doesn't have. Adjust the position - // of the final break to match what it will be in the output of the - // lb table. - *pislotFinalBreak += 1; - } - } - - if (twsh == ktwshNoWs && m_ipass == ptman->NumberOfLbPasses()) - { - int nRet = RemoveTrailingWhiteSpace(ptman, psstrmOut, twsh, pislotFinalBreak); - if (nRet == kBacktrack) // entire segment was white-space: - return kBacktrack; // backtrack, which will fail - } - if (pchstrm->AtEnd()) - { - psstrmOut->MarkFullyWritten(); - return kNextPass; - } - // otherwise we may need a few more characters for line-boundary contextualization. - } - - int ichwSegOffset; // offset from the official start of the segment - int cchw; // number of 16-bit chars consumed - GrFeatureValues fval; - int nUnicode = pchstrm->NextGet(ptman, &fval, &ichwSegOffset, &cchw); - gid16 chwGlyphID = ptman->GetGlyphIDFromUnicode(nUnicode); - - if (nUnicode == knCR || nUnicode == knLF || nUnicode == knLineSep || nUnicode == knParaSep || - nUnicode == knORC) - { - // Hard line-break: we're done. - // Note that we don't include the hard-break character in this segment. - pchstrm->HitHardBreak(); - pengst->SetHitHardBreak(); - psstrmOut->MarkFullyWritten(); - return kNextPass; - } - - GrSlotState * pslotNew; - ptman->State()->NewSlot(chwGlyphID, fval, 0, ichwSegOffset, nUnicode, &pslotNew); - - psstrmOut->NextPut(pslotNew); - psstrmOut->MapInputChunk(islotChunkI, islotChunkO, pchstrm->SegOffset(), false, false); - // Mapping the output chunks of the char stream has already been handled by the - // char stream. - - } - - psstrmOut->CalcIndexOffset(ptman); - - if (psstrmOut->PastEndOfPositioning(true) - || (ichSegLim > -1 && pchstrm->Pos() > ichSegLim + cchwPostXlbContext)) - { - // We have enough for this segment. - psstrmOut->MarkFullyWritten(); - } - - return kNextPass; -} - -/*---------------------------------------------------------------------------------------------- - Extend the output stream until it is using up the allotted amount of - physical space. Return kNextPass when all data has been processed successfully. - Return kBacktrack when space overflows, indicating that we need to backtrack - and find a break point. Otherwise, return the number of slots we - need from the previous pass. - - @param fWidthIsCharCount - kludge for test procedures - @param fInfiniteWidth - don't test for more space - @param fMustBacktrack - true if we need a good final break and haven't found one yet - @param lbMax - max allowed for the final slot - @param twsh - how we are handling trailing white-space -----------------------------------------------------------------------------------------------*/ -int GrPass::ExtendFinalOutput(GrTableManager * ptman, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput, - float xsSpaceAllotted, bool fWidthIsCharCount, bool fInfiniteWidth, - bool fHaveLineBreak, bool fMustBacktrack, LineBrk lbMax, TrWsHandling twsh, - int * pislotLB, float * pxsWidth) -{ - EngineState * pengst = ptman->State(); - - // This pass should be the final positioning pass. - Assert(dynamic_cast<GrPosPass*>(this)); - - // It would be very strange to be positioning based on something that happened in - // previous line. -- not true any more, since this will include the max-precontext-length. -// Assert(m_cslotSkipToResync == 0); - - int islotOutputLB = -1; - //int islotInitWritePos = psstrmOutput->WritePos(); - int islotNoLbUpTo = psstrmOutput->WritePos();; - - while (true) - { - // Do this right up front, so we are only measuring actual output. - if (m_pzpst->CanResyncSkip(psstrmOutput)) - m_pzpst->DoResyncSkip(psstrmOutput); - - bool fMoreSpace; - if (!m_pzpst->DidResyncSkip()) - fMoreSpace = true; - else if (fInfiniteWidth) - fMoreSpace = true; - else - fMoreSpace = psstrmOutput->MoreSpace(ptman, - xsSpaceAllotted, fWidthIsCharCount, - true, // always ignore trailing white space when we are first making the segment - twsh, - pxsWidth); - if (!fMoreSpace) - { - // Overflowed available space; backtrack and find a line break. - while (psstrmInput->SlotsToReprocess() > 0) - { - psstrmOutput->CopyOneSlotFrom(psstrmInput); - psstrmOutput->SetPosForNextRule(0, psstrmInput, IsPosPass()); - } - psstrmInput->ClearReprocBuffer(); - - *pislotLB = -1; - pengst->SetExceededSpace(); - pengst->SetHitHardBreak(false); - return kBacktrack; - } - - if (islotOutputLB != -1 && psstrmInput->SlotsToReprocess() == 0) - { - // Hit the inserted line break--we're done. - psstrmInput->ClearReprocBuffer(); - *pislotLB = islotOutputLB; - return kNextPass; - } - - int nslotAvailable = psstrmInput->SlotsPending(); - if ((nslotAvailable - ptman->PrevPassMaxBackup(m_ipass) - < MaxRuleContext() && !psstrmInput->FullyWritten()) - || !ptman->Pass(m_ipass-1)->DidResyncSkip()) - { - // Not enough available in the input--ask previous pass for more input. - // Ten is an arbitrary value--we ask for more that we really need to cut down - // on the number of times we loop between passes. - return max(MaxRuleContext() - (nslotAvailable - 10), 1); - } - - Assert(ptman->Pass(m_ipass - 1)->DidResyncSkip()); - - if (nslotAvailable == 0) - { - // No more input to process. If we have a valid line-break, or we don't care, - // we're done. Otherwise backtrack to find a valid break point. - Assert(psstrmInput->SlotsToReprocess() == 0); - psstrmInput->ClearReprocBuffer(); - if (fMustBacktrack) - { - *pislotLB = -1; - return kBacktrack; - } - else - { - psstrmOutput->MarkFullyWritten(); - return kNextPass; - } - } - - // Otherwise, we have enough input to run a rule. - - psstrmInput->SetRuleStartReadPos(); - psstrmOutput->SetRuleStartWritePos(); - - int ruln = -1; - if (m_pfsm) - ruln = m_pfsm->GetRuleToApply(ptman, this, psstrmInput, psstrmOutput); - ruln = CheckRuleValidity(ruln); - RunRule(ptman, ruln, psstrmInput, psstrmOutput); - - if (fHaveLineBreak) - { - islotOutputLB = - psstrmOutput->FindFinalLineBreak(ptman->LBGlyphID(), - islotNoLbUpTo, psstrmOutput->WritePos()); - islotNoLbUpTo = psstrmOutput->WritePos(); - } - - psstrmOutput->CalcIndexOffset(ptman); - } - - Assert(false); - - psstrmInput->ClearReprocBuffer(); - *pislotLB = -1; - return kNextPass; -} - -/*---------------------------------------------------------------------------------------------- - Remove undesirable trailing white-space. -----------------------------------------------------------------------------------------------*/ -int GrPass::RemoveTrailingWhiteSpace(GrTableManager * ptman, GrSlotStream * psstrmOut, - TrWsHandling twsh, int * pislotFinalBreak) -{ - EngineState * pengst = ptman->State(); - - Assert(twsh == ktwshNoWs); - Assert(m_ipass == ptman->NumberOfLbPasses()); // output of (final) lb pass - - int islotTmp = psstrmOut->FinalSegLim(); - if (islotTmp <= 0) - return kNextPass; - - GrSlotState * pslotLast = psstrmOut->SlotAt(islotTmp-1); - if (islotTmp > 0 && pslotLast->IsFinalLineBreak(ptman->LBGlyphID())) - { - islotTmp--; - pslotLast = (islotTmp > 0) ? psstrmOut->SlotAt(islotTmp-1) : NULL; - } - bool fRemovedWs = false; - while (islotTmp > 0 && pslotLast->Directionality() == kdircWhiteSpace) - { - islotTmp--; - pslotLast = (islotTmp > 0) ? psstrmOut->SlotAt(islotTmp-1) : NULL; - fRemovedWs = true; - } - if (fRemovedWs) - { - if (islotTmp <= 0) - { - // Entire segment was white-space: backtrack, which will fail. - return kBacktrack; - } - psstrmOut->SetSegLim(islotTmp); - *pislotFinalBreak = islotTmp - 1; - pengst->SetFinalLB(false); - pengst->SetRemovedTrWhiteSpace(); - ptman->UnwindAndReinit(islotTmp - 1); - } - - return kNextPass; -} - -/*---------------------------------------------------------------------------------------------- - Keep track of whether we're advancing through the input satisfactorily; - if not, forcibly advance. This is a safety net to avoid infinite loops; it - should never be necessary if they've set up their tables right. -----------------------------------------------------------------------------------------------*/ -void GrPass::CheckInputProgress(GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput, - int islotOrigInput) -{ - int islotInput = psstrmInput->ReadPosForNextGet(); -// Assert(islotInput >= islotOrigInput); -- no longer true now that we can back up - - if (islotInput <= psstrmInput->ReadPosMax()) - { - // Didn't advance. - if (m_pzpst->m_nRulesSinceAdvance >= m_nMaxRuleLoop) - { - bool fAdvanced = false; - // Forcibly advance. First try to advance to where we backed up from. - while (!psstrmInput->AtEnd() && - psstrmInput->ReadPosForNextGet() < psstrmInput->ReadPosMax()) - { - RecordHitMaxRuleLoop(psstrmInput->ReadPosForNextGet()); - psstrmOutput->CopyOneSlotFrom(psstrmInput); - fAdvanced = true; - } - // If that didn't do anything productive, just advance one slot. - if (!fAdvanced && !psstrmInput->AtEndOfContext()) - { - RecordHitMaxRuleLoop(psstrmInput->ReadPosForNextGet()); - psstrmOutput->CopyOneSlotFrom(psstrmInput); - } - - m_pzpst->m_nRulesSinceAdvance = 0; - } - else m_pzpst->m_nRulesSinceAdvance++; - } - else m_pzpst->m_nRulesSinceAdvance = 0; - - psstrmInput->SetReadPosMax(islotInput); -} - -/*---------------------------------------------------------------------------------------------- - Record the chunks in the streams' chunk maps. - - psstrmIn/Out - streams being processed - islotChunkIn/Out - start of chunks - cslotReprocessed - number of slots to reprocess before the rule was run -----------------------------------------------------------------------------------------------*/ -void GrPass::MapChunks(GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, - int islotChunkIn, int islotChunkOut, int cslotReprocessed) -{ - if (islotChunkOut > psstrmOut->WritePos()) - { - // backing up - int islotReadPosTmp = psstrmIn->ReadPosForNextGet(); -/// Assert((islotChunkIn - islotReadPosTmp) == (islotChunkOut - psstrmOut->WritePos())); -// psstrmIn->MapOutputChunk(psstrmOut->WritePos() - 1, islotReadPosTmp - 1, -// islotChunkOut, true, 0, true); -// psstrmOut->MapInputChunk(islotReadPosTmp - 1, psstrmOut->WritePos() - 1, -// islotChunkIn, true, true); - - // Resync. - if (psstrmOut->WritePos() == 0) - { - // Clear all the chunks. - psstrmIn->MapOutputChunk(-1, -1, 0, true, 0, true); - psstrmOut->MapInputChunk(-1, -1, islotReadPosTmp, true, true); - psstrmIn->AssertChunkMapsValid(psstrmOut); - return; - } - else if (islotReadPosTmp == 0) - { - // Clear all the chunks. - psstrmIn->MapOutputChunk(-1, -1, psstrmOut->WritePos(), true, 0, true); - psstrmOut->MapInputChunk(-1, -1, 0, true, true); - psstrmIn->AssertChunkMapsValid(psstrmOut); - return; - } - // Find the beginning of the current chunk. - int islotChunkOutAdj = min(islotChunkOut, psstrmOut->WritePos() - 1); - int islotChunkInAdj = psstrmOut->ChunkInPrev(islotChunkOutAdj); - while (islotChunkInAdj == -1 && islotChunkOutAdj > 0) - islotChunkInAdj = psstrmOut->ChunkInPrev(--islotChunkOutAdj); - - if (islotChunkInAdj == -1) - { - // Couldn't find the beginning of any chunk; zap them all. - psstrmIn->MapOutputChunk(-1, -1, psstrmOut->WritePos(), true, 0, true); - psstrmOut->MapInputChunk(-1, -1, psstrmOut->ReadPos(), true, true); - psstrmIn->AssertChunkMapsValid(psstrmOut); - return; - } - - if (psstrmIn->ChunkInNext(islotChunkInAdj) != islotChunkOutAdj) - { - islotChunkOutAdj = psstrmIn->ChunkInNext(islotChunkInAdj); - while (islotChunkOutAdj == -1 && islotChunkInAdj > 0) - islotChunkOutAdj = psstrmIn->ChunkInNext(--islotChunkInAdj); - } - - psstrmIn->MapOutputChunk(islotChunkOutAdj, islotChunkInAdj, - psstrmOut->WritePos(), false, 0, true); - psstrmOut->MapInputChunk(islotChunkInAdj, islotChunkOutAdj, - psstrmIn->ReadPos(), false, true); - } - else if (islotChunkOut == psstrmOut->WritePos()) - // no output generated--continue the previous chunk - ; - else if (islotChunkIn == psstrmIn->ReadPos()) - // no input consumed - ; - else - { - psstrmIn->MapOutputChunk(islotChunkOut, islotChunkIn, psstrmOut->WritePos(), - (cslotReprocessed > 0), cslotReprocessed, false); - psstrmOut->MapInputChunk(islotChunkIn, islotChunkOut, psstrmIn->ReadPos(), - (cslotReprocessed > 0), false); - } - - psstrmIn->AssertChunkMapsValid(psstrmOut); - - m_pzpst->m_nMaxChunk = max(m_pzpst->m_nMaxChunk, psstrmIn->LastNextChunkLength()); -} - -/*---------------------------------------------------------------------------------------------- - This method is something of a kludge. During the course of running the rules we try to - keep track of the seg-min location, but sometimes that gets confused due to insertions - and deletions at the segment boundaries. -----------------------------------------------------------------------------------------------*/ -void GrSubPass::DoCleanUpSegMin(GrTableManager * ptman, - GrSlotStream * psstrmIn, int islotInitReadPos, GrSlotStream * psstrmOut) -{ - int islotSegMinIn = psstrmIn->SegMin(); - if (islotSegMinIn == -1) - return; // input doesn't even know it - if (islotInitReadPos > islotSegMinIn) - return; // should already have figured it out - - // Otherwise this batch of processing likely set the seg-min on the output stream, - // so check it out. - - // First, if the seg-min of the input stream is zero, it should be zero on the output. - if (islotSegMinIn == 0) - { - psstrmOut->SetSegMin(0, true); - return; - } - - // If there is an initial line-break, the seg-min should be just before it. - int islot; - if (ptman->State()->HasInitialLB()) - { - gid16 chwLB = ptman->LBGlyphID(); - - // Unfortunately, the seg-min from the previous segment can get off, too. :-( - // Fix it, while we're at it. - if (!psstrmIn->SlotAt(islotSegMinIn)->IsInitialLineBreak(chwLB)) - { - for (islot = 0; islot < psstrmIn->ReadPos(); islot++) - if (psstrmIn->SlotAt(islot)->IsInitialLineBreak(chwLB)) - { - psstrmIn->SetSegMin(islot, true); - break; - } - } - if (psstrmOut->SegMin() > -1 - && psstrmOut->SlotAt(psstrmOut->SegMin())->IsInitialLineBreak(chwLB)) - { - return; // already okay - } - for (islot = 0; islot < psstrmOut->WritePos(); islot++) - if (psstrmOut->SlotAt(islot)->IsInitialLineBreak(chwLB)) - { - psstrmOut->SetSegMin(islot, true); - return; - } - Assert(false); // couldn't find it - } - - // Otherwise, figure it out using the associations. First observe that the seg-min - // will be in the corresponding chunk to the seg-min of the previous pass. - int islotChunkMinIn = psstrmIn->ChunkInNextMin(islotSegMinIn); - int islotChunkLimIn = psstrmIn->ChunkInNextLim(islotSegMinIn); - if (islotChunkMinIn == -1) islotChunkMinIn = 0; - if (islotChunkLimIn == -1) islotChunkLimIn = 1; - - int islotChunkMinOut = psstrmIn->ChunkInNext(islotChunkMinIn); - int islotChunkLimOut = psstrmIn->ChunkInNext(islotChunkLimIn); - if (islotChunkMinOut == -1) islotChunkMinOut = 0; - if (islotChunkLimOut == -1) islotChunkLimOut = 1; - - int islotSegMinOut = psstrmOut->SegMin(); - if (islotSegMinOut == -1) - { - // No reasonable guess; try to figure it out. - for (islot = islotChunkMinOut; islot < islotChunkLimOut; islot++) - { -// GrSlotState * pslotOut = psstrmOut->SlotAt(islot); - if (psstrmOut->SlotAt(islot)->BeforeAssoc() == 0) - { - islotSegMinOut = islot; - break; - } - } - if (islotSegMinOut == -1) - { - // Ick, couldn't figure it out. Let's hope we set it to something reasonable earlier. - Assert(psstrmOut->SegMin() > -1); - return; - } - } - // else we have a reasonable guess - - // islotSegMinOut is the best or at leastfirst slot in the chunk that maps into the segment. - // But if there is an adjacent slot inserted before it and it is in the chunk, - // we want to include that also. - while (islotSegMinOut > islotChunkMinOut - && psstrmOut->SlotAt(islotSegMinOut-1)->BeforeAssoc() >= 0) - { - islotSegMinOut--; - } - psstrmOut->SetSegMin(islotSegMinOut, true); -} - -/*---------------------------------------------------------------------------------------------- - If we are in a state where we are supposed to skip some of the initial output, - do so. The purpose of this is to resync when restarting for a segment other than the - first. Caller should ensure that there are enough slots to skip. -----------------------------------------------------------------------------------------------*/ -int PassState::DoResyncSkip(GrSlotStream * psstrmOutput) -{ - if (m_fDidResyncSkip) - return 0; - - if (m_cslotSkipToResync == 0) - { - m_fDidResyncSkip = true; - return 0; - } - - if (!CanResyncSkip(psstrmOutput)) - { - Assert(false); // caller makes sure this doesn't happen - return (m_cslotSkipToResync - psstrmOutput->WritePos()); - } - - psstrmOutput->ResyncSkip(m_cslotSkipToResync); - m_fDidResyncSkip = true; - - return 0; -} - -/*---------------------------------------------------------------------------------------------- - Run a constraint for a single rule. - - @param ruln - rule to test - @param psstrmIn - input stream - @param psstrmOut - for accessing items in the pre-context - @param cslotPreModContext - the number of items that need to be tested prior to the - current stream position - @param cslotMatched - the number of items matched after the current stream position -----------------------------------------------------------------------------------------------*/ -bool GrPass::RunConstraint(GrTableManager * ptman, int ruln, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, - int cslotPreModContext, int cslotMatched) -{ - int nRet = 0; - - if (m_prgibConstraintStart == NULL) - return true; - - int biStart = int(m_prgibConstraintStart[ruln]); - if (biStart == 0) - return true; // no constraints - - for (int islot = -cslotPreModContext; islot < cslotMatched; islot++) - { - nRet = RunCommandCode(ptman, m_prgbConstraintBlock + biStart, true, - psstrmIn, psstrmOut, islot); - - if (nRet == 0) // one slot failed - return false; - } - - return (nRet != 0); -} - -/*---------------------------------------------------------------------------------------------- - Check that we can interpret all the commands in the rule. If not, return -1 indicating - that we don't want to run a rule after all. This can happen when the version of the compiler - that generated the font is later than this engine. -----------------------------------------------------------------------------------------------*/ -int GrPass::CheckRuleValidity(int ruln) -{ - if (ruln == -1) - return -1; - - if (m_prgfRuleOkay[ruln]) - return ruln; - - int biStart = m_prgibActionStart[ruln]; - byte * pbNext = m_prgbActionBlock + biStart; - - // General purpose variables: -// int arg1, arg2, arg3, arg4; - int nSlotRef; - int nInputClass; - int nOutputClass; - int c; - int islotArg; - int nIndex; - int nGlyphAttr; - int nAttLevel; - int nFeat; - int nPState; -// SlotAttrName slat; - - int i; - -// int nRet = 0; - - while (true) // exit by encountering PopRet or RetTrue or RetZero - { - ActionCommand op = ActionCommand(*pbNext++); - - switch (op) - { - case kopNop: - break; - - case kopPushByte: - pbNext++; - break; - case kopPushByteU: - pbNext++; - break; - case kopPushShort: - pbNext++; - pbNext++; - break; - case kopPushShortU: - pbNext++; - pbNext++; - break; - case kopPushLong: - pbNext++; - pbNext++; - pbNext++; - pbNext++; - break; - - case kopNeg: - case kopTrunc8: case kopTrunc16: - case kopNot: - break; - - case kopAdd: case kopSub: - case kopMul: case kopDiv: - case kopMin: case kopMax: - case kopAnd: case kopOr: - case kopEqual: case kopNotEq: - case kopLess: case kopGtr: - case kopLessEq: case kopGtrEq: - break; - - case kopCond: - break; - - case kopNext: - break; - case kopNextN: - c = *pbNext; pbNext++; // count - break; - case kopPutGlyph8bitObs: - nOutputClass = *pbNext++; - break; - case kopPutGlyph: - pbNext += 2; - break; - case kopPutCopy: - nSlotRef = *pbNext++; - break; - case kopPutSubs8bitObs: - nSlotRef = *pbNext++; - nInputClass = *pbNext++; - nOutputClass = *pbNext++; - break; - case kopPutSubs: - nSlotRef = *pbNext++; - pbNext += 4; // 2 bytes each for classes - break; - case kopCopyNext: - break; - case kopInsert: - break; - case kopDelete: - break; - case kopAssoc: - c = *pbNext; pbNext++; - for (i = 0; i < c; i++) - pbNext++; - break; - case kopCntxtItem: - islotArg = *pbNext++; - c = *pbNext++; - break; - - case kopAttrSet: - case kopAttrAdd: - case kopAttrSub: - case kopAttrSetSlot: - pbNext++; // slot attribute ID - break; - case kopIAttrSet: - case kopIAttrAdd: - case kopIAttrSub: - case kopIAttrSetSlot: - pbNext++; // slot attribute ID - nIndex = *pbNext++; // index; eg, global ID for component - break; - - case kopPushSlotAttr: - pbNext++; - nSlotRef = *pbNext++; - break; - case kopPushISlotAttr: - pbNext++; - nSlotRef = *pbNext++; - nIndex = *pbNext++; - break; - - case kopPushGlyphAttrObs: - case kopPushAttToGAttrObs: - nGlyphAttr = *pbNext++; - nSlotRef = *pbNext++; - break; - case kopPushGlyphAttr: - case kopPushAttToGlyphAttr: - *pbNext += 3; - break; - case kopPushGlyphMetric: - case kopPushAttToGlyphMetric: - nGlyphAttr = *pbNext++; - nSlotRef = *pbNext++; - nAttLevel = *pbNext++; - break; - case kopPushFeat: - nFeat = *pbNext++; - nSlotRef = *pbNext++; - break; - - case kopPushProcState: - nPState = *pbNext++; - break; - case kopPushVersion: - break; - - case kopPopRet: - case kopRetZero: - case kopRetTrue: - m_prgfRuleOkay[ruln] = true; - return ruln; - - default: - // Uninterpretable command: - return -1; - } - } - - return ruln; // to keep compiler from griping -} - -/*---------------------------------------------------------------------------------------------- - Runs the rule, if any, otherwise just passes one character through. - The rule does nothing but set the line-break weights for the slots. - - @param ptman - the table manager that allocates slots - @param ruln - number of rule to run; -1 if none applies - @param psstrmIn/Out - input/output stream -----------------------------------------------------------------------------------------------*/ -void GrLineBreakPass::RunRule(GrTableManager * ptman, int ruln, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - // Remember the beginnings of the new chunk: - int islotIn = psstrmIn->ReadPos(); - int islotOut = psstrmOut->WritePos(); - int cslotReprocessed = psstrmIn->SlotsToReprocess(); - - if (ruln == -1) - { -#ifdef OLD_TEST_STUFF - if (RunTestRules(ptman, ruln, psstrmIn, psstrmOut)) -#else - if (false) -#endif // OLD_TEST_STUFF - {} - else - // Just pass one glyph through. - { - psstrmOut->CopyOneSlotFrom(psstrmIn); - psstrmOut->SetPosForNextRule(0, psstrmIn, false); - } - } - else - { - // Run the rule. -#ifdef OLD_TEST_STUFF - if (RunTestRules(ptman, ruln, psstrmIn, psstrmOut)) -#else - if (false) -#endif // OLD_TEST_STUFF - {} - else - { - int biStart = m_prgibActionStart[ruln]; - int iResult = RunCommandCode(ptman, m_prgbActionBlock + biStart, false, - psstrmIn, psstrmOut, 0); - psstrmOut->SetPosForNextRule(iResult, psstrmIn, false); - } - } - - CheckInputProgress(psstrmIn, psstrmOut, islotIn); - - MapChunks(psstrmIn, psstrmOut, islotIn, islotOut, cslotReprocessed); -} - -/*---------------------------------------------------------------------------------------------- - Runs the rule, if any, otherwise just passes one character through. - Keeps track of the association information in the slots and chunk - mappings for backtracking. - - @param ptman - the table manager that allocates slots - @param ruln - number of rule to run; -1 if none applies - @param psstrmIn/Out - input / output streams -----------------------------------------------------------------------------------------------*/ -void GrSubPass::RunRule(GrTableManager * ptman, int ruln, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - // Remember the beginnings of the new chunk: - int islotIn = psstrmIn->ReadPosForNextGet(); - int islotOut = psstrmOut->WritePos(); - int cslotReprocessed = psstrmIn->SlotsToReprocess(); - - if (ruln == -1) - { -#ifdef OLD_TEST_STUFF - if (RunTestRules(ptman, ruln, psstrmIn, psstrmOut)) -#else - if (false) -#endif // OLD_TEST_STUFF - {} - else - // Just pass one glyph through. - { - psstrmOut->CopyOneSlotFrom(psstrmIn); - psstrmOut->SetPosForNextRule(0, psstrmIn, false); - } - } - else - { - // Run the rule. -#ifdef OLD_TEST_STUFF - if (RunTestRules(ptman, ruln, psstrmIn, psstrmOut)) -#else - if (false) -#endif // OLD_TEST_STUFF - {} - else - /****************************/ - { - int biStart = m_prgibActionStart[ruln]; - int iResult = RunCommandCode(ptman, m_prgbActionBlock + biStart, false, - psstrmIn, psstrmOut, 0); - psstrmOut->SetPosForNextRule(iResult, psstrmIn, false); - - // Restore if we need line-boundary contextualization based on physical locations - ////psstrmOut->SetLBContextFlag(ptman, islotOut); - } - } - - CheckInputProgress(psstrmIn, psstrmOut, islotIn); - - MapChunks(psstrmIn, psstrmOut, islotIn, islotOut, cslotReprocessed); -} - -/*---------------------------------------------------------------------------------------------- - Runs the rule, if any, otherwise just positions one character in the standard way. - Keeps track of (among other things) the overall physical size of the output - and chunk mappings. - - @param ptman - the table manager that allocates slots - @param ruln - number of rule to run; -1 if none applies - @param psstrmIn / Out - input / output streams -----------------------------------------------------------------------------------------------*/ -void GrPosPass::RunRule(GrTableManager * ptman, int ruln, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - // Remember the beginnings of the new chunk: - int islotIn = psstrmIn->ReadPosForNextGet(); - int islotOut = psstrmOut->WritePos(); - int cslotReprocessed = psstrmIn->SlotsToReprocess(); - - int iResult = 0; - - Assert(psstrmIn->GotIndexOffset()); - // Don't do any positioning in anything being processed from the previous line. - if (psstrmIn->ReadPosForNextGet() < psstrmIn->IndexOffset()) - ruln = -1; - - if (ruln == -1) - { - // Just position one glyph in the standard way. - psstrmOut->CopyOneSlotFrom(psstrmIn); - iResult = 0; - } - else - { - // Run the rule. -#ifdef OLD_TEST_STUFF - if (RunTestRules(ptman, ruln, psstrmIn, psstrmOut)) -#else - if (false) -#endif // OLD_TEST_STUFF - {} - else - { - int biStart = m_prgibActionStart[ruln]; - iResult = RunCommandCode(ptman, m_prgbActionBlock + biStart, false, - psstrmIn, psstrmOut, 0); - } - } - - // Make sure an entire cluster is present in the output stream. Actually there might be - // interleaved clusters, which is the purpose for the loop. - int dislotClusterMax = 0; - do { - dislotClusterMax = psstrmIn->MaxClusterSlot(islotIn, psstrmIn->ReadPos()); - Assert(dislotClusterMax >= 0); - for (int islot = 0; islot < dislotClusterMax; islot++) - psstrmOut->CopyOneSlotFrom(psstrmIn); - iResult -= dislotClusterMax; - } while (dislotClusterMax > 0); - - psstrmOut->SetPosForNextRule(iResult, psstrmIn, true); - - // Restore if we need line-boundary contextualization based on physical locations - ////psstrmOut->SetLBContextFlag(ptman, islotOut); - - if (ruln > -1) - { - psstrmOut->CalcIndexOffset(ptman); - // Update the attachment trees and cluster metrics for slots modified by this rule. - // Note that this loop assumes that the reprocess buffer points to the identical - // slot objects as the output stream (not copies of the slots). - for (int islot = islotIn - psstrmIn->SlotsSkippedToResync(); - islot < psstrmOut->WritePos() + psstrmIn->SlotsToReprocess(); - islot++) - { - psstrmOut->SlotAt(islot)->HandleModifiedPosition(ptman, psstrmIn, psstrmOut, islot); - } - } - - CheckInputProgress(psstrmIn, psstrmOut, islotIn); - - MapChunks(psstrmIn, psstrmOut, islotIn, islotOut, cslotReprocessed); - - psstrmOut->AssertStreamIndicesValid(psstrmIn); -} - -/*---------------------------------------------------------------------------------------------- - Perform the reversal for internal bidirectionality. - Caller is responsible for updating the read- and write-positions. - Private. - - OBSOLETE - - @param nCurrDirection - direction level of range of reverse - @param psstrmIn, psstrmOut - streams - @param islotInMin, islotInLim - range to reverse - @param islotOutMin,islotOutLim - corresponding output positions; note that islotOutMin - will be greater than islotOutLim if we are reversing - reversing the slots (direction is odd) -----------------------------------------------------------------------------------------------*/ -#if 0 -void GrBidiPass::OldReverse(int nCurrDirection, - GrSlotStream * psstrmIn, int islotInMin, int islotInLim, - GrSlotStream * psstrmOut, int islotOutMin, int islotOutLim) -{ - int oInc = (islotOutLim > islotOutMin)? 1: -1; // which direction output is moving in - // buffer (if dir is even, oInc == 1; - // if odd, oInc == -1) - - int islotITmp = islotInMin; - int islotOTmp = islotOutMin; - - while (islotITmp != islotInLim) { - // Find end of sub-range at current level to reverse. - int islotSubLim = psstrmIn->OldDirLevelRange(NULL, islotITmp, nCurrDirection); - Assert(islotSubLim >= 0); - - if (islotSubLim == islotITmp) { - // Current slot is at this level--just copy it. - psstrmOut->SimpleCopyFrom(psstrmIn, islotITmp, islotOTmp); - islotOTmp += oInc; - islotITmp++; - } - else { - // There is a sub-range that needs to be reversed. - int islotONext = islotOTmp + ((islotSubLim-islotITmp) * oInc); - OldReverse(nCurrDirection+1, - psstrmIn, islotITmp, islotSubLim, - psstrmOut, islotONext - oInc, islotOTmp - oInc); - islotOTmp = islotONext; - islotITmp = islotSubLim; - } - } -} -#endif - -/*---------------------------------------------------------------------------------------------- - Perform the reversal for internal bidirectionality. - Caller is responsible for updating the read- and write-positions. - Return the number of slots NOT copied because they were markers. - Private. - - @param psstrmIn, psstrmOut - streams - @param vislotStarts, vislotStops - indices of ranges to reverse, from inner to outer -----------------------------------------------------------------------------------------------*/ -int GrBidiPass::Reverse(GrTableManager * ptman, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, - std::vector<int> & vislotStarts, std::vector<int> & vislotStops) -{ - Assert(vislotStarts.size() == vislotStops.size()); - - std::vector<int> vislotMap; // list of slot indices in the order they should be copied - // into the output - - int islotOuterStart = vislotStarts.back(); - int islotOuterStop = vislotStops.back(); - - // Initialize map as if nothing is reversed; eg for [2, 9]: (2 3 4 5 6 7 8 9) - int islot; - for (islot = 0; islot <= (islotOuterStop - islotOuterStart); islot++) - vislotMap.push_back(islot + islotOuterStart); - - // Do the inner reversals first, followed by the outer reversals. - size_t iislot; - for (iislot = 0; iislot < vislotStarts.size(); iislot++) - { - // Reverse the run. - int islotStart = vislotStarts[iislot] - islotOuterStart; - int islotStop = vislotStops[iislot] - islotOuterStart; - int islot1, islot2; - for (islot1 = islotStart, islot2 = islotStop; islot1 < islot2; islot1++, islot2--) - { - int islotTmp = vislotMap[islot1]; - vislotMap[islot1] = vislotMap[islot2]; - vislotMap[islot2] = islotTmp; - } - } - - // With vislotStarts = [7, 5, 2] and vislotStops = [8, 8, 9], we get - // first: (2 3 4 5 6 8 7 9) - // then: (2 3 4 7 8 5 6 9) - // and finally: (9 6 5 8 7 4 3 2) - - // Now copy the slots. - - int islotOutStart = psstrmOut->WritePos(); - int cslotNotCopied = 0; - for (iislot = 0; iislot < vislotMap.size(); iislot++) - { - GrSlotState * pslot = psstrmIn->SlotAt(vislotMap[iislot]); - // Don't copy bidi markers unless they have been set to use a specific glyph. - if (pslot->IsBidiMarker() && pslot->ActualGlyphForOutput(ptman) == 0) - cslotNotCopied++; - else - psstrmOut->SimpleCopyFrom(psstrmIn, vislotMap[iislot], - iislot + islotOutStart - cslotNotCopied); - } - return cslotNotCopied; -} - -/*---------------------------------------------------------------------------------------------- - Unwind the output for this pass, given that a change was assumed to have occurred - in the input at the given position. Return the position to which we unwound. -----------------------------------------------------------------------------------------------*/ -int GrPass::Unwind(GrTableManager * ptman, - int islotChanged, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, - bool fFirst) -{ - // Back up the number of slots required for the longest rule context, - // but if we land in the middle of a chunk, go forward to its boundary. - int islotIn = max(islotChanged - m_pzpst->MaxChunk(), 0); - if (!psstrmIn->NoReproc()) - islotIn = min(islotIn, psstrmIn->ReprocMin()); - psstrmIn->ClearReprocBuffer(); - int islotOut = 0; - if (islotIn < psstrmIn->SlotsSkippedToResync() || - islotIn == 0 || - psstrmIn->ReadPos() == 0) - { - // The next-chunk-map is invalid. The beginning of the chunk is 0. - islotIn = 0; - islotOut = 0; - } - else if (islotIn >= psstrmIn->ReadPos()) - { - // No need to unwind. - Assert(psstrmIn->NoReproc()); - return psstrmOut->WritePos(); - } - else - { - Assert(islotIn < psstrmIn->ReadPos()); - islotIn = min(islotIn, psstrmIn->ReadPos() - 1); - while (islotIn < psstrmIn->ReadPos() && - (islotOut = psstrmIn->ChunkInNext(islotIn)) == -1) - { - ++islotIn; - } - if (islotIn == psstrmIn->ReadPos()) - islotOut = psstrmOut->WritePos(); - } - - Assert(islotOut != -2); // because the chunk size must be <= than the max-chunk, - // so we should never hit the end of the output stream - - // Now we've found a chunk boundary. - -// if (fFirst) -// Unattach(psstrmIn, islotIn, psstrmOut, islotOut, islotChanged); -// else -// Unattach(psstrmIn, islotIn, psstrmOut, islotOut, -1); - - psstrmIn->UnwindInput(islotIn, PreBidiPass()); - psstrmOut->UnwindOutput(islotOut, IsPosPass()); - - if (psstrmIn->ReadPos() < psstrmIn->SlotsSkippedToResync()) - { - ptman->Pass(m_ipass - 1)->UndoResyncSkip(); - psstrmIn->ClearSlotsSkippedToResync(); - } - if (psstrmOut->WritePos() < psstrmOut->SlotsSkippedToResync()) - { - Assert(psstrmOut->SlotsSkippedToResync() == m_pzpst->m_cslotSkipToResync); - UndoResyncSkip(); - psstrmOut->ClearSlotsSkippedToResync(); - } - - if (ptman->LoggingTransduction()) - m_pzpst->UnwindLogInfo(islotIn, islotOut); - - return islotOut; -} - -/*---------------------------------------------------------------------------------------------- - For a GrBidiPass, just unwind to the beginning of the reordered chunk. -----------------------------------------------------------------------------------------------*/ -int GrBidiPass::Unwind(GrTableManager * ptman, - int islotChanged, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, - bool fFirst) -{ - int islotIn; - int islotOut; - - if (islotChanged == 0) - { - islotIn = 0; - islotOut = 0; - } - else { - islotIn = min(islotChanged, psstrmIn->ReadPos()); - islotIn = max(islotIn - 1, 0); - while (islotIn > 0 && !StrongDir(psstrmIn->SlotAt(islotIn)->Directionality())) - { - psstrmIn->SlotAt(islotIn)->ZapDirLevel(); - islotIn--; - } - Assert(islotIn == 0 || psstrmIn->SlotAt(islotIn)->DirHasBeenProcessed()); - islotOut = 0; - while (islotIn > 0 && (islotOut = psstrmIn->ChunkInNext(islotIn)) == -1) - --islotIn; - } - - if (islotOut == -1 || islotOut == -2) - islotOut = 0; - - // Now we've found a chunk boundary; islotI and islotO are the positions in the - // input and output streams, respectively. - - psstrmIn->UnwindInput(islotIn, false); - psstrmOut->UnwindOutput(islotOut, false); - - if (psstrmOut->WritePos() < m_pzpst->m_cslotSkipToResync) - { - Assert(false); // shouldn't be any of this mess for the Bidi pass - m_pzpst->m_fDidResyncSkip = false; - } - - if (ptman->LoggingTransduction()) - m_pzpst->UnwindLogInfo(islotIn, islotOut); - - return islotOut; -} - -/*---------------------------------------------------------------------------------------------- - Reinitialize part of the transduction logging information when we unwind the pass. -----------------------------------------------------------------------------------------------*/ -void PassState::UnwindLogInfo(int islotIn, int islotOut) -{ - while (m_crulrec > 0 && m_rgrulrec[m_crulrec-1].m_islot >= islotIn) - { - m_crulrec--; - m_rgrulrec[m_crulrec].m_islot = 0; - m_rgrulrec[m_crulrec].m_irul = 0; - m_rgrulrec[m_crulrec].m_fFired = false; - } - - for (int islot = islotOut; islot < 128; islot++) - { - m_rgcslotDeletions[islot] = 0; - m_rgfInsertion[islot] = false; - } -} - -/*---------------------------------------------------------------------------------------------- - Undo the side effects of attachments, ie, fix up the attachment trees as we unwind. - - @param islotLB the index of the line-break that was just inserted, or -1 if this is - not the first pass to include line-breaks; we want to skip this slot - in the processing in this method - - OBSOLETE -----------------------------------------------------------------------------------------------*/ -//:Ignore -void GrPosPass::Unattach(GrSlotStream * psstrmIn, int islotIn, - GrSlotStream * psstrmOut, int islotOut, int islotLB) -{ - // Because this is a positioning pass, there is a one-to-one correspondence between - // the slots in the input and the slots in the output. Thus we can make simplifying - // assumptions. Specifically, the chunk sizes are equal, except for the possiblity - // of a LB slot that we just inserted in the input stream. -#if 0 - -#ifdef _DEBUG - int islotDiff = (psstrmIn->ReadPos() - islotIn) - (psstrmOut->WritePos() - islotOut); - if (islotLB == -1) - Assert(islotDiff == 0); - else - Assert(islotDiff == 1); -#endif // _DEBUG - - int islotInLp = psstrmIn->ReadPos(); - int islotOutLp = psstrmOut->WritePos(); - for ( ; islotInLp-- > islotIn && islotOutLp-- > islotOut; ) - { - if (islotLB == islotInLp) - { - GrSlotState * pslotTmp = psstrmIn->SlotAt(islotInLp); - islotInLp--; - } - - GrSlotState * pslotIn = psstrmIn->SlotAt(islotInLp); - GrSlotState * pslotOut = psstrmOut->SlotAt(islotOutLp); - - if (pslotIn != pslotOut) - { - GrSlotState * pslotInRoot = pslotIn->AttachRoot(); - GrSlotState * pslotOutRoot = pslotOut->AttachRoot(); - - if (pslotOutRoot) - pslotOutRoot->RemoveLeaf(pslotOut); - if (pslotInRoot) - pslotInRoot->AddLeaf(pslotIn); - } - } -#endif // 0 -} -//:End Ignore - - -/*---------------------------------------------------------------------------------------------- - Record the fact that the given rule's constraint failed, for the purpose of logging - the transduction process. -----------------------------------------------------------------------------------------------*/ -void GrPass::RecordRuleFailed(int islot, int irul) -{ - m_pzpst->RecordRule(islot, irul, false); -} - - -/*---------------------------------------------------------------------------------------------- - Record the fact that the given rule fired, for the purpose of logging - the transduction process. -----------------------------------------------------------------------------------------------*/ -void GrPass::RecordRuleFired(int islot, int irul) -{ - m_pzpst->RecordRule(islot, irul, true); -} - - -/*---------------------------------------------------------------------------------------------- - Record the fact that we forcibly advanced due to the max-rule-loop. -----------------------------------------------------------------------------------------------*/ -void GrPass::RecordHitMaxRuleLoop(int islot) -{ - m_pzpst->RecordRule(islot, PassState::kHitMaxRuleLoop); -} - - -/*---------------------------------------------------------------------------------------------- - Record the fact that we forcibly advanced due to the max-backup. - - In theory it should be possible to call this, but in reality, it is pretty hard to be - able to say that there is a rule that would have fired except it was prevent by - MaxBackup. So currently this method is not called. -----------------------------------------------------------------------------------------------*/ -void GrPass::RecordHitMaxBackup(int islot) -{ - m_pzpst->RecordRule(islot, PassState::kHitMaxBackup); -} - - -/*---------------------------------------------------------------------------------------------- - Record some rule-related activity on a slot. -----------------------------------------------------------------------------------------------*/ -void PassState::RecordRule(int islot, int irul, bool fFired) -{ - if (m_crulrec >= 128) - return; - - m_rgrulrec[m_crulrec].m_irul = irul; - m_rgrulrec[m_crulrec].m_islot = islot; - m_rgrulrec[m_crulrec].m_fFired = true; - m_rgrulrec[m_crulrec].m_fFired = fFired; - m_crulrec++; -} - - -/*---------------------------------------------------------------------------------------------- - Record the fact that a slot was deleted before the given slot (in the output). -----------------------------------------------------------------------------------------------*/ -void PassState::RecordDeletionBefore(int islot) -{ - if (islot >= 128) - return; - - (m_rgcslotDeletions[islot])++; -} - -/*---------------------------------------------------------------------------------------------- - Record the fact that the given slot was inserted into the output. -----------------------------------------------------------------------------------------------*/ -void PassState::RecordInsertionAt(int islot) -{ - if (islot >= 128) - return; - - m_rgfInsertion[islot] = true; -} - -} // namespace gr diff --git a/Build/source/libs/graphite-engine/src/segment/GrPass.h b/Build/source/libs/graphite-engine/src/segment/GrPass.h deleted file mode 100644 index d4d6a16a9dc..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrPass.h +++ /dev/null @@ -1,748 +0,0 @@ -/*--------------------------------------------------------------------*//*:Ignore this sentence. -Copyright (C) 1999 - 2008 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: GrPass.h -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - The GrPass class and subclasses. -----------------------------------------------------------------------------------------------*/ -#ifdef _MSC_VER -#pragma once -#endif -#ifndef PASS_INCLUDED -#define PASS_INCLUDED - -//:End Ignore - -namespace gr -{ - -/*---------------------------------------------------------------------------------------------- - This class stores the state of processing in a single pass. - - Hungarian: zpst -----------------------------------------------------------------------------------------------*/ - -class PassState { - friend class GrPass; - friend class GrGlyphGenPass; - friend class GrLineBreakPass; - friend class GrSubPass; - friend class GrBidiPass; - friend class GrPosPass; - friend class FontMemoryUsage; - -public: - PassState() - { - } - - void InitForNewSegment(int ipass, int nMaxChunk); - void InitializeLogInfo(); - - int MaxChunk() - { - return m_nMaxChunk; - } - - void SetResyncSkip(int c) - { - m_cslotSkipToResync = c; - m_fDidResyncSkip = false; - } - int NeededToResync() - { - if (m_fDidResyncSkip) - return 0; - return m_cslotSkipToResync; - } - bool DidResyncSkip() - { - return m_fDidResyncSkip; - } - bool CanResyncSkip(GrSlotStream * psstrmOutput) - { - if (m_fDidResyncSkip) - return true; // already did it - // Are we in the position to do the resync-skip? - return m_cslotSkipToResync <= psstrmOutput->WritePos(); - } - int DoResyncSkip(GrSlotStream * psstrmOutput); - void UndoResyncSkip() - { - m_fDidResyncSkip = false; - } - - void UnwindLogInfo(int islotIn, int islotOut); - void RecordRule(int islot, int irul, bool fFired = false); - void RecordDeletionBefore(int islot); - void RecordInsertionAt(int islot); -#ifdef TRACING - void LogRulesFiredAndFailed(std::ostream & strmOut, GrSlotStream * psstrmIn); - void LogInsertionsAndDeletions(std::ostream & strmOut, GrSlotStream * psstrmOut); - void LogXmlRules(std::ostream & strmOut, GrTableManager *, GrSlotStream * psstrmIn, int nIndent); - void LogXmlGlyphs(std::ostream & strmOut, GrTableManager * ptman, GrSlotStream * psstrmOut, - int ipassJust1, bool fPreJust, bool fPostJust, bool fBidi, bool fBidiNext, int cslotsSkipped, - int nIndent); -#endif // TRACING - -protected: - int m_ipass; - - // Used to avoid infinite loops. If m_nRulesSinceAdvance > m_nMaxRuleLoop, - // and we have not passed the stream's ReadPosMax, forcibly advance. - int m_nRulesSinceAdvance; - - // Maximum length of chunk, used when unwinding the streams during backtracking. This - // must be initialized to m_nMaxRuleContext, but that is not always adequate, because - // when there is reprocessing going on the chunks may be longer. - int m_nMaxChunk; - - // Indicates how much of the pass's initial output should be automatically - // skipped over in order to resync with a chunk boundary. This handles the situation - // where we are reprocessing a little of the previous segment in order to handle - // cross-line-boundary contextuals. The goal is to skip over the output until we hit - // what we know (from processing the previous segment) is a chunk boundary. - // - // In most cases (and always when this is the first segment of the - // writing system) this number is 0. - int m_cslotSkipToResync; - bool m_fDidResyncSkip; - - enum { - kHitMaxBackup = -1, - kHitMaxRuleLoop = -2 - }; - - // For logging transduction process: record of one rule matched or fired - struct RuleRecord - { - int m_irul; // rule index, or kHitMaxBackup or kHitMaxRuleLoop - int m_islot; // slot index of input stream - bool m_fFired; - }; - RuleRecord m_rgrulrec[128]; - int m_crulrec; - - int m_rgcslotDeletions[128]; // number of deletions before slot i in output - bool m_rgfInsertion[128]; // true if slot i in output was inserted -}; - -/*---------------------------------------------------------------------------------------------- - This class handles finding and applying rules from the pass and storing - the results in the appropriate stream. - - Hungarian: pass -----------------------------------------------------------------------------------------------*/ -class GrPass { - friend class FontMemoryUsage; - -protected: - // Action command codes; these MUST match the corresponding definitions in the compiler: - enum ActionCommand { - kopNop = 0, - - kopPushByte, kopPushByteU, kopPushShort, kopPushShortU, kopPushLong, - - kopAdd, kopSub, kopMul, kopDiv, - kopMin, kopMax, - kopNeg, - kopTrunc8, kopTrunc16, - - kopCond, - - kopAnd, kopOr, kopNot, - kopEqual, kopNotEq, - kopLess, kopGtr, kopLessEq, kopGtrEq, - - kopNext, kopNextN, kopCopyNext, - kopPutGlyph8bitObs, kopPutSubs8bitObs, kopPutCopy, - kopInsert, kopDelete, - kopAssoc, - kopCntxtItem, - - kopAttrSet, kopAttrAdd, kopAttrSub, - kopAttrSetSlot, - kopIAttrSetSlot, - kopPushSlotAttr, kopPushGlyphAttrObs,kopPushGlyphMetric, kopPushFeat, - kopPushAttToGAttrObs, kopPushAttToGlyphMetric, - kopPushISlotAttr, - - kopPushIGlyphAttr, // not implemented - - kopPopRet, kopRetZero, kopRetTrue, - kopIAttrSet, kopIAttrAdd, kopIAttrSub, - kopPushProcState, kopPushVersion, - kopPutSubs, kopPutSubs2, kopPutSubs3, - kopPutGlyph, kopPushGlyphAttr, kopPushAttToGlyphAttr - - }; - - enum StackMachineFlag { - ksmfDone = 0, - ksmfContinue, - ksmfUnderflow, - ksmfStackNotEmptied - }; - -public: - // Constructor: - GrPass(int i); - // Destructor: - virtual ~GrPass(); - - int PassNumber() { return m_ipass; } - - bool ReadFromFont(GrIStream & grstrm, int fxdSilfVersion, int fxdRuleVersion, int nOffset); - void InitializeWithNoRules(); - - virtual void SetTopDirLevel(int n) - { // only GrBidiPass does anything interesting - } - - void SetPassState(PassState * pzpst) - { - m_pzpst = pzpst; - } - - virtual void ExtendOutput(GrTableManager *, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput, int nslotToGet, - TrWsHandling twsh, - int * pnRet, int * pcslotGot, int * pislotFinalBreak); - - int ExtendGlyphIDOutput(GrTableManager *, GrCharStream *, - GrSlotStream *, int ichSegLim, int cchwPostXlbContext, - LineBrk lb, int cslotToGet, bool fNeedFinalBreak, - TrWsHandling twsh, int * pislotFinalBreak); - - int ExtendFinalOutput(GrTableManager *, GrSlotStream * psstrmInput, - GrSlotStream * psstrmOutput, - float xsSpaceAllotted, bool fWidthIsCharCount, bool fInfiniteWidth, - bool fHaveLineBreak, bool fMustBacktrack, - LineBrk lbMax, TrWsHandling twsh, - int * pislotLB, float * pxsWidth); - - int RemoveTrailingWhiteSpace(GrTableManager * ptman, GrSlotStream * psstrmOut, - TrWsHandling twsh, int * pislotFinalBreak); - - virtual int Unwind(GrTableManager * ptman, - int islotChanged, GrSlotStream *psstrmInput, GrSlotStream * psstrmOutput, - bool fFirst); - - int MaxBackup() - { - return m_nMaxBackup; - } - - bool DidResyncSkip() - { - return m_pzpst->DidResyncSkip(); - } - int DoResyncSkip(GrSlotStream * psstrmOutput) - { - return m_pzpst->DoResyncSkip(psstrmOutput); - } - - void UndoResyncSkip() - { - m_pzpst->UndoResyncSkip(); - } - void SetResyncSkip(int n) - { - m_pzpst->SetResyncSkip(n); - } - - virtual void DoCleanUpSegMin(GrTableManager * ptman, - GrSlotStream * psstrmIn, int islotInitReadPos, GrSlotStream * psstrmOut) - { - } - - virtual bool IsPosPass() - { - return false; - } - - virtual bool PreBidiPass() = 0; - - bool RunConstraint(GrTableManager *, int ruln, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, - int cslotPreModContext, int cslotMatched); - - int RunCommandCode(GrTableManager * ptman, - byte * pbStart, bool fConstraints, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, int islot); - -protected: - int RunOneCommand(GrTableManager * ptman, bool fConstraints, - ActionCommand op, byte ** ppbArg, bool * pfMustGet, bool * pfInserting, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, int islot, - std::vector<int> & vnStack, StackMachineFlag * psmf); - void DoStackArithmetic2Args(ActionCommand op, std::vector<int> & vnStack, - StackMachineFlag * psmf); - void DoStackArithmetic1Arg(ActionCommand op, std::vector<int> & vnStack, - StackMachineFlag * psmf); - void DoConditional(std::vector<int> & vnStack, StackMachineFlag * psmf); - StackMachineFlag CheckStack(std::vector<int> & vnStack, int cn); - void DoNext(GrTableManager * ptman, - int cslot, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - void DoPutGlyph(GrTableManager * ptman, bool fInserting, int nReplacementClass, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - void DoPutCopy(GrTableManager * ptman, bool fInserting, int cslotCopyFrom, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - void DoPutSubs(GrTableManager * ptman, bool fInserting, - int cslotSel, int nSelClass, int nReplacementClass, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - void DoPutSubs2(GrTableManager * ptman, bool fInserting, - int cslotSel1, int nSelClass1, int cslotSel2, int nSelClass2, int nReplacementClass, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - void DoPutSubs3(GrTableManager * ptman, bool fInserting, - int cslotSel1, int nSelClass1, int cslotSel2, int nSelClass2, int cslotSel3, int nSelClass3, - int nReplacementClass, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - void DoPutSubsInit(GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, bool fInserting, - GrSlotState ** ppslotNextPut, bool * pfAtSegMin, bool * pfAtSegLim); - void DoPutSubsAux(GrTableManager * ptman, bool fInserting, gid16 nGlyphReplacement, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, GrSlotState * pslotNextInput, - bool fAtSegMin, bool fAtSegLim); - void SetNeutralAssocs(GrSlotState * pslotNew, GrSlotStream * psstrmIn); - void DoDelete(GrTableManager * ptman, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - void DoAssoc(int cnAssocs, std::vector<int> & vnAssocs, bool fInserting, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - void DoSetAttr(GrTableManager * ptman, - ActionCommand op, bool fInserrting, - SlotAttrName slat, int slati, std::vector<int> & vnStack, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - void DoPushSlotAttr(GrTableManager * ptman, - int nSlotRef, bool fInserting, - SlotAttrName slat, int slati, std::vector<int> & vnStack, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - void DoPushGlyphAttr(GrTableManager * ptman, int nSlotRef, bool fInserting, - int nGlyphAttr, std::vector<int> & vnStack, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - void DoPushAttToGlyphAttr(GrTableManager * ptman, int nSlotRef, bool fInserting, - int nGlyphAttr, std::vector<int> & vnStack, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - void DoPushGlyphMetric(GrTableManager * ptman, int nSlotRef, bool fInserting, - int nGlyphAttr, int nAttLevel, std::vector<int> & vnStack, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - void DoPushAttToGlyphMetric(GrTableManager * ptman, int nSlotRef, bool fInserting, - int nGlyphAttr, int nAttLevel, std::vector<int> & vnStack, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - void DoPushFeatValue(GrTableManager * ptman, int islot, bool fInsering, - int nFeat, std::vector<int> & vnStack, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - void DoPushProcState(GrTableManager * ptman, int nPState, std::vector<int> & vnStack); -protected: - void DoPushGlyphMetricAux(GrTableManager * ptman, - GrSlotState * pslot, int nGlyphAttr, int nAttLevel, - std::vector<int> & vnStack, GrSlotStream * psstrmIn); -public: - int SortKeyForRule(int ruln) - { - Assert(ruln < m_crul); - return m_prgchwRuleSortKeys[ruln]; - } - int PreModContextForRule(int ruln) - { - Assert(ruln < m_crul); - return m_prgcritRulePreModContext[ruln]; - } - - int MaxRulePreContext() - { - if (m_pfsm) - return m_pfsm->MaxRulePreContext(); - else - return 0; - } - - void RecordRuleFailed(int islot, int irul); - void RecordRuleFired(int islot, int irul); - void RecordHitMaxRuleLoop(int islot); - void RecordHitMaxBackup(int islot); -#ifdef TRACING - void LogRulesFiredAndFailed(std::ostream & strmOut, GrSlotStream * psstrmIn); - void LogInsertionsAndDeletions(std::ostream & strmOut, GrSlotStream * psstrmOut); - void LogXmlRules(std::ostream & strmOut, GrTableManager * ptman, - GrSlotStream * psstrmIn, int nIndent); - void LogXmlGlyphs(std::ostream & strmOut, GrTableManager * ptman, GrSlotStream * psstrmOut, - int ipassJust1, bool fPreJust, bool fPostJust, int cslotsSkipped, int nIndent); -#endif // TRACING - -protected: - int CheckRuleValidity(int ruln); - - virtual void RunRule(GrTableManager *, int ruln, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) = 0; - - void CheckInputProgress(GrSlotStream* input, GrSlotStream* psstrmOutput, - int islotOrigInput); - - void MapChunks(GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, - int islotChunkI, int islotChunkO, int cslotReprocessed); - - virtual void Unattach(GrSlotStream * psstrmIn, int islotIn, // GrPosPass overrides - GrSlotStream * psstrmOut, int islotOut, int islotLB) - { - } - - friend class EngineState; // let it call the method below - virtual int MaxRuleContext() // GrBidiPass overrides - { - return m_nMaxRuleContext; - } - -protected: - // Instance variables: - - int m_ipass; // index of pass - - int m_fxdVersion; - - // number of items required from previous pass; don't access directly, use the getter - // method, because GrBidiPass overrides to always use 1. - int m_nMaxRuleContext; - - GrFSM * m_pfsm; // Finite State Machine to give next rule - - int m_nMaxRuleLoop; // maximum number of rules to process before forcibly - // advancing input position - - int m_nMaxBackup; - - int m_crul; // number of rules - - // rule sort keys, indicating precedence of rules; m_crul of these - data16 * m_prgchwRuleSortKeys; - - // for each rule, the number of items in the context before the first modified item - // that the constraints need to be tested on - byte * m_prgcritRulePreModContext; - - // offset for pass-level constraints; just 1 of these - data16 m_cbPassConstraint; - // offsets for constraint and action code; m_crul+1 of each of these (the last - // indicates the total byte count) - data16 * m_prgibConstraintStart; - data16 * m_prgibActionStart; - - // blocks of constraint and action code - byte * m_prgbPConstraintBlock; // pass-level constraints - byte * m_prgbConstraintBlock; // rule constraints - byte * m_prgbActionBlock; - - int m_cbConstraints; // needed for memory instrumentation only - int m_cbActions; // needed for memory instrumentation only - - bool m_fHasDebugStrings; - data16 * m_prgibConstraintDebug; // m_crul+1 of these - data16 * m_prgibRuleDebug; // m_crul+1 of these - - bool m_fCheckRules; - bool * m_prgfRuleOkay; - - std::vector<int> m_vnStack; // for stack machine processing (more efficient than creating the - // vector each time) - - // state of process for this pass - PassState * m_pzpst; - -public: -#ifdef OLD_TEST_STUFF - // For test procedures: - StrAnsi m_staBehavior; - - virtual void SetUpTestData(); - - // overridden on appropriate subclasses: - virtual void SetUpReverseNumbersTest() { Assert(false); } - virtual void SetUpBidiNumbersTest() { Assert(false); } - - virtual void SetUpCrossLineContextTest() { Assert(false); } - virtual void SetUpReprocessTest() { Assert(false); } - virtual void SetUpLineEdgeContextTest(int ipass) { Assert(false); } - virtual void SetUpBidiAlgorithmTest() { Assert(false); } - virtual void SetUpPseudoGlyphsTest() { Assert(false); } - virtual void SetUpSimpleFSMTest() { Assert(false); } - virtual void SetUpRuleActionTest() { Assert(false); } - virtual void SetUpRuleAction2Test() { Assert(false); } - virtual void SetUpAssocTest() { Assert(false); } - virtual void SetUpAssoc2Test() { Assert(false); } - virtual void SetUpDefaultAssocTest() { Assert(false); } - virtual void SetUpFeatureTest() { Assert(false); } - virtual void SetUpLigatureTest() { Assert(false); } - virtual void SetUpLigature2Test() { Assert(false); } -#endif // OLD_TEST_STUFF - -}; // end of class GrPass - - -/*---------------------------------------------------------------------------------------------- - The initial pass that generates glyph IDs from Unicode input. - - Hungarian: pass -----------------------------------------------------------------------------------------------*/ -class GrGlyphGenPass : public GrPass -{ - friend class FontMemoryUsage; - -public: - GrGlyphGenPass(int ipass) : GrPass(ipass) - { - } - - virtual bool PreBidiPass() - { - return true; - } - -protected: - // Irrelevant when generating glyphs. - virtual void RunRule(GrTableManager *, int ruln, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) - { - Assert(false); - } - -}; // end of class GrGlyphGenPass - - -/*---------------------------------------------------------------------------------------------- - A pass containing rules that set the break weight values. - - Hungarian: pass -----------------------------------------------------------------------------------------------*/ -class GrLineBreakPass : public GrPass -{ - friend class FontMemoryUsage; - -public: - GrLineBreakPass(int ipass) : GrPass(ipass) - { - } - - virtual bool PreBidiPass() - { - return true; - } - -protected: - virtual void RunRule(GrTableManager *, int ruln, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput); - -public: -#ifdef OLD_TEST_STUFF - // For test procedures: - bool RunTestRules(GrTableManager *, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - bool RunTestRules(GrTableManager *, int ruln, GrSlotStream * psstrmIn, - GrSlotStream * psstrmOut); - - virtual void SetUpCrossLineContextTest(); - bool RunCrossLineContextTest(GrTableManager*, GrSlotStream* psstrmIn, - GrSlotStream* psstrmOut); - - virtual void SetUpReprocessTest(); - bool RunReprocessTest(GrTableManager *, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut); - - virtual void SetUpAssocTest(); - virtual void SetUpLigatureTest(); -#endif // OLD_TEST_STUFF - -}; // end of class GrLineBreakPass - - -/*---------------------------------------------------------------------------------------------- - A pass containing substitution rules. - - Hungarian: pass -----------------------------------------------------------------------------------------------*/ -class GrSubPass : public GrPass -{ - friend class FontMemoryUsage; - -public: - GrSubPass(int ipass) : GrPass(ipass) - { - } - - virtual bool PreBidiPass() - { - return true; - } - -protected: - virtual void RunRule(GrTableManager *, int ruln, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput); - - virtual void DoCleanUpSegMin(GrTableManager * ptman, - GrSlotStream * psstrmIn, int islotInitReadPos, GrSlotStream * psstrmOut); - -public: -#ifdef OLD_TEST_STUFF - // For test procedures: - bool RunTestRules(GrTableManager *, GrSlotStream * psstrmIn, - GrSlotStream * psstrmOut); - bool RunTestRules(GrTableManager *, int ruln, GrSlotStream * psstrmIn, - GrSlotStream * psstrmOut); - - virtual void SetUpReverseNumbersTest(); - bool RunReverseNumbersTest(GrTableManager*, GrSlotStream* psstrmIn, - GrSlotStream* psstrmOut); - - virtual void SetUpBidiNumbersTest(); - bool RunBidiNumbersTest(GrTableManager*, GrSlotStream* psstrmIn, - GrSlotStream* psstrmOut); - - virtual void SetUpCrossLineContextTest(); - bool RunCrossLineContextTest(GrTableManager*, GrSlotStream* psstrmIn, - GrSlotStream* psstrmOut); - - virtual void SetUpReprocessTest(); - bool RunReprocessTest(GrTableManager *, GrSlotStream * psstrmIn, - GrSlotStream * psstrmOut); - - virtual void SetUpLineEdgeContextTest(int ipass); - bool RunLineEdgeContextTest(GrTableManager *, GrSlotStream * psstrmIn, - GrSlotStream * psstrmOut); - - virtual void SetUpBidiAlgorithmTest(); - bool RunBidiAlgorithmTest(GrTableManager *, GrSlotStream * psstrmIn, - GrSlotStream * psstrmOut); - - virtual void SetUpPseudoGlyphsTest(); - bool RunPseudoGlyphsTest(GrTableManager *, GrSlotStream * psstrmIn, - GrSlotStream * psstrmOut); - - virtual void SetUpSimpleFSMTest(); - bool RunSimpleFSMTest(GrTableManager *, int ruln, GrSlotStream * psstrmIn, - GrSlotStream * psstrmOut); - virtual void SetUpRuleActionTest(); - virtual void SetUpRuleAction2Test(); - virtual void SetUpAssocTest(); - virtual void SetUpAssoc2Test(); - virtual void SetUpDefaultAssocTest(); - virtual void SetUpFeatureTest(); - virtual void SetUpLigatureTest(); - virtual void SetUpLigature2Test(); -#endif // OLD_TEST_STUFF - -}; // end of class GrSubPass - - -/*---------------------------------------------------------------------------------------------- - This class is the one the knows how to handle bidi reordering, including backtracking. - - Hungarian: pass -----------------------------------------------------------------------------------------------*/ -class GrBidiPass : public GrSubPass -{ - friend class FontMemoryUsage; - -public: - // Constructor: - GrBidiPass(int ipass) - : GrSubPass(ipass), - m_nTopDirection(0) - { - } - - virtual void SetTopDirLevel(int n) - { - m_nTopDirection = n; - } - - virtual bool PreBidiPass() - { - return false; - } - - virtual void ExtendOutput(GrTableManager *, - GrSlotStream * psstrmI, GrSlotStream * psstrmO, int nslotToGet, - TrWsHandling twsh, - int * pnRet, int * pcslotGot, int * pislotFinalBreak); - - virtual int Unwind(GrTableManager * ptman, - int islotChanged, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, - bool fFirst); -protected: - virtual int MaxRuleContext() - { - return 1; - } - -private: - //void OldReverse(int nCurrDirection, - // GrSlotStream * psstrmI, int islotI1, int islotI2, - // GrSlotStream * psstrmO, int islotO1, int islotO2); - - int Reverse(GrTableManager * ptman, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, - std::vector<int> & vislotStarts, std::vector<int> & vislotStops); - -protected: - // Instance variables: - int m_nTopDirection; // 0 for LTR, 1 for RTL -- CURRENTLY NOT USED; need to - // initialize it when we set the writing system direction - -#ifdef OLD_TEST_STUFF -public: - // For test procedures: - ////virtual void SetUpTestData(); - virtual void SetUpBidiNumbersTest(); - virtual void SetUpBidiAlgorithmTest(); -#endif // OLD_TEST_STUFF - -}; // end of class GrBidiPass - - -/*---------------------------------------------------------------------------------------------- - A pass containing positioning rules. - - Hungarian: pass -----------------------------------------------------------------------------------------------*/ -class GrPosPass : public GrPass -{ - friend class FontMemoryUsage; - -public: - GrPosPass(int ipass) : GrPass(ipass) - { - } - - virtual bool IsPosPass() - { - return true; - } - - virtual bool PreBidiPass() - { - return false; - } - -protected: - virtual void RunRule(GrTableManager *, int ruln, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput); - - virtual void Unattach(GrSlotStream * psstrmIn, int islotIn, - GrSlotStream * psstrmOut, int islotOut, int islotLB); - -public: -#ifdef OLD_TEST_STUFF - // For test procedures: - bool RunTestRules(GrTableManager *, GrSlotStream * psstrmIn, - GrSlotStream * psstrmOut); - bool RunTestRules(GrTableManager *, int ruln, GrSlotStream * psstrmIn, - GrSlotStream * psstrmOut); -#endif // OLD_TEST_STUFF - -}; // end of class GrPosPass - -} // namespace gr - - -#endif // PASS_INCLUDED diff --git a/Build/source/libs/graphite-engine/src/segment/GrPassActionCode.cpp b/Build/source/libs/graphite-engine/src/segment/GrPassActionCode.cpp deleted file mode 100644 index 83c58b27e48..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrPassActionCode.cpp +++ /dev/null @@ -1,1492 +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: GrPassActionCode.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - A continution of the GrPass file, including functions to run the action commands. - -This comment could create a merge conflict. It can be removed. -----------------------------------------------------------------------------------------------*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" - -#ifdef _MSC_VER -#pragma hdrstop -#endif -#undef THIS_FILE -DEFINE_THIS_FILE - -//:End Ignore - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local type definitions -//:>******************************************************************************************** - -typedef signed char Int8; // signed value -typedef unsigned char Uint8; // unsigned value - - -namespace gr -{ - -//:>******************************************************************************************** -//:> Methods -//:>******************************************************************************************** - -/*---------------------------------------------------------------------------------------------- - The main function to run a block of action or constraint code and return a result. - - @param ptman - table manager, for generating new slots; NULL when - running constraints - @param pbStart - address of the first command - @param fConstraints - true if we are running constraint tests; - false if we are running rule actions - @param psstrmIn - input stream - @param psstrmOut - output stream; when running constraints, used to access items - in the precontext - @param islot - slot being processed relative to the start of the rule; - used only for constraints; must be 0 for rule actions -----------------------------------------------------------------------------------------------*/ -int GrPass::RunCommandCode(GrTableManager * ptman, - byte * pbStart, bool fConstraints, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, int islot) -{ - byte * pbNext = pbStart; - -// std::vector<int> vnStack; -// vnStack.EnsureSpace(128); // make it nice and big - m_vnStack.clear(); - - gAssert(fConstraints || islot == 0); - - // There are two states: fMustGet = true means we need to get a slot to work on from - // the input; fMustGet = false means we have a slot and we need to do a Next before - // we can get the next one. - bool fMustGet = !fConstraints; - - bool fInserting = false; // set to true by an Insert command - - int nRet = 0; - - while (true) - { - ActionCommand op = ActionCommand(*pbNext++); - StackMachineFlag smf; - nRet = RunOneCommand(ptman, fConstraints, op, - &pbNext, &fMustGet, &fInserting, - psstrmIn, psstrmOut, islot, - m_vnStack, &smf); - - if (smf == ksmfDone) - return nRet; - - if (smf == ksmfUnderflow) - { - Warn("Underflow in Graphite stack machine"); - gAssert(false); - FontException fexptn; - fexptn.version = -1; - fexptn.subVersion = -1; - fexptn.errorCode = kferrUnknown; - throw fexptn; // disastrous error in rendering; fall back to dumb rendering - } - } - return nRet; // not needed, but to avoid compiler warning -} - -/*---------------------------------------------------------------------------------------------- - Perform a single command. Specifically, read the arguments from the byte buffer and the - run the appropriate functions. - - @param ptman - table manager, for generating new slots; or NULL - @param fConstraints - true if we are running constraints; false if we are running - rule actions - @param op - command operator - @param ppbArg - pointer to first argument - @param pfMustGet - state: getting input or processing it; when running constraints, - always false - @param pfInserting - true if current item is to be inserted, or was inserted - @param psstrmIn - input stream - @param psstrmOut - output stream - @param islot - the slot being processed relative to the beginning of the rule; - only relevant for constraint testing, must be 0 for rule actions - @param vnStack - the stack of values being manipulated - @param psmf - error code, done flag, or continue flag -----------------------------------------------------------------------------------------------*/ -int GrPass::RunOneCommand(GrTableManager * ptman, bool fConstraints, - ActionCommand op, byte ** ppbArg, bool * pfMustGet, bool * pfInserting, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, int islot, - std::vector<int> & vnStack, StackMachineFlag * psmf) -{ - *psmf = ksmfContinue; - - // General purpose variables: - int arg1, arg2, arg3, arg4; - int nSlotRef; - int nInputClass; - int nOutputClass; - int c; - int islotArg; - int nIndex; - int nGlyphAttr; - int nAttLevel; - int nFeat; - int nPState; - SlotAttrName slat; - - int i; - std::vector<int> vnTmp; - - byte * pbNext = *ppbArg; - - int nRet = 0; - - switch (op) - { - case kopNop: - break; - - case kopPushByte: - arg1 = Int8(*pbNext++); - vnStack.push_back(arg1); - break; - case kopPushByteU: - arg1 = Uint8(*pbNext++); - vnStack.push_back(arg1); - break; - case kopPushShort: - arg1 = Int8(*pbNext++); - arg2 = Uint8(*pbNext++); - vnStack.push_back((arg1 << 8) + arg2); - break; - case kopPushShortU: - arg1 = Uint8(*pbNext++); - arg2 = Uint8(*pbNext++); - vnStack.push_back((arg1 << 8) + arg2); - break; - case kopPushLong: - arg1 = Int8(*pbNext++); - arg2 = Uint8(*pbNext++); - arg3 = Uint8(*pbNext++); - arg4 = Uint8(*pbNext++); - vnStack.push_back((arg1 << 24) + (arg2 << 16) + (arg3 << 8) + arg4); - break; - - case kopNeg: - case kopTrunc8: case kopTrunc16: - case kopNot: - DoStackArithmetic1Arg(op, vnStack, psmf); - if (*psmf != ksmfContinue) - return 0; - break; - - case kopAdd: case kopSub: - case kopMul: case kopDiv: - case kopMin: case kopMax: - case kopAnd: case kopOr: - case kopEqual: case kopNotEq: - case kopLess: case kopGtr: - case kopLessEq: case kopGtrEq: - DoStackArithmetic2Args(op, vnStack, psmf); - if (*psmf != ksmfContinue) - return 0; - break; - - case kopCond: - DoConditional(vnStack, psmf); - if (*psmf != ksmfContinue) - return 0; - break; - - case kopNext: - if (fConstraints) - { - gAssert(false); - } - else - { - gAssert(!*pfMustGet); - DoNext(ptman, 1, psstrmIn, psstrmOut); - *pfMustGet = true; - *pfInserting = false; - } - break; - case kopNextN: - c = Int8(*pbNext++); - if (fConstraints) - { - gAssert(false); - } - else - { - gAssert(false); // for now we don't allow anything other than moving one slot - gAssert(!*pfMustGet); // forward at a time - DoNext(ptman, c, psstrmIn, psstrmOut); - *pfMustGet = true; - } - break; - case kopPutGlyph8bitObs: - case kopPutGlyph: - if (op == kopPutGlyph8bitObs) - nOutputClass = Uint8(*pbNext++); - else - { - nOutputClass = (Uint8(*pbNext++) << 8); - nOutputClass += Uint8(*pbNext++); - } - if (fConstraints) - { - gAssert(false); - } - else - { - gAssert(*pfMustGet); - DoPutGlyph(ptman, *pfInserting, nOutputClass, psstrmIn, psstrmOut); - *pfMustGet = false; - } - break; - case kopPutCopy: - nSlotRef = Int8(*pbNext++); - if (fConstraints) - { - gAssert(false); - } - else - { - gAssert(*pfMustGet); - DoPutCopy(ptman, *pfInserting, nSlotRef, psstrmIn, psstrmOut); - *pfMustGet = false; - } - break; - case kopPutSubs8bitObs: - case kopPutSubs: - nSlotRef = Int8(*pbNext++); - if (op == kopPutSubs8bitObs) - { - nInputClass = Uint8(*pbNext++); - nOutputClass = Uint8(*pbNext++); - } - else - { - nInputClass = (Uint8(*pbNext++) << 8); - nInputClass += Uint8(*pbNext++); - nOutputClass = (Uint8(*pbNext++) << 8); - nOutputClass += Uint8(*pbNext++); - } - if (fConstraints) - { - gAssert(false); - } - else - { - gAssert(*pfMustGet); - DoPutSubs(ptman, *pfInserting, nSlotRef, nInputClass, nOutputClass, - psstrmIn, psstrmOut); - *pfMustGet = false; - } - break; - case kopCopyNext: - if (fConstraints) - { - gAssert(false); - } - else - { - gAssert(*pfMustGet); - gAssert(!*pfInserting); // 0 means copy this slot - DoPutCopy(ptman, *pfInserting, 0, psstrmIn, psstrmOut); - DoNext(ptman, 1, psstrmIn, psstrmOut); - // *pfMustGet still = true - } - break; - case kopInsert: - if (fConstraints) - { - gAssert(false); - } - else - { - gAssert(*pfMustGet); - *pfInserting = true; - // *pfMustGet still = true - - if (ptman->LoggingTransduction()) - m_pzpst->RecordInsertionAt(psstrmOut->WritePos()); - } - break; - case kopDelete: - if (fConstraints) - { - gAssert(false); - } - else - { - gAssert(*pfMustGet); - DoDelete(ptman, psstrmIn, psstrmOut); - *pfMustGet = false; - } - break; - case kopAssoc: - c = Uint8(*pbNext++); - // std::vector<int> vnTmp; - for (i = 0; i < c; i++) - vnTmp.push_back(Int8(*pbNext++)); - if (fConstraints) - { - gAssert(false); - } - else - { - gAssert(!*pfMustGet); - DoAssoc(c, vnTmp, *pfInserting, psstrmIn, psstrmOut); - } - break; - case kopCntxtItem: - islotArg = Int8(*pbNext++); - c = Uint8(*pbNext++); - if (fConstraints) - { - // Old approach: - // If this is NOT the relevant item, push TRUE, which causes the subsequent tests - // (which are eventually ORed with it) to become irrelevant. - //vnStack.Push((int)(islotArg != islot)); - - // If this is not the relevant item, skip the specified number of bytes. - if (islotArg != islot) - { - pbNext += c; - vnStack.push_back(1); - } - } - else - { - gAssert(false); - } - break; - - case kopAttrSet: - case kopAttrAdd: - case kopAttrSub: - case kopAttrSetSlot: - slat = SlotAttrName(Uint8(*pbNext++)); // slot attribute ID - if (fConstraints) - { - gAssert(false); - } - else - { - gAssert(!*pfMustGet); - DoSetAttr(ptman, op, *pfInserting, slat, -1, vnStack, psstrmIn, psstrmOut); - if (*psmf != ksmfContinue) - return 0; - } - break; - case kopIAttrSet: - case kopIAttrAdd: - case kopIAttrSub: - case kopIAttrSetSlot: - slat = SlotAttrName(Uint8(*pbNext++)); // slot attribute ID - nIndex = Uint8(*pbNext++); // index; eg, global ID for component - if (fConstraints) - { - gAssert(false); - } - else - { - gAssert(!*pfMustGet); - DoSetAttr(ptman, op, *pfInserting, slat, nIndex, vnStack, - psstrmIn, psstrmOut); - if (*psmf != ksmfContinue) - return 0; - } - break; - - case kopPushSlotAttr: - slat = SlotAttrName(Uint8(*pbNext++)); - nSlotRef = Int8(*pbNext++); - if (fConstraints) - nSlotRef += islot + 1; // +1 to peek ahead to a slot we haven't "got" yet - DoPushSlotAttr(ptman, nSlotRef, *pfInserting, slat, -1, vnStack, psstrmIn, psstrmOut); - if (*psmf != ksmfContinue) - return 0; - break; - case kopPushISlotAttr: - slat = SlotAttrName(Uint8(*pbNext++)); - nSlotRef = Int8(*pbNext++); - nIndex = Uint8(*pbNext++); - if (fConstraints) - nSlotRef += islot + 1; // +1 to peek ahead to a slot we haven't "got" yet - DoPushSlotAttr(ptman, nSlotRef, *pfInserting, slat, nIndex, vnStack, psstrmIn, psstrmOut); - if (*psmf != ksmfContinue) - return 0; - break; - - case kopPushGlyphAttrObs: - case kopPushAttToGAttrObs: - case kopPushGlyphAttr: - case kopPushAttToGlyphAttr: - if (op == kopPushGlyphAttrObs || op == kopPushAttToGAttrObs) - nGlyphAttr = Uint8(*pbNext++); - else { - nGlyphAttr = (Uint8(*pbNext++) << 8); - nGlyphAttr += Uint8(*pbNext++); - } - nSlotRef = Int8(*pbNext++); - if (fConstraints) - nSlotRef += islot + 1; // +1 to peek ahead to a slot we haven't "got" yet - if (op == kopPushAttToGlyphAttr || op == kopPushAttToGAttrObs) - DoPushAttToGlyphAttr(ptman, nSlotRef, *pfInserting, nGlyphAttr, - vnStack, psstrmIn, psstrmOut); - else - DoPushGlyphAttr(ptman, nSlotRef, *pfInserting, nGlyphAttr, vnStack, - psstrmIn, psstrmOut); - if (*psmf != ksmfContinue) - return 0; - break; - case kopPushGlyphMetric: - case kopPushAttToGlyphMetric: - nGlyphAttr = Uint8(*pbNext++); - nSlotRef = Int8(*pbNext++); - nAttLevel = Int8(*pbNext++); - if (fConstraints) - nSlotRef += islot + 1; // +1 to peek ahead to a slot we haven't "got" yet - if (op == kopPushAttToGlyphMetric) - DoPushAttToGlyphMetric(ptman, nSlotRef, *pfInserting, nGlyphAttr, nAttLevel, - vnStack, psstrmIn, psstrmOut); - else - DoPushGlyphMetric(ptman, nSlotRef, *pfInserting, nGlyphAttr, nAttLevel, - vnStack, psstrmIn, psstrmOut); - if (*psmf != ksmfContinue) - return 0; - break; - case kopPushFeat: - nFeat = Uint8(*pbNext++); - nSlotRef = Int8(*pbNext++); - if (fConstraints) - nSlotRef += islot + 1; // +1 to peek ahead to a slot we haven't "got" yet -// else -// nSlotRef = 0; - DoPushFeatValue(ptman, nSlotRef, *pfInserting, nFeat, vnStack, psstrmIn, psstrmOut); - if (*psmf != ksmfContinue) - return 0; - break; - case kopPushProcState: - nPState = Uint8(*pbNext++); - gAssert(fConstraints); - DoPushProcState(ptman, nPState, vnStack); - break; - case kopPushVersion: - vnStack.push_back(kRuleVersion); - break; - case kopPopRet: - if ((*psmf = CheckStack(vnStack, 1)) != ksmfContinue) - return 0; - nRet = vnStack.back(); - vnStack.pop_back(); - if (vnStack.size() != 0) - { - gAssert(false); - *psmf = ksmfStackNotEmptied; - } - else - *psmf = ksmfDone; - break; - case kopRetZero: - nRet = 0; - if (vnStack.size() != 0) - { - gAssert(false); - *psmf = ksmfStackNotEmptied; - } - else - *psmf = ksmfDone; - break; - case kopRetTrue: - nRet = 1; - if (vnStack.size() != 0) - { - gAssert(false); - *psmf = ksmfStackNotEmptied; - } - else - *psmf = ksmfDone; - break; - - default: - gAssert(false); - } - - *ppbArg = pbNext; - return nRet; -} - -/*---------------------------------------------------------------------------------------------- - Perform arithmetic functions that take two arguments. -----------------------------------------------------------------------------------------------*/ -void GrPass::DoStackArithmetic2Args(ActionCommand op, std::vector<int> & vnStack, - StackMachineFlag * psmf) -{ - if ((*psmf = CheckStack(vnStack, 2)) != ksmfContinue) - return; - - int nArg2 = vnStack.back(); - vnStack.pop_back(); - int nArg1 = vnStack.back(); - vnStack.pop_back(); - - int nResult; - - switch (op) - { - case kopAdd: nResult = nArg1 + nArg2; break; - case kopSub: nResult = nArg1 - nArg2; break; - case kopMul: nResult = nArg1 * nArg2; break; - case kopDiv: nResult = nArg1 / nArg2; break; - case kopMin: nResult = min(nArg1, nArg2); break; - case kopMax: nResult = max(nArg1, nArg2); break; - case kopAnd: nResult = (nArg1 != 0 && nArg2 != 0)? 1: 0; break; - case kopOr: nResult = (nArg1 != 0 || nArg2 != 0)? 1: 0; break; - case kopEqual: nResult = (nArg1 == nArg2)? 1: 0; break; - case kopNotEq: nResult = (nArg1 != nArg2)? 1: 0; break; - case kopLess: nResult = (nArg1 < nArg2)? 1: 0; break; - case kopLessEq: nResult = (nArg1 <= nArg2)? 1: 0; break; - case kopGtr: nResult = (nArg1 > nArg2)? 1: 0; break; - case kopGtrEq: nResult = (nArg1 >= nArg2)? 1: 0; break; - default: - Assert(false); - } - - vnStack.push_back(nResult); -} - -/*---------------------------------------------------------------------------------------------- - Perform arithmetic functions that take one argument. -----------------------------------------------------------------------------------------------*/ -void GrPass::DoStackArithmetic1Arg(ActionCommand op, std::vector<int> & vnStack, - StackMachineFlag * psmf) -{ - if ((*psmf = CheckStack(vnStack, 1)) != ksmfContinue) - return; - - int nArg = vnStack.back(); - vnStack.pop_back(); - int nResult; - - switch (op) - { - case kopNeg: nResult = nArg * -1; break; - case kopTrunc8: nResult = nArg & 0xFF; break; - case kopTrunc16: nResult = nArg & 0xFFFF; break; - case kopNot: nResult = (nArg == 0)? 1: 0; break; - default: - Assert(false); - } - - vnStack.push_back(nResult); -} - -/*---------------------------------------------------------------------------------------------- - Perform the conditional statement. -----------------------------------------------------------------------------------------------*/ -void GrPass::DoConditional(std::vector<int> & vnStack, StackMachineFlag * psmf) -{ - if ((*psmf = CheckStack(vnStack, 3)) != ksmfContinue) - return; - - int nArg3 = vnStack.back(); - vnStack.pop_back(); - int nArg2 = vnStack.back(); - vnStack.pop_back(); - int nArg1 = vnStack.back(); - vnStack.pop_back(); - - if (nArg1 == 0) - vnStack.push_back(nArg3); - else - vnStack.push_back(nArg2); -} - -/*---------------------------------------------------------------------------------------------- - Check to make sure the stack has the appropriate number of items on it; if not, - return a stack error flag. -----------------------------------------------------------------------------------------------*/ -GrPass::StackMachineFlag GrPass::CheckStack(std::vector<int> & vnStack, int cn) -{ - if (signed(vnStack.size()) < cn) - return ksmfUnderflow; - else - return ksmfContinue; -} - -/*---------------------------------------------------------------------------------------------- - We are finished processing a slot; go on to the next slot, or possibly go backwards. -----------------------------------------------------------------------------------------------*/ -void GrPass::DoNext(GrTableManager * ptman, - int cslot, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - gAssert(cslot == 1); // for now anyway -} - -/*---------------------------------------------------------------------------------------------- - Set the next glyph to be the given class. There should only be one member of the class, - but if there happens to be more than one, just use the first member. - All the slot attributes remain unchanged from the current input slot; associations are - neutralized. - - @param ptman - table manager, for generating new slots - @param fInserting - true if this slot is being inserted, not copied - @param nReplacementClass - class from which to take replacement glyph (corresponding to - selector slot's glyph's index in selector class) - @param psstrmIn / Out - input/output streams -----------------------------------------------------------------------------------------------*/ -void GrPass::DoPutGlyph(GrTableManager * ptman, bool fInserting, int nReplacementClass, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - EngineState * pengst = ptman->State(); - - // If we are exactly at the segment boundary, pass the information on to the output stream. - // Note that inserted items always go outside the segment, if they are at the boundary - // (you DON'T want them between the segment boundary and the LB slot!). - bool fSetSegMin = psstrmIn->AtSegMin() && !fInserting; - bool fSetSegLim = psstrmIn->AtSegLim(); - - // Slot to copy features and text properties from: - GrSlotState * pslotNextInput; - if (psstrmIn->AtEndOfContext()) - { - gAssert(fInserting); - pslotNextInput = psstrmIn->RuleInputSlot(0, psstrmOut); - } - else - pslotNextInput = (fInserting)? psstrmIn->Peek(): psstrmIn->NextGet(); - - gid16 nGlyphReplacement = ptman->GetClassGlyphIDAt(nReplacementClass, 0); - - GrSlotState * pslotNew; - if (fInserting) - { - pengst->NewSlot(nGlyphReplacement, pslotNextInput, m_ipass, &pslotNew); - // leave associations empty; eventually they will be "neutralized" - } - else - { - pengst->NewSlotCopy(pslotNextInput, m_ipass, &pslotNew); - pslotNew->SetGlyphID(nGlyphReplacement); - ptman->SetSlotAttrsFromGlyphAttrs(pslotNew); - } - - if (fSetSegMin) - psstrmOut->SetSegMinToWritePos(false); - if (fSetSegLim) - psstrmOut->SetSegLimToWritePos(false); - psstrmOut->NextPut(pslotNew); -} - -/*---------------------------------------------------------------------------------------------- - Copy a glyph from the given slot in the input to the output. All the associations and slot - attributes are copied from the specified slot as well. Consume a slot from the input - (which may or may not be the slot we're copying). - - @param ptman - table manager, for generating new slots - @param fInserting - true if this slot is being inserted, not copied - @param cslotCopyFrom - slot to copy from - @param psstrmIn / Out - input/output streams -----------------------------------------------------------------------------------------------*/ -void GrPass::DoPutCopy(GrTableManager * ptman, bool fInserting, int cslotCopyFrom, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - EngineState * pengst = ptman->State(); - - // If we are exactly at the segment boundary, pass the information on to the output stream. - // Note that inserted items always go outside the segment, if they are at the boundary. - bool fSetSegMin = psstrmIn->AtSegMin() && !fInserting; - bool fSetSegLim = psstrmIn->AtSegLim(); - - if (!fInserting) - { - gAssert(!psstrmIn->AtEndOfContext()); - // Absorb next slot - psstrmIn->NextGet(); - } - - GrSlotState * pslotCopyFrom = psstrmIn->RuleInputSlot(cslotCopyFrom, psstrmOut); - - GrSlotState * pslotNew; - pengst->NewSlotCopy(pslotCopyFrom, m_ipass, &pslotNew); - - if (fSetSegMin) - psstrmOut->SetSegMinToWritePos(false); - if (fSetSegLim) - psstrmOut->SetSegLimToWritePos(false); - psstrmOut->NextPut(pslotNew); -} - -/*---------------------------------------------------------------------------------------------- - Copy the current slot from the input to the output, substituting the corresponding glyph - in the output class. All the associations and slot attributes remain unchanged from the - current input slot. - - @param ptman - table manager, for generating new slots - @param fInserting - true if this slot is being inserted, not copied - @param cslotSel - selector slot, relative to current slot - @param nSelectorClass - class of selector slot - @param nReplacementClass - class from which to take replacement glyph (corresponding to - selector slot's glyph's index in selector class) - @param psstrmIn / Out - input/output streams -----------------------------------------------------------------------------------------------*/ -void GrPass::DoPutSubs(GrTableManager * ptman, bool fInserting, - int cslotSel, int nSelClass, int nReplacementClass, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - bool fAtSegMin, fAtSegLim; - GrSlotState * pslotNextInput; - DoPutSubsInit(psstrmIn, psstrmOut, fInserting, &pslotNextInput, &fAtSegMin, &fAtSegLim); - - GrSlotState * pslotInSelector = psstrmIn->RuleInputSlot(cslotSel, psstrmOut); - - gid16 gidSelector = pslotInSelector->GlyphID(); - int nSelIndex = ptman->GetIndexInGlyphClass(nSelClass, gidSelector); - gAssert(nSelIndex != -1); - gid16 gidReplacement = (nSelIndex == -1)? - gidSelector: - ptman->GetClassGlyphIDAt(nReplacementClass, nSelIndex); - - DoPutSubsAux(ptman, fInserting, gidReplacement, psstrmIn, psstrmOut, pslotNextInput, - fAtSegMin, fAtSegLim); -} - -/*---------------------------------------------------------------------------------------------- - Copy the current slot from the input to the output, substituting the corresponding glyph - in the output class based on 2 input classes. All the associations and slot attributes - remain unchanged from the current input slot. - - @param ptman - table manager, for generating new slots - @param fInserting - true if this slot is being inserted, not copied - @param cslotSel - selector slot, relative to current slot - @param nSelectorClass - class of selector slot - @param nReplacementClass - class from which to take replacement glyph (corresponding to - selector slot's glyph's index in selector class) - @param psstrmIn / Out - input/output streams -----------------------------------------------------------------------------------------------*/ -void GrPass::DoPutSubs2(GrTableManager * ptman, bool fInserting, - int cslotSel1, int nSelClass1, int cslotSel2, int nSelClass2, int nReplacementClass, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - bool fAtSegMin, fAtSegLim; - GrSlotState * pslotNextInput; - DoPutSubsInit(psstrmIn, psstrmOut, fInserting, &pslotNextInput, &fAtSegMin, &fAtSegLim); - - GrSlotState * pslotInSelector1 = psstrmIn->RuleInputSlot(cslotSel1, psstrmOut); - gid16 gidSelector1 = pslotInSelector1->GlyphID(); - int nSelIndex1 = ptman->GetIndexInGlyphClass(nSelClass1, gidSelector1); - gAssert(nSelIndex1 != -1); - //size_t cClassLen1 = ptman->NumberOfGlyphsInClass(nSelClass1); - - GrSlotState * pslotInSelector2 = psstrmIn->RuleInputSlot(cslotSel2, psstrmOut); - gid16 gidSelector2 = pslotInSelector2->GlyphID(); - int nSelIndex2 = ptman->GetIndexInGlyphClass(nSelClass2, gidSelector2); - gAssert(nSelIndex2 != -1); - size_t cClassLen2 = ptman->NumberOfGlyphsInClass(nSelClass2); - - int nSelIndex = (nSelIndex1 == -1 || nSelIndex2 == -1) ? - -1 : - (nSelIndex1 * static_cast<int>(cClassLen2)) + nSelIndex2; - - gid16 gidReplacement = (nSelIndex == -1)? - gidSelector1: - ptman->GetClassGlyphIDAt(nReplacementClass, nSelIndex); - - DoPutSubsAux(ptman, fInserting, gidReplacement, psstrmIn, psstrmOut, pslotNextInput, - fAtSegMin, fAtSegLim); -} - -/*---------------------------------------------------------------------------------------------- - Copy the current slot from the input to the output, substituting the corresponding glyph - in the output class based on 2 input classes. All the associations and slot attributes - remain unchanged from the current input slot. - - @param ptman - table manager, for generating new slots - @param fInserting - true if this slot is being inserted, not copied - @param cslotSel - selector slot, relative to current slot - @param nSelectorClass - class of selector slot - @param nReplacementClass - class from which to take replacement glyph (corresponding to - selector slot's glyph's index in selector class) - @param psstrmIn / Out - input/output streams -----------------------------------------------------------------------------------------------*/ -void GrPass::DoPutSubs3(GrTableManager * ptman, bool fInserting, - int cslotSel1, int nSelClass1, int cslotSel2, int nSelClass2, int cslotSel3, int nSelClass3, - int nReplacementClass, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - bool fAtSegMin, fAtSegLim; - GrSlotState * pslotNextInput; - DoPutSubsInit(psstrmIn, psstrmOut, fInserting, &pslotNextInput, &fAtSegMin, &fAtSegLim); - - GrSlotState * pslotInSelector1 = psstrmIn->RuleInputSlot(cslotSel1, psstrmOut); - gid16 gidSelector1 = pslotInSelector1->GlyphID(); - int nSelIndex1 = ptman->GetIndexInGlyphClass(nSelClass1, gidSelector1); - gAssert(nSelIndex1 != -1); - //size_t cClassLen1 = ptman->NumberOfGlyphsInClass(nSelClass1); - - GrSlotState * pslotInSelector2 = psstrmIn->RuleInputSlot(cslotSel2, psstrmOut); - gid16 gidSelector2 = pslotInSelector2->GlyphID(); - int nSelIndex2 = ptman->GetIndexInGlyphClass(nSelClass2, gidSelector2); - gAssert(nSelIndex2 != -1); - size_t cClassLen2 = ptman->NumberOfGlyphsInClass(nSelClass2); - -// GrSlotState * pslotInSelector3 = psstrmIn->RuleInputSlot(cslotSel3, psstrmOut); -// gid16 gidSelector3 = pslotInSelector3->GlyphID(); - int nSelIndex3 = ptman->GetIndexInGlyphClass(nSelClass3, gidSelector2); - gAssert(nSelIndex3 != -1); - size_t cClassLen3 = ptman->NumberOfGlyphsInClass(nSelClass3); - - int nSelIndex = (nSelIndex1 == -1 || nSelIndex2 == -1 || nSelIndex3 == -1) ? - -1 : - (((nSelIndex1 * static_cast<int>(cClassLen2)) + nSelIndex2) * static_cast<int>(cClassLen3)) + nSelIndex3; - - gid16 gidReplacement = (nSelIndex == -1)? - gidSelector1: - ptman->GetClassGlyphIDAt(nReplacementClass, nSelIndex); - - DoPutSubsAux(ptman, fInserting, gidReplacement, psstrmIn, psstrmOut, pslotNextInput, - fAtSegMin, fAtSegLim); -} - - -/*---------------------------------------------------------------------------------------------- - Initial common part of all the DoPutSubs... methods. -----------------------------------------------------------------------------------------------*/ -void GrPass::DoPutSubsInit(GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, bool fInserting, - GrSlotState ** ppslotNextInput, bool * pfAtSegMin, bool * pfAtSegLim) -{ - // Do this before reading from stream. - *pfAtSegMin = psstrmIn->AtSegMin(); - *pfAtSegLim = psstrmIn->AtSegLim(); - - // Slot to copy features and text properties from: - if (psstrmIn->AtEndOfContext()) - { - gAssert(fInserting); - *ppslotNextInput = psstrmIn->RuleInputSlot(0, psstrmOut); - } - else - *ppslotNextInput = (fInserting)? psstrmIn->Peek(): psstrmIn->NextGet(); -} - -/*---------------------------------------------------------------------------------------------- - Common part of all the DoPutSubs... methods. -----------------------------------------------------------------------------------------------*/ -void GrPass::DoPutSubsAux(GrTableManager * ptman, bool fInserting, gid16 nGlyphReplacement, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, GrSlotState * pslotNextInput, - bool fAtSegMin, bool fAtSegLim) -{ - EngineState * pengst = ptman->State(); - - // If we are exactly at the segment boundary, pass the information on to the output stream. - // Note that inserted items always go outside the segment, if they are at the boundary. - bool fSetSegMin = fAtSegMin && !fInserting; - bool fSetSegLim = fAtSegLim; - - GrSlotState * pslotNew; - if (fInserting) - { - pengst->NewSlot(nGlyphReplacement, pslotNextInput, m_ipass, &pslotNew); - // leave associations empty; eventually they will be "neutralized" - } - else - { - pengst->NewSlotCopy(pslotNextInput, m_ipass, &pslotNew); - pslotNew->SetGlyphID(nGlyphReplacement); - ptman->SetSlotAttrsFromGlyphAttrs(pslotNew); - } - - if (fSetSegMin) - psstrmOut->SetSegMinToWritePos(false); - if (fSetSegLim) - psstrmOut->SetSegLimToWritePos(false); - psstrmOut->NextPut(pslotNew); -} - -/*---------------------------------------------------------------------------------------------- - A slot has just been inserted. Clear all the associations; eventually (unless we go on - to set the associations explicitly) we will set its before-assoc to the slot after it - and its after-assoc to the slot before it. This makes it basically unselectable. - OBSOLETE - handled by slot initialization code -----------------------------------------------------------------------------------------------*/ -void GrPass::SetNeutralAssocs(GrSlotState * pslotNew, GrSlotStream * psstrmIn) -{ - pslotNew->ClearAssocs(); -} - -/*---------------------------------------------------------------------------------------------- - Delete the next slot in the input. - - @param psstrmIn - input stream - @param psstrmOut - output stream -----------------------------------------------------------------------------------------------*/ -void GrPass::DoDelete(GrTableManager * ptman, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - if (psstrmIn->AtSegMin()) - psstrmOut->SetSegMinToWritePos(); - if (psstrmIn->AtSegLim()) - psstrmOut->SetSegLimToWritePos(); - - GrSlotState * pslot = psstrmIn->NextGet(); - pslot->MarkDeleted(); - - if (ptman->LoggingTransduction()) - m_pzpst->RecordDeletionBefore(psstrmOut->WritePos()); -} - -/*---------------------------------------------------------------------------------------------- - Set the associations for the current slot. Any previous associations will be overwritten. - - @param cn - number of associations - @param vnAssoc - list of associations - @param fInserting - whether current slot was inserted - @param psstrmIn / Out - input/output streams -----------------------------------------------------------------------------------------------*/ -void GrPass::DoAssoc(int cnAssocs, std::vector<int> & vnAssocs, bool fInserting, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - gAssert((unsigned)cnAssocs == vnAssocs.size()); - - // Sort the list of associations. It's okay to use a simple bubble sort - // since we expect the list to be very short. Ideally we should remove duplicates - // too but I don't think duplicates actually hurt anything. - for (int i1 = 0; i1 < cnAssocs - 1; i1++) - { - for (int i2 = i1 + 1; i2 < cnAssocs; i2++) - { - if (vnAssocs[i2] < vnAssocs[i1]) - { - int nTmp = vnAssocs[i2]; - vnAssocs[i2] = vnAssocs[i1]; - vnAssocs[i1] = nTmp; - } - } - } - - std::vector<GrSlotState *> vpslotAssocs; - vpslotAssocs.resize(cnAssocs); - for (int i = 0; i < cnAssocs; i++) - vpslotAssocs[i] = psstrmIn->RuleInputSlot(vnAssocs[i], psstrmOut); - - GrSlotState * pslot = psstrmOut->RuleOutputSlot(); - pslot->Associate(vpslotAssocs); -} - -/*---------------------------------------------------------------------------------------------- - Set a slot attribute for the current slot; the value is on the stack. - - @param op - command - @param fInserting - whether current slot was inserted - @param slat - slot attribute to set - @param slati - slot attribute index, or -1 for non-indexed attribute - @param vnStack - stack to read value from - @param psstrmIn / Out - input/output streams -----------------------------------------------------------------------------------------------*/ -void GrPass::DoSetAttr(GrTableManager * ptman, ActionCommand op, bool fInserting, - SlotAttrName slat, int slati, std::vector<int> & vnStack, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - int nVal = vnStack.back(); - vnStack.pop_back(); - - if (slat == kslatUserDefnV1) - slat = kslatUserDefn; - - if (slati != -1 && slat != kslatCompRef && slat != kslatUserDefn) - { - // Invalid slot attribute index. - gAssert(false); - slati = -1; - } - - if (slati == -1 && (slat == kslatCompRef || slat == kslatUserDefn)) - { - // Missing slot attribute index. - gAssert(false); - slati = 0; - } - - if (slat == kslatPosX || slat == kslatPosY) - { - // Doesn't make sense to set the pos attribute. - gAssert(false); - return; - } - - GrSlotState * pslotIn = psstrmIn->RuleInputSlot(0, psstrmOut); - - GrSlotState * pslotComp; - - int nOldVal; - - if (op == kopAttrAdd || op == kopAttrSub || op == kopIAttrAdd || op == kopIAttrSub) - { - // Incrementing or decrementing. - - gAssert(!fInserting); - - switch (slat) - { - case kslatAdvX: nOldVal = pslotIn->AdvanceX(ptman); break; - case kslatAdvY: nOldVal = pslotIn->AdvanceY(ptman); break; - case kslatShiftX: nOldVal = pslotIn->ShiftX(); break; - case kslatShiftY: nOldVal = pslotIn->ShiftY(); break; - - case kslatAttAtX: nOldVal = pslotIn->AttachAtX(ptman, psstrmIn); break; - case kslatAttAtY: nOldVal = pslotIn->AttachAtY(); break; - case kslatAttAtXoff: nOldVal = pslotIn->AttachAtXOffset(); break; - case kslatAttAtYoff: nOldVal = pslotIn->AttachAtYOffset(); break; - - case kslatAttWithX: nOldVal = pslotIn->AttachWithX(ptman, psstrmIn); break; - case kslatAttWithY: nOldVal = pslotIn->AttachWithY(); break; - case kslatAttWithXoff: nOldVal = pslotIn->AttachWithXOffset(); break; - case kslatAttWithYoff: nOldVal = pslotIn->AttachWithYOffset(); break; - - case kslatUserDefn: nOldVal = pslotIn->UserDefn(slati); break; - - case kslatMeasureSol: nOldVal = pslotIn->MeasureSol(); break; - case kslatMeasureEol: nOldVal = pslotIn->MeasureEol(); break; - - case kslatJStretch: nOldVal = pslotIn->JStretch(); break; - case kslatJShrink: nOldVal = pslotIn->JShrink(); break; - case kslatJStep: nOldVal = pslotIn->JStep(); break; - case kslatJWeight: nOldVal = pslotIn->JWeight(); break; - case kslatJWidth: nOldVal = pslotIn->JWidth(); break; - - // These are kind of odd, but maybe. - case kslatAttLevel: nOldVal = pslotIn->AttachLevel(); break; - case kslatBreak: nOldVal = pslotIn->BreakWeight(); break; - case kslatDir: nOldVal = pslotIn->Directionality(); break; - - default: - // Kind of attribute that it makes no sense to increment. - gAssert(false); - return; - } - - if (op == kopAttrAdd || op == kopIAttrAdd) - nVal = nOldVal + nVal; - else - { - gAssert(op == kopAttrSub || op == kopIAttrSub); - nVal = nOldVal - nVal; - } - } - - GrSlotState * pslotOut = psstrmOut->RuleOutputSlot(); - - if (pslotOut->IsLineBreak(ptman->LBGlyphID())) - { - switch (slat) - { - case kslatAdvX: - case kslatAdvY: - case kslatShiftX: - case kslatShiftY: - - case kslatAttTo: - case kslatAttLevel: - case kslatAttAtX: - case kslatAttAtY: - case kslatAttAtGpt: - case kslatAttAtXoff: - case kslatAttAtYoff: - case kslatAttWithX: - case kslatAttWithY: - case kslatAttWithGpt: - case kslatAttWithXoff: - case kslatAttWithYoff: - - case kslatMeasureSol: - case kslatMeasureEol: - - case kslatJStretch: - case kslatJShrink: - case kslatJStep: - case kslatJWeight: - case kslatJWidth: - slat = kslatNoEffect; - break; - default: - ; // okay, do nothing - } - } - - nVal = GrGlyphSubTable::ConvertValueForVersion(nVal, slat, -1, m_fxdVersion); - - switch (slat) - { - case kslatAdvX: pslotOut->SetAdvanceX(nVal); break; - case kslatAdvY: pslotOut->SetAdvanceY(nVal); break; - case kslatShiftX: pslotOut->SetShiftX(nVal); break; - case kslatShiftY: pslotOut->SetShiftY(nVal); break; - - case kslatAttTo: pslotOut->SetAttachTo(nVal); break; - case kslatAttLevel: pslotOut->SetAttachLevel(nVal); break; - case kslatAttAtX: pslotOut->SetAttachAtX(nVal); break; - case kslatAttAtY: pslotOut->SetAttachAtY(nVal); break; - case kslatAttAtGpt: pslotOut->SetAttachAtGpoint(nVal); break; - case kslatAttAtXoff: pslotOut->SetAttachAtXOffset(nVal); break; - case kslatAttAtYoff: pslotOut->SetAttachAtYOffset(nVal); break; - case kslatAttWithX: pslotOut->SetAttachWithX(nVal); break; - case kslatAttWithY: pslotOut->SetAttachWithY(nVal); break; - case kslatAttWithGpt: pslotOut->SetAttachWithGpoint(nVal); break; - case kslatAttWithXoff: pslotOut->SetAttachWithXOffset(nVal); break; - case kslatAttWithYoff: pslotOut->SetAttachWithYOffset(nVal); break; - - case kslatUserDefn: pslotOut->SetUserDefn(slati, nVal); break; - - case kslatCompRef: - gAssert(nVal - 1 >= psstrmIn->RuleStartReadPos() - psstrmIn->ReadPosForNextGet()); - pslotComp = psstrmIn->RuleInputSlot(nVal, psstrmOut); - pslotOut->SetCompRefSlot(ptman, slati, pslotComp); - break; - - case kslatMeasureSol: pslotOut->SetMeasureSol(nVal); break; - case kslatMeasureEol: pslotOut->SetMeasureEol(nVal); break; - - case kslatJStretch: pslotOut->SetJStretch(nVal); break; - case kslatJShrink: pslotOut->SetJShrink(nVal); break; - case kslatJStep: pslotOut->SetJStep(nVal); break; - case kslatJWeight: pslotOut->SetJWeight(nVal); break; - case kslatJWidth: pslotOut->SetJWidth(nVal); break; - - case kslatBreak: pslotOut->SetBreakWeight(nVal); break; - case kslatDir: pslotOut->SetDirectionality(DirCode(nVal)); break; - case kslatInsert: pslotOut->SetInsertBefore(bool(nVal)); break; - - case kslatNoEffect: - // Do nothing. - break; - - default: - // Kind of attribute that it makes no sense to set. - gAssert(false); - return; - } -} - -/*---------------------------------------------------------------------------------------------- - Push value of a slot attribute onto the stack. - - @param nSlotRef - slot whose attribute we are interested in - @param fInserting - whether current slot was inserted - @param slat - slot attribute to get - @param slati - slot attribute index, or -1 for non-indexed attribute - @param vnStack - stack to push onto - @param psstrmIn - input stream -----------------------------------------------------------------------------------------------*/ -void GrPass::DoPushSlotAttr(GrTableManager * ptman, - int nSlotRef, bool fInserting, - SlotAttrName slat, int slati, std::vector<int> & vnStack, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - GrSlotState * pslot = psstrmIn->RuleInputSlot(nSlotRef, psstrmOut, true); - if (pslot == NULL) - { - // Non-existent pre-context item. - vnStack.push_back(0); - return; - } - - int nVal; - int xyBogus; - - if (slat == kslatUserDefnV1) - slat = kslatUserDefn; - - if (slati != -1 && slat != kslatCompRef && slat != kslatUserDefn) - { - // Invalid slot attribute index. - gAssert(false); - slati = -1; - } - - if (slati == -1 && (slat == kslatCompRef || slat == kslatUserDefn)) - { - // Missing slot attribute index. - gAssert(false); - slati = 0; - } - - switch (slat) - { - case kslatAdvX: nVal = pslot->AdvanceX(ptman); break; - case kslatAdvY: nVal = pslot->AdvanceY(ptman); break; - case kslatShiftX: nVal = pslot->ShiftX(); break; - case kslatShiftY: nVal = pslot->ShiftY(); break; - - case kslatPosX: pslot->Position(ptman, psstrmIn, &nVal, &xyBogus); break; - case kslatPosY: pslot->Position(ptman, psstrmIn, &xyBogus, &nVal); break; - - case kslatAttTo: nVal = pslot->AttachTo(); break; - case kslatAttLevel: nVal = pslot->AttachLevel(); break; - case kslatAttAtX: nVal = pslot->AttachAtX(ptman, psstrmIn); break; - case kslatAttAtY: nVal = pslot->AttachAtY(); break; - case kslatAttAtGpt: nVal = pslot->AttachAtGpoint(); break; - case kslatAttAtXoff: nVal = pslot->AttachAtXOffset(); break; - case kslatAttAtYoff: nVal = pslot->AttachAtYOffset(); break; - case kslatAttWithX: nVal = pslot->AttachWithX(ptman, psstrmIn); break; - case kslatAttWithY: nVal = pslot->AttachWithY(); break; - case kslatAttWithGpt: nVal = pslot->AttachWithGpoint(); break; - case kslatAttWithXoff: nVal = pslot->AttachWithXOffset(); break; - case kslatAttWithYoff: nVal = pslot->AttachWithYOffset(); break; - - case kslatMeasureSol: nVal = pslot->MeasureSol(); break; - case kslatMeasureEol: nVal = pslot->MeasureEol(); break; - - case kslatJStretch: nVal = pslot->JStretch(); break; - case kslatJShrink: nVal = pslot->JShrink(); break; - case kslatJStep: nVal = pslot->JStep(); break; - case kslatJWeight: nVal = pslot->JWeight(); break; - case kslatJWidth: nVal = pslot->JWidth(); break; - - case kslatBreak: nVal = pslot->BreakWeight(); break; - case kslatDir: nVal = pslot->Directionality(); break; - case kslatInsert: nVal = pslot->InsertBefore(); break; - - case kslatUserDefn: nVal = pslot->UserDefn(slati); break; - - // Currently no way to look up component.X.ref. - - default: - // Invalid attribute. - gAssert(false); - nVal = 0; - } - - vnStack.push_back(nVal); -} - -/*---------------------------------------------------------------------------------------------- - Push value of a glyph attribute onto the stack. - - @param nSlotRef - slot whose attribute we are interested in - @param fInserting - whether current slot was inserted - @param nGlyphAttr - glyph attribute to get - @param vnStack - stack to push onto - @param psstrmIn - input stream -----------------------------------------------------------------------------------------------*/ -void GrPass::DoPushGlyphAttr(GrTableManager * ptman, int nSlotRef, bool fInserting, - int nGlyphAttr, - std::vector<int> & vnStack, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - GrSlotState * pslot = psstrmIn->RuleInputSlot(nSlotRef, psstrmOut, true); - if (pslot == NULL) - { - // Non-existent pre-context item. - vnStack.push_back(0); - return; - } - int nVal = pslot->GlyphAttrValueEmUnits(ptman, nGlyphAttr); - vnStack.push_back(nVal); -} - -/*---------------------------------------------------------------------------------------------- - Push value of a glyph attribute onto the stack. The slot of interest is the slot to - which the current slot is attached. - - @param nSlotRef - leaf slot - @param fInserting - whether current slot was inserted - @param nGlyphAttr - glyph attribute to get - @param vnStack - stack to push onto - @param psstrmIn - input stream -----------------------------------------------------------------------------------------------*/ -void GrPass::DoPushAttToGlyphAttr(GrTableManager * ptman, int nSlotRef, bool fInserting, - int nGlyphAttr, std::vector<int> & vnStack, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - // Note that it is the slot in the output stream that has - // the relevant attach.to attribute set. - GrSlotState * pslotLeaf = psstrmOut->RuleOutputSlot(0); - int srAttTo = pslotLeaf->AttachTo(); - if (srAttTo == 0) - { - gAssert(false); - vnStack.push_back(0); - return; - } - - GrSlotState * pslotRoot = psstrmIn->RuleInputSlot(nSlotRef + srAttTo, psstrmOut); - int nVal = pslotRoot->GlyphAttrValueEmUnits(ptman, nGlyphAttr); - vnStack.push_back(nVal); -} - -/*---------------------------------------------------------------------------------------------- - Push value of a glyph metric onto the stack. - - @param nSlotRef - slot whose attribute we are interested in - @param fInserting - whether current slot was inserted - @param nGlyphAttr - glyph attribute to get - @param nAttLevel - for accessing composite metrics - @param vnStack - stack to push onto - @param psstrmIn - input stream -----------------------------------------------------------------------------------------------*/ -void GrPass::DoPushGlyphMetric(GrTableManager * ptman, int nSlotRef, bool fInserting, - int nGlyphAttr, int nAttLevel, - std::vector<int> & vnStack, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - GrSlotState * pslot = psstrmIn->RuleInputSlot(nSlotRef, psstrmOut, true); - if (pslot == NULL) - { - // Non-existent pre-context item. - vnStack.push_back(0); - return; - } - - DoPushGlyphMetricAux(ptman, pslot, nGlyphAttr, nAttLevel, vnStack, psstrmIn); -} - -/*---------------------------------------------------------------------------------------------- - Push value of a glyph metric onto the stack. The slot of interest is the slot to - which the current slot is attached. - - @param nSlotRef - slot whose attribute we are interested in - @param fInserting - whether current slot was inserted - @param nGlyphAttr - glyph attribute to get - @param nAttLevel - for accessing composite metrics - @param vnStack - stack to push onto - @param psstrmIn - input stream - @param psstrmOut - output stream -----------------------------------------------------------------------------------------------*/ -void GrPass::DoPushAttToGlyphMetric(GrTableManager * ptman, int nSlotRef, bool fInserting, - int nGlyphAttr, int nAttLevel, - std::vector<int> & vnStack, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - // Note that it is the slot in the output stream that has - // the relevant attach.to attribute set. - GrSlotState * pslotLeaf = psstrmOut->RuleOutputSlot(0); - int srAttTo = pslotLeaf->AttachTo(); - if (srAttTo == 0) - { - gAssert(false); - vnStack.push_back(0); - return; - } - - GrSlotState * pslot = psstrmIn->RuleInputSlot(nSlotRef + srAttTo, psstrmOut); - - DoPushGlyphMetricAux(ptman, pslot, nGlyphAttr, nAttLevel, vnStack, psstrmIn); -} - -/*--------------------------------------------------------------------------------------------*/ - -void GrPass::DoPushGlyphMetricAux(GrTableManager * ptman, - GrSlotState * pslot, int nGlyphAttr, int nAttLevel, - std::vector<int> & vnStack, GrSlotStream * psstrmIn) -{ - int mVal; - GlyphMetric gmet = GlyphMetric(nGlyphAttr); - if (nAttLevel == 0 || gmet == kgmetAscent || gmet == kgmetDescent) - { - mVal = pslot->GlyphMetricEmUnits(ptman, nGlyphAttr); - } - else - { - pslot->CalcCompositeMetrics(ptman, psstrmIn, nAttLevel, true); - - float xy; - switch (gmet) - { - case kgmetLsb: xy = pslot->ClusterLsb(psstrmIn); break; - case kgmetRsb: xy = pslot->ClusterRsb(psstrmIn); break; - case kgmetBbTop: xy = pslot->ClusterBbTop(psstrmIn); break; - case kgmetBbBottom: xy = pslot->ClusterBbBottom(psstrmIn); break; - case kgmetBbLeft: xy = pslot->ClusterBbLeft(psstrmIn); break; - case kgmetBbRight: xy = pslot->ClusterBbRight(psstrmIn); break; - case kgmetBbHeight: xy = pslot->ClusterBbHeight(psstrmIn); break; - case kgmetBbWidth: xy = pslot->ClusterBbWidth(psstrmIn); break; -// case kgmetAdvHeight: xy = pslot->ClusterAdvHeight(psstrmIn); break; - case kgmetAdvWidth: xy = pslot->ClusterAdvWidth(psstrmIn); break; - default: - gAssert(false); - xy = 0; - } - mVal = ptman->LogToEmUnits(xy); - } - - vnStack.push_back(mVal); -} - -/*---------------------------------------------------------------------------------------------- - Push a feature value onto the stack. For rule actions, the slot of interest is the - current slot. - - @param nSlotRef - slot being examined - @param fInserting - whether current slot was inserted - @param nFeat - feature of interest - @param vnStack - stack to push onto - @param psstrmIn - input stream - @param psstrmOut - output stream -----------------------------------------------------------------------------------------------*/ -void GrPass::DoPushFeatValue(GrTableManager * ptman, int nSlotRef, bool fInserting, - int nFeat, std::vector<int> & vnStack, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut) -{ - gAssert(!fInserting); - - GrSlotState * pslot = psstrmIn->RuleInputSlot(nSlotRef, psstrmOut, true); - if (pslot == NULL) - { - // Non-existent pre-context item. - vnStack.push_back(0); - return; - } - - int nVal = pslot->FeatureValue(nFeat); - vnStack.push_back(nVal); -} - -/*---------------------------------------------------------------------------------------------- - Push a processing-state value onto the stack. - - @param nFeat - feature of interest - @param vnStack - stack to push onto -----------------------------------------------------------------------------------------------*/ -void GrPass::DoPushProcState(GrTableManager * ptman, int nPState, std::vector<int> & vnStack) -{ - int nValue; - if (nPState == kpstatJustifyMode) - { - // Convert from internal modes to user modes. - int jmodi = ptman->InternalJustificationMode(); - switch (jmodi) - { - case kjmodiNormal: - case kjmodiCanShrink: - nValue = kjmoduNormal; - break; - case kjmodiMeasure: - nValue = kjmoduMeasure; - break; - case kjmodiJustify: - nValue = kjmoduJustify; - break; - default: - gAssert(false); - nValue = kjmoduNormal; - } - } - else if (nPState == kpstatJustifyLevel) - nValue = 1; // TODO: get justify level from ptman - vnStack.push_back(nValue); -} - -} // namespace gr diff --git a/Build/source/libs/graphite-engine/src/segment/GrPseudoMap.h b/Build/source/libs/graphite-engine/src/segment/GrPseudoMap.h deleted file mode 100644 index c6fec210808..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrPseudoMap.h +++ /dev/null @@ -1,48 +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: GrPseudoMap.h -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - The GrPseudoMap class. -----------------------------------------------------------------------------------------------*/ -#ifdef _MSC_VER -#pragma once -#endif -#ifndef GR_PSEUDOMAP_INCLUDED -#define GR_PSEUDOMAP_INCLUDED - -//:End Ignore - -namespace gr -{ - -/*---------------------------------------------------------------------------------------------- - A mapping between a Unicode value and a pseudo-glyph. - - Hungarian: psd -----------------------------------------------------------------------------------------------*/ - -class GrPseudoMap -{ -public: - unsigned int Unicode() { return m_nUnicode; } - gid16 PseudoGlyph() { return m_chwPseudo; } - - void SetUnicode(int n) { m_nUnicode = n; } - void SetPseudoGlyph(gid16 chw) { m_chwPseudo = chw; } - -protected: - // Instance variables: - unsigned int m_nUnicode; - gid16 m_chwPseudo; -}; - -} // namespace gr - -#endif // !GR_PSEUDOMAP_INCLUDED diff --git a/Build/source/libs/graphite-engine/src/segment/GrSlotState.cpp b/Build/source/libs/graphite-engine/src/segment/GrSlotState.cpp deleted file mode 100644 index f2d61e45eed..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrSlotState.cpp +++ /dev/null @@ -1,1481 +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: GrSlotState.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - GrSlotState class implementation. --------------------------------------------------------------------------------*//*:End Ignore*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" - -#ifdef _MSC_VER -#pragma hdrstop -#endif -#undef THIS_FILE -DEFINE_THIS_FILE - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -namespace gr -{ - -//:>******************************************************************************************** -//:> Methods -//:>******************************************************************************************** - -/*---------------------------------------------------------------------------------------------- - Initialize slots. -----------------------------------------------------------------------------------------------*/ -// standard for pass 0 slots -void GrSlotState::Initialize(gid16 chw, GrEngine * pgreng, - GrFeatureValues fval, int ipass, int ichwSegOffset, int nUnicode) -{ - Assert(ipass == 0); - m_chwGlyphID = chw; - m_chwActual = kInvalidGlyph; - m_xysGlyphWidth = -1; - m_bStyleIndex = byte(fval.m_nStyleIndex); - u_intslot nullSlot; - nullSlot.pslot = NULL; - std::fill_n(PUserDefnBuf(), m_cnUserDefn, nullSlot); - std::fill_n(PCompRefBuf(), m_cnCompPerLig, nullSlot); - std::fill_n(PSlatiBuf(), m_cnCompPerLig, nullSlot); - u_intslot * pFeatBuf = PFeatureBuf(); - for (size_t i = 0; i < m_cnFeat; i++) - pFeatBuf[i].nValue = fval.m_rgnFValues[i]; - m_ipassFsmCol = -1; - m_colFsm = -1; - - m_ipassModified = ipass; - m_ichwSegOffset = ichwSegOffset; - m_nUnicode = nUnicode; - m_vpslotAssoc.clear(); - pgreng->InitSlot(this, nUnicode); - - switch (nUnicode) - { - case knLRM: m_spsl = kspslLRM; break; - case knRLM: m_spsl = kspslRLM; break; - case knLRO: m_spsl = kspslLRO; break; - case knRLO: m_spsl = kspslRLO; break; - case knLRE: m_spsl = kspslLRE; break; - case knRLE: m_spsl = kspslRLE; break; - case knPDF: m_spsl = kspslPDF; break; - default: - Assert(m_spsl == kspslNone); - m_spsl = kspslNone; - break; - } -} - -// line-break slots -void GrSlotState::Initialize(gid16 chw, GrEngine * pgreng, - GrSlotState * pslotFeat, int ipass, int ichwSegOffset) -{ - m_chwGlyphID = chw; - m_chwActual = kInvalidGlyph; - m_xysGlyphWidth = -1; - u_intslot nullSlot; - nullSlot.pslot = NULL; - std::fill_n(PUserDefnBuf(), m_cnUserDefn, nullSlot); - std::fill_n(PCompRefBuf(), m_cnCompPerLig, nullSlot); - std::fill_n(PSlatiBuf(), m_cnCompPerLig, nullSlot); - CopyFeaturesFrom(pslotFeat); - m_ipassModified = ipass; - m_ichwSegOffset = ichwSegOffset; - m_nUnicode = -1; - m_vpslotAssoc.clear(); - pgreng->InitSlot(this); - // Caller is responsible for setting m_spsl. - m_ipassFsmCol = -1; - m_colFsm = -1; -} - -// for inserting new slots after pass 0 (under-pos and unicode are irrelevant) -void GrSlotState::Initialize(gid16 chw, GrEngine * pgreng, - GrSlotState * pslotFeat, int ipass) -{ - m_chwGlyphID = chw; - m_chwActual = kInvalidGlyph; - m_xysGlyphWidth = -1; - u_intslot nullSlot; - nullSlot.pslot = NULL; - std::fill_n(PUserDefnBuf(), m_cnUserDefn, nullSlot); - std::fill_n(PCompRefBuf(), m_cnCompPerLig, nullSlot); - std::fill_n(PSlatiBuf(), m_cnCompPerLig, nullSlot); - CopyFeaturesFrom(pslotFeat); - m_ipassModified = ipass; - m_ichwSegOffset = kInvalid; - m_nUnicode = kInvalid; - m_vpslotAssoc.clear(); - pgreng->InitSlot(this); - m_spsl = kspslNone; - m_ipassFsmCol = -1; - m_colFsm = -1; -} - -/*---------------------------------------------------------------------------------------------- - The slot has been modified by the given pass and therefore is in a new state; - make a new SlotState initialized from the old one. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::InitializeFrom(GrSlotState * pslotOld, int ipass) -{ - CopyFrom(pslotOld, false); - - m_ipassModified = ipass; - m_pslotPrevState = pslotOld; - m_ichwSegOffset = kInvalid; - m_vpslotAssoc.clear(); - m_vpslotAssoc.push_back(pslotOld); - - m_dircProc = pslotOld->m_dircProc; - m_fDirProcessed = pslotOld->m_fDirProcessed; - - // Since we're going on to a new pass, no point in copying these: - m_ipassFsmCol = -1; - m_colFsm = -1; - - ////FixAttachmentTree(pslotOld); -} - -/*---------------------------------------------------------------------------------------------- - Copy the features and style information from the given slot. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::CopyFeaturesFrom(GrSlotState * pslotSrc) -{ - m_bStyleIndex = pslotSrc->m_bStyleIndex; - Assert(m_cnFeat == pslotSrc->m_cnFeat); - std::copy(pslotSrc->PFeatureBuf(), pslotSrc->PFeatureBuf() + m_cnFeat, PFeatureBuf()); -} - -/*---------------------------------------------------------------------------------------------- - Copy the basic information. - Warning: the functions below will break if GrSlotState and subclasses are given virtual - methods. In that case, we will need to copy from the address of the first variable in - GrSlotAbstract. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::CopyFrom(GrSlotState * pslot, bool fCopyEverything) -{ - GrSlotAbstract::CopyAbstractFrom(pslot); - std::copy(pslot->m_prgnVarLenBuf, pslot->m_prgnVarLenBuf + CExtraSpace(), m_prgnVarLenBuf); - - if (fCopyEverything) - { - Assert(false); - m_ipassModified = pslot->m_ipassModified; - m_pslotPrevState = pslot->m_pslotPrevState; - m_ichwSegOffset = pslot->m_ichwSegOffset; - m_colFsm = pslot->m_colFsm; - m_ipassFsmCol = pslot->m_ipassFsmCol; - // TODO: copy m_vpslotAssocs. - m_fNeutralAssocs = pslot->m_fNeutralAssocs; - } - - m_dislotRootFixed = pslot->m_dislotRootFixed; - - m_vdislotAttLeaves.resize(pslot->m_vdislotAttLeaves.size()); - for (size_t i = 0; i < pslot->m_vdislotAttLeaves.size(); i++) - m_vdislotAttLeaves[i] = pslot->m_vdislotAttLeaves[i]; - - m_islotPosPass = pslot->m_islotPosPass; - m_nUnicode = pslot->m_nUnicode; - m_dircProc = pslot->m_dircProc; - m_fDirProcessed = pslot->m_fDirProcessed; - m_cnUserDefn = pslot->m_cnUserDefn; - m_cnFeat = pslot->m_cnFeat; - m_bStyleIndex = pslot->m_bStyleIndex; - m_mAdvanceX = pslot->m_mAdvanceX; - m_mAdvanceY = pslot->m_mAdvanceY; - m_mShiftX = pslot->m_mShiftX; - m_mShiftY = pslot->m_mShiftY; - m_srAttachTo = pslot->m_srAttachTo; - m_nAttachLevel = pslot->m_nAttachLevel; - m_mAttachAtX = pslot->m_mAttachAtX; - m_mAttachAtY = pslot->m_mAttachAtY; - m_mAttachAtXOffset = pslot->m_mAttachAtXOffset; - m_mAttachAtYOffset = pslot->m_mAttachAtYOffset; - m_mAttachWithX = pslot->m_mAttachWithX; - m_mAttachWithY = pslot->m_mAttachWithY; - m_mAttachWithXOffset = pslot->m_mAttachWithXOffset; - m_mAttachWithYOffset = pslot->m_mAttachWithYOffset; - m_nAttachAtGpoint = pslot->m_nAttachAtGpoint; - m_nAttachWithGpoint = pslot->m_nAttachWithGpoint; - m_fAttachMod = pslot->m_fAttachMod; - m_fShiftMod = pslot->m_fShiftMod; - m_fIgnoreAdvance = pslot->m_fIgnoreAdvance; - - m_nCompositeLevel = kNegInfinity; // uncalculated, so don't need to copy the positions?? -} - -void GrSlotAbstract::CopyAbstractFrom(GrSlotState * pslot) -{ - u_intslot * pnBufSave = m_prgnVarLenBuf; - *this = *pslot; - m_prgnVarLenBuf = pnBufSave; - Assert(m_prgnVarLenBuf); -} - -/*---------------------------------------------------------------------------------------------- - Initialize the output slot from the one use within the passes, with the basic information. - Warning: this function will break if GrSlotState and subclasses are given virtual - methods. In that case, we will need to copy from the address of the first variable in - GrSlotAbstract. -----------------------------------------------------------------------------------------------*/ -void GrSlotOutput::InitializeOutputFrom(GrSlotState * pslot) -{ - CopyAbstractFrom(pslot); - - // Copy just the component information, which is of length (m_cnCompPerLig * 2) - //std::copy(pslot->PCompRefBuf(), - // pslot->PCompRefBuf() + (m_cnCompPerLig * 2), - // this->PCompRefBufSlout()); -} - -/*---------------------------------------------------------------------------------------------- - Return the ID of the actual glyph that will be used for output and metrics. This is the - same for most glyphs, but will be different for pseudo-glyphs. -----------------------------------------------------------------------------------------------*/ -gid16 GrSlotAbstract::ActualGlyphForOutput(GrTableManager * ptman) -{ - if (m_chwActual == kInvalidGlyph) - m_chwActual = ptman->ActualGlyphForOutput(m_chwGlyphID); - return m_chwActual; -} -/*---------------------------------------------------------------------------------------------- - We are replacing the old slot with the recipient. Replace the pointers in any attachment - root or attached leaf slots. - OBSOLETE -----------------------------------------------------------------------------------------------*/ -void GrSlotState::FixAttachmentTree(GrSlotState * pslotOld) -{ -#if 0 - pslotOld->m_vpslotAttLeaves.CopyTo(m_vpslotAttLeaves); - for (int islot = 0; islot < m_vpslotAttLeaves.Size(); islot++) - { - Assert(m_vpslotAttLeaves[islot]->m_pslotAttRoot == pslotOld); - m_vpslotAttLeaves[islot]->m_pslotAttRoot = this; - } - - m_pslotAttRoot = pslotOld->m_pslotAttRoot; - if (m_pslotAttRoot) - { - for (int islot = 0; islot < m_pslotAttRoot->m_vpslotAttLeaves.Size(); islot++) - { - if (m_pslotAttRoot->m_vpslotAttLeaves[islot] == pslotOld) - { - m_pslotAttRoot->m_vpslotAttLeaves.Delete(islot); - m_pslotAttRoot->m_vpslotAttLeaves.Push(this); - return; - } - } - Assert(false); // didn't find old slot in the list - } -#endif // 0 -} - -/*---------------------------------------------------------------------------------------------- - Make sure all the values are cached that are needed to be copied to the output slots -----------------------------------------------------------------------------------------------*/ -void GrSlotState::EnsureCacheForOutput(GrTableManager * ptman) -{ - // Make sure the actual glyph ID is set. - gid16 gidActual = ActualGlyphForOutput(ptman); - - // Make sure the glyph metrics are stored. - Font * pfont = ptman->State()->GetFont(); - if (IsLineBreak(ptman->LBGlyphID())) - { - GetGlyphMetric(pfont, kgmetAscent, 0); - GetGlyphMetric(pfont, kgmetDescent, 0); - m_xysGlyphX = 0; - m_xysGlyphY = 0; - m_xysGlyphHeight = 0; - m_xysGlyphWidth = 0; - m_xysAdvX = 0; - m_xysAdvY = 0; - m_bIsSpace = true; - } - else - { - //IsSpace(ptman); // cache this flag--doing bb-top below will do it - - GetGlyphMetric(pfont, kgmetAscent, gidActual); - GetGlyphMetric(pfont, kgmetDescent, gidActual); - GetGlyphMetric(pfont, kgmetBbTop, gidActual); - // call above will also cache all the values below - //GetGlyphMetric(pfont, kgmetBbBottom, gidActual); - //GetGlyphMetric(pfont, kgmetBbLeft, gidActual); - //GetGlyphMetric(pfont, kgmetBbRight, gidActual); - //GetGlyphMetric(pfont, kgmetAdvWidth, gidActual); - //GetGlyphMetric(pfont, kgmetAdvHeight, gidActual); - } -} - -/*---------------------------------------------------------------------------------------------- - Set the associations for the slot. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::Associate(GrSlotState * pslot) -{ - m_vpslotAssoc.clear(); - m_vpslotAssoc.push_back(pslot); -} - -void GrSlotState::Associate(GrSlotState * pslotBefore, GrSlotState * pslotAfter) -{ - m_vpslotAssoc.clear(); - m_vpslotAssoc.push_back(pslotBefore); - m_vpslotAssoc.push_back(pslotAfter); -} - -void GrSlotState::Associate(std::vector<GrSlotState*> & vpslot) -{ - m_vpslotAssoc.clear(); - ///vpslot.CopyTo(m_vpslotAssoc); -- bug in CopyTo, so we do it ourselves: - for (size_t islot = 0; islot < vpslot.size(); ++islot) - { - m_vpslotAssoc.push_back(vpslot[islot]); - } - - // Set its character styles and features from the associated slot. - if (vpslot.size() > 0) // && !m_pslotPrevState - { - std::copy(m_vpslotAssoc[0]->PFeatureBuf(), - m_vpslotAssoc[0]->PFeatureBuf() + m_cnFeat, PFeatureBuf()); - } -} - -/*---------------------------------------------------------------------------------------------- - Clear the associations for the slot. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::ClearAssocs() -{ - m_vpslotAssoc.clear(); -} - -/*---------------------------------------------------------------------------------------------- - Return a list of (ie, add into the vector) all the underlying associations, relative - to the official beginning of the segment. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::AllAssocs(std::vector<int> & vichw) -{ - if (PassModified() == 0) - { - Assert(m_ichwSegOffset != kInvalid); - vichw.push_back(m_ichwSegOffset); - } - else - { - for (size_t i = 0; i < m_vpslotAssoc.size(); ++i) - m_vpslotAssoc[i]->AllAssocs(vichw); - } -} - -/*---------------------------------------------------------------------------------------------- - Return the underlying position of the before-association, relative to the official - beginning of the segment. May be -1, if this slot maps to a character in the previous - segment, or >= the length of the segment, if it maps to a character in the following - segment. -----------------------------------------------------------------------------------------------*/ -int GrSlotState::BeforeAssoc() -{ - GrSlotState * pslot = this; - while (pslot->PassModified() > 0) - { - pslot = pslot->RawBeforeAssocSlot(); - if (pslot == NULL) - { - return kPosInfinity; - } - } - Assert(pslot->m_ichwSegOffset != kInvalid); - return pslot->m_ichwSegOffset; -} - -/*---------------------------------------------------------------------------------------------- - Return the underlying position of the after-association, relative to the official - beginning of the segment. May be -1, if this slot maps to a character in the previous - segment, or >= the length of the segment, if it maps to a character in the following - segment. -----------------------------------------------------------------------------------------------*/ -int GrSlotState::AfterAssoc() -{ - GrSlotState * pslot = this; - while (pslot->PassModified() > 0) - { - pslot = pslot->RawAfterAssocSlot(); - if (pslot == NULL) - { - return kNegInfinity; - } - } - Assert(pslot->m_ichwSegOffset != kInvalid); - return pslot->m_ichwSegOffset; -} - -/*---------------------------------------------------------------------------------------------- - It is possible to get into a state where we are associated with an invalid state. - For instance, slot C may be associated with slots B1 and B2, but slot B1 is not associated - with any earlier slot, in which case slot C should remove the association with B1 and just - be associated with B2. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::CleanUpAssocs() -{ - for (size_t i = 0; i < m_vpslotAssoc.size(); i++) - m_vpslotAssoc[i]->CleanUpAssocs(); - - GrSlotState * pslot; - - pslot = RawBeforeAssocSlot(); - while (pslot && BeforeAssoc() == kPosInfinity) - { - // The before association is bogus--delete it. - m_vpslotAssoc.erase(m_vpslotAssoc.begin()); - pslot = RawBeforeAssocSlot(); - } - - pslot = RawAfterAssocSlot(); - while (pslot && AfterAssoc() == kNegInfinity) - { - // The after association is bogus--delete it. - m_vpslotAssoc.pop_back(); - pslot = RawAfterAssocSlot(); - } -} - -/*---------------------------------------------------------------------------------------------- - Fill in the array of the given output slot with the underlying positions of the - ligature components, relative to the official beginning of the segment. - Positions may be < 0, if this slot maps to a character in the previous segment, - or >= the length of the segment, if it maps to a character in the following segment. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::SetComponentRefsFor(GrSlotOutput * pslout, int slatiArg) -{ - if (PassModified() > 0) - { - GrSlotState * pslot; - int slati; - if (HasComponents()) - { - for (int iComponent = 0; iComponent < m_cnCompPerLig; iComponent++) - { - pslot = CompRefSlot(iComponent); - slati = Slati(iComponent); - if (pslot) - { - Assert(slati != -1); - Assert(PassModified() >= pslot->PassModified()); - pslot->SetComponentRefsFor(pslout, slati); - } - } - } - else - { - // Follow the chain back through the passes. - pslot = RawBeforeAssocSlot(); - if (pslot) - { - Assert(PassModified() >= pslot->PassModified()); - // Passing slati here is definitely needed for our Arabic font: for instance when - // you type something like "mla", so the l is transformed into a temporary glyph - // before creating the ligature. However, this seems to have broken something, - // which I will probably find eventually. :-( - pslot->SetComponentRefsFor(pslout, slatiArg); - //pslot->SetComponentRefsFor(pslout, -1); - } - } - } - else - { - Assert(m_ichwSegOffset != kInvalid); - pslout->AddComponentReference(m_ichwSegOffset, slatiArg); - } -} - -/*---------------------------------------------------------------------------------------------- - Fill in the vector with the underlying positions of the - ligature components, relative to the official beginning of the segment. - Positions may be < 0, if this slot maps to a character in the previous segment, - or >= the length of the segment, if it maps to a character in the following segment. - ENHANCE: merge with method above. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::AllComponentRefs(std::vector<int> & vichw) -{ - if (PassModified() > 0) - { - GrSlotState * pslot; - if (HasComponents()) - { - for (int iComponent = 0; iComponent < m_cnCompPerLig; iComponent++) - { - pslot = CompRefSlot(iComponent); - if (pslot) - { - Assert(PassModified() >= pslot->PassModified()); - pslot->AllComponentRefs(vichw); - } - } - } - else - { - // ENHANCE: Strictly speaking we should probably have separate before- - // and after-lists for the components, but I think it would be pretty - // rare to have both deletion and ligatures overlapping, so I'm not - // going to bother with it for now. - //for (int islot = 0; islot < AssocsSize(); islot++) - for (int islot = 0; islot < 1; islot++) - { - m_vpslotAssoc[islot]->AllComponentRefs(vichw); - } - } - } - else - { - Assert(m_ichwSegOffset != kInvalid); - vichw.push_back(m_ichwSegOffset); - } -} - -/*---------------------------------------------------------------------------------------------- - Get the value of the component.???.ref attribute for the slot. - Note that 'i' is the local index for the component as defined for this glyph. -----------------------------------------------------------------------------------------------*/ -GrSlotState * GrSlotState::CompRefSlot(int i) -{ - Assert(i < m_cnCompPerLig); - if (i < m_cnCompPerLig) - return CompRef(i); - else - return NULL; -} - -/*---------------------------------------------------------------------------------------------- - Set the value of the component.???.ref attribute for the slot. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::SetCompRefSlot(GrTableManager * ptman, int slati, GrSlotState * pslotComp) -{ - // Convert the global identifer for the component to the index for this glyph. - int icomp = ptman->ComponentIndexForGlyph(GlyphID(), slati); - Assert(icomp != -1); - if (icomp == -1) - // Component not defined for this glyph--ignore. - return; - Assert(icomp < m_cnCompPerLig); - - if (m_fHasComponents == false) - { - // None have been set yet; initialize them. - for (int iLoop = 0; iLoop < m_cnCompPerLig; iLoop++) - { - SetCompRef(iLoop, NULL); - SetSlati(iLoop, -1); - } - } - - m_fHasComponents = true; - int iLoop; - for (iLoop = 0; iLoop < m_cnCompPerLig; iLoop++) - { - if (Slati(iLoop) == slati) - break; - if (Slati(iLoop) == -1) - break; - } - //if (icomp < m_cnCompPerLig) - if (iLoop < m_cnCompPerLig) - { - //SetCompRef(icomp, pslotComp); - SetCompRef(iLoop, pslotComp); - SetSlati(iLoop, slati); - } -} - -/*---------------------------------------------------------------------------------------------- - Return the underlying position for the slot, relative to the official beginning of the - segment. -----------------------------------------------------------------------------------------------*/ -int GrSlotState::SegOffset() -{ - if (m_ichwSegOffset == kInvalid) - { - Assert(m_pslotPrevState); - Assert(m_ipassModified > 0); - return m_pslotPrevState->SegOffset(); - } - else - { - Assert(m_pslotPrevState == NULL); - Assert(m_ipassModified == 0); - return m_ichwSegOffset; - } -} - -/*---------------------------------------------------------------------------------------------- - Return the value of the glyph attribute (in design units, if this is a measurement). -----------------------------------------------------------------------------------------------*/ -int GrSlotState::GlyphAttrValueEmUnits(GrTableManager * ptman, int nAttrID) -{ - return ptman->GlyphAttrValue(m_chwGlyphID, nAttrID); -} - -/*---------------------------------------------------------------------------------------------- - Return the value of the glyph metric, in design coordinates (ie, based on the font's - em-square). -----------------------------------------------------------------------------------------------*/ -int GrSlotState::GlyphMetricEmUnits(GrTableManager * ptman, int nMetricID) -{ - int mValue; - if (ptman->State()->GetFont()) - { - // Get the actual metric, possibly adjusted for hinting, then convert back to - // design units. - float xysValue = GlyphMetricLogUnits(ptman, nMetricID); - mValue = ptman->LogToEmUnits(xysValue); - } - else - // Ask the font directly. - ////mValue = ??? - mValue = 0; - - return mValue; -} - -/*---------------------------------------------------------------------------------------------- - Return the value of the glyph attribute, converted to source device coordinates. - The attribute is assumed to be one whose value is a measurement. -----------------------------------------------------------------------------------------------*/ -float GrSlotState::GlyphAttrValueLogUnits(GrTableManager * ptman, int nAttrID) -{ - int mValue = GlyphAttrValueEmUnits(ptman, nAttrID); - float xysRet = ptman->EmToLogUnits(mValue); - return xysRet; -} - -/*---------------------------------------------------------------------------------------------- - Return the value of the glyph metric, in the source device's logical units. -----------------------------------------------------------------------------------------------*/ -float GrSlotState::GlyphMetricLogUnits(GrTableManager * ptman, int nMetricID) -{ -#ifdef OLD_TEST_STUFF - if (ptman->GlyphTable() == NULL) - return 0; -#endif // OLD_TEST_STUFF - -#ifdef _DEBUG - if (IsLineBreak(ptman->LBGlyphID())) - { - Warn("Getting metrics of line-break slot"); - } -#endif // _DEBUG - if (IsLineBreak(ptman->LBGlyphID())) - { - return 0; - } - - return GetGlyphMetric(ptman->State()->GetFont(), nMetricID, - ActualGlyphForOutput(ptman)); -} - - -float GrSlotOutput::GlyphMetricLogUnits(Font * pfont, int nMetricID) -{ - Assert(m_chwActual != kInvalidGlyph); - if (m_chwActual == kInvalidGlyph) - return 0; - - return GetGlyphMetric(pfont, nMetricID, m_chwActual); -} - -//float GrSlotOutput::GlyphMetricLogUnits(int gmet) -- obsolete: no longer caching these values -//{ -// // When the font is not passed as an argument, the values better be cached! -// -// switch (gmet) -// { // There may be off by one errors below, depending on what width and height mean -// case kgmetLsb: -// return m_xysGlyphX; -// case kgmetRsb: -// return (m_xysAdvX - m_xysGlyphX - m_xysGlyphWidth); -// case kgmetBbTop: -// return m_xysGlyphY; -// case kgmetBbBottom: -// return (m_xysGlyphY - m_xysGlyphHeight); -// case kgmetBbLeft: -// return m_xysGlyphX; -// case kgmetBbRight: -// return (m_xysGlyphX + m_xysGlyphWidth); -// case kgmetBbHeight: -// return m_xysGlyphHeight; -// case kgmetBbWidth: -// return m_xysGlyphWidth; -// case kgmetAdvWidth: -// return m_xysAdvX; -// case kgmetAdvHeight: -// return m_xysAdvY; -// default: -// Warn("GetGlyphMetric was asked for an illegal metric."); -// }; -// -// return 0; -//} - - -float GrSlotAbstract::GetGlyphMetric(Font * pfont, int nMetricID, gid16 chwGlyphID) -{ - GlyphMetric gmet = GlyphMetric(nMetricID); - - float yAscent, yDescent; - gr::Point ptAdvances; - gr::Rect rectBb; - - if (kgmetAscent == gmet) - { - //if (m_xysFontAscent != -1) - // return m_xysFontAscent; - pfont->getFontMetrics(&yAscent); - //m_xysFontAscent = xysRet; - //if (pfont) - // m_xysFontAscent = yAscent; - return yAscent; - } - - if (kgmetDescent == gmet) - { - //if (m_xysFontDescent != -1) - // return m_xysFontDescent; - pfont->getFontMetrics(NULL, &yDescent); - //m_xysFontDescent = xysRet; - //if (pfont) - // m_xysFontDescent = yDescent; - return yDescent; - } - - float xysGlyphX, xysGlyphY, xysGlyphWidth, xysGlyphHeight, xysAdvX, xysAdvY; - //if (m_xysGlyphWidth == -1) - //{ - pfont->getGlyphMetrics(chwGlyphID, rectBb, ptAdvances); - - xysGlyphX = rectBb.left; - xysGlyphY = rectBb.top; - xysGlyphWidth = (rectBb.right - rectBb.left); - xysGlyphHeight = (rectBb.top - rectBb.bottom); - xysAdvX = ptAdvances.x; - xysAdvY = ptAdvances.y; - - m_bIsSpace = (0 == xysGlyphX && 0 == xysGlyphY); // should agree with test done in IsSpace() below - - if (m_bIsSpace == 1) - { - // White space glyph - only case where nGlyphX == nGlyphY == 0 - // nGlyphWidth & nGlyphHeight are always set to 16 for unknown reasons, so correct. - xysGlyphWidth = xysGlyphHeight = 0; - } - //} - - switch (gmet) - { // There may be off-by-one errors below, depending on what width and height mean - case kgmetLsb: - return xysGlyphX; - case kgmetRsb: - return (xysAdvX - xysGlyphX - xysGlyphWidth); - case kgmetBbTop: - return xysGlyphY; - case kgmetBbBottom: - return (xysGlyphY - xysGlyphHeight); - case kgmetBbLeft: - return xysGlyphX; - case kgmetBbRight: - return (xysGlyphX + xysGlyphWidth); - case kgmetBbHeight: - return xysGlyphHeight; - case kgmetBbWidth: - return xysGlyphWidth; - case kgmetAdvWidth: - return xysAdvX; - case kgmetAdvHeight: - return xysAdvY; - default: - Warn("GetGlyphMetric was asked for an illegal metric."); - }; - - return 0; -} - -/*---------------------------------------------------------------------------------------------- - Test the glyph id to see if it is a white space glyph. -----------------------------------------------------------------------------------------------*/ -int GrSlotState::IsSpace(GrTableManager * ptman) -{ - gid16 gidActual = ActualGlyphForOutput(ptman); - - ////if (m_xysGlyphWidth == -1) - ////{ - //// res = ptman->State()->GraphicsObject()->GetGlyphMetrics(gidActual, - //// &m_xysGlyphWidth, &m_xysGlyphHeight, - //// &m_xysGlyphX, &m_xysGlyphY, &m_xysAdvX, &m_xysAdvY); - //// if (ResultFailed(res)) - //// { - //// WARN(res); - //// return 2; // will test as true but can be distinguished by separate value - //// } - - //// gr::Point ptAdvances; - //// gr::Rect rectBb; - //// ptman->State()->Font()->getGlyphMetrics(gidActual, rectBb, ptAdvances); - ////} - - if (m_bIsSpace == -1) - GetGlyphMetric(ptman->State()->GetFont(), kgmetBbLeft, gidActual); - // One call is enough to cache the information. - //GetGlyphMetric(ptman->State()->Font(), kgmetBbBottom, gidActual); - - // should agree with test done in GetGlyphMetric() above - //////m_bIsSpace = (0 == m_xysGlyphX && 0 == m_xysGlyphY); - - Assert(m_bIsSpace == 0 || m_bIsSpace == 1); - - return m_bIsSpace; -} - -bool GrSlotOutput::IsSpace() -{ - Assert(m_bIsSpace == 0 || m_bIsSpace == 1); - return m_bIsSpace; -} - -/*---------------------------------------------------------------------------------------------- - If any of the attach attributes have been modified, fix things up. Set up the attachment - tree, and set any needed default positions. Zap the cached positions of any following - glyphs in the stream. - - @param psstrm - the stream in which the modifications were made - @param islotThis - the index of the attached (leaf) slot in the stream; - -1 if we don't know -----------------------------------------------------------------------------------------------*/ -void GrSlotState::HandleModifiedPosition(GrTableManager * ptman, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, int islotThis) -{ - if (!m_fAttachMod && !m_fShiftMod) - return; - - if (islotThis == -1) - { - for (int islot = 0; islot < psstrmOut->WritePos(); islot++) - { - if (psstrmOut->SlotAt(islot) == this) - { - islotThis = islot; - break; - } - } - Assert(islotThis > -1); - } - - if (m_fAttachMod) - { - // Attachments. - - // Note that it doesn't make sense to attach a slot to itself, so if the value of - // the attach.to attribute is 0, that means clear the attachment. - GrSlotState * pslotNewRoot = AttachRoot(psstrmOut); - - AttachToRoot(ptman, psstrmOut, pslotNewRoot); - - if (pslotNewRoot) - { - // If this is an attachment with no positions, attach the two glyphs side by side - // in the appropriate order. - bool fRtl = ((pslotNewRoot->PostBidiDirLevel(ptman) % 2) != 0); - if ((fRtl && m_srAttachTo < 0) || (!fRtl && m_srAttachTo > 0)) - { - // The root is on the right, the leaf is on the left. - if (m_mAttachAtX == kNotYetSet && m_nAttachAtGpoint == kNotYetSet) - m_mAttachAtX = 0; - if (m_mAttachWithX == kNotYetSet && m_nAttachWithGpoint == kNotYetSet) - m_mAttachWithX = short(AdvanceX(ptman)); - } - else - { - // The root is on the left, the leaf is on the right. - if (m_mAttachAtX == kNotYetSet && m_nAttachAtGpoint == kNotYetSet) - m_mAttachAtX = short(pslotNewRoot->AdvanceX(ptman)); - if (m_mAttachWithX == kNotYetSet && m_nAttachWithGpoint == kNotYetSet) - m_mAttachWithX = 0; - } - } - } - else - { - // Shifting, or changing the advance width. - Assert(m_fShiftMod); - EnsureLocalAttachmentTree(ptman, psstrmIn, psstrmOut, islotThis); - ZapMetricsAndPositionDownToBase(psstrmOut); - ZapMetricsOfLeaves(psstrmOut); - } - - if (psstrmOut->m_ipass == ptman->NumberOfPasses() - 1) - ptman->InitPosCache(); // cached position is most likely no longer valid - - // Invalidate the positions of this and any following glyphs. - for (int islot = islotThis + 1; islot < psstrmOut->WritePos(); islot++) - psstrmOut->SlotAt(islot)->ZapPosition(); - - m_fAttachMod = false; - m_fShiftMod = false; -} - -/*---------------------------------------------------------------------------------------------- - The shift attribute of a slot has been modified. Make sure any slots that are part of the - same attachment cluster are local to this stream. The reason for this is so that the - position calculations stay consistent within the stream. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::EnsureLocalAttachmentTree(GrTableManager * ptman, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, int islotThis) -{ - if (m_dislotRootFixed) - { - GrSlotState * pslotRoot = SlotAtOffset(psstrmOut, m_dislotRootFixed); - psstrmOut->EnsureLocalCopy(ptman, pslotRoot, psstrmIn); - pslotRoot = SlotAtOffset(psstrmOut, m_dislotRootFixed); // get the new one! - pslotRoot->EnsureLocalAttachmentTree(ptman, psstrmIn, psstrmOut, islotThis + m_dislotRootFixed); - } - for (size_t islot = 0; islot < m_vdislotAttLeaves.size(); islot++) - { - GrSlotState * pslotLeaf = SlotAtOffset(psstrmOut, m_vdislotAttLeaves[islot]); - psstrmOut->EnsureLocalCopy(ptman, pslotLeaf, psstrmIn); - } -} - -/*---------------------------------------------------------------------------------------------- - The recipient slot is being attached to the argument slot. - NOTE: the caller is responsible to zap the cached positions of following glyphs - in the stream. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::AttachToRoot(GrTableManager * ptman, GrSlotStream * psstrm, - GrSlotState * pslotNewRoot) -{ - GrSlotState * pslotOldRoot = (m_dislotRootFixed == 0) ? - NULL : - SlotAtOffset(psstrm, m_dislotRootFixed); - - if (pslotOldRoot) - { - if (pslotOldRoot != pslotNewRoot) - pslotOldRoot->RemoveLeaf(m_dislotRootFixed); - pslotOldRoot->ZapMetricsAndPositionDownToBase(psstrm); - pslotOldRoot->ZapMetricsOfLeaves(psstrm); - } - - ZapCompositeMetrics(); - - if (pslotNewRoot && pslotNewRoot != pslotOldRoot) - { - pslotNewRoot->AddLeaf(m_srAttachTo); - pslotNewRoot->ZapMetricsAndPositionDownToBase(psstrm); - pslotNewRoot->ZapMetricsOfLeaves(psstrm); - } - - m_dislotRootFixed = m_srAttachTo; -} - -/*---------------------------------------------------------------------------------------------- - Return the absolute position of the glyph, relative to the start of the segment, - in font design units. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::Position(GrTableManager * ptman, - GrSlotStream * psstrmOut, int * pmXPos, int * pmYPos) -{ - Assert(!m_fAttachMod); // the attachment tree should be set up - Assert(!m_fShiftMod); - - float xsWidth, xsVisWidth; - if (m_xsPositionX == kNegInfFloat || m_ysPositionY == kNegInfFloat) - ptman->CalcPositionsUpTo(psstrmOut->m_ipass, this, &xsWidth, &xsVisWidth); - - *pmXPos = ptman->LogToEmUnits(m_xsPositionX); - *pmYPos = ptman->LogToEmUnits(m_ysPositionY); -} - -/*---------------------------------------------------------------------------------------------- - Recalculate the metrics for this slot, which has attachments on it (or possibly - did in the past). -----------------------------------------------------------------------------------------------*/ -void GrSlotState::AdjustRootMetrics(GrTableManager * ptman, GrSlotStream * psstrm) -{ - Assert(m_dislotRootFixed == m_srAttachTo); - GrSlotState * pslotRoot = AttachRoot(psstrm); - CalcRootMetrics(ptman, psstrm, kPosInfinity); - if (pslotRoot) - pslotRoot->AdjustRootMetrics(ptman, psstrm); -} - -/*---------------------------------------------------------------------------------------------- - Calculate the composite metrics for this slot. - - @param psstrm - stream for which we are calculating it - @param nLevel - attachment level we are asking for; kPosInifinity means all levels - @param fThorough - true: do a thorough recalculation; false: don't recalculate - metrics for leaves (are they assumed to be accurate???) - --currently not used -----------------------------------------------------------------------------------------------*/ -void GrSlotState::CalcCompositeMetrics(GrTableManager * ptman, GrSlotStream * psstrm, - int nLevel, bool fThorough) -{ - if (m_nCompositeLevel == nLevel) - return; - - if (fThorough) - { - Assert(m_dislotRootFixed == m_srAttachTo); - GrSlotState * pslotRoot = AttachRoot(psstrm); - - InitMetrics(ptman, pslotRoot); - - for (size_t islot = 0; islot < m_vdislotAttLeaves.size(); islot++) - { - GrSlotState * pslotLeaf = SlotAtOffset(psstrm, m_vdislotAttLeaves[islot]); - if (pslotLeaf->AttachLevel() <= nLevel) - pslotLeaf->CalcCompositeMetrics(ptman, psstrm, nLevel, fThorough); - else - // this slot will be ignored in the composite metrics - pslotLeaf->ZapRootMetrics(); - } - CalcRootMetrics(ptman, psstrm, nLevel); - - m_nCompositeLevel = nLevel; - } - else - { - Assert(false); // for now - - // Don't bother with the leaves. - InitRootMetrics(ptman); - } -} - -/*---------------------------------------------------------------------------------------------- - Calculate the metrics for this node and all its leaf nodes. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::CalcRootMetrics(GrTableManager * ptman, GrSlotStream * psstrm, int nLevel) -{ - for (size_t idislot = 0; idislot < m_vdislotAttLeaves.size(); idislot++) - { - GrSlotState * pslot = SlotAtOffset(psstrm, m_vdislotAttLeaves[idislot]); - if (pslot->AttachLevel() > nLevel) - continue; - - m_xsClusterXOffset = min(m_xsClusterXOffset, pslot->m_xsClusterXOffset); - if (!pslot->m_fIgnoreAdvance) - { - m_xsClusterAdv = max( - m_xsClusterAdv, - pslot->m_xsClusterAdv + m_xsRootShiftX); - } - m_xsClusterBbLeft = min(m_xsClusterBbLeft, pslot->m_xsClusterBbLeft); - m_xsClusterBbRight = max(m_xsClusterBbRight, pslot->m_xsClusterBbRight); - m_ysClusterBbTop = max(m_ysClusterBbTop, pslot->m_ysClusterBbTop); - m_ysClusterBbBottom = min(m_ysClusterBbBottom, pslot->m_ysClusterBbBottom); - } -} - -/*---------------------------------------------------------------------------------------------- - Reset the cluster metrics of this slot. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::InitMetrics(GrTableManager * ptman, GrSlotState * pslotRoot) -{ - InitLeafMetrics(ptman, pslotRoot); - InitRootMetrics(ptman); -} - -/*---------------------------------------------------------------------------------------------- - Initialize the variables that store the offsets of just this node (ignoring any of its - leaves) relative to the cluster base. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::InitLeafMetrics(GrTableManager * ptman, GrSlotState * pslotRoot) -{ - float xsShiftX = ptman->EmToLogUnits(ShiftX()); - float ysShiftY = ptman->EmToLogUnits(ShiftY()); - - if (ptman->RightToLeft()) - xsShiftX *= -1; - - if (IsBase()) - { - // The x-value below has to be zero because the shift is incorporated into - // m_xsRootShiftX. (m_ysRootShiftY, on the other hand, isn't used anywhere.) - m_xsOffsetX = 0; - m_ysOffsetY = ysShiftY; - - m_xsRootShiftX = xsShiftX; - m_ysRootShiftY = ysShiftY; - Assert(!IsLineBreak(ptman->LBGlyphID()) - || (m_xsRootShiftX == 0 && m_ysRootShiftY == 0)); - return; - } - - Assert(!IsLineBreak(ptman->LBGlyphID())); - - // Hint-adjusted logical coordinates equivalent to attach.at and attach.with attributes. - // If attach.at or attach.with attributes were unset, the defaults for a side-by-side - // attachment should have been supplied in HandleModifiedPosition(). - float xsAttAtX, ysAttAtY, xsAttWithX, ysAttWithY; - AttachLogUnits(ptman, pslotRoot, &xsAttAtX, &ysAttAtY, &xsAttWithX, &ysAttWithY); - - m_xsOffsetX = xsAttAtX - xsAttWithX; - m_xsOffsetX += pslotRoot->m_xsOffsetX; - m_xsOffsetX += xsShiftX; - - m_ysOffsetY = ysAttAtY - ysAttWithY; - m_ysOffsetY += pslotRoot->m_ysOffsetY; - m_ysOffsetY += ysShiftY; - - // Cumulative effect of shifts on this and all base nodes: - m_xsRootShiftX = pslotRoot->m_xsRootShiftX + xsShiftX; - m_ysRootShiftY = pslotRoot->m_ysRootShiftY + ysShiftY; -} - -/*---------------------------------------------------------------------------------------------- - Initialize the variables that store the offsets of this node taking into account its - leaves; these are relative to the cluster base. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::InitRootMetrics(GrTableManager * ptman) -{ - if (IsLineBreak(ptman->LBGlyphID())) - { - m_fIgnoreAdvance = true; - m_xsClusterXOffset = 0; - m_xsClusterAdv = 0; - m_xsClusterBbLeft = 0; - m_xsClusterBbRight = 0; - m_ysClusterBbTop = 0; - m_ysClusterBbBottom = 0; - return; - } - - float xsAdvanceX = ptman->EmToLogUnits(AdvanceX(ptman)); - - // If the glyph's advance width is zero, then we NEVER want it to have any affect, - // even if the glyph is attached way out to the right of its base's advance. - m_fIgnoreAdvance = (xsAdvanceX == 0); - - float xsBbLeft = GlyphMetricLogUnits(ptman, kgmetBbLeft); - float xsBbRight = GlyphMetricLogUnits(ptman, kgmetBbRight); - float ysBbTop = GlyphMetricLogUnits(ptman, kgmetBbTop); - float ysBbBottom = GlyphMetricLogUnits(ptman, kgmetBbBottom); - - // Any shifts should be ignored for the sake of calculating actual position or width, - // hence we subtract the cumulative effect of the shifts. - m_xsClusterXOffset = m_xsOffsetX - m_xsRootShiftX; - m_xsClusterAdv = m_xsOffsetX + xsAdvanceX - m_xsRootShiftX; - - m_xsClusterBbLeft = m_xsOffsetX + xsBbLeft; - m_xsClusterBbRight = m_xsOffsetX + xsBbRight; - m_ysClusterBbTop = m_ysOffsetY + ysBbTop; - m_ysClusterBbBottom = m_ysOffsetY + ysBbBottom; -} - -/*---------------------------------------------------------------------------------------------- - X-offset of a single glyph relative to the previous advance position. -----------------------------------------------------------------------------------------------*/ -float GrSlotState::GlyphXOffset(GrSlotStream * psstrm, float fakeItalicRatio) -{ - float xsRet = Base(psstrm)->ClusterRootOffset() + m_xsOffsetX; - - // fake an italic slant - xsRet += m_ysOffsetY * fakeItalicRatio; - - return xsRet; -} - -/*---------------------------------------------------------------------------------------------- - Y-offsets of a single glyph relative to the previous advance position. -----------------------------------------------------------------------------------------------*/ -float GrSlotState::GlyphYOffset(GrSlotStream * psstrm) -{ - return m_ysOffsetY; -} - -/*---------------------------------------------------------------------------------------------- - Return the offset of the last leaf of the cluster, relative to this slot, which is - the base. Return kNegInfinity if there are not enough slots in the stream to tell. -----------------------------------------------------------------------------------------------*/ -int GrSlotState::LastLeafOffset(GrSlotStream * psstrm) -{ - int islotRet = 0; - for (size_t idislot = 0; idislot < m_vdislotAttLeaves.size(); idislot++) - { - int dislot = m_vdislotAttLeaves[idislot]; - Assert(dislot != 0); - if (!psstrm->HasSlotAtPosPassIndex(PosPassIndex() + dislot)) - return kNegInfinity; - GrSlotState * pslotLeaf = SlotAtOffset(psstrm, dislot); - int islotTmp = pslotLeaf->LastLeafOffset(psstrm); - if (islotTmp == kNegInfinity) - return kNegInfinity; - islotRet = max(islotRet, (dislot + islotTmp)); - } - return islotRet; -} - -/*---------------------------------------------------------------------------------------------- - Return the attach positions in the device context's logical units, - adjusted for hinting if possible. - - Note that m_nAttachAt/WithGpoint = 0 is always an invalid value (resulting from a - glyph attribute that was defined in terms of x/y coordinates that didn't map to an - actual on-curve point). Therefore the x/y coordinates should be used to do the - attachment. In the case where we actually want point #0 on the curve, - m_nAttachAt/WithGpoint will have the special value 'kGpointZero' (the glyph attribute - is defined this way). -----------------------------------------------------------------------------------------------*/ -void GrSlotState::AttachLogUnits(GrTableManager * ptman, GrSlotState * pslotRoot, - float * pxsAttAtX, float * pysAttAtY, - float * pxsAttWithX, float * pysAttWithY) -{ - if (m_nAttachAtGpoint == kNotYetSet || m_nAttachAtGpoint == 0) - { - // Use x- and y-coordinates; no adjustment for hinting is done. - int mX = m_mAttachAtX + m_mAttachAtXOffset; - int mY = m_mAttachAtY + m_mAttachAtYOffset; - - *pxsAttAtX = ptman->EmToLogUnits(mX); - *pysAttAtY = ptman->EmToLogUnits(mY); - } - else - { - // Look up the actual on-curve point. - int nGpoint = m_nAttachAtGpoint; - if (nGpoint == kGpointZero) - nGpoint = 0; - bool fImpl = ptman->GPointToXY(pslotRoot->GlyphID(), nGpoint, pxsAttAtX, pysAttAtY); - - // Debuggers: - //int mXTmpAt = m_mAttachAtX + m_mAttachAtXOffset; - //int mYTmpAt = m_mAttachAtY + m_mAttachAtYOffset; - //int xsAttAtXTmp = ptman->EmToLogUnits(mXTmpAt); - //int ysAttAtYTmp = ptman->EmToLogUnits(mYTmpAt); - //fImpl = false; - - if (!fImpl) - { - // Fall back to using x- and y-coordinates; no adjustment for hinting. - int mX = m_mAttachAtX + m_mAttachAtXOffset; - int mY = m_mAttachAtY + m_mAttachAtYOffset; - *pxsAttAtX = ptman->EmToLogUnits(mX); - *pysAttAtY = ptman->EmToLogUnits(mY); - } - else - { - // Adjust by offsets. - *pxsAttAtX += ptman->EmToLogUnits(m_mAttachAtXOffset); - *pysAttAtY += ptman->EmToLogUnits(m_mAttachAtYOffset); - } - } - - if (m_nAttachWithGpoint == kNotYetSet || m_nAttachWithGpoint == 0) - { - // Use x- and y-coordinates; no adjustment for hinting is done. - int mX = m_mAttachWithX + m_mAttachWithXOffset; - int mY = m_mAttachWithY + m_mAttachWithYOffset; - - *pxsAttWithX = ptman->EmToLogUnits(mX); - *pysAttWithY = ptman->EmToLogUnits(mY); - } - else - { - // Look up the actual on-curve point. - int nGpoint = m_nAttachWithGpoint; - if (nGpoint == kGpointZero) - nGpoint = 0; - bool fImpl = ptman->GPointToXY(m_chwGlyphID, nGpoint, pxsAttWithX, pysAttWithY); - - // Debuggers: - //int mXTmpWith = m_mAttachWithX + m_mAttachWithXOffset; - //int mYTmpWith = m_mAttachWithY + m_mAttachWithYOffset; - //int xsAttWithXTmp = ptman->EmToLogUnits(mXTmpWith); - //int ysAttWithYTmp = ptman->EmToLogUnits(mYTmpWith); - //fImpl = false; - - if (!fImpl) - { - // Fall back to using x- and y-coordinates; no adjustment for hinting. - int mX = m_mAttachWithX + m_mAttachWithXOffset; - int mY = m_mAttachWithY + m_mAttachWithYOffset; - *pxsAttWithX = ptman->EmToLogUnits(mX); - *pysAttWithY = ptman->EmToLogUnits(mY); - } - else - { - // Adjust by offsets. - *pxsAttWithX += ptman->EmToLogUnits(m_mAttachWithXOffset); - *pysAttWithY += ptman->EmToLogUnits(m_mAttachWithYOffset); - } - } -} - -/*---------------------------------------------------------------------------------------------- - Return the slot that is 'dislot' slots away from this slot in the given stream. - Only valid for streams that are the input to or output of positioning passes. -----------------------------------------------------------------------------------------------*/ -GrSlotState * GrSlotState::SlotAtOffset(GrSlotStream * psstrm, int dislot) -{ - Assert(psstrm->m_fUsedByPosPass); - return psstrm->SlotAtPosPassIndex(PosPassIndex() + dislot); -} - -/*---------------------------------------------------------------------------------------------- - If the direction level has not been calculated at this point, assume it is the - top direction. This should only happen if there was no bidi pass to set it. - This method should only be called by the positioning passes; it assumes any bidi - pass has been run. -----------------------------------------------------------------------------------------------*/ -int GrSlotState::PostBidiDirLevel(GrTableManager * ptman) -{ - if (m_nDirLevel == -1) - { - Assert(!ptman->HasBidiPass()); - return ptman->TopDirectionLevel(); - } - return m_nDirLevel; -} - -/*---------------------------------------------------------------------------------------------- - Return true if this glyph represents a LRM code. -----------------------------------------------------------------------------------------------*/ -bool GrSlotState::IsLrm() -{ - if (PassModified() == 0) - return (m_nUnicode == knLRM); - return m_pslotPrevState->IsLrm(); -} - -/*---------------------------------------------------------------------------------------------- - Return true if this glyph represents a RLM code. -----------------------------------------------------------------------------------------------*/ -bool GrSlotState::IsRlm() -{ - if (PassModified() == 0) - return (m_nUnicode == knRLM); - return m_pslotPrevState->IsRlm(); -} - - -/*---------------------------------------------------------------------------------------------- - Used by GlyphInfo -----------------------------------------------------------------------------------------------*/ -//float GrSlotOutput::AdvanceX(Segment * pseg) -//{ -// return pseg->EmToLogUnits(m_mAdvanceX); -//} -//float GrSlotOutput::AdvanceY(Segment * pseg) -//{ -// return pseg->EmToLogUnits(m_mAdvanceY); -//} -float GrSlotOutput::MaxStretch(Segment * pseg, int level) -{ - Assert(level == 0); - return (level == 0) ? pseg->EmToLogUnits(m_mJStretch0) : 0; -} -float GrSlotOutput::MaxShrink(Segment * pseg, int level) -{ - Assert(level == 0); - return (level == 0) ? pseg->EmToLogUnits(m_mJShrink0) : 0; -} -float GrSlotOutput::StretchStep(Segment * pseg, int level) -{ - Assert(level == 0); - return (level == 0) ? pseg->EmToLogUnits(m_mJStep0) : 0; -} -int GrSlotOutput::JustWeight(int level) -{ - Assert(level == 0); - return (level == 0) ? m_nJWeight0 : 0; -} -float GrSlotOutput::JustWidth(Segment * pseg, int level) -{ - Assert(level == 0); - return (level == 0) ? pseg->EmToLogUnits(m_mJWidth0) : 0; -} -float GrSlotOutput::MeasureSolLogUnits(Segment * pseg) -{ - return pseg->EmToLogUnits(m_mMeasureSol); -} -float GrSlotOutput::MeasureEolLogUnits(Segment * pseg) -{ - return pseg->EmToLogUnits(m_mMeasureEol); -} - -/*---------------------------------------------------------------------------------------------- - Make a copy of the GrSlotOutput. This is used in making an identical copy of the segment. - Warning: this function will break if GrSlotState and subclasses are given virtual - methods. In that case, we will need to copy from the address of the first variable in - GrSlotAbstract. -----------------------------------------------------------------------------------------------*/ -void GrSlotOutput::ExactCopyFrom(GrSlotOutput * pslout, u_intslot * pnVarLenBuf, int cnExtraPerSlot) -{ - // The chunk of the object from GrSlotAbstract can be copied exactly, - // except for the variable-length buffer. - *this = *pslout; - m_prgnVarLenBuf = pnVarLenBuf; - std::copy(pslout->m_prgnVarLenBuf, pslout->m_prgnVarLenBuf + cnExtraPerSlot, - m_prgnVarLenBuf); - - // Now copy the stuff specific to GrSlotOutput. - m_ichwBeforeAssoc = pslout->m_ichwBeforeAssoc; - m_ichwAfterAssoc = pslout->m_ichwAfterAssoc; - m_cComponents = pslout->m_cComponents; - - m_isloutClusterBase = pslout->m_isloutClusterBase; - m_disloutCluster = pslout->m_disloutCluster; - m_xsClusterXOffset = pslout->m_xsClusterXOffset; - m_xsClusterAdvance = pslout->m_xsClusterAdvance; - m_igbb = pslout->m_igbb; - m_xsAdvanceX = pslout->m_xsAdvanceX; -// m_ysAdvanceY = pslout->m_ysAdvanceY; -// m_rectBB = pslout->m_rectBB; -} - -/*---------------------------------------------------------------------------------------------- - Shift the glyph to the opposite end of the segment. This is needed for white-space-only - segments whose direction is being changed. -----------------------------------------------------------------------------------------------*/ -void GrSlotOutput::ShiftForDirDepthChange(float dxsSegWidth) -{ - float dxsShift = dxsSegWidth - m_xsAdvanceX - (2 * m_xsPositionX); - int tmp; tmp = (int) dxsShift; - m_xsPositionX += dxsShift; -// m_rectBB.left += dxsShift; -// m_rectBB.right += dxsShift; -} - -/*---------------------------------------------------------------------------------------------- - Return the indices of all the glyphs attached to this cluster, in logical order. - Return an empty vector if this glyph is not the base glyph or if there are no - attached glyphs. - This method return glyph indices, not slot indices. -----------------------------------------------------------------------------------------------*/ -void GrSlotOutput::ClusterMembers(Segment * pseg, int isloutThis, std::vector<int> & visloutRet) -{ - if (m_isloutClusterBase == -1 || m_isloutClusterBase == isloutThis) // yes, a base - pseg->ClusterMembersForGlyph(isloutThis, m_disloutCluster, visloutRet); - else - { - Assert(visloutRet.size() == 0); - } -} - -} // namespace gr diff --git a/Build/source/libs/graphite-engine/src/segment/GrSlotState.h b/Build/source/libs/graphite-engine/src/segment/GrSlotState.h deleted file mode 100644 index d000927d1a4..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrSlotState.h +++ /dev/null @@ -1,1287 +0,0 @@ -/*--------------------------------------------------------------------*//*:Ignore this sentence. -Copyright (C) 1999 - 2008 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: GrSlotState.h -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Copyright (C) 1999 by SIL International. All rights reserved. - -Description: - Classes GrSlotAbstract, GrSlotState, and GrSlotOutput -----------------------------------------------------------------------------------------------*/ -#ifdef _MSC_VER -#pragma once -#endif -#ifndef SLOTSTATE_INCLUDED -#define SLOTSTATE_INCLUDED - -namespace gr -{ - -class GrSlotAbstract; -class GrSlotState; -class GrSlotOutput; -class GrSlotStream; -class Font; - -//:End Ignore - - -/*---------------------------------------------------------------------------------------------- - Subsumes GrSlotState and GrSlotOutput, both of which represent a single glyph - and its slot attributes and features. - - Hungarian: slab -----------------------------------------------------------------------------------------------*/ -class GrSlotAbstract -{ - friend class GrSlotStream; - friend class GlyphInfo; - -public: - // Constructor: - GrSlotAbstract() - { - } - - ~GrSlotAbstract() - { - // the table manager is responsible for destroying the contents of m_prgnVarLenBuf - } - - void BasicInitializeAbstract(int cnCompPerLig, u_intslot * pnBuf) - { - m_dirc = kNotYetSet8; - m_lb = kNotYetSet8; - m_fInsertBefore = true; - m_nDirLevel = -1; - - m_bIsSpace = -1; // unknown - - m_fInsertBefore = true; - - m_mMeasureSol = 0; - m_mMeasureEol = 0; - - m_mJStretch0 = 0; - m_mJShrink0 = 0; - m_mJStep0 = 0; - m_nJWeight0 = 0; - m_mJWidth0 = 0; - - m_cnCompPerLig = byte(cnCompPerLig); - m_prgnVarLenBuf = pnBuf; - } - - void CopyAbstractFrom(GrSlotState * pslot); - - void SetBufferPtr(u_intslot * pn) - { - m_prgnVarLenBuf = pn; - } - - gid16 GlyphID() { return m_chwGlyphID; } - gid16 RawActualGlyph() { return m_chwActual; } - float GetGlyphMetric(Font * pfont, int nGlyphMetricID, gid16 chwGlyphID); - - //GrSlotState * CompRefSlot(int i); - - int BreakWeight() - { - return (int)m_lb; - } - DirCode Directionality() - { - return DirCode(int(m_dirc)); - } - int InsertBefore() - { - return m_fInsertBefore; - } - int MeasureSol() - { - return m_mMeasureSol; - } - int MeasureEol() - { - return m_mMeasureEol; - } - - int DirLevel() - { - return m_nDirLevel; - } - - int SpecialSlotFlag() - { - return m_spsl; - } - void SetSpecialSlotFlag(int spsl) - { - m_spsl = sdata8(spsl); - } - - enum { - kNotYetSet = 0x7FFF, - kNotYetSet8 = 0x7F, - kInvalidGlyph = 0xFFFF - }; - - gid16 ActualGlyphForOutput(GrTableManager * ptman); - - // Needed for GlyphInfo: - float XPosition() - { - return m_xsPositionX; - } - float YPosition() - { - return m_ysPositionY; // relative to baseline (positive is up) - } - -protected: - gid16 m_chwGlyphID; - gid16 m_chwActual; // actual glyph to output (which is a different glyph for pseudos) - - sdata8 m_spsl; // special slot flag: LB, bidi marker - -// bool m_fInitialLB; // for LB slots: true if this is the initial LB; - // false if it is the terminating LB - // TODO: remove - - sdata8 m_dirc; // default = kNotYetSet8 (read from glyph attr) - sdata8 m_lb; // default = kNotYetSet8 (read from glyph attr) - - sdata8 m_nDirLevel; - - // Slot attributes that are used by GrSlotOutput: - short m_mMeasureSol; - short m_mMeasureEol; - - unsigned short m_mJStretch0; - unsigned short m_mJShrink0; - unsigned short m_mJStep0; - int m_mJWidth0; - byte m_nJWeight0; - - bool m_fInsertBefore; // default = true - - sdata8 m_bIsSpace; // 0 = false, 1 = true, -1 = unknown - - byte m_cnCompPerLig; - // There is a large block managed by either the GrTableManager (for GrSlotState) - // or the segment (for GrSlotOutput); this variable points at the sub-buffer for this - // particular slot: - u_intslot * m_prgnVarLenBuf; - - float m_xsPositionX; - float m_ysPositionY; - -}; // end of class GrSlotAbstract - - -/*---------------------------------------------------------------------------------------------- - A GrSlotState represents one slot as modified by a pass in the table. - Each time a slot state is modified, a new instance is created, copying the relevant - information. - - Hungarian: slot - - Other hungarian: - m - integer indicating glyph design units ("em-units") - sr - integer indicating slot reference -----------------------------------------------------------------------------------------------*/ -class GrSlotState : public GrSlotAbstract -{ - friend class GrSlotStream; - friend class FontMemoryUsage; - -public: - enum { kNeutral = 99 }; - - // Constructors: - GrSlotState() - : GrSlotAbstract(), - m_pslotPrevState(NULL) - { - m_vpslotAssoc.clear(); - //m_fInitialLB = false; // TODO: remove - m_spsl = kspslNone; - m_fNeutralAssocs = false; - m_dircProc = kdircUnknown; - m_fDirProcessed = false; - - m_vdislotAttLeaves.clear(); - m_fAttachMod = false; - m_fShiftMod = false; - m_dislotRootFixed = 0; - ZapCompositeMetrics(); - } - - ~GrSlotState() - { - } - - void BasicInitialize(int cnUserDefn, int cnCompPerLig, int cnFeat, u_intslot * pnBuf) - { - BasicInitializeAbstract(cnCompPerLig, pnBuf); - - m_xysGlyphWidth = -1; - m_xysFontAscent = -1; - m_xysFontDescent = -1; - - m_mAdvanceX = kNotYetSet; - m_mAdvanceY = kNotYetSet; - m_mShiftX = 0; - m_mShiftY = 0; - - m_fAdvXSet = false; // for transduction logging - m_fAdvYSet = false; - - m_srAttachTo = 0; - m_nAttachLevel = 0; - - m_mAttachAtX = kNotYetSet; - m_mAttachAtY = 0; - m_nAttachAtGpoint = kNotYetSet; - m_mAttachAtXOffset = 0; - m_mAttachAtYOffset = 0; - m_mAttachWithX = kNotYetSet; - m_mAttachWithY = 0; - m_nAttachWithGpoint = kNotYetSet; - m_mAttachWithXOffset = 0; - m_mAttachWithYOffset = 0; - - m_islotPosPass = kNotYetSet; - - m_cnUserDefn = byte(cnUserDefn); - m_cnFeat = byte(cnFeat); - - m_fHasComponents = false; - } - - void Initialize(gid16 chw, GrEngine *, GrFeatureValues fval, - int ipass, int ichwSegOffset, int nUnicode = -1); - void Initialize(gid16 chw, GrEngine *, GrSlotState * pslotFeat, - int ipass, int ichwSegOffset); - void Initialize(gid16 chw, GrEngine *, GrSlotState * pslotFeat, - int ipass); - - void InitializeFrom(GrSlotState * pslot, int ipass); - void CopyFeaturesFrom(GrSlotState * pslotSrc); - void FixAttachmentTree(GrSlotState * pslotOld); - - void CopyFrom(GrSlotState * pslot, bool fCopyEverything = true); - - // General: - int RawSegOffset() { return m_ichwSegOffset; } - - void SetGlyphID(gid16 chw) - { - m_chwGlyphID = chw; - m_chwActual = kInvalidGlyph; - m_xysGlyphWidth = -1; // indicate glyph metrics are invalid - m_ipassFsmCol = -1; - m_colFsm = -1; - } - - int PosPassIndex() - { - return m_islotPosPass; - } - void SetPosPassIndex(int islot, bool fInputToPosPass1) - { - // If we're resetting it, it should be to the same value as before: - Assert(fInputToPosPass1 || m_islotPosPass == kNotYetSet || m_islotPosPass == islot); - m_islotPosPass = islot; - } - void IncPosPassIndex() - { - m_islotPosPass++; - } - void ZapPosPassIndex() - { - m_islotPosPass = kNotYetSet; - } - - int StyleIndex() { return m_bStyleIndex; } - - int AttachTo() { return m_srAttachTo; } - int AttachLevel() { return m_nAttachLevel; } - - int RawAttachAtX() { return m_mAttachAtX; } - int AttachAtY() { return m_mAttachAtY; } - int AttachAtGpoint() { return m_nAttachAtGpoint; } - int AttachAtXOffset() { return m_mAttachAtXOffset; } - int AttachAtYOffset() { return m_mAttachAtYOffset; } - - int RawAttachWithX() { return m_mAttachWithX; } - int AttachWithY() { return m_mAttachWithY; } - int AttachWithGpoint() { return m_nAttachWithGpoint; } - int AttachWithXOffset() { return m_mAttachWithXOffset; } - int AttachWithYOffset() { return m_mAttachWithYOffset; } - - void Associate(GrSlotState *); - void Associate(GrSlotState *, GrSlotState *); - void Associate(std::vector<GrSlotState*> &); - void ClearAssocs(); - - int AssocsSize() { return m_vpslotAssoc.size(); } - GrSlotState * RawBeforeAssocSlot() - { - if (m_vpslotAssoc.size() == 0) - return NULL; - return m_vpslotAssoc[0]; - } - GrSlotState * RawAfterAssocSlot() - { - if (m_vpslotAssoc.size() == 0) - return NULL; - return m_vpslotAssoc.back(); - } - ////GrSlotState * AssocSlot(int i) { return m_vpslotAssoc[i]; } - - GrSlotState * AssocSlot(int i) - { - if (i < 0) - return NULL; - if (i >= signed(m_vpslotAssoc.size())) - return NULL; - - GrSlotState * pslotAssoc = m_vpslotAssoc[i]; - // handle possible reprocessing - while (pslotAssoc && pslotAssoc->PassModified() == m_ipassModified) - pslotAssoc = pslotAssoc->m_pslotPrevState; - return pslotAssoc; - } - - void AllAssocs(std::vector<int> & vichw); - int BeforeAssoc(); - int AfterAssoc(); - - void CleanUpAssocs(); - - void SetComponentRefsFor(GrSlotOutput *, int iComp = -1); - void AllComponentRefs(std::vector<int> & vichw); - - int PassModified() { return m_ipassModified; } - int SegOffset(); - int UnderlyingPos(); - GrSlotState * PrevState() { return m_pslotPrevState; } - - void MarkDeleted() // for now, do nothing - { - } - - int IsSpace(GrTableManager * ptman); - - // TODO: remove argument from these methods; it is no longer needed. - bool IsLineBreak(gid16 chwLB) - { - return (IsInitialLineBreak(chwLB) || IsFinalLineBreak(chwLB)); - //return (m_chwGlyphID == chwLB); // TODO: remove - } - bool IsInitialLineBreak(gid16 chwLB) - { - return (m_spsl == kspslLbInitial); - //return (IsLineBreak(chwLB) && m_fInitialLB == true); // TODO: remove - } - bool IsFinalLineBreak(gid16 chwLB) - { - return (m_spsl == kspslLbFinal); - //return (IsLineBreak(chwLB) && m_fInitialLB == false); // TODO: remove - } - - bool IsBidiMarker() - { - switch (m_spsl) - { - case kspslLRM: - case kspslRLM: - case kspslLRO: - case kspslRLO: - case kspslLRE: - case kspslRLE: - case kspslPDF: - return true; - default: - return false; - } - return false; - } - - bool HasComponents() { return m_fHasComponents; } - - // Directionality as determined by the bidi algorithm - DirCode DirProcessed() // return the value - { - Assert(m_dirc != kNotYetSet8); - if (m_dircProc == kdircUnknown) - m_dircProc = DirCode(m_dirc); - return m_dircProc; - } - void SetDirProcessed(DirCode dirc) // set the directionality - { - m_dircProc = dirc; - } - bool DirHasBeenProcessed() // has this slot been fully processed? - { - return m_fDirProcessed; - } - void MarkDirProcessed() // this slot has been fully processed - { - m_fDirProcessed = true; - } - - int RawAdvanceX() { return m_mAdvanceX; } - int RawAdvanceY() { return m_mAdvanceY; } - int ShiftX() { return m_mShiftX; } - int ShiftY() { return m_mShiftY; } - - // Slot attributes that must be calculated: - - int AdvanceX(GrTableManager * ptman) - { - if (m_mAdvanceX == kNotYetSet) - // Initialize it from the glyph metric (adjusted for hinting). - m_mAdvanceX = short(GlyphMetricEmUnits(ptman, kgmetAdvWidth)); - return m_mAdvanceX; - } - - int AdvanceY(GrTableManager * ptman) - { - if (m_mAdvanceY == kNotYetSet) - // Initialize it from the glyph metric (adjusted for hinting). - m_mAdvanceY = short(GlyphMetricEmUnits(ptman, kgmetAdvHeight)); - return m_mAdvanceY; - } - - int AttachAtX(GrTableManager * ptman, GrSlotStream * psstrm) - { - if (m_mAttachAtX == kNotYetSet) - { - Assert(false); // Should have already been set in HandleModifiedPosition, - // but just in case... - if (m_srAttachTo == 0) - return 0; - else - m_mAttachAtX = short(AttachRoot(psstrm)->AdvanceX(ptman)); // attach on the right - } - return m_mAttachAtX; - } - - int AttachWithX(GrTableManager * ptman, GrSlotStream * psstrm) - { - if (m_mAttachAtX == kNotYetSet) - { - Assert(false); // Should have already been set in HandleModifiedPosition, - // but just in case. - if (!m_srAttachTo == 0) - return 0; - else - m_mAttachAtX = 0; // attach on the right - } - return m_mAttachAtX; - } - - int JStretch() - { - return m_mJStretch0; - } - int JShrink() - { - return m_mJShrink0; - } - int JStep() - { - return m_mJStep0; - } - int JWeight() - { - return m_nJWeight0; - } - int JWidth() - { - return m_mJWidth0; - } - - // Slot attribute setters: - - void SetAdvanceX(int mVal) - { - Assert(mVal < 0xFFFF); m_mAdvanceX = short(mVal & 0xFFFF); m_fShiftMod = true; - m_fAdvXSet = true; // for transduction logging - } - void SetAdvanceY(int mVal) - { - Assert(mVal < 0xFFFF); m_mAdvanceY = short(mVal & 0xFFFF); m_fShiftMod = true; - m_fAdvYSet = true; // for transduction logging - } - void SetShiftX(int mVal) - { - Assert(mVal < 0xFFFF); m_mShiftX = short(mVal & 0xFFFF); - m_fShiftMod = true; - } - void SetShiftY(int mVal) - { - Assert(mVal < 0xFFFF); m_mShiftY = short(mVal & 0xFFFF); - m_fShiftMod = true; - } - - void SetAttachTo(int srVal) - { - Assert(srVal < 0xFFFF); - m_srAttachTo = short(srVal & 0xFFFF); - m_fAttachMod = true; - } - void SetAttachLevel(int nVal) { - Assert(nVal < 0xFFFF); m_nAttachLevel = short(nVal & 0xFFFF); m_fAttachMod = true; } - - void SetAttachAtX(int mVal) - { - Assert(mVal < 0xFFFF); - m_mAttachAtX = short(mVal) & 0xFFFF; - m_fAttachMod = true; - } - void SetAttachAtY(int mVal) { - Assert(mVal < 0xFFFF); m_mAttachAtY = short(mVal & 0xFFFF); m_fAttachMod = true; } - void SetAttachAtGpoint(int nVal) { - m_nAttachAtGpoint = short(nVal); m_fAttachMod = true; } - void SetAttachAtXOffset(int mVal) { - Assert(mVal < 0xFFFF); m_mAttachAtXOffset = short(mVal & 0xFFFF); m_fAttachMod = true; } - void SetAttachAtYOffset(int mVal) { - Assert(mVal < 0xFFFF); m_mAttachAtYOffset = short(mVal & 0xFFFF); m_fAttachMod = true; } - - void SetAttachWithX(int mVal) { - Assert(mVal < 0xFFFF); m_mAttachWithX = short(mVal & 0xFFFF); m_fAttachMod = true; } - void SetAttachWithY(int mVal) { - Assert(mVal < 0xFFFF); m_mAttachWithY = short(mVal & 0xFFFF); m_fAttachMod = true; } - void SetAttachWithGpoint(int nVal) { - m_nAttachWithGpoint = short(nVal); m_fAttachMod = true; } - void SetAttachWithXOffset(int mVal) { - Assert(mVal < 0xFFFF); m_mAttachWithXOffset = short(mVal & 0xFFFF); m_fAttachMod = true; } - void SetAttachWithYOffset(int mVal) { - Assert(mVal < 0xFFFF); m_mAttachWithYOffset = short(mVal & 0xFFFF); m_fAttachMod = true; } - - void SetCompRefSlot(GrTableManager * ptman, int i, GrSlotState * pslotComp); - - void SetBreakWeight(int lb) { m_lb = sdata8(lb); } - void SetInsertBefore(bool f) { m_fInsertBefore = f; } - - void SetDirectionality(DirCode dirc) { m_dirc = sdata8(dirc); } - void SetDirLevel(int n) { m_nDirLevel = sdata8(n); } - - void SetMeasureSol(int mVal) { m_mMeasureSol = short(mVal); } - void SetMeasureEol(int mVal) { m_mMeasureEol = short(mVal); } - - void SetJStretch(int mVal) { m_mJStretch0 = short(mVal); } - void SetJShrink(int mVal) { m_mJShrink0 = short(mVal); } - void SetJStep(int mVal) { m_mJStep0 = short(mVal); } - void SetJWeight(int nVal) { m_nJWeight0 = byte(nVal); } - void SetJWidth(int mVal) { m_mJWidth0 = mVal; } - void AddJWidthToAdvance(GrTableManager * ptman) - { - // Don't change m_fShiftMod. - m_mAdvanceX = short(m_mJWidth0 + AdvanceX(ptman)); // make sure it is calculated - m_mJWidth0 = 0; - m_fAdvXSet = true; // for transduction logging - } - - int PostBidiDirLevel(GrTableManager * ptman); - - bool BaseEarlierInStream(); - - void ZapDirLevel() - { - m_nDirLevel = -1; - m_dircProc = kdircUnknown; - m_fDirProcessed = false; - } - - int GlyphAttrValueEmUnits(GrTableManager * ptman, int nAttrID); - int GlyphMetricEmUnits(GrTableManager * ptman, int nGlyphMetricID); - - float GlyphAttrValueLogUnits(GrTableManager * ptman, int nAttrID); - float GlyphMetricLogUnits(GrTableManager * ptman, int nGlyphMetricID); - -// void HandleModifiedCluster(GrTableManager * ptman, -// GrSlotStream * psstrm, int islotThis); - void HandleModifiedPosition(GrTableManager * ptman, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, int islotThis); - - void CalcCompositeMetrics(GrTableManager * ptman, GrSlotStream * psstrm, - int nLevel, bool fThorough = false); - - void Position(GrTableManager * ptman, - GrSlotStream * psstrmOut, int * pmXPos, int * pmYPos); - - void ZapPosition() - { - m_xsPositionX = kNegInfFloat; - m_ysPositionY = kNegInfFloat; - } - - void SetXPos(float xs) - { - m_xsPositionX = xs; - } - void SetYPos(float ys) - { - m_ysPositionY = ys; // relative to baseline (positive is up) - } - - float ClusterRootOffset() { return -m_xsClusterXOffset; } // the offset of the root - // relative to the whole cluster - - float ClusterAdvWidthFrom(float xs) { return xs + m_xsClusterAdv; } - float ClusterBbLeftFrom(float xs) { return xs + m_xsClusterBbLeft; } - float ClusterBbRightFrom(float xs) { return xs + m_xsClusterBbRight; } - - float ClusterLsb(GrSlotStream * psstrm, float xs) - { - return ClusterBbLeft(psstrm) + xs; - } - float ClusterRsb(GrSlotStream * psstrm, float xs) - { - return ClusterAdvWidthFrom(xs) - ClusterBbRightFrom(xs); - } - - float ClusterAdvWidth(GrSlotStream * psstrm) - { - return ClusterAdvWidthFrom(Base(psstrm)->ClusterRootOffset()); - } -// int ClusterAdvHeight(GrSlotStream * psstrm) -// { -// Assert(m_mAdvanceY != kNotYetSet); -// return EmUnitsToTwips(m_mAdvanceY); -// } - float ClusterBbLeft(GrSlotStream * psstrm) - { - return ClusterBbLeftFrom(Base(psstrm)->ClusterRootOffset()); - } - float ClusterBbRight(GrSlotStream * psstrm) - { - return ClusterBbRightFrom(Base(psstrm)->ClusterRootOffset()); - } - float ClusterBbTop(GrSlotStream * psstrm) - { - return m_ysClusterBbTop; - } - float ClusterBbBottom(GrSlotStream * psstrm) - { - return m_ysClusterBbBottom; - } - float ClusterBbWidth(GrSlotStream * psstrm) - { - return m_xsClusterBbRight - m_xsClusterBbLeft + 1; - } - float ClusterBbHeight(GrSlotStream * psstrm) - { - return m_ysClusterBbTop - m_ysClusterBbBottom + 1; - } - float ClusterLsb(GrSlotStream * psstrm) - { - return ClusterBbLeft(psstrm); - } - float ClusterRsb(GrSlotStream * psstrm) - { - return ClusterAdvWidth(psstrm) - ClusterBbRight(psstrm); - } - - float GlyphXOffset(GrSlotStream * psstrm, float fakeItalicRatio = 0); - float GlyphYOffset(GrSlotStream * psstrm = NULL); - - bool IsBase() - { - Assert(m_dislotRootFixed == m_srAttachTo); - return (m_dislotRootFixed == 0); - } - - bool HasClusterMembers() - { - return (m_vdislotAttLeaves.size() > 0); - } - - GrSlotState * AttachRoot(GrSlotStream * psstrm) - { - if (m_srAttachTo == 0) - return NULL; - else - return SlotAtOffset(psstrm, m_srAttachTo); - } - - int AttachRootPosPassIndex() - { - return PosPassIndex() + m_srAttachTo; - } - - GrSlotState * Base(GrSlotStream * psstrm) - { - GrSlotState * pslotRoot = AttachRoot(psstrm); - if (!pslotRoot) - return this; - else - return pslotRoot->Base(psstrm); - } - - int LastLeafOffset(GrSlotStream * psstrm); - - void AddLeaf(int dislot) - { - m_vdislotAttLeaves.push_back(dislot * -1); - } - void RemoveLeaf(int dislot) - { - for (size_t iislot = 0; iislot < m_vdislotAttLeaves.size(); iislot++) - { - if (m_vdislotAttLeaves[iislot] == dislot * -1) - { - m_vdislotAttLeaves.erase(m_vdislotAttLeaves.begin() + iislot); - return; - } - } - Assert(false); - } - - bool HasAsRoot(GrSlotStream * psstrm, GrSlotState * pslot) - { - GrSlotState * pslotRoot = AttachRoot(psstrm); - if (pslotRoot == pslot) - return true; - else if (pslotRoot == NULL) - return false; - else - return pslotRoot->HasAsRoot(psstrm, pslot); - } - - bool HasAsPreviousState(GrSlotState * pslot) - { - if (this == pslot) - return true; - else - return m_pslotPrevState->HasAsPreviousState(pslot); - } - - void EnsureCacheForOutput(GrTableManager * ptman); - - bool IsLrm(); - bool IsRlm(); - - // Cache of FSM column information for the most recent pass: - int FsmColumn() { return m_colFsm; } - int PassNumberForColumn() { return m_ipassFsmCol; } - void CacheFsmColumn(int ipass, int col) - { - m_colFsm = col; - m_ipassFsmCol = ipass; - } - - // Variable-length buffer--includes four sub-buffers: - // * user-defined variables - // * component.???.ref assignments - // * mapping from components used to global attribute IDs for components - // * feature values - - // user-defined slot attributes - int UserDefn(int slati) - { - Assert(slati < m_cnUserDefn); - return m_prgnVarLenBuf[slati].nValue; - } - void SetUserDefn(int slati, int nVal) - { - Assert(slati < m_cnUserDefn); - m_prgnVarLenBuf[slati].nValue = nVal; - } - u_intslot * PUserDefnBuf() - { - return m_prgnVarLenBuf; - } - - // pointer to the associated slot which is the value of the comp.ref attribute - GrSlotState * CompRef(int slati) - { - Assert(slati < m_cnCompPerLig); - return m_prgnVarLenBuf[m_cnUserDefn + slati].pslot; - } - void SetCompRef(int slati, GrSlotState * pvSlot) - { - Assert(slati < m_cnCompPerLig); - m_prgnVarLenBuf[m_cnUserDefn + slati].pslot = pvSlot; - } - u_intslot * PCompRefBuf() - { - return m_prgnVarLenBuf + m_cnUserDefn; - } - - // global component identifier - int Slati(int i) - { - Assert(i < m_cnCompPerLig); - return m_prgnVarLenBuf[m_cnUserDefn + m_cnCompPerLig + i].nValue; - } - void SetSlati(int i, int n) - { - Assert(i < m_cnCompPerLig); - m_prgnVarLenBuf[m_cnUserDefn + m_cnCompPerLig + i].nValue = n; - } - u_intslot * PSlatiBuf() - { - return m_prgnVarLenBuf + m_cnUserDefn + m_cnCompPerLig; - } - - // feature settings - int FeatureValue(int i) - { - Assert(i < m_cnFeat); - return m_prgnVarLenBuf[m_cnUserDefn + (m_cnCompPerLig * 2) + i].nValue; - } - - u_intslot * PFeatureBuf() - { - return m_prgnVarLenBuf + m_cnUserDefn + (m_cnCompPerLig * 2); - } - - int CExtraSpace() - { - return m_cnUserDefn + (m_cnCompPerLig * 2) + m_cnFeat; - } - - GrSlotState * CompRefSlot(int i); - - void GetFeatureValues(GrFeatureValues * pfval) - { - pfval->m_nStyleIndex = m_bStyleIndex; - std::fill(pfval->m_rgnFValues, pfval->m_rgnFValues + kMaxFeatures, 0); - for (size_t i = 0; i < m_cnFeat; i++) - pfval->m_rgnFValues[i] = PFeatureBuf()[i].nValue; - } - - // For transduction logging: -#ifdef TRACING - void SlotAttrsModified(bool * rgfMods, bool fPreJust, int * pccomp, int * pcassoc); - void LogSlotAttributeValue(GrTableManager *, std::ostream &, int ipass, int slat, int icomp, - bool fPreJust, bool fPostJust); - void LogAssociation(GrTableManager * ptman, - std::ostream & strmOut, int ipass, int iassoc, bool fBoth, bool fAfter); - void LogXmlAttributes(std::ostream & strmOut, GrTableManager * ptman, GrSlotStream * psstrmOut, - int ipass, int islot, - bool fPreJust, bool fPostJust, bool fBidi, bool fBidiNext, int nIndent); - int GetSlotAttrValue(std::ostream & strmOut, GrTableManager * ptman, - int ipass, int slat, int iIndex, bool fPreJust, bool fPostJust); - int m_islotTmpIn; // for use by transduction log; index of slot in input stream - int m_islotTmpOut; // ditto; index of slot in output stream -#endif // TRACING - -protected: - - // Instance variables: - int m_ipassModified; // pass in which this slot was modified - - GrSlotState * m_pslotPrevState; - - int m_ichwSegOffset; // for original (pass 0) slot states: position in - // underlying text relative to the official - // beginning of the segment; - // should == kInvalid for other slot states - int m_islotPosPass; // index of slot in positioning streams, relative to first official - // slot in the segment (possibly the LB slot) - - int m_colFsm; // which FSM column this glyph corresponds to... - int m_ipassFsmCol; // ...for the most recent pass - - std::vector<GrSlotState*> m_vpslotAssoc; // association mappings - - bool m_fNeutralAssocs; // true if we've set the associations to some neutral - // default, rather than them being set explicitly - // within a rule - - int m_nUnicode; // for debugging - - DirCode m_dircProc; // directionality as processed in bidi algorithm - bool m_fDirProcessed; - - // affects length of variable-length buffer - byte m_cnUserDefn; - byte m_cnFeat; - - byte m_bStyleIndex; - - // Slot attributes: - short m_mAdvanceX; - short m_mAdvanceY; - short m_mShiftX; - short m_mShiftY; - - short m_srAttachTo; - short m_nAttachLevel; - - short m_mAttachAtX; - short m_mAttachAtY; - short m_mAttachAtXOffset; - short m_mAttachAtYOffset; - short m_mAttachWithX; - short m_mAttachWithY; - short m_mAttachWithXOffset; - short m_mAttachWithYOffset; - - short m_nAttachAtGpoint; - short m_nAttachWithGpoint; - - // Raw glyph metrics (directly from font) - float m_xysFontAscent; - float m_xysFontDescent; - float m_xysGlyphWidth; - float m_xysGlyphHeight; - float m_xysGlyphX; - float m_xysGlyphY; - float m_xysAdvX; - float m_xysAdvY; - - // Attachment and metrics - - // This is a flag that is set whenever we change the value of any of the attach - // slot attributes. Then when we want to find out something about the attachments, - // if it is set, we have some work to do in updating the pointers and metrics. - bool m_fAttachMod; - - // This is a flag that is set whenever we change the value of any of the shift or - // advance slot attributes. It forces us to zap the metrics. - bool m_fShiftMod; - - // This glyph (and all its leaves, if any) have a zero advance width; - // never allow it to affect the advance width of a cluster it is part of. - bool m_fIgnoreAdvance; - - int m_dislotRootFixed; // the offset of the slot (relative to this one) that considers - // this slot to be one of its leaves - std::vector<int> m_vdislotAttLeaves; - - // The following are used by the CalcCompositeMetrics() method and depend on - // the cluster level that was passed as an argument. - - int m_nCompositeLevel; // cluster level last used to calculate composite metrics; - // kNegInfinity if uncalculated - - // offsets for this node only, relative to cluster base - float m_xsOffsetX; - float m_ysOffsetY; // relative to baseline (positive is up) - - // offsets for this node and its leaves, relative to cluster base (y-coords are - // relative to baseline) - float m_xsClusterXOffset; - float m_xsClusterAdv; - float m_xsClusterBbLeft; - float m_xsClusterBbRight; - float m_ysClusterBbTop; - float m_ysClusterBbBottom; - - // cumulative total of shifts for this node and roots; advance needs to ignore these - float m_xsRootShiftX; - float m_ysRootShiftY; - - bool m_fHasComponents; // default = false - - // Private methods: - - void CopyAbstractFrom(GrSlotState * pslot); - - void AdjustRootMetrics(GrTableManager * ptman, GrSlotStream *); - void InitMetrics(GrTableManager * ptman, GrSlotState * pslotRoot); - void InitLeafMetrics(GrTableManager * ptman, GrSlotState * pslotRoot); - void InitRootMetrics(GrTableManager * ptman); - void CalcRootMetrics(GrTableManager * ptman, GrSlotStream *, int nLevel); - void AttachToRoot(GrTableManager * ptman, GrSlotStream *, GrSlotState * pslotNewRoot); - void AttachLogUnits(GrTableManager * ptman, - GrSlotState * pslotRoot, - float * pxsAttAtX, float * pysAttAtY, - float * pxsAttWithX, float * pysAttWithY); - - GrSlotState * SlotAtOffset(GrSlotStream * psstrm, int dislot); // ENHANCE SharonC: inline? - - void EnsureLocalAttachmentTree(GrTableManager * ptman, - GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, int islotThis); - - void ZapCompositeMetrics() - { - m_nCompositeLevel = kNegInfinity; - m_xsPositionX = kNegInfFloat; - m_ysPositionY = kNegInfFloat; - m_xsOffsetX = 0; - m_ysOffsetY = 0; - m_xsRootShiftX = 0; - m_ysRootShiftY = 0; - ZapRootMetrics(); - } - - void ZapRootMetrics() - { - m_xsClusterXOffset = 0; - m_xsClusterAdv = 0; - m_xsClusterBbLeft = 0; - m_xsClusterBbRight = 0; - m_ysClusterBbTop = 0; - m_ysClusterBbBottom = 0; - m_fIgnoreAdvance = false; - } - - void ZapMetricsAndPositionDownToBase(GrSlotStream * psstrm) - { - ZapCompositeMetrics(); - if (m_dislotRootFixed) - SlotAtOffset(psstrm, m_dislotRootFixed)->ZapMetricsAndPositionDownToBase(psstrm); - } - - void ZapMetricsOfLeaves(GrSlotStream * psstrm, bool fThis = false) - { - if (fThis) - ZapCompositeMetrics(); - for (size_t islot = 0; islot < m_vdislotAttLeaves.size(); islot++) - { - SlotAtOffset(psstrm, m_vdislotAttLeaves[islot])->ZapMetricsOfLeaves(psstrm, true); - } - } - -public: // for transduction logging - bool m_fAdvXSet; - bool m_fAdvYSet; - -}; // end of class GrSlotState - - -/*---------------------------------------------------------------------------------------------- - A GrSlotOutput represents one slot as the final output of the final pass. These - are recorded in the segment. - - Hungarian: slout -----------------------------------------------------------------------------------------------*/ -class GrSlotOutput : public GrSlotAbstract -{ - friend class GlyphInfo; - friend class Segment; - friend class SegmentMemoryUsage; - -public: - GrSlotOutput() - { - m_cComponents = 0; - m_isloutClusterBase = -1; // not part of any cluster - m_disloutCluster = 0; - m_igbb = -1; - } - - void ExactCopyFrom(GrSlotOutput * pslout, u_intslot * pnVarLenBuf, int cnExtraPerSlot); - - void InitializeOutputFrom(GrSlotState * pslot); - - int BeforeAssoc() - { - return m_ichwBeforeAssoc; // relative to the official beginning of the segment - } - int AfterAssoc() - { - return m_ichwAfterAssoc; // relative to the official beginning of the segment - } - - void SetBeforeAssoc(int ichw) - { - m_ichwBeforeAssoc = ichw; - } - void SetAfterAssoc(int ichw) - { - m_ichwAfterAssoc = ichw; - } - void AddComponentReference(int ichw, int slati) - { - if (m_cComponents >= m_cnCompPerLig) - { - Assert(false); // ignore the requested component ref - } - else - { - m_prgnVarLenBuf[m_cComponents].nValue - = ichw; - - // OBSOLETE comment: - // Maps the used components to the defined components. Normally this will be - // one-to-one and the buffer will hold [0,1,2...]. But possibly we may - // have defined components a, b, and c, but only mapped a and c to actual - // characters. This buffer will then hold [0,2]. - - m_prgnVarLenBuf[m_cnCompPerLig + m_cComponents].nValue - = slati; - -// Assert(iComp >= m_cComponents); // because we process them in order they are defined - // in, but we could have skipped some that are - // defined - m_cComponents++; - } - } - int NumberOfComponents() // the number used by the rules - { - return m_cComponents; - } - // Index of ligature components, relative to the beginning of the segment. - // iComp is index of components USED in this glyph. - int UnderlyingComponent(int iComp) - { - Assert(iComp < m_cnCompPerLig); - return m_prgnVarLenBuf[iComp].nValue; - } - int ComponentId(int iComp) - { - return m_prgnVarLenBuf[m_cnCompPerLig + iComp].nValue; - } - - //u_intslot * PCompRefBufSlout() - //{ - // return m_prgnVarLenBuf; - //} - - int CExtraSpaceSlout() - { - return (m_cnCompPerLig * 2); - } - - void SetClusterBase(int islout) - { - m_isloutClusterBase = islout; - } - - int ClusterBase() - { - return m_isloutClusterBase; - } - - bool IsPartOfCluster() - { - return (m_isloutClusterBase > -1); - } - - //int NumClusterMembers() - //{ - // return m_visloutClusterMembers.size(); - //} - //int ClusterMember(int iislout) - //{ - // return m_visloutClusterMembers[iislout]; - //} - - void AddClusterMember(int isloutThis, int isloutAttached) - { - m_disloutCluster = sdata8(max(int(m_disloutCluster), abs(isloutThis - isloutAttached))); - } - - void ClusterMembers(Segment * pseg, int islout, std::vector<int> & visloutRet); - - int ClusterRange() - { - return m_disloutCluster; - } - - float ClusterXOffset() { return m_xsClusterXOffset; } - float ClusterAdvance() { return m_xsClusterAdvance; } - void SetClusterXOffset(float xs) { m_xsClusterXOffset = xs; } - void SetClusterAdvance(float xs) { m_xsClusterAdvance = xs; } - - float GlyphMetricLogUnits(Font * pfont, int nGlyphMetric); - //float GlyphMetricLogUnits(int nMetricID); - - int GlyphBbIndex() { return m_igbb; } - void SetGlyphBbIndex (int i) { m_igbb = i; } - - Rect BoundingBox(Font & font) - { - Rect rectBB; - rectBB.left = m_xsPositionX + GlyphMetricLogUnits(&font, kgmetBbLeft); - if (IsSpace()) - rectBB.right = m_xsPositionX + GlyphMetricLogUnits(&font, kgmetAdvWidth); - else - rectBB.right = m_xsPositionX + GlyphMetricLogUnits(&font, kgmetBbRight); - rectBB.top = m_ysPositionY + GlyphMetricLogUnits(&font, kgmetBbTop); - rectBB.bottom = m_ysPositionY + GlyphMetricLogUnits(&font, kgmetBbBottom); - return rectBB; - } - - bool IsLineBreak() - { - return (IsInitialLineBreak() || IsFinalLineBreak()); - } - bool IsInitialLineBreak() - { - return (m_spsl == kspslLbInitial); - } - bool IsFinalLineBreak() - { - return (m_spsl == kspslLbFinal); - } - - //float AdvanceXMetric() - //{ - // return m_xysAdvX; - //} - - bool IsSpace(); - - void AdjustPosXBy(float dxs) - { - m_xsPositionX += dxs; - //m_rectBB.left += dxs; - //m_rectBB.right += dxs; - } - - void ShiftForDirDepthChange(float dxsSegWidth); - - // Used by GlyphInfo - int IndexAttachedTo(); - //inline float AdvanceX(Segment * pseg); - //inline float AdvanceY(Segment * pseg); - float MaxStretch(Segment * pseg, int level); - float MaxShrink(Segment * pseg, int level); - float StretchStep(Segment * pseg, int level); - int JustWeight(int level); - float JustWidth(Segment * pseg, int level); - float MeasureSolLogUnits(Segment * pseg); - float MeasureEolLogUnits(Segment * pseg); - Rect ComponentRect(Segment * pseg, int icomp); - -protected: - // Instance variables: - - sdata8 m_cComponents; - - data8 m_disloutCluster; // how far to search on either side of this glyph to find - // other members of the cluster; - // 0 means there are no cluster members or this glyph is - // attached to some other base - - int m_isloutClusterBase; // the index of the slot that serves as the base for the - // cluster this slot is a part of; -1 if not part of cluster - - int m_ichwBeforeAssoc; // index of associated character in the string - int m_ichwAfterAssoc; // (relative to the official beginning of the segment) - // char might possibly not be officially in this segment, - // in which case value is infinity - - // Measurements for highlighting an entire cluster, relative to origin of this slot, - // which is the cluster base. - float m_xsClusterXOffset; - float m_xsClusterAdvance; // for single non-cluster glyphs, advance width of positioned glyph - - // Index into m_prggbb in Segment; -1 indicates a line break slot that is not rendered: - int m_igbb; - - float m_xsAdvanceX; -// float m_ysAdvanceY; -- not used -// Rect m_rectBB; - -}; // end of class GrSlotOutput - -} // namespace gr - - -#endif // !SLOTSTATE_INCLUDED diff --git a/Build/source/libs/graphite-engine/src/segment/GrSlotStream.cpp b/Build/source/libs/graphite-engine/src/segment/GrSlotStream.cpp deleted file mode 100644 index db6a5c8af7e..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrSlotStream.cpp +++ /dev/null @@ -1,2368 +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: GrSlotStream.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - GrSlotStream class implementation. -----------------------------------------------------------------------------------------------*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" - -#include "GrConstants.h" - -#ifdef _MSC_VER -#pragma hdrstop -#endif -#undef THIS_FILE -DEFINE_THIS_FILE - -//:End Ignore - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -namespace gr -{ - -//:>******************************************************************************************** -//:> Methods -//:>******************************************************************************************** - -/*---------------------------------------------------------------------------------------------- - Answer true if there is nothing valid available to read from the stream. -----------------------------------------------------------------------------------------------*/ -bool GrSlotStream::AtEnd() -{ - Assert(AssertValid()); - - if (m_islotReprocPos > -1 && m_islotReprocPos < signed(m_vpslotReproc.size())) - return false; - - if (m_islotSegLim > -1 && m_islotReadPos >= m_islotSegLim) - // We've determined the segment limit, and we're at or past it. - return true; - - return (m_islotReadPos == m_islotWritePos); -} - -/*---------------------------------------------------------------------------------------------- - Answer true if there is nothing at all available to read from the stream. - For substitution passes, we need to consider slots that may be beyond what we know - will be the official end of the segment. -----------------------------------------------------------------------------------------------*/ -bool GrSlotStream::AtEndOfContext() -{ - if (m_fUsedByPosPass) - return AtEnd(); - - if (m_islotReprocPos > -1 && m_islotReprocPos < signed(m_vpslotReproc.size())) - return false; - - return (m_islotReadPos == m_islotWritePos); -} - -/*---------------------------------------------------------------------------------------------- - Append a slot to the end of the stream. -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::NextPut(GrSlotState * pslot) -{ - Assert(AssertValid()); - - if (m_islotWritePos < signed(m_vpslot.size())) - { - m_vpslot[m_islotWritePos] = pslot; - } - else - { - m_vpslot.push_back(pslot); - m_vislotPrevChunkMap.push_back(-1); - m_vislotNextChunkMap.push_back(-1); - } - - if (m_fUsedByPosPass && GotIndexOffset()) - pslot->SetPosPassIndex(m_islotWritePos - m_cslotPreSeg, m_fInputToPosPass1); - - m_islotWritePos++; -} - -/*---------------------------------------------------------------------------------------------- - Get the next slot from the stream. -----------------------------------------------------------------------------------------------*/ -GrSlotState * GrSlotStream::NextGet() -{ - Assert(AssertValid()); - Assert(!AtEndOfContext()); - - GrSlotState * pslotRet; - - if (m_islotReprocPos > -1) - { - if (m_islotReprocPos >= signed(m_vpslotReproc.size())) - { - // Finished reprocessing. - Assert((unsigned)m_islotReprocPos == m_vpslotReproc.size()); - m_islotReprocPos = -1; - // But leave the m_vpslotReproc array in place so that earlier slots can - // be accessed by the rules. - pslotRet = m_vpslot[m_islotReadPos]; - m_islotReadPos++; - } - else - { - // Read from the reprocess buffer. - pslotRet = m_vpslotReproc[m_islotReprocPos]; - m_islotReprocPos++; - } - } - else - { - // Read normally. - pslotRet = m_vpslot[m_islotReadPos]; - m_islotReadPos++; - } - - Assert(!m_fUsedByPosPass || pslotRet->PosPassIndex() != GrSlotAbstract::kNotYetSet); - - return pslotRet; -} - -/*--------------------------------------------------------------------------------------------- - Peek at the next slot from the stream (dislot = 0 means the very next slot). - Only used for peeking forward. RuleInputSlot is used for accessing any possible - slot in the rule's context. -----------------------------------------------------------------------------------------------*/ -GrSlotState * GrSlotStream::Peek(int dislot) -{ - Assert(AssertValid()); - Assert(!AtEndOfContext()); - Assert(dislot >= 0); - - GrSlotState * pslotRet; - - if (m_islotReprocPos > -1) - { - int cslotReproc = m_vpslotReproc.size() - m_islotReprocPos; // num left in reproc buffer - if (dislot >= cslotReproc) - { - // Not quite enough slots in the reprocess buffer. - pslotRet = m_vpslot[m_islotReadPos + dislot - cslotReproc]; - } - else if (m_islotReprocPos + dislot < 0) - { - // Reading prior to the reprocess buffer - pslotRet = m_vpslot[m_islotReadPos + dislot - cslotReproc]; - } - else - { - // Read from the reprocess buffer. - pslotRet = m_vpslotReproc[m_islotReprocPos + dislot]; - } - } - else - { - // Read normally. - Assert(m_islotWritePos - m_islotReadPos > dislot); - pslotRet = m_vpslot[m_islotReadPos + dislot]; - } - - return pslotRet; -} - -/*--------------------------------------------------------------------------------------------- - Treat the stream, which is really the output stream, as an input stream, - retrieving a recently output slot. This happens when we are reading before the - current stream position when the rule is being matched, or before the original - stream position when the rule is being run. - - @param dislot - how far back to peek before the write position - when the rule started; a negative number - (NOTE: the current write position is irrelevant) - @param fNullOkay - true if it's okay to return NULL in the situation where we're asking - for something before the beginning of the stream -----------------------------------------------------------------------------------------------*/ -GrSlotState * GrSlotStream::PeekBack(int dislot, bool fNullOkay) -{ - Assert(dislot < 0); - if (dislot < m_islotRuleStartWrite * -1) - { - Assert(fNullOkay); - return NULL; - } - GrSlotState * pslotRet; - if (m_islotReprocPos > -1) - { - if (dislot < m_islotReprocLim - m_islotRuleStartWrite && - dislot >= m_islotReprocLim - m_islotRuleStartWrite - signed(m_vpslotReproc.size())) - { - // Read from the reprocess buffer. - // Review: this is weird; can it ever happen? - pslotRet = m_vpslotReproc[m_vpslotReproc.size() - - (m_islotReprocLim - m_islotRuleStartWrite) + dislot]; - } - else - pslotRet = m_vpslot[m_islotRuleStartWrite + dislot]; - } - else - pslotRet = m_vpslot[m_islotRuleStartWrite + dislot]; - - return pslotRet; -} - -/*--------------------------------------------------------------------------------------------- - Skip the given number of slots in the stream. - ENHANCE: implement more efficiently -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::Skip(int dislot) -{ - for (int islot = 0; islot < dislot; ++islot) - NextGet(); -} - -/*---------------------------------------------------------------------------------------------- - Perform assertions to ensure that the stream is in a valid state. -----------------------------------------------------------------------------------------------*/ -bool GrSlotStream::AssertValid() -{ - Assert(m_islotWritePos <= signed(m_vpslot.size())); - Assert(m_islotReadPos <= m_islotWritePos); - // Streams used by the positioning passes (input or output) should not be working - // with slots beyond the segment lim - Assert(m_islotSegLim == -1 || !m_fUsedByPosPass || m_islotReadPos <= m_islotSegLim); - Assert(m_vpslot.size() == m_vislotPrevChunkMap.size()); - Assert(m_vpslot.size() == m_vislotNextChunkMap.size()); - return true; -} - -/*---------------------------------------------------------------------------------------------- - Return the number of slots that have been completely output by the previous pass but not - yet processed by the following pass. ("Completely" output means that they do not need - to be reprocessed by the same pass, only then are they available as valid input.) - Include any slots that are present by virtue of needing to be reprocessed by the - corresponding output stream. -----------------------------------------------------------------------------------------------*/ -int GrSlotStream::SlotsPending() -{ - Assert(AssertValid()); - if (m_islotSegLim > -1) - return (m_islotSegLim - m_islotReadPos + SlotsToReprocess()); - else - return (m_islotWritePos - m_islotReadPos + SlotsToReprocess()); -} - -int GrSlotStream::SlotsPendingInContext() -{ - Assert(AssertValid()); - if (m_fUsedByPosPass) - return SlotsPending(); - else - return (m_islotWritePos - m_islotReadPos + SlotsToReprocess()); -} - -int GrSlotStream::TotalSlotsPending() -{ - int cslot = SlotsPendingInContext(); - if (m_fUsedByPosPass && m_islotSegLim > -1) - { - int ctmp = m_islotWritePos - m_islotReadPos + SlotsToReprocess(); - if (ctmp > cslot) - { - int x; x = 3; - } - cslot = max(cslot, ctmp); - } - return cslot; -} - -/*---------------------------------------------------------------------------------------------- - Return true if this pass is input or output to a positioning pass and we're past the end - of the segment. So this stream is virtually finished. -----------------------------------------------------------------------------------------------*/ -bool GrSlotStream::PastEndOfPositioning(bool fOutput) -{ - if (m_fUsedByPosPass && m_islotSegLim > -1) - { - if (fOutput) // this stream is functioning as an output stream - return (m_islotWritePos >= m_islotSegLim); - else // this stream is functioning as an input stream - return (m_islotReadPos >= m_islotSegLim); - } - return false; -} - -/*---------------------------------------------------------------------------------------------- - Mark the stream as fully written, so that the output pass doesn't keep trying to ask - for more input. -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::MarkFullyWritten() -{ - m_fFullyWritten = true; -} - -/*---------------------------------------------------------------------------------------------- - Return the position of the first glyph at or following the given position - that is in the top direction, or -1 if we do not have a complete range. - - @param ptman - @param islotStart - @nTopDirLevel - top direction: 0 = left-to-right, 1 = right-to-left -----------------------------------------------------------------------------------------------*/ -int GrSlotStream::OldDirLevelRange(EngineState * pengst, int islotStart, int nTopDirLevel) -{ - Assert(m_islotReadPos <= islotStart); - Assert(islotStart < m_islotWritePos); - - int islot = islotStart; - int nSlotDirLevel = GetSlotDirLevel(pengst, islot, nTopDirLevel, nTopDirLevel, - kdircUnknown, kdircNeutral); - if (nSlotDirLevel == -1) - return -1; - while (nSlotDirLevel > nTopDirLevel) - { - islot++; - if (islot >= m_islotWritePos) - { - if (m_fFullyWritten) - return islot; - else - return -1; - } - else if (m_islotSegLim > -1 && islot >= m_islotSegLim) - { - return islot; - } - - nSlotDirLevel = GetSlotDirLevel(pengst, islot, nTopDirLevel, nTopDirLevel, - kdircUnknown, kdircNeutral); - if (nSlotDirLevel == -1) - return -1; - } - return islot; -} - -/*---------------------------------------------------------------------------------------------- - Return the position of the first glyph at or following the given position - that is in the top direction, or -1 if we do not have a complete range. - - @param ptman - @param islotStart - @nTopDirLevel - top direction: 0 = left-to-right, 1 = right-to-left -----------------------------------------------------------------------------------------------*/ -int GrSlotStream::DirLevelRange(EngineState * pengst, int islotStart, int nTopDirLevel, - std::vector<int> & vislotStarts, std::vector<int> & vislotStops) -{ - Assert(m_islotReadPos <= islotStart); - Assert(islotStart < m_islotWritePos); - - std::vector<int> vislotStartStack; // indices of starts of ranges to reverse - - // Stack corresponding to embedding and override markers: - std::vector<DirCode> vdircMarkerStack; - std::vector<DirCode> vdircOverrideStack; - std::vector<int> vnLevelStack; - - vislotStarts.clear(); - vislotStops.clear(); - - //vislotStartStack.Push(islot); - - int islotSegLim = (FullyWritten() || m_islotSegLim > -1) ? - FinalSegLim() : - WritePos() + 100; // arbitrarily large number - - if (islotStart > islotSegLim) - { - // Don't do anything fancy with stuff beyond the end of the segment. - return 0; - } - - DirCode dircMarker = kdircNeutral; // none so far - int nCurrLevel = nTopDirLevel; - int nMarkerLevel = nTopDirLevel; - //bool fHitMark = false; - DirCode dircOverride = kdircNeutral; - int islot = islotStart; - Assert(islot <= m_islotWritePos); - - while (true) - { - GrSlotState * pslot = m_vpslot[islot]; - DirCode dirc = pslot->DirProcessed(); - bool fIncludeLast = false; - int nSlotDirLevel; - if (dirc == kdircLRO || dirc == kdircLRE) // steps X1, X3 in the Unicode bidi algorithm - { - vdircMarkerStack.push_back(dircMarker); - vdircOverrideStack.push_back(dircOverride); - vnLevelStack.push_back(nCurrLevel); - dircMarker = dirc; - dircOverride = (dirc == kdircLRO) ? kdircL : kdircNeutral; - nSlotDirLevel = (nCurrLevel % 2) ? - nCurrLevel + 1 : nCurrLevel + 2; // next highest LTR level - nMarkerLevel = nSlotDirLevel; - - pslot->SetDirProcessed(dircMarker); - pslot->SetDirLevel(nMarkerLevel); - pslot->MarkDirProcessed(); - } - else if (dirc == kdircRLO || dirc == kdircRLE) // steps X2, X4 - { - vdircMarkerStack.push_back(dircMarker); - vdircOverrideStack.push_back(dircOverride); - vnLevelStack.push_back(nCurrLevel); - dircMarker = dirc; - dircOverride = (dirc == kdircRLO) ? kdircR : kdircNeutral; - nSlotDirLevel = (nCurrLevel % 2) ? - nCurrLevel + 2 : nCurrLevel + 1; // next highest RTL level - nMarkerLevel = nSlotDirLevel; - - pslot->SetDirProcessed(dircMarker); - pslot->SetDirLevel(nMarkerLevel); - pslot->MarkDirProcessed(); - } - else if (dirc == kdircPDF) - { - if (dircMarker == kdircNeutral) - pslot->SetDirProcessed((nCurrLevel % 2) ? kdircR : kdircL); - else - pslot->SetDirProcessed(RightToLeftDir(dircMarker) ? kdircPdfR : kdircPdfL); - pslot->SetDirLevel(nMarkerLevel); - pslot->MarkDirProcessed(); - - if (vnLevelStack.size()) - { - dircMarker = vdircMarkerStack.back(); - vdircMarkerStack.pop_back(); - dircOverride = vdircOverrideStack.back(); - vdircOverrideStack.pop_back(); - nMarkerLevel = vnLevelStack.back(); - vnLevelStack.pop_back(); - nSlotDirLevel = nMarkerLevel; - fIncludeLast = true; - } - else // ignore - nSlotDirLevel = nCurrLevel; - } - else - { - nSlotDirLevel = GetSlotDirLevel(pengst, islot, nTopDirLevel, nMarkerLevel, - dircMarker, dircOverride); - if (nSlotDirLevel == -1) - return -1; // not enough slots - } - - Assert(pengst->WhiteSpaceOnly() || nCurrLevel >= nTopDirLevel); - while (nSlotDirLevel > nCurrLevel) - { - vislotStartStack.push_back(islot); - nCurrLevel++; - } - // otherwise... - while (nTopDirLevel <= nCurrLevel && nSlotDirLevel < nCurrLevel) - { - if (vislotStartStack.size()) - { - int islotStartTmp = vislotStartStack.back(); - vislotStartStack.pop_back(); - vislotStarts.push_back(islotStartTmp); - vislotStops.push_back(islot - 1); // previous character was the end of the range - } - else - Assert(pengst->WhiteSpaceOnly()); // the space is higher than the segment itself - nCurrLevel--; - } - // In the case of white-space-only segments, the space may be bumped up to a level - // higher than the segment itself. - Assert(pengst->WhiteSpaceOnly() || vislotStartStack.size() + nTopDirLevel == (unsigned)nCurrLevel); - Assert(pengst->WhiteSpaceOnly() || vnLevelStack.size() == vdircMarkerStack.size()); - Assert(pengst->WhiteSpaceOnly() || vdircOverrideStack.size() == vdircMarkerStack.size()); - - if (nCurrLevel <= nTopDirLevel) - { - if (fIncludeLast) - { - // Include in the range to reverse the PDF or the char after the LRM/RLM. - // (Note: don't use a size_t below: we are decrementing below zero.) - for (int i = signed(vislotStops.size()) - 1; i >= 0 && vislotStops[i] == islot-1; i--) - { - vislotStops[i] = islot; - } - islot++; - } - break; // reached end of reversible range - } - - islot++; - if (islot >= m_islotWritePos) - { - if (m_fFullyWritten) - break; // end of input - else - return -1; // not enough slots - } - else if (islot >= islotSegLim) - { - break; // end of input - } - } - - // Reached the end of a reversable range. - while (vislotStartStack.size() > 0) - { - int islotStartTmp = vislotStartStack.back(); - vislotStartStack.pop_back(); - vislotStarts.push_back(islotStartTmp); - //vislotStops.push_back(min(islot, ReadPos() - 1)); - //vislotStops.push_back(min(islot, max(ReadPos() - 1, islotStartTmp))); - vislotStops.push_back(min(islot - 1, islotSegLim - 1)); - nCurrLevel--; - } - Assert(pengst->WhiteSpaceOnly() || nCurrLevel == nTopDirLevel); - Assert(vislotStarts.size() == vislotStops.size()); - - // The start- and stop-lists were generated in the order that we hit the stops, in other - // words, from inner to outer. Which is the order in which we need to do the reversals, too. - - return islot; -} - - -/*---------------------------------------------------------------------------------------------- - Return the direction level of the glyph at the given position, according to the - Unicode bidi algorithm. Return -1 if there aren't enough slots in the stream to - figure it out. - - ???? How should this handle the reprocessing sub-stream???? - - @param ptman - @param islot - slot for which information is requested - @param nOuterLevel - 0 = left-to-right, 1 = right-to-left - @param nCurrLevel - @param dircMarker - most recent override or embedding marker, if any - (for interpreting PDF codes) - @param dircOverride - override imposed by LRO or RLO -----------------------------------------------------------------------------------------------*/ -int GrSlotStream::GetSlotDirLevel(EngineState * pengst, int islot, - int nOuterLevel, int nCurrLevel, DirCode dircMarker, DirCode dircOverride) -{ -// Assert(m_psstrmReprocess == NULL); - - GrSlotState * pslot = m_vpslot[islot]; - - int nDirLevel = pslot->DirLevel(); - if (nDirLevel > -1) - // already figured out - return nDirLevel; - - if (pengst->WhiteSpaceOnly()) - { - // White-space-only segments should not have any reordering. - nDirLevel = pengst->ParaRightToLeft(); - pslot->SetDirLevel(nDirLevel); - pslot->MarkDirProcessed(); - return nDirLevel; - } - - DirCode dirc = pslot->DirProcessed(); - - if (!pslot->DirHasBeenProcessed() && (WeakDir(dirc) || NeutralDir(dirc)) ) - { - // Resolve weak and neutral types; process an entire run of weak types at once, - // in several passes. - - int islotWeakRunLim = islot + 1; - while (true) - { - if (islotWeakRunLim >= m_islotWritePos) - { - if (!m_fFullyWritten) - return -1; // get more slots - else - break; - } - else if (m_islotSegLim > -1 && islotWeakRunLim >= SegLimIfKnown()) - { - break; - } - if (StrongDir(m_vpslot[islotWeakRunLim]->DirProcessed())) - // ignore the line-break; we need the next strong dir after that - //// && !m_vpslot[islotWeakRunLim]->IsFinalLineBreak(ptman->LBGlyphID())) - { - break; - } - if (m_vpslot[islotWeakRunLim]->DirProcessed() == kdircPDF && - dircMarker != kdircUnknown) - { - // A valid PDF is a strong code. TODO: replace kdircPDF with kdircPdfL/R - break; - } - - islotWeakRunLim++; - } - - int islotLp; - - // X6. Handle directional overrides: LRO, RLO. - if (dircOverride != kdircNeutral) - { - for (islotLp = islot; islotLp < islotWeakRunLim; islotLp++) - { - m_vpslot[islotLp]->SetDirProcessed(dircOverride); - m_vpslot[islotLp]->MarkDirProcessed(); - } - goto LSetDir; - } - - DirCode dircLp; - //DirCode dircTmp; - - // W1. Non-spacing marks get the type of the previous slot. - for (islotLp = islot; islotLp < islotWeakRunLim; islotLp++) - { - Assert(!m_vpslot[islotLp]->DirHasBeenProcessed()); - - if (m_vpslot[islotLp]->DirProcessed() == kdircNSM) - { -#ifdef _DEBUG - if (islotLp <= 0) - { - Warn("Pathological case in bidi algorithm"); - } -#endif // _DEBUG - dircLp = AdjacentNonBndNeutralCode(pengst, islotLp - 1, -1, dircMarker); - - m_vpslot[islotLp]->SetDirProcessed(dircLp); - } - } - - // W2. European numbers are changed to Arabic numbers if the previous strong type - // was an Arabic letter. - DirCode dircPrevStrong = AdjacentStrongCode(pengst, islot - 1, -1, dircMarker); - if (dircPrevStrong == kdircRArab) - { - for (islotLp = islot; islotLp < islotWeakRunLim; islotLp++) - { - dircLp = m_vpslot[islotLp]->DirProcessed(); - if (dircLp == kdircEuroNum) - m_vpslot[islotLp]->SetDirProcessed(kdircArabNum); - } - } - - // W4. A single European separator between two Latin numbers changes to a Latin number. - // A single common separator between two numbers of the same type changes to that - // type. - for (islotLp = islot; islotLp < islotWeakRunLim; islotLp++) - { - dircLp = m_vpslot[islotLp]->DirProcessed(); - if ((dircLp == kdircEuroSep || dircLp == kdircComSep) && - islotLp + 1 < m_islotWritePos) // don't test last slot in stream - { - DirCode dircPrev = AdjacentNonBndNeutralCode(pengst, islotLp - 1, -1, dircMarker); - DirCode dircNext = AdjacentNonBndNeutralCode(pengst, islotLp + 1, 1, dircMarker); - if (dircPrev == dircNext) - { - if (dircLp == kdircEuroSep && dircPrev == kdircEuroNum) - { - m_vpslot[islotLp]->SetDirProcessed(kdircEuroNum); - } - else if (dircLp == kdircComSep && - (dircPrev == kdircEuroNum || dircPrev == kdircArabNum)) - { - m_vpslot[islotLp]->SetDirProcessed(dircPrev); - } - } - } - } - - // W5, W6. A sequence of European number terminators adjacent to Latin numbers changes - // to Latin numbers. - // This appears to be an ambiguity in the official algorithm: do we search backward - // first, or forward? For our purposes, it is easier to search backward first. - for (islotLp = islot; islotLp < islotWeakRunLim; islotLp++) - { - dircLp = m_vpslot[islotLp]->DirProcessed(); - if (dircLp == kdircEuroTerm || dircLp == kdircBndNeutral) - { - if (TerminatorSequence(pengst, islotLp - 1, -1, dircMarker) == kdircEuroNum) - dircLp = kdircEuroNum; - else - { - if (TerminatorSequence(pengst, islotLp + 1, 1, dircMarker) == kdircEuroNum) - dircLp = kdircEuroNum; - // else could possibly be unknown if we are at the end of the stream - } - } - - // W6. Separators and terminators change to neutral. (Don't change - // boundary neutrals at this point, because that would confuse step Pre-L1.) - if (dircLp == kdircEuroSep || dircLp == kdircEuroTerm || dircLp == kdircComSep) - { - dircLp = kdircNeutral; - } - m_vpslot[islotLp]->SetDirProcessed(dircLp); - } - - // W7. European numbers are changed to plain left-to-right if the previous strong type - // was left-to-right. - dircPrevStrong = AdjacentStrongCode(pengst, islot - 1, -1, dircMarker); - if (dircPrevStrong == kdircL) - { - for (islotLp = islot; islotLp < islotWeakRunLim; islotLp++) - { - dircLp = (m_vpslot[islotLp]->DirProcessed()); - if (dircLp == kdircEuroNum) - m_vpslot[islotLp]->SetDirProcessed(kdircL); - } - } - - // Pre-L1. Make a list of all the trailing whitespace characters that need to take - // on the direction of the final line break (ie, the top direction). We can't actually - // change them yet, because that would confuse the loop below. But we have to - // record them now because they might get changed in the loop below. - std::vector<int> vislotTrailingWS; - int islotFinalLB = -1; - for (islotLp = islotWeakRunLim; islotLp-- > islot; ) - { - if (m_vpslot[islotLp]->IsFinalLineBreak(pengst->TableManager()->LBGlyphID())) - { - islotFinalLB = islotLp; - for (int islotLp2 = islotLp; islotLp2-- > islot; ) - { - dircLp = m_vpslot[islotLp2]->DirProcessed(); - if (dircLp == kdircWhiteSpace || dircLp == kdircBndNeutral) - vislotTrailingWS.push_back(islotLp2); - else - break; // hit something other than whitespace or neutral - } - break; - } - } - - // N1. A sequence of neutrals takes the direction of the strong surrounding text if - // the text on both sides has the same direction. Latin and Arabic numbers are treated - // as if they are right-to-left. - // (If they are not the same, leave the type as neutral.) - for (islotLp = islot; islotLp < islotWeakRunLim; islotLp++) - { - dircLp = m_vpslot[islotLp]->DirProcessed(); - - // Change Boundary Neutrals to plain neutrals (must happen after Pre-L1). - if (dircLp == kdircBndNeutral) - { - m_vpslot[islotLp]->SetDirProcessed(kdircNeutral); - dircLp = kdircNeutral; - } - - if (NeutralDir(dircLp)) - { - // First, look for either a strong code or a number. If we get at least - // one strong code and a number with the same direction, use that strong - // code. - DirCode dircPrev = AdjacentStrongCode(pengst, islotLp - 1, -1, dircMarker, true); - DirCode dircNext = AdjacentStrongCode(pengst, islotLp + 1, 1, dircMarker, true); - - if (dircNext == kdircUnknown) - return -1; - - if (dircPrev == kdircUnknown) - dircPrev = dircNext; - - DirCode dircResult = kdircUnknown; - if (dircNext == kdircNeutral) - {} - else if (RightToLeftDir(dircPrev) == RightToLeftDir(dircNext) && - (StrongDir(dircNext) || StrongDir(dircPrev))) - { - // Got a strong matching direction. - dircResult = (StrongDir(dircPrev)) ? dircPrev : dircNext; - } - else if (dircNext == kdircPdfL || dircNext == kdircPdfR) - { - // A following PDF flag wins, because it represents the edge of a run. - dircResult = dircNext; - } - else if (StrongDir(dircNext) && StrongDir(dircPrev)) - { // We must have text in different directions. - } - else - { - // Try again, insisting on strong codes, no numbers. - if (!StrongDir(dircPrev)) - dircPrev = AdjacentStrongCode(pengst, islotLp - 1, -1, dircMarker, false); - if (!StrongDir(dircNext)) - dircNext = AdjacentStrongCode(pengst, islotLp + 1, 1, dircMarker, false); - if (dircPrev == kdircUnknown) - dircPrev = dircNext; - - if (RightToLeftDir(dircPrev) == RightToLeftDir(dircNext) && - (StrongDir(dircNext) || StrongDir(dircPrev))) - { - // Got a strong matching direction. - dircResult = (StrongDir(dircPrev)) ? dircPrev : dircNext; - } - } - - if (dircResult != kdircUnknown) - { - dircResult = (RightToLeftDir(dircResult)) ? kdircR : kdircL; - m_vpslot[islotLp]->SetDirProcessed(dircResult); - } - // else leave as neutral - } - } - - // L1. Now change trailing neutrals recorded above to the directionality of - // the immediately following line-break, if any. - if (islotFinalLB != -1) - { - DirCode dircLB = m_vpslot[islotFinalLB]->DirProcessed(); - dircLB = (dircLB == kdircLlb) ? kdircL : kdircR; - for (int iislot = 0; iislot < signed(vislotTrailingWS.size()); iislot++) - { - int islotTmp = vislotTrailingWS[iislot]; - m_vpslot[islotTmp]->SetDirProcessed(dircLB); - } - } - - // Mark all the slots processed. - for (islotLp = islot; islotLp < islotWeakRunLim; islotLp++) - m_vpslot[islotLp]->MarkDirProcessed(); - } - else - m_vpslot[islot]->MarkDirProcessed(); - -LSetDir: - - // Final resolution. - - dirc = pslot->DirProcessed(); - - if (dirc != kdircLlb && dirc != kdircRlb && dircOverride != kdircNeutral) - { - // Enforce whatever is imposed by the override. - m_vpslot[islot]->SetDirProcessed(dircOverride); - nDirLevel = nCurrLevel; - } - else if ((nCurrLevel % 2) == 0) // current level is even (left-to-right) - { - switch (dirc) - { - case kdircNeutral: - case kdircWhiteSpace: - nDirLevel = nCurrLevel; - break; - - case kdircL: - nDirLevel = nCurrLevel; - break; - - case kdircLlb: - case kdircRlb: // all line-breaks have the direction of the paragraph - nDirLevel = nOuterLevel; - break; - - case kdircR: - case kdircRArab: - nDirLevel = nCurrLevel + 1; - break; - - case kdircEuroNum: - case kdircArabNum: - nDirLevel = nCurrLevel + 2; - break; - - default: - Assert(false); - nDirLevel = nCurrLevel; - } - } - else // current level is odd (right-to-left) - { - switch (dirc) - { - case kdircNeutral: - case kdircWhiteSpace: - nDirLevel = nCurrLevel; - break; - - case kdircR: - //case kdircRlb: - case kdircRArab: - nDirLevel = nCurrLevel; - break; - - case kdircL: - //case kdircLlb: - case kdircEuroNum: - case kdircArabNum: - nDirLevel = nCurrLevel + 1; - break; - - case kdircLlb: - case kdircRlb: // all line-breaks have the direction of the paragraph - nDirLevel = nOuterLevel; - break; - - default: - Assert(false); - nDirLevel = nCurrLevel; - } - } - pslot->SetDirLevel(nDirLevel); - - return nDirLevel; -} - -/*---------------------------------------------------------------------------------------------- - Return the next or previous strong code, kdircNeutral if we don't find one, - or kdircUnknown if we need more slots to process. - - @param islot - index of slot of interest - @param nInc - +1 to search forward, -1 to search backward - @param fNumbersAreStrong - true if we want to treat numbers as having strong - directionality - @param dircPDF - how to interpret PDF codes (from corresponding RLO, etc) -----------------------------------------------------------------------------------------------*/ -DirCode GrSlotStream::AdjacentStrongCode(EngineState * pengst, int islot, int nInc, - DirCode dircPDF, bool fNumbersAreStrong) -{ - if (islot < 0) - return pengst->InitialStrongDir(); - - else if (islot >= m_islotWritePos) - { - if (m_fFullyWritten || (m_islotSegLim > -1 && islot >= SegLimIfKnown())) - return kdircNeutral; - else - return kdircUnknown; - } - - DirCode dirc = m_vpslot[islot]->DirProcessed(); - - if (dirc == kdircPDF && StrongDir(dircPDF)) - return (RightToLeftDir(dircPDF)) ? kdircPdfR : kdircPdfL; - if (StrongDir(dirc)) - return dirc; - if (fNumbersAreStrong && (dirc == kdircEuroNum || dirc == kdircArabNum)) - return dirc; - - return AdjacentStrongCode(pengst, islot + nInc, nInc, dircPDF, fNumbersAreStrong); -} - -/*---------------------------------------------------------------------------------------------- - Return kdircEuroNum if there is a terminator sequence starting or ending with a - European number. Return kdircUnknown if we need more slots to process. - Return kdircNeutral otherwise. - - @param islot - index of slot of interest - @param nInc - +1 to search forward, -1 to search backward - @param dircPDF - how to interpret PDF codes (from corresponding RLO, etc) -----------------------------------------------------------------------------------------------*/ -DirCode GrSlotStream::TerminatorSequence(EngineState * pengst, int islot, int nInc, - DirCode dircPDF) -{ - if (islot < 0) - return pengst->InitialTermDir(); - - else if (islot >= m_islotWritePos) - { - if (m_fFullyWritten) - return kdircNeutral; - else - return kdircUnknown; - } - - DirCode dirc = m_vpslot[islot]->DirProcessed(); - - if (dirc == kdircPDF) - return (RightToLeftDir(dircPDF)) ? kdircPdfR : kdircPdfL; - else if (dirc == kdircEuroNum) - // number found at end of terminator sequence - return kdircEuroNum; - else if (dirc == kdircEuroTerm) - // yes, this slot is a terminator; are there more? - return TerminatorSequence(pengst, islot + nInc, nInc, dircPDF); - else if (dirc == kdircLlb || dirc == kdircRlb) - // line-break slot--ignore and keep going - return TerminatorSequence(pengst, islot + nInc, nInc, dircPDF); - else if (dirc == kdircBndNeutral) - // boundary neutral--ignore and keep going - return TerminatorSequence(pengst, islot + nInc, nInc, dircPDF); - else - // no number found - return kdircNeutral; -} - -/*---------------------------------------------------------------------------------------------- - Return the previous code that is not a Boundary Neutral. Return Other Neutral if there - is no such. - - @param islot - index of slot of interest - @param nInc - +1 to search forward, -1 to search backward - @param dircPDF - how to interpret PDF codes (from corresponding RLO, etc) -----------------------------------------------------------------------------------------------*/ -DirCode GrSlotStream::AdjacentNonBndNeutralCode(EngineState * pengst, int islot, int nInc, - DirCode dircPDF) -{ - Assert(islot < m_islotWritePos); - if (islot < 0) - return kdircNeutral; // or should we use: ptman->InitialStrongDir() ?? - - else if (islot >= m_islotWritePos) - { - if (m_fFullyWritten) - return kdircNeutral; - else - return kdircUnknown; - } - - DirCode dirc = m_vpslot[islot]->DirProcessed(); - - if (dirc == kdircBndNeutral) - return AdjacentNonBndNeutralCode(pengst, islot + nInc, nInc, dircPDF); - else if (dirc == kdircPDF) - return (RightToLeftDir(dircPDF)) ? kdircPdfR : kdircPdfL; - else - return dirc; -} - -/*---------------------------------------------------------------------------------------------- - Directionality type functions. -----------------------------------------------------------------------------------------------*/ -bool StrongDir(DirCode dirc) -{ - return (dirc == kdircL || dirc == kdircR || dirc == kdircRArab || - dirc == kdircLRO || dirc == kdircRLO || dirc == kdircLRE || dirc == kdircRLE || - dirc == kdircPdfL || dirc == kdircPdfR); -} - -bool WeakDir(DirCode dirc) -{ - return (dirc == kdircEuroNum || dirc == kdircEuroSep || - dirc == kdircEuroTerm || dirc == kdircArabNum || - dirc == kdircComSep || dirc == kdircBndNeutral || dirc == kdircNSM); -} - -bool NeutralDir(DirCode dirc) -{ - return (dirc == kdircWhiteSpace || dirc == kdircNeutral); -} - -/*---------------------------------------------------------------------------------------------- - Special values used by the bidi algorithm. -----------------------------------------------------------------------------------------------*/ -bool BidiCode(int nUnicode) -{ - switch (nUnicode) - { - case knLRM: - case knRLM: - case knLRO: - case knRLO: - case knLRE: - case knRLE: - case knPDF: - return true; - default: - break; - } - return false; -} - -/*---------------------------------------------------------------------------------------------- - Return true if the directionality should be treated as right-to-left. - Used for the step of resolving neutrals (N1). -----------------------------------------------------------------------------------------------*/ -bool RightToLeftDir(DirCode dirc) -{ - switch (dirc) - { - case kdircL: - case kdircLRO: - case kdircLRE: - case kdircPdfL: - return false; - - case kdircR: - case kdircRArab: - case kdircArabNum: - case kdircEuroNum: - case kdircRLO: - case kdircRLE: - case kdircPdfR: - return true; - - case kdircNeutral: - return false; - - default: - Assert(false); - return false; - } -} - -/*---------------------------------------------------------------------------------------------- - Copy a slot from prevStream, incrementing the positions. -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::CopyOneSlotFrom(GrSlotStream * psstrmPrev) -{ -#ifdef _DEBUG - gid16 chw; chw = psstrmPrev->Peek()->GlyphID(); -#endif - - // If we are exactly at the segment boundary, pass the information on to this stream. - if (psstrmPrev->AtSegMin()) - SetSegMinToWritePos(); - if (psstrmPrev->AtSegLim()) - SetSegLimToWritePos(); - - NextPut(psstrmPrev->NextGet()); - - AssertValid(); - psstrmPrev->AssertValid(); -} - -/*---------------------------------------------------------------------------------------------- - Copy one slot from the input stream to the recipient, which is the output stream. - Used when reversing ranges of glyphs; caller is responsible for adjusting the read- - and write-positions of the streams. - - REVIEW: How should this handle the reprocessing sub-stream? Currently this is not a problem - because this function is only used by the bidi pass, which never has intra-pass - reprocessing. -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::SimpleCopyFrom(GrSlotStream * psstrmI, int islotInput, int islotOutput) -{ - if (signed(m_vpslot.size()) < islotOutput + 1) - { - m_vpslot.resize(islotOutput + 1); - m_vislotPrevChunkMap.resize(islotOutput + 1); - m_vislotNextChunkMap.resize(islotOutput + 1); - } - - m_vpslot[islotOutput] = psstrmI->m_vpslot[islotInput]; - m_vislotPrevChunkMap[islotOutput] = -1; - m_vislotNextChunkMap[islotOutput] = -1; - - Assert(m_fUsedByPosPass); - if (m_fUsedByPosPass && GotIndexOffset()) - m_vpslot[islotOutput]->SetPosPassIndex(islotOutput - m_cslotPreSeg, m_fInputToPosPass1); - -} - -/*---------------------------------------------------------------------------------------------- - Return true if there is physical space to add more glyphs, false if the positioning - has caused them to use all the alotted space. Recipient is assumed to be output - stream from the final pass. - - @param ptman - table manager, for handling the positioning - @param pgg - graphics device - @param xsSpaceAllotted - how much space is available - @param fWidthIsCharCount - kludge for test procedures - @param fIgnoreTrailingWS - true if we are ignoring trailing white-space (currently - always true) - @param twsh - how the segment is handling trailing white-space - @param pxsWidth - return width of stuff so far -----------------------------------------------------------------------------------------------*/ -bool GrSlotStream::MoreSpace(GrTableManager * ptman, - float xsSpaceAllotted, bool fWidthIsCharCount, - bool fIgnoreTrailingWS, TrWsHandling twsh, - float * pxsWidth) -{ - Assert(ptman->NumberOfPasses() - 1 == m_ipass); - - if (fWidthIsCharCount) - { - // Used in test procedures - *pxsWidth = (float)m_islotWritePos; - return (m_islotWritePos < xsSpaceAllotted); - } - else - { - *pxsWidth = -1; - if (!GotIndexOffset()) - return true; - if (WritePos() <= IndexOffset()) - return true; - int dislot = MaxClusterSlot(WritePos()); - if (dislot == kNegInfinity || dislot > 0) - // We're in the middle of processing a cluster--we have to keep processing, - // so for now assume there is more space. - return true; - - float xsWidth, xsVisWidth; - ptman->CalcPositionsUpTo(m_ipass, NULL, &xsWidth, &xsVisWidth); - - *pxsWidth = (fIgnoreTrailingWS || twsh == ktwshOnlyWs) ? xsVisWidth : xsWidth; - return (*pxsWidth < xsSpaceAllotted); - } -} - -/*---------------------------------------------------------------------------------------------- - Work backwards from the prevLineBreak position (or if none, the readPos) to find the - previous line-break of the given weight or less. Return the position of the inserted - line-break slot, or -1 if no appropriate break point was found. Recipient should be - the output of the final line break pass, or if none, the output of the - glyph-generation pass. - - @param ptman - table manager, for supplying new slots - @param islotPrevBreak - position of previous inserted line break - @param fInsertedLB - did we actually insert a line-break glyph before? - @param islotStartTry - where to start looking, or -1 for the end of the stream - @param lb - (max) break weight to allow - @param twsh - how we are handling trailing white-space - @param islotMin - first slot that is officially part of the segment (after initial LB) - @param plbNextToTry - the best we found -----------------------------------------------------------------------------------------------*/ -int GrSlotStream::InsertLineBreak(GrTableManager * ptman, - int islotPrevBreak, bool fInsertedLB, int islotStartTry, - LineBrk lb, TrWsHandling twsh, int islotMin, - LineBrk * plbNextToTry) -{ - EngineState * pengst = ptman->State(); - - Assert(!fInsertedLB || islotPrevBreak > -1); - - int ichwSegOffset; - int islot; - LineBrk lbFound; - if (!FindSegmentEnd(ptman, islotStartTry, lb, twsh, islotMin, - &islot, &ichwSegOffset, &lbFound, plbNextToTry)) - { - return -1; // didn't find a legal break - } - - GrSlotState * pslotCopyFeat = pengst->AnAdjacentSlot(m_ipass, islot + 1); - Assert(pslotCopyFeat); - - if (islotPrevBreak > -1 && fInsertedLB) - { - //GrSlotState * pslotOld = m_vpslot[islotPrevBreak]; - - m_vpslot.erase(m_vpslot.begin() + islotPrevBreak); - m_vislotPrevChunkMap.erase(m_vislotPrevChunkMap.begin() + islotPrevBreak); - m_vislotNextChunkMap.erase(m_vislotNextChunkMap.begin() + islotPrevBreak); - AdjustPrevStreamNextChunkMap(ptman, islotPrevBreak + 1, -1); - } - else - { - m_islotReadPos++; - m_islotWritePos++; - } - - GrSlotState * pslotNew; - pengst->NewSlot(ptman->LBGlyphID(), pslotCopyFeat, 0, ichwSegOffset, &pslotNew); - - pslotNew->SetSpecialSlotFlag(kspslLbFinal); - pslotNew->SetBreakWeight(lbFound); - pslotNew->SetDirectionality(ptman->RightToLeft() ? kdircRlb : kdircLlb); - - int islotLB = islot + 1; - m_vpslot.insert(m_vpslot.begin() + islotLB, pslotNew); - // Inserting -1 makes it part of a chunk with the previous char/glyph - m_vislotPrevChunkMap.insert(m_vislotPrevChunkMap.begin() + islotLB, -1); - m_vislotNextChunkMap.insert(m_vislotNextChunkMap.begin() + islotLB, -1); - AdjustPrevStreamNextChunkMap(ptman, islotLB, 1); - // We don't need to adjust the following stream because we are going to unwind it anyway. - - if (m_fUsedByPosPass && GotIndexOffset()) - { - pslotNew->SetPosPassIndex(islot - m_cslotPreSeg, m_fInputToPosPass1); - // Increment the stream index for the following slots. - for (int islotTmp = islotLB; - islotTmp < ((islotPrevBreak == -1) ? m_islotWritePos : islotPrevBreak + 1); - islotTmp++) - { - SlotAt(islotTmp)->IncPosPassIndex(); - } - } - - m_islotSegLim = islotLB + 1; // after the line-break glyph - - return islotLB; -} - -/*---------------------------------------------------------------------------------------------- - Make a segment break that does not correspond to a line break; ie, don't insert - a line-break glyph. - - Work backwards from the prevLineBreak position (or if none, the readPos) to find the - previous line-break of the given weight or less. Return the position of the final slot - in the segment, or -1 if no appropriate break point was found. Recipient should be - the output of the final line break pass, if any, or the glyph-generation pass. - - @param ptman - table manager, for supplying new slots - @param islotPrevBreak - position of previous inserted line break - @param fInsertedLB - did we actually insert a line-break glyph previously; currently - ignored - @param islotStartTry - where to start looking, or -1 for the end of the stream - @param lb - (max) break weight to allow - @param twsh - how we are handling trailing white-space - @param islotMin - first slot that is officially part of the segment (after initial LB) -----------------------------------------------------------------------------------------------*/ -int GrSlotStream::MakeSegmentBreak(GrTableManager * ptman, - int islotPrevBreak, bool fInsertedLB, int islotStartTry, - LineBrk lb, TrWsHandling twsh, int islotMin, - LineBrk * plbNextToTry) -{ - int ichwSegOffset; - int islot; - LineBrk lbFound; - if (!FindSegmentEnd(ptman, islotStartTry, lb, twsh, islotMin, - &islot, &ichwSegOffset, &lbFound, plbNextToTry)) - { - return -1; // didn't find a legal break - } - - // Review: do we need to delete any previously-inserted line-break glyph from the stream? - // Doesn't seem like this has been a problem so far. - - m_islotSegLim = islot + 1; // after the final glyph of this segment - - return islot; -} - -/*---------------------------------------------------------------------------------------------- - Work backwards from the prev line break position (or if none, the readPos) to find an - earlier line-break of the given weight or less. - Recipient should be the output of the final line break pass, if any, or the output - of the glyph-generation pass. - - @param ptman - table manager, for supplying new slots - @param islotStartTry - where to start looking, or -1 for the end of the stream - @param lb - (max) break weight to allow - @param twsh - how we are handling trailing white-space - @param islotMin - first slot that is officially part of the segment (after initial LB) - @param pislot - slot AFTER which the break will go (not the lim of the segment) - @param pichwSegOffset - offset relative to the segment - @param plbFound - weight of break to be created - @param plbNextToTry - best found, in case we didn't find one at the requested level - - @return Whether or not an appropriate break was found. -----------------------------------------------------------------------------------------------*/ -bool GrSlotStream::FindSegmentEnd(GrTableManager * ptman, - int islotStartTry, LineBrk lb, TrWsHandling twsh, int islotMin, - int * pislot, int * pichwSegOffset, LineBrk * plbFound, - LineBrk * plbNextToTry) -{ - Assert(AssertValid()); - Assert(m_ipass == ptman->NumberOfLbPasses()); - - if (islotStartTry < 0) - return false; - - *pislot = islotStartTry; - GrSlotState * pslot = m_vpslot[*pislot]; - *plbNextToTry = klbClipBreak; // worst break - - ptman->State()->SetRemovedTrWhiteSpace(false); - - while (twsh != ktwshOnlyWs) // in white-space only case, ignore lb values - { - if (*pislot < islotMin) - { - return false; - } - *plbFound = LineBrk(pslot->m_lb); - // Sanity check - if (abs(*plbFound) > klbClipBreak) - { -// Assert(false); - Warn("Unusually large breakweight"); - *plbFound = (LineBrk)((*plbFound < 0) ? -klbClipBreak : klbClipBreak); - } - *plbNextToTry = (LineBrk)(min(static_cast<int>(*plbNextToTry), abs(*plbFound))); - *pichwSegOffset = pslot->SegOffset(); - - if (int(*plbFound) >= 0 && *plbFound <= lb) - break; - - --(*pislot); - if (*pislot < 0) - { - return false; - } - pslot = m_vpslot[*pislot]; - - if (int(*plbFound) <= 0 && ((int)*plbFound * -1) <= lb) - { - *plbFound = LineBrk(int(*plbFound) * -1); - break; - } - } - - // Found a good break. - - if (twsh == ktwshOnlyWs) - { - // white-space-only segment - while (pslot->Directionality() != kdircWhiteSpace) - { - --(*pislot); - if (*pislot < 0) - return false; - pslot = m_vpslot[*pislot]; - *pichwSegOffset = pslot->SegOffset(); - } - } - else if (twsh == ktwshNoWs) - { - // no trailing white-space: remove it - while (pslot->Directionality() == kdircWhiteSpace) - { - --(*pislot); - if (*pislot < 0) - return false; - pslot = m_vpslot[*pislot]; - *pichwSegOffset = pslot->SegOffset(); - ptman->State()->SetRemovedTrWhiteSpace(true); - } - } - - return true; -} - -/*---------------------------------------------------------------------------------------------- - Return true if the stream (which should be the output of the last linebreak pass) has - a better break at some earlier point than the one we found. - - @param islotBreak - position of inserted or final break point in stream, or index - of last valid slot -----------------------------------------------------------------------------------------------*/ -bool GrSlotStream::HasEarlierBetterBreak(int islotBreak, LineBrk lbFound, gid16 chwLB) -{ - Assert(AssertValid()); - - int islot = islotBreak; - if (SlotAt(islot)->IsFinalLineBreak(chwLB)) - islot--; - - if (lbFound == klbNoBreak) - lbFound = (LineBrk)SlotAt(islot)->BreakWeight(); - - while (islot >= 0) - { - if (SlotAt(islot)->IsInitialLineBreak(chwLB)) - return false; - if (SlotAt(islot)->BreakWeight() < lbFound) - return true; - islot--; - } - - return false; -} - -/*---------------------------------------------------------------------------------------------- - Make sure the stream contains a local instance of the given slot, not a copy used by - a previous pass. -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::EnsureLocalCopy(GrTableManager * ptman, GrSlotState * pslot, - GrSlotStream * psstrmIn) -{ - //Assert(m_vpslot[islot + m_cslotPreSeg] == pslot); - Assert(pslot->PassModified() <= m_ipass); - - if (pslot->PassModified() < m_ipass) - { - int islot = pslot->PosPassIndex(); - Assert(SlotAtPosPassIndex(islot) == pslot); - GrSlotState * pslotNew; - ptman->State()->NewSlotCopy(pslot, m_ipass, &pslotNew); - m_vpslot[islot + m_cslotPreSeg] = pslotNew; - - psstrmIn->ReplaceSlotInReprocessBuffer(pslot, pslotNew); - } -} - -/*---------------------------------------------------------------------------------------------- - A slot has been replace within the coorsponding output stream. Make sure the reprocess - buffer of this stream constains the same slot. -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::ReplaceSlotInReprocessBuffer(GrSlotState * pslotOld, GrSlotState * pslotNew) -{ - if (m_islotReprocPos > -1) - { - for (size_t islot = 0; islot < m_vpslotReproc.size(); islot++) - { - if (m_vpslotReproc[islot] == pslotOld) - m_vpslotReproc[islot] = pslotNew; - } - } -} - -/*---------------------------------------------------------------------------------------------- - Inserting a line break can potentially alter the directionality of preceeding glyphs. - Zap the information that has been calculated. - - @param islotLB - index of the inserted final line-break glyph -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::ZapCalculatedDirLevels(int islotLB) -{ - int islot; - for (islot = m_islotWritePos; islot-- > islotLB; ) - m_vpslot[islot]->ZapDirLevel(); - - for (islot = islotLB; islot-- > 0; ) - { - if (StrongDir(m_vpslot[islot]->Directionality())) - // We've found a strong direction code; don't need to zap beyond this point. - return; - - m_vpslot[islot]->ZapDirLevel(); - } -} - -/*---------------------------------------------------------------------------------------------- - Return the slot index of the last slot in the cluster for the just-processed chunk, - relative to the last slot in the chunk. - - Return kNegInfinity if there are not enough slots in the stream to tell. This can - happen while we are in the middle of processing a cluster. -----------------------------------------------------------------------------------------------*/ -int GrSlotStream::MaxClusterSlot(int islotChunkMin, int islotChunkLim) -{ - Assert(islotChunkLim > islotChunkMin); - - if (!m_fUsedByPosPass) - return 0; // no clusters yet - - int islotRet = SlotAt(islotChunkLim - 1)->PosPassIndex(); - - for (int islot = islotChunkMin; islot < islotChunkLim; islot++) - { - GrSlotState * pslot = SlotAt(islot); - - if (m_cslotPreSeg == -1) - return kNegInfinity; - if (!HasSlotAtPosPassIndex(pslot->AttachRootPosPassIndex())) - return kNegInfinity; - - GrSlotState * pslotBase = pslot->Base(this); - - int dislotOffset = pslotBase->LastLeafOffset(this); - if (dislotOffset == kNegInfinity) - return kNegInfinity; - islotRet = max(islotRet, pslotBase->PosPassIndex() + dislotOffset); - } - - // Make it relative to the last slot in the chunk. - islotRet -= SlotAt(islotChunkLim - 1)->PosPassIndex(); - - return islotRet; -} - -/*---------------------------------------------------------------------------------------------- - Return the break weight of the given slot, which should be a line-break. - OBSOLETE?? -----------------------------------------------------------------------------------------------*/ -LineBrk GrSlotStream::BreakWeightAt(gid16 chwLB, int islot) -{ - GrSlotState * pslot = GetSlotAt(islot); - Assert(pslot->IsLineBreak(chwLB)); - return LineBrk(pslot->m_lb); -} - -/*---------------------------------------------------------------------------------------------- - Append an initial or final line break of the given weight to the stream. - - @param ptman - table manager, for generating new slot - @param lb - break weight for the line-break glyph - @param dirc - directionality code for the line-break glyph - @param islotLB - where to insert, or -1 if at the end - @param fInitial - is this an initial line-break, or a final break? - @param ichwSegOffset - offset relative to the beginning of the segment -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::AppendLineBreak(GrTableManager * ptman, GrCharStream * pchstrm, - LineBrk lb, DirCode dirc, int islotLB, bool fInitial, int ichwSegOffset) -{ - EngineState * pengst = ptman->State(); - - Assert(AssertValid()); -/// Assert(m_islotReprocPos == -1); - - Assert(islotLB == -1 || fInitial); - if (islotLB == -1) - islotLB = m_islotWritePos; - -// int islot = m_islotWritePos; - - GrSlotState * pslotCopyFeat = pengst->AnAdjacentSlot(m_ipass, islotLB); - GrSlotState * pslotNew; - if (pslotCopyFeat) - pengst->NewSlot(ptman->LBGlyphID(), pslotCopyFeat, 0, ichwSegOffset, &pslotNew); - else - { - GrFeatureValues fval; - pchstrm->CurrentFeatures(ptman, &fval); - pengst->NewSlot(ptman->LBGlyphID(), fval, 0, ichwSegOffset, -1, &pslotNew); - } - - pslotNew->m_lb = sdata8(lb); - pslotNew->SetSpecialSlotFlag(fInitial ? kspslLbInitial : kspslLbFinal); - //pslotNew->m_fInitialLB = fInitial; // TODO: remove - pslotNew->SetDirectionality(dirc); - - m_vpslot.insert(m_vpslot.begin() + islotLB, pslotNew); - // Make it part of a chunk with previous char/glyph - m_vislotPrevChunkMap.insert(m_vislotPrevChunkMap.begin() + islotLB, -1); - m_vislotNextChunkMap.insert(m_vislotNextChunkMap.begin() + islotLB, -1); - if (m_ipass > 0) - AdjustPrevStreamNextChunkMap(ptman, islotLB, 1); - - m_islotWritePos++; - - if (m_fUsedByPosPass && GotIndexOffset()) - { - pslotNew->SetPosPassIndex(islotLB - m_cslotPreSeg, m_fInputToPosPass1); - // Increment the stream index for the following slots. - for (int islotTmp = islotLB + 1; islotTmp < m_islotWritePos; islotTmp++) - { - SlotAt(islotTmp)->IncPosPassIndex(); - } - } - - if (fInitial) - m_islotSegMin = islotLB; // just before the LB - else - m_islotSegLim = islotLB + 1; // just after the LB -} - -/*---------------------------------------------------------------------------------------------- - Return the index of the line break glyph within the specified range, or -1 if none. - Recipient is functioning as the output stream. - - @param chwLB - glyph ID being used for line-break glyphs - @param islotMin/Lim - range to search -----------------------------------------------------------------------------------------------*/ -int GrSlotStream::FindFinalLineBreak(gid16 chwLB, int islotMin, int islotLim) -{ - for (int islot = islotMin; islot < islotLim; ++islot) - { - if (m_vpslot[islot]->IsFinalLineBreak(chwLB)) - return islot; - } - return -1; -} - -/*---------------------------------------------------------------------------------------------- - A slot has been inserted (nInc == 1) or deleted (nInc == -1). Adjust the next-chunk map - of the previous stream to match. -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::AdjustPrevStreamNextChunkMap(GrTableManager * ptman, int islotMod, int nInc) -{ - if (m_ipass == 0) - return; // no previous stream to adjust - - int islotTmp = max(islotMod - 5, 0); - while (islotTmp > 0 && m_vislotPrevChunkMap[islotTmp] == -1) - islotTmp--; - - ptman->InputStream(m_ipass)->AdjustNextChunkMap( - ((islotTmp <= 0) ? 0 : m_vislotPrevChunkMap[islotTmp]), - islotMod, nInc); -} - -/*---------------------------------------------------------------------------------------------- - An insertion or deletion has occurred at the given location in the following stream - (specifically of an line-break glyph). Adjust the next-chunk-map accordingly so - the indices still match. -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::AdjustNextChunkMap(int islotMin, int islotInsOrDel, int nInc) -{ - for (int islot = islotMin; islot < m_islotWritePos; islot++) - { - if (m_vislotNextChunkMap[islot] != -1 && m_vislotNextChunkMap[islot] >= islotInsOrDel) - m_vislotNextChunkMap[islot] += nInc; - } -} - -/*---------------------------------------------------------------------------------------------- - Unwind the read position of the stream, so that the following pass will begin - reading from the new position. The recipient is functioning as the input stream. -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::UnwindInput(int islotNewPos, bool fPreBidiPass) -{ - Assert(m_islotReprocPos == -1); - Assert(islotNewPos <= m_islotReadPos); - - int islot; - for (islot = islotNewPos; islot < m_islotReadPos; ++islot) - m_vislotNextChunkMap[islot] = -1; - - m_islotReadPos = islotNewPos; - m_islotReadPosMax = m_islotReadPos; - - Assert(m_islotReadPos <= m_islotWritePos); - if (fPreBidiPass) - { - for (islot = m_islotReadPos; islot < m_islotWritePos; ++islot) - SlotAt(islot)->ZapDirLevel(); - } -} - -/*---------------------------------------------------------------------------------------------- - Unwind the write position of the stream, so that the pass will begin writing - at the new position. The recipient is functioning as the output stream -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::UnwindOutput(int islotNewPos, bool fOutputOfPosPass) -{ - Assert(islotNewPos <= m_islotWritePos); - - int islot; - for (islot = islotNewPos; islot < m_islotWritePos; ++islot) - { - m_vislotPrevChunkMap[islot] = -1; - - if (!fOutputOfPosPass && m_fUsedByPosPass) - // This stream is the input to the first positioning pass, ie, the output - // of the last sub pass or the bidi pass. Zap the stream indices, - // since unwinding this pass could cause them to be invalid due to a later - // reordering. - SlotAt(islot)->ZapPosPassIndex(); - } - - m_islotWritePos = islotNewPos; - - m_fFullyWritten = false; - - if (m_islotSegMin > m_islotWritePos) - m_islotSegMin = -1; - if (m_islotSegLim > m_islotWritePos) - m_islotSegLim = -1; -} - -/*---------------------------------------------------------------------------------------------- - We've just created a new chunk, with the recipient as the output stream. The beginning - of the chunk is passed as 'islotOutput' and the end of the chunk is assumed to be the - write-position of the recipient. Store the mappings into the corresponding - input position. - - @param islotInputMin - beginning of chunk in input stream - @param islotOutputMin - beginning of chunk in output stream (recipient) - @param islotInputLim - end of chunk in input stream (currently not used) - @param fSkipChunkStart - if true, either we have reprocessed part of a - previously created chunk, - or there was no input consumed; - in either case, don't record the beginning of the chunk, - just make this chunk be part of the previous - @param fBackingUp - this chunk results in the stream position moving backwards, - so clear anything we're backing over -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::MapInputChunk(int islotInputMin, int islotOutputMin, int islotInputLim, - bool fSkipChunkStart, bool fBackingUp) -{ - Assert(AssertValid()); - Assert(islotOutputMin >= -1); - - if (!fSkipChunkStart) - { - Assert(islotOutputMin >= 0); - if (islotOutputMin >= 0) // just in case an invalid value was passed - m_vislotPrevChunkMap[islotOutputMin] = islotInputMin; - } - - int islot; - for (islot = max(0, islotOutputMin + 1); islot < m_islotWritePos; ++islot) - m_vislotPrevChunkMap[islot] = -1; // not a chunk boundary - -// if (fBackingUp && m_islotWritePos < m_vislotPrevChunkMap.Size()) -// m_vislotPrevChunkMap[m_islotWritePos] = -1; - - if (fBackingUp) - for (islot = m_islotWritePos; islot < signed(m_vislotPrevChunkMap.size()); islot++) - m_vislotPrevChunkMap[islot] = -1; - -// m_vislotPrevChunkMap[m_islotWritePos] = islotInputLim; -} - -/*---------------------------------------------------------------------------------------------- - Return the length of the final chunk, where the recipient is the input stream. -----------------------------------------------------------------------------------------------*/ -int GrSlotStream::LastNextChunkLength() -{ - int cslotRet = 1; - for (int islot = m_islotReadPos; islot-- > 0; ) - { - if (m_vislotNextChunkMap[islot] != -1) - return cslotRet; - cslotRet++; - } - return cslotRet + 1; -} - -/*---------------------------------------------------------------------------------------------- - We've just created a new chunk, with the recipient as the input stream. The beginning of - the chunk is passed as 'islotInputMin' and the end of the chunk is assumed to be the - read-position of the recipient. Store the mappings into the corresponding - output position. - - @param islotOutputMin - beginning of chunk in output stream - @param islotInputMin - beginning of chunk in input stream (recipient) - @param islotOutputLim - end of chunk in output stream (currently not used) - @param fSkipChunkStart - if true, either we have reprocessed part of a - previously created chunk, - or there was no output generated; - in either case, don't record the beginning of the chunk, - just make this chunk be part of the previous - @param fBackingUp - this chunk results in the stream position moving backwards, - so clear anything we're backing over -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::MapOutputChunk(int islotOutputMin, int islotInputMin, int islotOutputLim, - bool fSkipChunkStart, int cslotReprocess, bool fBackingUp) -{ - Assert(AssertValid()); - - // Note: islotInputMin can be less than -1 if there is a large reprocess buffer near the - // beginning of the input stream. In which case, fSkipChunk start should be true and - // cslotReprocess large enough to keep any of the stuff below from having any problems. - //Assert(islotInputMin >= -1); - - if (!fSkipChunkStart) - { - Assert(islotInputMin >= 0); - if (islotInputMin >= 0) // just in case an invalid value was passed - m_vislotNextChunkMap[islotInputMin] = islotOutputMin; - } - - int islot; - for (islot = max(0, islotInputMin + 1 + cslotReprocess); islot < m_islotReadPos; ++islot) - m_vislotNextChunkMap[islot] = -1; // not a chunk boundary - -// if (fBackingUp && m_islotReadPos < m_vislotNextChunkMap.Size()) -// m_vislotNextChunkMap[m_islotReadPos] = -1; - - if (fBackingUp) - for (islot = m_islotReadPos; islot < signed(m_vislotNextChunkMap.size()); islot++) - m_vislotNextChunkMap[islot] = -1; - -// m_vislotNextChunkMap[m_islotReadPos] = islotOutputLim; -} - -/*---------------------------------------------------------------------------------------------- - Ensure that the chunk maps for a pair of streams match properly. The recipient is - the input stream. -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::AssertChunkMapsValid(GrSlotStream * psstrmOut) -{ -#ifdef _DEBUG - GrSlotStream * psstrmIn = this; - - Assert(m_ipass == 0 || (m_ipass + 1 == psstrmOut->m_ipass)); - - int islotMapNext; - int islotMapPrev; - int islot; - for (islot = 0; islot < m_islotReadPos; ++islot) - { - islotMapNext = psstrmIn->ChunkInNext(islot); - Assert(islotMapNext != -2); - if (islotMapNext != -1) - { - islotMapPrev = psstrmOut->ChunkInPrev(islotMapNext); - if (islotMapPrev == -2) - { - Assert(islot == psstrmOut->WritePos()); - } - else - { - Assert(islot == islotMapPrev); - } - } - } - - for (islot = 0; islot < psstrmOut->m_islotWritePos; ++islot) - { - islotMapPrev = psstrmOut->ChunkInPrev(islot); - Assert(islotMapPrev != -2); - if (islotMapPrev != -1) - { - islotMapNext = psstrmIn->ChunkInNext(islotMapPrev); - if (islotMapNext == -2) - { - Assert(islot == psstrmIn->ReadPos()); - } - else - { - Assert(islot == islotMapNext); - } - } - } -#endif // _DEBUG -} - -/*---------------------------------------------------------------------------------------------- - Ensure that corresponding items in the streams of a positioning pass have matching - stream indices. The recipient is the output stream. -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::AssertStreamIndicesValid(GrSlotStream * psstrmIn) -{ -#ifdef _DEBUG - if (!GotIndexOffset()) - return; - - Assert(m_fUsedByPosPass); - - for (int islot = 0; islot < WritePos(); islot++) - { - GrSlotState * pslotOut = SlotAt(islot); - GrSlotState * pslotIn = - psstrmIn->SlotAt(islot + psstrmIn->IndexOffset() - IndexOffset()); - Assert(pslotOut->PosPassIndex() == pslotIn->PosPassIndex()); - Assert(pslotOut->HasAsPreviousState(pslotIn)); - } -#endif // _DEBUG -} - -/*---------------------------------------------------------------------------------------------- - Ensure that the roots of all attachments made in this chunk are present - in the output stream. (Currently the compiler ensures this by making it an error - to write rules that don't do this.) -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::AssertAttachmentsInOutput(int islotMin, int islotLim) -{ -#ifdef _DEBUG - for (int islot = islotMin; islot < islotLim; islot++) - { - GrSlotState * pslotOut = SlotAt(islot); - int dislot = pslotOut->AttachTo(); - Assert(islotMin <= islot + dislot); - Assert(islot + dislot < islotLim); - } -#endif // _DEBUG -} - -/*---------------------------------------------------------------------------------------------- - Answer the slot index corresponding to the start of the chunk (as mapped to the following - stream). - ENHANCE: make more robust. -----------------------------------------------------------------------------------------------*/ -int GrSlotStream::ChunkInNextMin(int islot) -{ - int islotRet = islot; - while (m_vislotNextChunkMap[islotRet] == -1 && islotRet > 0) - --islotRet; - return islotRet; -} - -/*---------------------------------------------------------------------------------------------- - Answer the slot index corresponding to the end of the chunk (as mapped to the following - stream). - ENHANCE: make more robust. -----------------------------------------------------------------------------------------------*/ -int GrSlotStream::ChunkInNextLim(int islot) -{ - int islotRet = islot + 1; - if (islotRet == m_islotReadPos) - return islot; - while (m_vislotNextChunkMap[islotRet] == -1 && islotRet < m_islotReadPos) - { - ++islotRet; - Assert(islotRet < signed(m_vislotNextChunkMap.size())); - } - return islotRet; -} - -/*---------------------------------------------------------------------------------------------- - Skip over the given number slots. This is used to resync the streams when we - are restarting a new segment. Specifically the output stream informs the - input stream of the number of slots to skip to get the boundary for a chunk that - the output finds interesting. -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::ResyncSkip(int cslot) -{ - Assert(AssertValid()); - m_islotReadPos += cslot; - m_cslotSkippedForResync = cslot; - // Should never skip past the beginning of the line. - Assert(m_islotSegMin == -1 || m_islotReadPos <= m_islotSegMin); -} - -/*---------------------------------------------------------------------------------------------- - Record the number of slots in the stream that are previous to the official start of the - segment. -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::CalcIndexOffset(GrTableManager * ptman) -{ - if (GotIndexOffset()) - return; // already figured it - - if (m_islotSegMin > -1) - { - m_cslotPreSeg = m_islotSegMin; - if (m_fUsedByPosPass) - { - for (int islotPre = 0; islotPre < WritePos(); islotPre++) - { - SlotAt(islotPre)->SetPosPassIndex(islotPre - m_cslotPreSeg, - m_fInputToPosPass1); - } - } - } - // else can't figure it out yet - - // Old code: -#if 0 - gid16 chwLB = ptman->LBGlyphID(); - - for (int islot = 0; islot < WritePos(); islot++) - { - if (SlotAt(islot)->IsLineBreak(chwLB)) - { - if (SlotAt(islot)->IsInitialLineBreak(chwLB)) - { - m_cslotPreSeg = islot; - } - else - { - // Otherwise, we hit the final line break, which is kind of strange, because - // in this case there is no initial line break, and we should have set - // m_cslotPreSeg to 0 immediately when it was initialized. - Assert(false); - m_cslotPreSeg = 0; - } - - if (m_fUsedByPosPass) - { - for (int islotPre = 0; islotPre < WritePos(); islotPre++) - { - SlotAt(islotPre)->SetPosPassIndex(islotPre - m_cslotPreSeg, - m_fInputToPosPass1); - } - } - return; - } - - } - // No line breaks yet, so no way to tell. -#endif -} - -/*---------------------------------------------------------------------------------------------- - Set the positions in the streams for the next rule. The recipient is the output stream. - If we are moving backwards, copy part of the output stream back to (a temporary buffer - in) the input stream, so that we can reprocess it. - - @param cslotArg - how far to skip forward or back; most commonly zero -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::SetPosForNextRule(int cslotArg, GrSlotStream * psstrmIn, - bool fOutputOfPosPass) -{ - Assert(AssertValid()); - - int cslot = cslotArg; - // Can't reprocess what has already been read by the next pass. MaxBackup should allow - // the flexibility needed, but if not, we fix it here. - if (m_islotWritePos + cslot < m_islotReadPos) - cslot = m_islotReadPos - m_islotWritePos; - - Assert(psstrmIn->m_ipass == m_ipass-1); - - if (cslot >= 0) - { - // Skipping forward. - Assert(cslot <= psstrmIn->SlotsPendingInContext()); - for (int islot = 0; islot < cslot; islot++) - CopyOneSlotFrom(psstrmIn); - } - else - { - // Reprocessing. - - // Save corresponding positions before doing the back-up. - int islotReadPosInSave = psstrmIn->ReadPosForNextGet(); - int islotWritePosOutSave = this->WritePos(); - - std::vector<GrSlotState*> vpslotTmp; - int islot; - if (psstrmIn->SlotsToReprocess() > 0) - { - // Stick any slots still to reprocess in a temporary buffer. - for (islot = psstrmIn->m_islotReprocPos; - islot < signed(psstrmIn->m_vpslotReproc.size()); - islot++) - { - vpslotTmp.push_back(psstrmIn->m_vpslotReproc[islot]); - } - } - - psstrmIn->ClearReprocBuffer(); - psstrmIn->m_islotReprocLim = psstrmIn->m_islotReadPos; - - for (islot = cslot; islot < 0; islot++) - psstrmIn->m_vpslotReproc.push_back(m_vpslot[m_islotWritePos+islot]); - for (islot = 0; islot < signed(vpslotTmp.size()); islot++) - psstrmIn->m_vpslotReproc.push_back(vpslotTmp[islot]); - psstrmIn->m_islotReprocPos = 0; - - if (!fOutputOfPosPass && m_fUsedByPosPass) - { - // Last substitution pass; zap the stream indices, since they may - // now be invalid. - for (islot = 0; islot < signed(psstrmIn->m_vpslotReproc.size()); islot++) - psstrmIn->m_vpslotReproc[islot]->ZapPosPassIndex(); - } - - // If either the min or lim is in the middle of the reprocess buffer, - // adjust as necessary to match where it is in the output stream. - int islotSegMinIn = psstrmIn->SegMin(); - if (islotSegMinIn > -1 && - psstrmIn->ReadPosForNextGet() <= islotSegMinIn && - islotSegMinIn < islotReadPosInSave) - { - Assert(this->SegMin() > -1); - int dislotIn = islotReadPosInSave - islotSegMinIn; - int dislotOut = islotWritePosOutSave - SegMin(); - psstrmIn->SetSegMin(islotSegMinIn + dislotIn - dislotOut, true); - if (psstrmIn->m_cslotPreSeg > psstrmIn->SegMin()) - psstrmIn->m_cslotPreSeg = -1; - } - int islotSegLimIn = psstrmIn->SegLimIfKnown(); - if (islotSegLimIn > -1 && - psstrmIn->ReadPosForNextGet() <= islotSegLimIn && - islotSegLimIn < islotReadPosInSave) - { - int islotSegLimOut = this->SegLimIfKnown(); - Assert(islotSegLimOut > -1); - int dislotIn = islotReadPosInSave - islotSegLimIn; - int dislotOut = islotWritePosOutSave - islotSegLimOut; - psstrmIn->SetSegLim(islotSegLimIn + dislotIn - dislotOut); - } - - m_islotWritePos += cslot; - - if (m_islotSegMin >= m_islotWritePos) - m_islotSegMin = -1; - if (m_islotSegLim >= m_islotWritePos) - m_islotSegLim = -1; - } -} - -/*---------------------------------------------------------------------------------------------- - If a rule was run over a LB glyph, set the appropriate flag in the table manager. - CURRENTLY NOT USED -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::SetLBContextFlag(GrTableManager * ptman, int islotStart) -{ - gid16 chwLB = ptman->LBGlyphID(); - for (int islot = islotStart; islot < WritePos(); islot++) - { - GrSlotState * pslot = SlotAt(islot); - if (pslot->IsInitialLineBreak(chwLB)) - ptman->State()->SetStartLineContext(true); - if (pslot->IsFinalLineBreak(chwLB)) - ptman->State()->SetEndLineContext(true); - } -} - -/*---------------------------------------------------------------------------------------------- - Return the number of slots that have been output by the current pass but must be - reprocessed by this same pass. The recipient is serving as the input stream. -----------------------------------------------------------------------------------------------*/ -int GrSlotStream::SlotsToReprocess() -{ - Assert(AssertValid()); - - if (m_islotReprocPos == -1) - return 0; - return (m_vpslotReproc.size() - m_islotReprocPos); -} - -/*---------------------------------------------------------------------------------------------- - Get the input at the given slot, that is, the original input, ignoring the issue of - reprocessing. -----------------------------------------------------------------------------------------------*/ -GrSlotState * GrSlotStream::GetSlotAt(int islot) -{ - return m_vpslot[islot]; -} - -/*---------------------------------------------------------------------------------------------- - Return the "current" input item from the rule's perspective, ie, the last slot read. - So dislotOffset = 0 means not the slot at the read position but one slot earlier. - - If dislotOffset is less the the original read position that was in effect at the - beginning of the rule, we need to read from the output stream, which has the - up-to-date values. See the class comment for more details. - - @param dislotOffset - offset from current stream position - @param fNullOkay - true if it's okay to return NULL in the situation where we're asking - for something before the beginning of the stream -----------------------------------------------------------------------------------------------*/ - -GrSlotState * GrSlotStream::RuleInputSlot(int dislotOffset, GrSlotStream * psstrmOutput, - bool fNullOkay) -{ - Assert(m_islotRuleStartRead <= m_islotReadPos); - - if (dislotOffset > 0) - return Peek(dislotOffset - 1); - - int cslotOffsetBack = dislotOffset * -1; - - if (m_islotReprocLim > -1) - { - // There is a reprocess buffer. - - // Position when starting the rule should never be earlier than the - // beginning of the reprocess buffer. - Assert(m_islotRuleStartRead >= m_islotReprocLim - signed(m_vpslotReproc.size())); - - // number of items following the reprocess buffer: - int cslotPostReproc = m_islotReadPos - m_islotReprocLim; - - if (cslotOffsetBack >= cslotPostReproc) - { - // number of items in the reprocess buffer that were valid when the rule - // was started: - int cslotValidReproc = m_islotReprocLim - m_islotRuleStartRead; - - if (cslotOffsetBack >= cslotPostReproc + cslotValidReproc) - { - // Read from the output stream. - int dislotTmp = dislotOffset - 1 + cslotPostReproc + cslotValidReproc; - Assert(dislotTmp < 0); - return psstrmOutput->PeekBack(dislotTmp); - } - else - { - if (m_islotReprocPos > -1) - { - // Current read pos is inside reprocess buffer. - Assert(cslotPostReproc == 0); - int islotStartReadReprocBuf = m_vpslotReproc.size() - cslotValidReproc; - Assert(islotStartReadReprocBuf >= 0); - int islotInReprocBuf = m_islotReprocPos - cslotOffsetBack - 1; - if (islotInReprocBuf < islotStartReadReprocBuf) - { - // Return a slot from before the reprocess buffer, from the - // output stream (which is serving as our input stream for precontext - // items). - return psstrmOutput->PeekBack(islotInReprocBuf - islotStartReadReprocBuf); - } - else if (islotInReprocBuf < 0) - { - Assert(false); - //int islotReprocMin = m_islotReprocLim - m_vpslotReproc.Size(); - //return m_vpslot[islotReprocMin + islotInReprocBuf]; - } - else - // Read from the reprocess buffer. - return m_vpslotReproc[islotInReprocBuf]; - } - else - // Looking backwards into the reprocess buffer. - return m_vpslotReproc[ - m_vpslotReproc.size() - cslotOffsetBack + cslotPostReproc - 1]; - } - } - } - - // There is no reprocess buffer, or it is not a factor. - - if (m_islotReadPos + dislotOffset - 1 < m_islotRuleStartRead) - { - // Read from the output stream. - return psstrmOutput->PeekBack(m_islotReadPos + dislotOffset - 1 - m_islotRuleStartRead, - fNullOkay); - } - else - { - // Read normally from the input stream. - return m_vpslot[m_islotReadPos - cslotOffsetBack - 1]; - } -} - -/*---------------------------------------------------------------------------------------------- - Return the "current" output item from the rule's perspective, ie, the last slot written. - So dislotOffset = 0 means not the slot at the write position but one slot earlier. -----------------------------------------------------------------------------------------------*/ - -GrSlotState * GrSlotStream::RuleOutputSlot(int dislotOffset) -{ - return m_vpslot[m_islotWritePos - 1 + dislotOffset]; -} - -/*---------------------------------------------------------------------------------------------- - For any slot in the final output that has no associations, set the "before" pointer to - the following slot and the "after" pointer to the preceding slot. The idea of this is - that it will make it impossible to select a the glyph separately. - - Note that if the slot is the first on the line, it will not be associated with - a slot in the previous segment. - - @param chwLB - the glyph IB for the line-break glyphs -----------------------------------------------------------------------------------------------*/ -void GrSlotStream::SetNeutralAssociations(gid16 chwLB) -{ - for (int islot = 0; islot < m_islotWritePos; ++islot) - { - GrSlotState * pslot = SlotAt(islot); - if (pslot->PassModified() > 0 && - (pslot->BeforeAssoc() == kPosInfinity || pslot->AfterAssoc() == kNegInfinity)) - { - pslot->CleanUpAssocs(); - if (pslot->BeforeAssoc() != kPosInfinity && pslot->AfterAssoc() != kNegInfinity) - continue; - - Assert(pslot->BeforeAssoc() == kPosInfinity && pslot->AfterAssoc() == kNegInfinity); - - GrSlotState * pslotBefore = FindAssociatedSlot(islot, 1, chwLB); - GrSlotState * pslotAfter = FindAssociatedSlot(islot, -1, chwLB); - - if (pslotBefore && pslotAfter) - pslot->Associate(pslotBefore, pslotAfter); - else if (pslotBefore) - pslot->Associate(pslotBefore); - else if (pslotAfter) - pslot->Associate(pslotAfter); - else - // Weird, but can happen with an empty segment. - Warn("No assocations"); - -// Assert(pslot->m_vpslotAssoc.Size() > 0); - pslot->m_fNeutralAssocs = true; - } - } -} - -/*---------------------------------------------------------------------------------------------- - Find the next or previous slot in the final output that has explicit associations, or - return NULL if none. - - @param islot - starting slot - @param nInc - +1 if we want to find the next slot, -1 if we want the previous slot - @param chwLB - the glyph IB for the line-break glyphs -----------------------------------------------------------------------------------------------*/ -GrSlotState * GrSlotStream::FindAssociatedSlot(int islot, int nInc, gid16 chwLB) -{ - int islotNext = islot + nInc; - - while (islotNext >= 0 && islotNext < m_islotWritePos) - { - GrSlotState * pslotRet = SlotAt(islotNext); - if (pslotRet->IsLineBreak(chwLB)) - { } - else if (pslotRet->PassModified() == 0 || - (pslotRet->m_vpslotAssoc.size() > 0 && pslotRet->m_fNeutralAssocs == false)) - { - return pslotRet; - } - islotNext += nInc; - } - return NULL; -} - -} // namespace gr diff --git a/Build/source/libs/graphite-engine/src/segment/GrSlotStream.h b/Build/source/libs/graphite-engine/src/segment/GrSlotStream.h deleted file mode 100644 index 006191252dc..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrSlotStream.h +++ /dev/null @@ -1,577 +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: GrSlotStream.h -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Classes GrSlotStream and GrSlotState. -----------------------------------------------------------------------------------------------*/ -#ifdef _MSC_VER -#pragma once -#endif -#ifndef SLOTSTREAM_INCLUDED -#define SLOTSTREAM_INCLUDED - -//:End Ignore - -namespace gr -{ - -class EngineState; -class Font; - -/*---------------------------------------------------------------------------------------------- - Each GrSlotStream represents the output of one pass, which also serves as the input - of the following pass. Hence it has two positions, a write position for when it is - serving as an output stream, and a read position for when it is serving as an input - stream. The TableManager holds a list of the streams. - - The reading of slot streams is complicated by two factors. First, it may be necessary - to access the "pre-context" items of a rule, which are the slots before the current - stream position at the point when the rule is matched. These items will not be modified - by the rule, but may have been modified by a previous rule in the same pass, Therefore - we need to read these slots from the output stream, rather than the input stream, - because the output stream has the current slot attribute values that we want to work with. - In order make this happen, we keep track of the read and write positions of - the streams at the time the current rule was matched (m_islotRuleStartRead and - m_islotRuleStartWrite) and whenever we try to read a slot before m_islotRuleStartRead, - we read the corresponding slot from the output stream instead. - - Second, a rule may explicitly set the advance position so that some items are - actually reprocessed (and potentially modified) by the same pass. When this happens, - we actually copy the slots to reprocess from the output stream back - into a temporary buffer (m_vpslotReproc) in the input stream, and set up the stream so - that the next read operations will read from the buffer. - - It gets tricky because these two mechanisms can overlap with each other, so care - must be taken to read from the right place: the input stream in the normal way, - the reprocess buffer, or the output stream. See the RuleInputSlot method. - - Another messy bit of code has to do with maintaining chunks. These are used for - backtracking and unwinding after inserting a line-break. Adjacent streams have maps - showing how many slots were processed by a single rule; the maps must be consisent - between adjacent rules. The following is an example of a pair of valid chunk maps: - - Input stream Output stream - Pos next-map prev-map - 0 0 0 - 1 -1 -1 - 2 2 2 - 3 4 -1 - 4 -1 3 - 5 -1 -1 - 6 7 -1 - 7 -1 6 - 8 -1 -1 - - A -1 means that slot is not at the beginning of a chunk. Otherwise, there must be a - corresponding value in the parallel map of the adjacent stream--eg, the input stream's - next-map(3) == 4 and the output stream's prev-map(4) == 3. Assertions are run - regularly to ensure that the chunk maps stay valid. - - So above, the first chunk corresponds to slots 0-1 in the input and 0-1 in the output; - two slots were processed by the rule. The second chunk corresponds to slot 2 - in the input and slots 2-3 in the output (a slot was inserted). - The third corresponds to slots 3-5 in the input and 4-6 in the output (three slots - processed). The fourth chunk covers slots 6-8 in the input and 7-8 in the output - (one slot was deleted). - - ENHANCE SharonC: explain the effect of skipped slots on the chunk maps. - - Hungarian: sstrm -----------------------------------------------------------------------------------------------*/ -class GrSlotStream { - - friend class GrSlotState; - friend class FontMemoryUsage; - -public: - // Constructor: - GrSlotStream(int ipass) - { - m_ipass = ipass; - m_vpslot.clear(); - m_vislotPrevChunkMap.clear(); - m_vislotNextChunkMap.clear(); - m_vpslotReproc.clear(); - } - - // Destructor: - ~GrSlotStream() - { - ReleaseSlots(0, m_vpslot.size()); - } - - void ReleaseSlots(int islotMin, int islotLim) - { - // A slot stream is responsible for deleting the slot states that it created, - // that is, the ones whose modified tag equals this stream's pass index. - // NO LONGER TRUE - there is a master list of them managed by the GrTableManager. -// for (int islot = islotMin; islot < islotLim; ++islot) -// { -// if (m_vpslot[islot]->m_ipassModified == m_ipass) -// delete m_vpslot[islot]; -// } - } - - // Getters: - int WritePos() { return m_islotWritePos; } - int ReadPos() { return m_islotReadPos; } - bool FullyWritten() { return m_fFullyWritten; } - - int SlotsPresent() { return m_vpslot.size(); } - - // Setters: - void SetWritePos(int islot) - { - m_islotWritePos = islot; - } - void SetReadPos(int islot) - { - m_islotReadPos = islot; - } - - void Initialize(int ipassPos1, bool fAnythingPrevious) - { - m_islotWritePos = 0; - m_islotReadPos = 0; - m_islotReprocPos = -1; - m_islotReprocLim = -1; - m_islotRuleStartRead = 0; - m_islotRuleStartWrite = 0; - m_islotReadPosMax = 0; - m_cslotSkippedForResync = 0; - m_cslotPreSeg = (fAnythingPrevious) ? -1 : 0; - m_fFullyWritten = false; - m_islotSegMin = -1; - m_islotSegLim = -1; - m_fUsedByPosPass = (m_ipass + 1 >= ipassPos1); - m_fInputToPosPass1 = (m_ipass + 1 == ipassPos1); - m_vpslot.clear(); // not responsible for destroying the slots - m_vislotPrevChunkMap.clear(); - m_vislotNextChunkMap.clear(); - } - -public: - bool AtEnd(); - bool AtEndOfContext(); - void NextPut(GrSlotState* pslot); - GrSlotState * NextGet(); - GrSlotState * Peek(int dislot = 0); - GrSlotState * PeekBack(int dislot, bool fNullOkay = false); - void Skip(int = 1); - GrSlotState * SlotAt(int islot) - { - return m_vpslot[islot]; - } - - int OutputOfPass() - { - return m_ipass; - } - - // This function is intended to be used within positioning passes where there is a - // one-to-one correspondence beween the slots in consecutive streams. - GrSlotState * OutputSlotAt(int islot) - { - return Peek(islot - ReadPosForNextGet()); - } - - int ReadPosForNextGet() - { - return ReadPos() - SlotsToReprocess(); - } - - // Only valid for streams that are the input or output to a positioning pass. - GrSlotState * SlotAtPosPassIndex(int islot) - { - Assert(GotIndexOffset()); - Assert(m_fUsedByPosPass); - return m_vpslot[islot + m_cslotPreSeg]; - } - - // Only valid for streams that are the input or output to a positioning pass. - bool HasSlotAtPosPassIndex(int islot) - { - Assert(GotIndexOffset()); - Assert(m_fUsedByPosPass); - return (signed(m_vpslot.size()) > (islot + m_cslotPreSeg)); - } - - bool AssertValid(); - void AssertChunkMapsValid(GrSlotStream * psstrmOut); - void AssertStreamIndicesValid(GrSlotStream * psstrmIn); - void AssertAttachmentsInOutput(int islotMin, int islotLim); - bool NoReproc() - { - return (m_islotReprocPos == -1 || (m_islotReprocPos >= signed(m_vpslotReproc.size()))); - } - - int SlotsPending(); - int SlotsPendingInContext(); - int TotalSlotsPending(); - bool PastEndOfPositioning(bool fOutput); - - void ClearReprocBuffer() - { - m_islotReprocPos = -1; - m_islotReprocLim = -1; - m_vpslotReproc.clear(); - } - - int ReprocLim() - { - return m_islotReprocLim; - } - - int ReprocMin() - { - Assert(m_islotReprocPos > -1); - return m_islotReprocLim - m_vpslot.size(); - } - - int RuleStartReadPos() - { - return m_islotRuleStartRead; - } - - void SetRuleStartReadPos() - { - if (m_islotReprocPos > -1) - m_islotRuleStartRead = m_islotReprocLim - SlotsToReprocess(); - else - m_islotRuleStartRead = m_islotReadPos; - } - - int RuleStartWritePos() - { - return m_islotRuleStartWrite; - } - - void SetRuleStartWritePos() - { - m_islotRuleStartWrite = m_islotWritePos; - } - - void MarkFullyWritten(); - - void SetSegMin(int islot, bool fAdjusting = false) - { - Assert(fAdjusting || m_islotSegMin == -1 || m_islotSegMin == islot); - m_islotSegMin = islot; - } - void SetSegMinToWritePos(bool fMod = true) - { - if (m_islotSegMin == -1) - m_islotSegMin = m_islotWritePos; - else - Assert(m_islotSegMin <= m_islotWritePos); // eg, already set to before the initial LB - } - int SegMin() - { - return m_islotSegMin; - } - void SetSegLim(int islot) - { - m_islotSegLim = islot; - } - void SetSegLimToWritePos(bool fMod = true) - { - if (m_islotSegLim > -1 && !fMod) - { - Assert(m_islotSegLim <= m_islotWritePos); - return; - } - m_islotSegLim = m_islotWritePos; - } - int SegLimIfKnown() - { - return m_islotSegLim; - } - int FinalSegLim() - { - if (m_islotSegLim > -1) - return m_islotSegLim; - else - return m_islotWritePos; - } - - // Return true if we are exactly at the segment min. - bool AtSegMin() - { - if (m_islotSegMin == -1) - return false; - return (m_islotSegMin == ReadPosForNextGet()); - } - - // Return true if we are exactly at the segment lim. - bool AtSegLim() - { - if (m_islotSegLim == -1) - return false; - return (m_islotSegLim == ReadPosForNextGet()); - } - - int ReadPosMax() - { - return m_islotReadPosMax; - } - void SetReadPosMax(int islot) - { - m_islotReadPosMax = std::max(m_islotReadPosMax, islot); - } - - int OldDirLevelRange(EngineState * pengst, int islotStart, int nTopDirection); - int DirLevelRange(EngineState * pengst, int islotStart, int nTopDirection, - std::vector<int> & vislotStarts, std::vector<int> & vislotStops); - int GetSlotDirLevel(EngineState * pengst, int islot, - int nOuterLevel, int nCurrLevel, DirCode dircMarker, DirCode dircOverride); - DirCode AdjacentStrongCode(EngineState * pengst, int islot, int nInc, - DirCode dircPDF, bool fNumbersAreStrong = false); - DirCode TerminatorSequence(EngineState * pengst, int islot, int nInc, DirCode dircPDF); - DirCode AdjacentNonBndNeutralCode(EngineState * pengst, int islot, int nInc, - DirCode dircPDF); - - void CopyOneSlotFrom(GrSlotStream * psstrmPrev); - void SimpleCopyFrom(GrSlotStream * psstrmI, int islotInput, int islotOutput); - - bool MoreSpace(GrTableManager * ptman, - float xsSpaceAllotted, bool fWidthIsCharCount, - bool fIgnoreTrailingWS, TrWsHandling twsh, - float * pxsWidth); - - int InsertLineBreak(GrTableManager * ptman, - int islotPrevBreak, bool fInsertedLB, int islotStartTry, - LineBrk lb, TrWsHandling twsh, int islotMin, LineBrk * plbNextToTry); - int MakeSegmentBreak(GrTableManager * ptman, - int islotPrevBreak, bool fInsertedLB, int islotStartTry, - LineBrk lb, TrWsHandling twsh, int islotMin, LineBrk * plbNextToTry); - bool FindSegmentEnd(GrTableManager * ptman, - int islotStartTry, LineBrk lb, TrWsHandling twsh, int islotMin, - int * pislot, int * pichwSegOffset, - LineBrk * plbFound, LineBrk * plbNextToTry); - bool HasEarlierBetterBreak(int islotBreak, LineBrk lbFound, gid16 chwLB); - LineBrk BreakWeightAt(gid16 chwLB, int islot); - void AppendLineBreak(GrTableManager *, GrCharStream * pchstrm, - LineBrk, DirCode dirc, int islot, bool fInitial, int ichwSegOffset); - int FindFinalLineBreak(gid16 chwLB, int islotMin, int islotLim); - void AdjustPrevStreamNextChunkMap(GrTableManager * ptman, int islotMod, int nInc); - void AdjustNextChunkMap(int islotMin, int islotMod, int nInc); - - void EnsureLocalCopy(GrTableManager * ptman, GrSlotState * pslot, GrSlotStream * psstrmIn); - void ReplaceSlotInReprocessBuffer(GrSlotState * pslotOld, GrSlotState * pslotNew); - - void ZapCalculatedDirLevels(int islotLB); - - int MaxClusterSlot(int islotChunkLim) - { - return MaxClusterSlot(islotChunkLim - 1, islotChunkLim); - } - int MaxClusterSlot(int islotChunkMin, int islotChunkLim); - - void UnwindInput( int islot, bool fPreBidiPass); - void UnwindOutput(int islot, bool fOutputOfPosPass); - - void MapInputChunk( int islotIn, int islotOut, int islotInLim, - bool fReprocessing, bool fBackingUp); - void MapOutputChunk(int islotOut, int islotIn, int islotOutLim, - bool fReprocessing, int cslotReprocess, bool fBackingUp); - - int LastNextChunkLength(); - - int ChunkInPrev(int i) - { - Assert(i >= 0); - Assert(i < signed(m_vislotPrevChunkMap.size())); - Assert(i < m_islotWritePos); - return m_vislotPrevChunkMap[i]; - } - int ChunkInNext(int i) - { - Assert(i >= 0); - Assert(i < signed(m_vislotNextChunkMap.size())); - Assert(i < m_islotReadPos); - return m_vislotNextChunkMap[i]; - } - - int ChunkInNextMin(int islot); - int ChunkInNextLim(int islot); - - void ResyncSkip(int nslot); - int SlotsSkippedToResync() - { - return m_cslotSkippedForResync; - } - void ClearSlotsSkippedToResync() - { - m_cslotSkippedForResync = 0; - } - - int IndexOffset() - { - Assert(GotIndexOffset()); // should have been calculated - return m_cslotPreSeg; - } - void SetIndexOffset(int c) - { - m_cslotPreSeg = c; - } - bool GotIndexOffset() - { - return (m_cslotPreSeg >= 0); - } - void CalcIndexOffset(GrTableManager * ptman); - - void SetPosForNextRule(int nslot, GrSlotStream * psstrmInput, bool fOutputOfPosPass); - void SetLBContextFlag(GrTableManager * ptman, int islotStart); - int SlotsToReprocess(); - - void SetNeutralAssociations(gid16 chwLB); -protected: - GrSlotState * FindAssociatedSlot(int islot, int nInc, gid16 chwLB); - - GrSlotState * GetSlotAt(int islot); - -public: - // Used by the action code: - void BackupReadPos(int cslot = 1) - { - for (int islot = 0; islot < cslot; islot++) - { - if (m_islotReprocLim > -1 && m_islotReprocLim == m_islotReadPos) - { - if (m_islotReprocPos == -1) - m_islotReprocPos = m_vpslotReproc.size() - 1; - else - --m_islotReprocPos; - Assert(m_islotReprocPos >= 0); - } - else - --m_islotReadPos; - } - } - - GrSlotState * RuleInputSlot(int dislot = 0, GrSlotStream * psstrmOut = NULL, - bool fNullOkay = false); - GrSlotState * RuleOutputSlot(int dislot = 0); - - void PutSlotAt(GrSlotState * pslot, int islot) - { - // Currently only used for the final pass, when applying justify.width to - // the advance width. - Assert(signed(m_vpslot.size()) > islot); - Assert(WritePos() > islot); - Assert(ReadPos() <= islot); - Assert(SlotsToReprocess() == 0); - m_vpslot[islot] = pslot; - } - -protected: - // Instance variables: - int m_ipass; // which pass this stream is serving as OUTPUT of - - std::vector<GrSlotState*> m_vpslot; // the slots being processed - - // Chunking information: - std::vector<int> m_vislotPrevChunkMap; // chunk mapping into previous stream; - // -1 if not at a chunk boundary - // (this information is needed for - // reinitialization after inserting a line break) - - std::vector<int> m_vislotNextChunkMap; // chunk mapping into next stream, or -1 - // (this information is needed for backtracking) - - // Since most streams serve as both input and output, there are two positions. - // Note that readPos <= writePos always. - int m_islotWritePos; // where previous pass should put next output - int m_islotReadPos; // where following pass should start processing from - - // When we are reprocessing some of the output from the next stream: - std::vector<GrSlotState*> m_vpslotReproc; // temporary buffer - int m_islotReprocLim; // the read position corresponding to the end of the reprocess - // buffer; -1 if buffer is invalid - int m_islotReprocPos; // index into m_vpslotReproc from where we should read next; - // -1 if we are not reprocessing - - int m_islotRuleStartRead; // read position when the rule was started; any requests before - // this point should access the output stream, because it has - // the most up-to-date values. - int m_islotRuleStartWrite; // write position when the rule started - - bool m_fFullyWritten; // set to true when we can't get any more from the - // previous pass; initially false. - - int m_islotSegMin; // the official min of the segment; -1 if not yet set - int m_islotSegLim; // the official lim of the segment; -1 if not yet set - // (only set for the output of the final line-break pass - // and those beyond) - - int m_cslotSkippedForResync; // number of slots skipped to resync; - // specifically, the number of slots' worth of the - // next-chunk-map that are invalid, not mapped - // to any slots in the following stream - - int m_cslotPreSeg; // number of slots previous to the official beginning of the segment; - // -1 if we haven't figured it out yet. Used for keeping streams - // in the positioning pass in sync; not particularly useful for - // substitution passes, and will possibly be left uncalculated. - - bool m_fUsedByPosPass; // true if this is input to or output from a positioning pass - bool m_fInputToPosPass1; // true if this is the input to the first positioning pass - - // Max value of m_islotReadPos; used for recognizing infinite loops and forcibly - // advancing (see GrPass::CheckInputProgress). - int m_islotReadPosMax; - -public: - // For transduction logging: -#ifdef TRACING -// void LogSlotGlyphs(std::ofstream & strmOut, gid16 chwLB); -#endif // TRACING - - // For test procedures: - int NumberOfSlots() { return m_vpslot.size(); } - GrSlotState * LastSlotWritten() - { - if (m_islotWritePos == 0) - return NULL; - else - return m_vpslot[m_islotWritePos-1]; - } - GrSlotState * LastSlotRead() - { - if (m_islotReadPos == 0) - return NULL; - else - return m_vpslot[m_islotReadPos-1]; - } - - gid16 GlyphIDAt(int islot) - { - return m_vpslot[islot]->m_chwGlyphID; - } - - int PreChunk() // answer the number of prepended items that are not in any chunk; - // should be obsolete now - { - int islot; - for (islot = 0; islot < m_islotReadPos; ++islot) - { - if (m_vislotNextChunkMap[islot] != -1) - return islot; - } - Assert(false); - return islot; - } - -}; // end of class GrSlotStream - -} // namespace gr - - -#endif // !SLOTSTREAM_INCLUDED diff --git a/Build/source/libs/graphite-engine/src/segment/GrTableManager.cpp b/Build/source/libs/graphite-engine/src/segment/GrTableManager.cpp deleted file mode 100644 index fde364e7e2e..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrTableManager.cpp +++ /dev/null @@ -1,2691 +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: GrTableManager.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - GrTableManager, which handles the interactions between passes, including the demand-pull - algorithm. --------------------------------------------------------------------------------*//*:End Ignore*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" - -#ifdef _MSC_VER -#pragma hdrstop -#endif -#undef THIS_FILE -DEFINE_THIS_FILE -//#ifndef _WIN32 -#include <stdlib.h> -#include <math.h> -//#endif - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -namespace gr -{ - -//:>******************************************************************************************** -//:> Methods -//:>******************************************************************************************** - -/*---------------------------------------------------------------------------------------------- - Constructors and initializers -----------------------------------------------------------------------------------------------*/ -EngineState::EngineState() - : m_ipassJustCalled(-1), - m_fStartLineContext(false), - m_fEndLineContext(false), - ////m_pgg(NULL), - m_cslotPreSeg(0), - m_islotblkCurr(-1), - m_islotNext(kSlotBlockSize), - m_fInitialLB(false), - m_fFinalLB(false), - m_fInsertedLB(false), - m_fExceededSpace(false), - m_fHitHardBreak(false), - m_fRemovedWhtsp(false), - m_dxsShrinkPossible(GrSlotState::kNotYetSet), - m_islotPosNext(-1), - m_xsPosXNext(0), - m_ysPosYNext(0), - m_dxsTotWidthSoFar(0), - m_dxsVisWidthSoFar(0), - m_prgzpst(NULL), - m_prgpsstrm(NULL) -{ - m_vslotblk.clear(); - m_vprgnSlotVarLenBufs.clear(); -} - -void EngineState::Initialize(GrEngine * pgreng, GrTableManager * ptman) -{ - m_ptman = ptman; - m_cpass = ptman->NumberOfPasses(); // duplicate for convenience - - m_cUserDefn = pgreng->NumUserDefn(); - m_cFeat = pgreng->NumFeat(); - m_cCompPerLig = pgreng->NumCompPerLig(); - - if (m_prgzpst) - delete[] m_prgzpst; - m_prgzpst = new PassState[m_cpass]; - ptman->StorePassStates(m_prgzpst); -} - -/*---------------------------------------------------------------------------------------------- - Destructors -----------------------------------------------------------------------------------------------*/ -GrTableManager::~GrTableManager() -{ - for (int ipass = 0; ipass < m_cpass; ++ipass) - delete Pass(ipass); - - delete[] m_prgppass; -} - -EngineState::~EngineState() -{ - DestroySlotBlocks(); - - delete[] m_prgzpst; - - if (m_prgpsstrm) - { - for (int isstrm = 0; isstrm < m_cpass; ++isstrm) - delete OutputStream(isstrm); - - delete[] m_prgpsstrm; - } -} - -/*---------------------------------------------------------------------------------------------- - Delete all the slots. -----------------------------------------------------------------------------------------------*/ -void EngineState::DestroySlotBlocks() -{ - Assert(m_vslotblk.size() == m_vprgnSlotVarLenBufs.size()); - for (size_t islotblk = 0; islotblk < m_vslotblk.size(); ++islotblk) - { - delete[] m_vslotblk[islotblk]; - delete[] m_vprgnSlotVarLenBufs[islotblk]; - } - m_vslotblk.clear(); - m_vprgnSlotVarLenBufs.clear(); -} - -/*---------------------------------------------------------------------------------------------- - Create the passes, and them fill them in by reading from the file stream. -----------------------------------------------------------------------------------------------*/ -bool GrTableManager::CreateAndReadPasses(GrIStream & grstrm, - int fxdSilfVersion, int fxdRuleVersion, - int cpassFont, long lSubTableStart, int * rgnPassOffsets, - int ipassSub1Font, int ipassPos1Font, int ipassJust1Font, byte ipassPostBidiFont) -{ - Assert(ipassSub1Font <= ipassJust1Font); - Assert(ipassJust1Font <= ipassPos1Font); - Assert(ipassPos1Font <= cpassFont); - if (ipassSub1Font > ipassJust1Font || ipassJust1Font > ipassPos1Font - || ipassPos1Font > cpassFont) - { - return false; // bad table - } - - // Adjusted indices based on the fact that we have a glyph generation pass that is - // pass 0, and possibly a bidi pass: - m_cpass = cpassFont + 1; - int ipassLB1, ipassSub1, ipassBidi, ipassPos1, ipassJust1; - ipassLB1 = 1; - ipassSub1 = ipassSub1Font + 1; - if (ipassPostBidiFont == 0xFF) - { - // No bidi pass. - m_fBidi = false; - // Add 1 below to account for the glyph-generation pass. - ipassPos1 = ipassPos1Font + 1; - ipassJust1 = ipassJust1Font + 1; - ipassBidi = ipassJust1; - } - else - { - m_fBidi = true; - m_cpass++; - Assert(ipassPostBidiFont == ipassJust1Font); - ipassJust1 = ipassJust1Font + 2; - ipassPos1 = ipassPos1Font + 2; - ipassBidi = ipassJust1 - 1; - } - - // Always make at least one positioning pass, even if there are no rules. - if (ipassPos1 == m_cpass) - { - m_cpass++; - } - - m_prgppass = new GrPass*[m_cpass + 1]; - m_prgppass[0] = new GrGlyphGenPass(0); - - int ipass = 1; - int ipassFont = 0; - m_cpassLB = 0; - m_ipassJust1 = 1; - m_ipassPos1 = 1; - for ( ; ipass < m_cpass; ipass++, ipassFont++) - { - if (ipass < ipassSub1) - { - m_prgppass[ipass] = new GrLineBreakPass(ipass); - m_prgppass[ipass]->ReadFromFont(grstrm, fxdSilfVersion, fxdRuleVersion, - lSubTableStart + rgnPassOffsets[ipassFont]); - m_cpassLB++; - m_ipassJust1++; - m_ipassPos1++; - } - else if (ipassSub1 <= ipass && ipass < ipassBidi) - { - m_prgppass[ipass] = new GrSubPass(ipass); - m_prgppass[ipass]->ReadFromFont(grstrm, fxdSilfVersion, fxdRuleVersion, - lSubTableStart + rgnPassOffsets[ipassFont]); - m_ipassJust1++; - m_ipassPos1++; - } - else if (ipassBidi == ipass && ipass < ipassJust1) - { - m_prgppass[ipass] = new GrBidiPass(ipass); - m_prgppass[ipass]->SetTopDirLevel(TopDirectionLevel()); - ipassFont--; // no corresponding pass in font - m_ipassJust1++; - m_ipassPos1++; - } - else if (ipassJust1 <= ipass && ipass < ipassPos1) - { - // A justification pass is, in essence, a substitution pass. - m_prgppass[ipass] = new GrSubPass(ipass); - m_prgppass[ipass]->ReadFromFont(grstrm, fxdSilfVersion, fxdRuleVersion, - lSubTableStart + rgnPassOffsets[ipassFont]); - m_ipassPos1++; - } - else if (ipassPos1 <= ipass) - { - m_prgppass[ipass] = new GrPosPass(ipass); - if (ipassFont < cpassFont) - { - m_prgppass[ipass]->ReadFromFont(grstrm, fxdSilfVersion, fxdRuleVersion, - lSubTableStart + rgnPassOffsets[ipassFont]); - } - else - { - // No positioning pass in font: create a bogus one. - m_prgppass[ipass]->InitializeWithNoRules(); - } - } - else - { - Assert(false); - return false; // bad table - } - } - - return true; -} - -/*---------------------------------------------------------------------------------------------- - Create passes corresponding to an invalid font. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::CreateEmpty() -{ - m_cpass = 2; - - m_prgppass = new GrPass*[2]; - m_prgppass[0] = new GrGlyphGenPass(0); - - m_prgppass[1] = new GrPosPass(1); - m_prgppass[1]->InitializeWithNoRules(); - - m_ipassPos1 = 1; - m_cpassLB = 0; - m_fBidi = false; - - m_engst.CreateEmpty(); -} - -void EngineState::CreateEmpty() -{ - m_fStartLineContext = false; - m_fEndLineContext = false; -} - -/*---------------------------------------------------------------------------------------------- - Create the slot streams corresponding to the passes. -----------------------------------------------------------------------------------------------*/ -void EngineState::CreateSlotStreams() -{ - if (m_prgpsstrm) - return; - - m_prgpsstrm = new GrSlotStream * [m_cpass]; - for (int ipass = 0; ipass < m_cpass; ++ipass) - { - m_prgpsstrm[ipass] = new GrSlotStream(ipass); - } -} - -/*---------------------------------------------------------------------------------------------- - Store information about the pass-states in the pass objects. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::StorePassStates(PassState * rgzpst) -{ - for (int ipass = 0; ipass < m_cpass; ipass++) - Pass(ipass)->SetPassState(rgzpst + ipass); -} - -/*---------------------------------------------------------------------------------------------- - Demand-driven loop: with goal of filling up final slot stream, loop backward and forward - filling up slot streams until final stream has reached physical capacity. - - @param pgjus - justification agent; NULL if justification is of no interest - @param jmodi - (internal) justification mode - @param fStartLine, fEndLine - @param ichSegLim - known end of segment; -1 when using backtracking - @param dxWidthRequested - available width; when justifying, exact width desired - @param dxUnjustifiedWidth - when justifying, what the width would be normally - @param fNeedFinalBreak - true if the end of the segment needs to be a valid break point - @param fMoreText - true if char stream doesn't go up to text-stream lim - @param ichFontLim - end of the range that could be rendered by this font - @param fInfiniteWidth - used for "measured" segments - @param fWidthIsCharCount - kludge for test procedures: the width is a character count, - not a pixel count - @param lbPref - try for longest segment ending with this breakweight - - when justifying, lb to assume - @param lbMax - max (last resort) breakweight if no preferred break possible - @param ichwCallerBtLim - caller's backtrack lim; -1 if caller is not backtracking - @param twsh - how to handle trailing white-space - @param fParaRtl - overall paragraph direction - @param nDirDepth - direction depth of this segment -----------------------------------------------------------------------------------------------*/ -void GrTableManager::Run(Segment * psegNew, Font * pfont, - GrCharStream * pchstrm, IGrJustifier * pgjus, int jmodi, - LayoutEnvironment & layout, - int ichSegLim, - float dxWidthRequested, float dxUnjustifiedWidth, - bool fNeedFinalBreak, bool fMoreText, int ichFontLim, - bool fInfiniteWidth, bool fWidthIsCharCount, - int ichwCallerBtLim, - int nDirDepth, SegEnd estJ) -{ - bool fStartLine = layout.startOfLine(); - bool fEndLine = layout.endOfLine(); - LineBrk lbPref = layout.bestBreak(); - LineBrk lbMax = layout.worstBreak(); - TrWsHandling twsh = layout.trailingWs(); - bool fParaRtl = layout.rightToLeft(); - Segment * psegPrev = layout.prevSegment(); - Segment * psegInit = layout.segmentForInit(); - std::ostream * pstrmLog = layout.loggingStream(); - - m_engst.Initialize(Engine(), this); // do this after the tables have been fully read - m_engst.m_jmodi = jmodi; - m_engst.m_ipassJustCalled = -1; - m_engst.m_twsh = twsh; - m_engst.m_fParaRtl = fParaRtl; - m_engst.m_dxsShrinkPossible = GrSlotState::kNotYetSet; - m_fLogging = (pstrmLog != NULL); - - int cbPrev; - byte * pbPrevSegDat = NULL; - if (psegPrev) - cbPrev = psegPrev->NextSegInitBuffer(&pbPrevSegDat); - else if (psegInit) - cbPrev = psegInit->ThisSegInitBuffer(&pbPrevSegDat); - else - cbPrev = 0; - - if (pchstrm->IsEmpty()) - { - m_engst.m_lbPrevEnd = klbNoBreak; - InitSegmentAsEmpty(psegNew, pfont, pchstrm, fStartLine, fEndLine); - psegNew->SetWidths(0, 0); - psegNew->SetUpOutputArrays(pfont, this, NULL, 0, 0, 0, twsh, - fParaRtl, nDirDepth, true); - psegNew->SetLayout(layout); - return; - } - - int islotUnderBreak = -1; // position of inserted or final break point in underlying - // data; none so far (if an actual LB has been inserted, - // this is the index of that slot; otherwise it is the - // index of the last valid slot) - int islotSurfaceBreak = -1; // position of line break in surface stream; none so far - LineBrk lbBestToTry = lbPref; - LineBrk lbFound = klbNoBreak; - - float dxMaxWidth = dxWidthRequested; - - if (m_engst.m_jmodi == kjmodiJustify) - { - Assert(fInfiniteWidth); - lbBestToTry = klbClipBreak; - lbFound = lbPref; - } - - float dxWidth; - - std::vector<int> vnslotNeeded; - vnslotNeeded.resize(m_cpass); - - m_engst.InitializeStreams(this, pchstrm, cbPrev, pbPrevSegDat, fNeedFinalBreak, &islotUnderBreak); - - int ipassCurr; - int nNeedInput; // kNextPass: go on to the next pass - // kBacktrack: need to insert a line break - // > 0: need more input from previous pass - - int cchwPostXlbContext = m_pgreng->PostXlbContext(); - if (ichSegLim > -1) - { - // When we know exactly where the end of the segment will be, get as much as - // we need from the character stream, and then fill up the remaining streams. - // (3 below is an arbitrary number; we just want to get slightly more than - // we really need.) - vnslotNeeded[0] = ichSegLim - pchstrm->Min() + cchwPostXlbContext + 3; - for (int ipass = 1; ipass < m_cpass; ipass++) - vnslotNeeded[ipass] = 10000; - // Start at pass 0. - ipassCurr = 0; - } - else - { - // When we're doing line-breaking to find the end of the segment, use the - // demand-driven approach that tries to fill up the available space. - vnslotNeeded[m_cpass - 1] = 1; - - // Start at the last pass. (It might be more efficient to start at the first pass and - // generate a small arbitrary number of glyphs.) - ipassCurr = m_cpass - 1; - } - - while (ipassCurr < m_cpass) - { - if (ipassCurr == 0) - { - int nNeedNow = vnslotNeeded[0]; - // Zeroth pass: generate glyph IDs from the underlying input. - nNeedInput = Pass(0)->ExtendGlyphIDOutput(this, - pchstrm, OutputStream(0), ichSegLim, cchwPostXlbContext, lbPref, - nNeedNow, fNeedFinalBreak, m_engst.m_twsh, &islotUnderBreak); - Assert(nNeedInput == kNextPass || nNeedInput == kBacktrack); - vnslotNeeded[0] -= nNeedNow; - } - else if (ipassCurr < m_cpass - 1) - { - // Middle pass. - int cslotNeedNow = vnslotNeeded[ipassCurr]; - cslotNeedNow = max(1, cslotNeedNow); - int cslotGot; - Pass(ipassCurr)->ExtendOutput(this, - InputStream(ipassCurr), OutputStream(ipassCurr), cslotNeedNow, twsh, - &nNeedInput, &cslotGot, &islotUnderBreak); - vnslotNeeded[ipassCurr] -= cslotGot; - //if (nNeedInput != kNextPass && nNeedInput != kBacktrack) - // nNeedInput = max(nNeedInput, cslotNeedNow - cslotGot); - } - else // (ipassCurr == m_cpass - 1) - { - // Final pass: position and test allotted space. - float dxWidthWShrink = dxMaxWidth; - if (m_engst.m_dxsShrinkPossible != GrSlotState::kNotYetSet) - dxWidthWShrink += (int)m_engst.m_dxsShrinkPossible; - nNeedInput = Pass(ipassCurr)->ExtendFinalOutput(this, - InputStream(ipassCurr), OutputStream(ipassCurr), - dxWidthWShrink, fWidthIsCharCount, fInfiniteWidth, - (islotUnderBreak > -1), (fNeedFinalBreak && lbFound == klbNoBreak), - lbMax, twsh, - &islotSurfaceBreak, &dxWidth); - } - - if (m_engst.m_jmodi == kjmodiJustify) - { - if (ipassCurr < m_ipassJust1 && !OutputStream(ipassCurr)->FullyWritten()) - { - // When justifying, fill up all the streams up to the point where we need - // to interact with the justification routine. - // I think this code is obsolete. - int nStillNeed = 1000; - if ((ipassCurr == 1 && nNeedInput != kNextPass) || ipassCurr == 0) - nStillNeed = ichSegLim - (pchstrm->Pos() - pchstrm->Min()) - + cchwPostXlbContext + 3; - if (nStillNeed > 0) - { - if (nNeedInput == kNextPass) - ipassCurr++; // repeat this pass - nNeedInput = nStillNeed; - } - } - else if (nNeedInput == kNextPass && ipassCurr + 1 == m_ipassJust1) - { - CallJustifier(pgjus, ipassCurr, dxUnjustifiedWidth, dxWidthRequested, fEndLine); - } - } - DetermineShrink(pgjus, ipassCurr); - - if (nNeedInput == kBacktrack) - { - // Final output has overflowed its space--find (or adjust) the break point. - - bool fFoundBreak = Backtrack(&islotUnderBreak, - &lbBestToTry, lbMax, twsh, fMoreText, ichwCallerBtLim, &lbFound); - if (!fFoundBreak) - { - // Nothing will fit. Initialize the new segment just enough so that - // we can delete it. - InitSegmentToDelete(psegNew, pfont, pchstrm); - return; - } - } - else if (nNeedInput == kNextPass) - { - // This pass is sufficiently full--return to following pass. - ipassCurr++; - } - else - { - // Get more input from previous pass. - ipassCurr--; - vnslotNeeded[ipassCurr] = nNeedInput; - } - } - - // At this point we have fully transduced all the text for this segment. - - // Figure out why we broke the segment and what the caller is supposed to do about it. - SegEnd est; - if (m_engst.m_jmodi == kjmodiJustify) - { - // Don't change what was passed in. - est = estJ; - } - else if (m_engst.m_fRemovedWhtsp) // (islotUnderBreak > -1 && twsh == ktwshNoWs) - { - Assert(!m_engst.m_fInsertedLB); - est = kestMoreWhtsp; - } - - else if (m_engst.m_fHitHardBreak) - { - est = kestHardBreak; - } - - else if (!m_engst.m_fExceededSpace && !fMoreText) - // Rendered to the end of the original requested range. - est = kestNoMore; - -// else if (!m_fExceededSpace && !fNextIsSameWs && fMoreText) -// // Writing system break; may be more room on the line. But see tweak below. -// *pest = kestWsBreak; - - else if (m_engst.m_fExceededSpace) - { - // Exceeded available space, found a legal break. - if (twsh == ktwshNoWs && m_engst.m_fRemovedWhtsp) - est = kestMoreWhtsp; - else - est = kestMoreLines; - } - - else if (twsh == ktwshOnlyWs) - { - est = kestOkayBreak; // but see tweak below - } - - else - { - // Broke because of something like a font change. Determine whether this is a legal - // break or not. - // TODO SharonC: handle the situation where it is legal to break BEFORE the first - // character of the following segment. - Assert(fMoreText); - //Assert(fNextIsSameWs); - if (ichwCallerBtLim > -1) - { - Assert(m_engst.m_fInsertedLB); - } - else if (ichSegLim > -1) - { - // We stopped where caller said to. - Assert(fInfiniteWidth); - } - else - { - Assert(!m_engst.m_fInsertedLB); - Assert(islotUnderBreak == -1 || m_engst.m_fFinalLB); - } - int islotTmp = OutputStream(m_cpass - 1)->WritePos(); - GrSlotState * pslotTmp; - if (m_engst.m_fFinalLB || m_engst.m_fInsertedLB) - pslotTmp = OutputStream(m_cpass-1)->SlotAt(islotTmp - 2); - else - pslotTmp = OutputStream(m_cpass-1)->SlotAt(islotTmp - 1); - - if (abs(pslotTmp->BreakWeight()) <= lbPref) - est = kestOkayBreak; - - else if (abs(pslotTmp->BreakWeight()) > lbMax) - est = kestBadBreak; - - else if (OutputStream(m_cpassLB)->HasEarlierBetterBreak(islotUnderBreak, lbFound, - this->LBGlyphID())) - { - est = kestBadBreak; - } - else - est = kestOkayBreak; - - // We no longer have the ability to know whether or not the next segment will use - // the same writing system. - //if (est == kestBadBreak && m_engst.m_fExceededSpace && !fNextIsSameWs && fMoreText) - // est = kestWsBreak; - } - - // Make a segment out of it and return it. - int dichSegLen; - InitNewSegment(psegNew, pfont, pchstrm, pgjus, - islotUnderBreak, islotSurfaceBreak, fStartLine, fEndLine, ichFontLim, lbFound, est, - &dichSegLen); - if (psegNew->segmentTermination() == kestNothingFit) - { - return; - } - else if (psegNew->segmentTermination() == kestHardBreak && - psegNew->startCharacter() == psegNew->stopCharacter()) - { - // Empty segment caused by a hard-break. - m_engst.m_lbPrevEnd = klbNoBreak; - psegNew->SetWidths(0, 0); - psegNew->SetUpOutputArrays(pfont, this, NULL, 0, 0, 0, twsh, - fParaRtl, nDirDepth, true); - psegNew->SetLayout(layout); - return; - } - - psegNew->RecordInitializationForThisSeg(cbPrev, pbPrevSegDat); - - if ((est == kestNoMore || est == kestWsBreak) && twsh == ktwshOnlyWs && - dichSegLen < pchstrm->Lim() - pchstrm->Min()) - { - // If we are asking for white-space only, and we didn't use up everything in the font - // range, we could possibly have gotten an initial white-space only segment - // (as opposed to a writing system break). - est = kestOkayBreak; - psegNew->FixTermination(est); - } - - SetFinalPositions(psegNew, fWidthIsCharCount); - - // Do this before fixing up the associations below, so we can see the raw ones produced by the - // rules themselves. - //if (m_pgreng->LoggingTransduction()) - // WriteTransductionLog(pchstrm, *ppsegRet, - // cbPrev, pbPrevSegDat, pbNextSegDat, pcbNextSegDat); - WriteTransductionLog(pstrmLog, pchstrm, psegNew, cbPrev, pbPrevSegDat); - - RecordAssocsAndOutput(pfont, psegNew, twsh, fParaRtl, nDirDepth); - - // Do this after fixing up the associations. - //if (m_pgreng->LoggingTransduction()) - // WriteAssociationLog(pchstrm, *ppsegRet); - WriteAssociationLog(pstrmLog, pchstrm, psegNew); - - psegNew->SetLayout(layout); -} - -/*---------------------------------------------------------------------------------------------- - Create a new segment to return. - - @param pchstrm - input stream - @param pgjus - justification agent, in case this segment needs to be - stretched or shrunk - @param islotLBStreamBreak - position of inserted line break slot (which should be equal - to the position in the glyph generation stream); - -1 if no line-break was inserted (we rendered to the - end of the range) - @param islotSurfaceBreak - position of line break slot in final (surface) stream - @param fStartLine - does this segment start a line? - @param fEndLine - does this segment end a line? - @param ichFontLim - end of range that could be rendered by this font - @param lbEndFound - line break found; possibly adjusted here - @param est - why did the segment terminate -----------------------------------------------------------------------------------------------*/ -void GrTableManager::InitNewSegment(Segment * psegNew, - Font * pfont, GrCharStream * pchstrm, IGrJustifier * pgjus, - int islotLBStreamBreak, int islotSurfaceBreak, bool fStartLine, bool fEndLine, int ichFontLim, - LineBrk lbEndFound, SegEnd est, int * pdichSegLen) -{ - LineBrk lbStart = m_engst.m_lbPrevEnd; - LineBrk lbEnd = lbEndFound; - if (est == kestBadBreak) - lbEnd = klbLetterBreak; - - int ichwMin = pchstrm->Min(); - int ichwLim; - -// int cslotPreSegStream0 = m_cslotPreSeg; -// if (m_fInitialLB && m_cpassLB > 0) -// { -// // Initial LB is included in m_cslotPreSeg, but is not in stream 0. -// // --Not really needed, because both islotLBStreamBreak and m_cslotPreSeg take -// // the initial LB into account if it is there. -// cslotPreSegStream0--; -// } - - // No longer have to subtract this, because the chunk map takes it into - // consideration. - //int cslotPreInitialLB = m_cslotPreSeg - (m_fInitialLB ? 1 : 0); - - //int ichwOldTmp; - - if (m_engst.m_fInsertedLB) - { - Assert(islotLBStreamBreak > -1); - int ichwSegLim = m_engst.LbSlotToSegLim(islotLBStreamBreak, pchstrm, m_cpassLB); - ichwLim = ichwSegLim + pchstrm->Min(); // - cslotPreInitialLB; - - // Old result, for debugging: - //ichwOldTmp = islotLBStreamBreak + pchstrm->Min() - m_cslotPreSeg; - } - else if (m_engst.m_fFinalLB || islotLBStreamBreak == -1) - ichwLim = pchstrm->Lim(); - else - { - int ichwSegLim = m_engst.LbSlotToSegLim(islotLBStreamBreak, pchstrm, m_cpassLB); - ichwLim = ichwSegLim + pchstrm->Min(); // - cslotPreInitialLB; - - // Old result, for debugging: - // islotLBStreamBreak is the last slot in the segment, not the LB glyph; hence +1. - //ichwOldTmp = islotLBStreamBreak + pchstrm->Min() - m_cslotPreSeg + 1; - } - - *pdichSegLen = ichwLim - ichwMin; - - if (ichwMin >= ichwLim) - { - if (est == kestHardBreak) - { - // Empty segment cause by a hard-break. - InitSegmentAsEmpty(psegNew, pfont, pchstrm, fStartLine, fEndLine); - psegNew->FixTermination(est); - } - else - { - // Invalid empty segment. - Assert(ichwMin == ichwLim); - InitSegmentToDelete(psegNew, pfont, pchstrm); - } - return; - } - - Assert(psegNew); - - psegNew->Initialize(pchstrm->TextSrc(), - ichwMin, ichwLim, - lbStart, lbEnd, est, fStartLine, fEndLine, m_pgreng->RightToLeft()); - - psegNew->SetEngine(m_pgreng); - psegNew->SetFont(pfont); - psegNew->SetJustifier(pgjus); - psegNew->SetFaceName(m_pgreng->FaceName(), m_pgreng->BaseFaceName()); - - bool fNextSegNeedsContext = - !(est == kestNoMore || est == kestWsBreak - || ichwLim >= pchstrm->Lim() || ichwLim >= ichFontLim); - - InitializeForNextSeg(psegNew, islotLBStreamBreak, islotSurfaceBreak, lbEnd, - fNextSegNeedsContext, pchstrm); - - psegNew->SetPreContext(0 - m_pgreng->PreXlbContext()); -} - -/*---------------------------------------------------------------------------------------------- - The newly created segment is invalid, for instance, because we were backtracking and - couldn't find a valid break point. Initialize it just enough so that it can be - deleted by the client. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::InitSegmentToDelete(Segment * psegNew, Font * pfont, - GrCharStream * pchstrm) -{ - psegNew->Initialize(pchstrm->TextSrc(), 0, 0, - klbClipBreak, klbClipBreak, kestNothingFit, false, false, - m_pgreng->RightToLeft()); - - psegNew->SetEngine(m_pgreng); - psegNew->SetFont(pfont); - psegNew->SetJustifier(NULL); // can't justify an empty segment - psegNew->SetFaceName(m_pgreng->FaceName(), m_pgreng->BaseFaceName()); - psegNew->SetPreContext(0); -} - -/*---------------------------------------------------------------------------------------------- - Map from the given slot (which is generally the final LB slot) to the end of the segment, - taking into account the fact that a single slot may represent two 16-bit surrogates. - - There are several approaches that seem reasonable but do NOT work. (I tried them!) - You can't calculate it directly from the length of the streams, because that doesn't take - into account the possible presence of surrogate pairs in the character stream. You can't - use the chunk map at the point of the LB, because if a rule spanned a LB the chunk won't - have ended there and so there won't be any valid information. - - What seems to work is to figure out the slot(s) in the zeroth stream using the associations - and then use the segment offset for this slot. This should be reliable because there is - always a one-to-one correspondence between glyphs in the line-break passes (ie, no - insertions or deletions), so the associations should be dependable and straightforward. -----------------------------------------------------------------------------------------------*/ -int EngineState::LbSlotToSegLim(int islotLB, GrCharStream * pchstrm, int cpassLB) -{ - Assert(islotLB < OutputStream(cpassLB)->WritePos()); - - // Figure out the corresponding characters in the zeroth stream. These should be straight- - // forward to figure out because no substitutions are permitted in the LB passes. - // I do the slots before and after the LB, if possible, as a sanity check. - GrSlotStream * psstrmLB = OutputStream(cpassLB); - GrSlotState * pslotPreLB = (m_fFinalLB || m_fInsertedLB) ? - psstrmLB->SlotAt(islotLB - 1) : - psstrmLB->SlotAt(islotLB); - GrSlotState * pslotPostLB = (psstrmLB->WritePos() > islotLB + 1) ? - psstrmLB->SlotAt(islotLB + 1) : - NULL; - - int ichwPreLB = pslotPreLB->AfterAssoc(); - - int ichwSegLim; - if (pslotPostLB) - { - ichwSegLim = pslotPostLB->BeforeAssoc(); - Assert(ichwPreLB + 1 == ichwSegLim - || ichwPreLB + 2 == ichwSegLim); // in case of a surrogate - } - else - { - ichwSegLim = ichwPreLB + 1; - while (!pchstrm->AtUnicodeCharBoundary(ichwSegLim)) - ichwSegLim++; - Assert(pchstrm->AtUnicodeCharBoundary(ichwSegLim)); - } - - // Old buggy routine that doesn't handle the case where a rule (and hence the chunk map) did - // not end at the LB character: - // Map backwards through the LB pass streams, if any. - //int islotAdjusted = islotLB + 1; // after the LB - //for (int ipass = m_cpassLB; ipass > 0; ipass--) - //{ - // islotAdjusted = ChunkInPrev(ipass, islotAdjusted, pchstrm); - //} - // - //int ichwSegLim = ChunkInPrev(0, islotAdjusted, pchstrm); - - // Mapping from 32-bit to 16-bit should only increase the index. Except that there - // may be a LB in the slot stream that is not in the character stream, so it could be - // one less. - Assert(ichwSegLim + m_cslotPreSeg >= islotLB - 1); - - return ichwSegLim; -} - -/*---------------------------------------------------------------------------------------------- - Return the chunk mapping into the previous stream, taking into account the fact that it - is not recorded for the write-position. -----------------------------------------------------------------------------------------------*/ -int GrTableManager::ChunkInPrev(int ipass, int islot, GrCharStream * pchstrm) -{ - GrSlotStream * psstrmOut = OutputStream(ipass); - GrSlotStream * psstrmIn = (ipass == 0) ? NULL : InputStream(ipass); - - int islotTmp = islot; - int islotAdjusted; - do { - if (islot >= psstrmOut->WritePos()) - { - Assert(islot == psstrmOut->WritePos()); - islotAdjusted = (ipass == 0) ? pchstrm->SegOffset() : psstrmIn->ReadPos(); - Assert(islotAdjusted > -1); - } - else - islotAdjusted = psstrmOut->ChunkInPrev(islotTmp); - islotTmp--; - } while (islotAdjusted == -1); - - return islotAdjusted; -} - -/*---------------------------------------------------------------------------------------------- - Create a new segment corresponding to an empty string. - - @param pchstrm - input stream - @param fStartLine - does this segment start a line? - @param fEndLine - does this segment end a line? -----------------------------------------------------------------------------------------------*/ -void GrTableManager::InitSegmentAsEmpty(Segment * psegNew, Font * pfont, - GrCharStream * pchstrm, bool fStartLine, bool fEndLine) -{ - LineBrk lbStart = m_engst.m_lbPrevEnd; - LineBrk lbEnd = klbNoBreak; - - int ichwMin = 0; - int ichwLim = 0; - - Assert(psegNew); - - psegNew->Initialize(pchstrm->TextSrc(), ichwMin, ichwLim, - lbStart, lbEnd, kestNoMore, fStartLine, fEndLine, m_pgreng->RightToLeft()); - - psegNew->SetEngine(m_pgreng); - psegNew->SetFont(pfont); - psegNew->SetJustifier(NULL); // can't justify an empty segment - psegNew->SetFaceName(m_pgreng->FaceName(), m_pgreng->BaseFaceName()); - - byte pbNextSegDat[256]; - int cbNextSegDat; - int * pcbNextSegDat = &cbNextSegDat; - - // Initialization for (theoretical) next segment. - byte * pb = pbNextSegDat; - *pb++ = byte(lbEnd); - *pb++ = kdircNeutral; - *pb++ = kdircNeutral; - *pb++ = 0; - for (int ipass = 0; ipass < m_cpass; ipass++) - *pb++ = 0; - *pcbNextSegDat = 0; - psegNew->RecordInitializationForNextSeg(*pcbNextSegDat, pbNextSegDat); - - psegNew->SetPreContext(0); -} - -/*---------------------------------------------------------------------------------------------- - Find a line-break and unwind the passes. Return true if we were able to - backtrack successfully (which may have meant using a less-than-optimal line-break). - Return false if no line-break could be found (because maxBreakWeight did not allow - letter breaks or clipping--generally because there was already something on this - line). - - @param pislotPrevBreak - position of previously-created break, -1 if none; - this is the index of the line-break glyph if any, - or the index of the last slot in the segment; - adjusted to contain the position of the newly - found break - @param plbMin - minimum (best) line break weight to try - @param lbMax - maximum (worst possible) line break weight - @param twsh - how to handle trailing white-space - @param fMoreText - true if char stream doesn't go up to original lim - @param ichwCallerBtLim - caller's backtrack lim; -1 if caller is not backtracking - @param plbFound - kind of line-break created -----------------------------------------------------------------------------------------------*/ -bool GrTableManager::Backtrack(int * pislotPrevBreak, - LineBrk * plbMin, LineBrk lbMax, TrWsHandling twsh, bool fMoreText, - int ichwCallerBtLim, - LineBrk * plbFound) -{ - int islotStartTry; - //if (*pislotPrevBreak == ichwCallerBtLim - 1) - //{ - // islotStartTry = *pislotPrevBreak; - //} - //else - if (*pislotPrevBreak == -1) - { - // If no line break has been found so far, figure out where to start trying based - // on where the final stream choked. - GrSlotStream * psstrmFinal = OutputStream(m_cpass-1); - if ((islotStartTry - = m_engst.TraceStreamZeroPos(psstrmFinal->WritePos()-1, TopDirectionLevel())) - == -1) - { - // Just start looking at the end of what's been generated. - islotStartTry = OutputStream(m_cpassLB)->ReadPos() - 1; - } - } - else - { - // Start just before previous line break. - if (m_engst.m_fInsertedLB || m_engst.m_fFinalLB) - islotStartTry = *pislotPrevBreak - 2; // skip inserted LB and previous slot - else - islotStartTry = *pislotPrevBreak - 1; // skip previous slot - } - if (ichwCallerBtLim > -1 && islotStartTry > ichwCallerBtLim - 1) - { - islotStartTry = ichwCallerBtLim - 1; - } - - // Determine if we want to insert an actual line-break "glyph". Don't do that if - // we are omitting trailing white space or we are at a writing-system or font break. - bool fInsertLB; - if (twsh == ktwshNoWs) - // omitting trailing white-space - fInsertLB = false; - else if (twsh == ktwshOnlyWs) - // trailing white-space segment - fInsertLB = true; - else if (ichwCallerBtLim > -1) - // backtracking - fInsertLB = true; - else if (*pislotPrevBreak > -1) - // no longer at the edge of the writing system or font - fInsertLB = true; - else if (!fMoreText) - // at final edge of total range to render - fInsertLB = true; - else - fInsertLB = false; - - // Try to insert a line-break in the output of the (final) line-break pass (if any, or - // the output of the glyph-generation pass). First try the preferred (strictest) - // break weight and gradually relax. - LineBrk lb = *plbMin; - Assert(*plbMin <= lbMax); - GrSlotStream * psstrmLB = OutputStream(m_cpassLB); - islotStartTry = min(islotStartTry, psstrmLB->WritePos() - 1); - int islotNewBreak = -1; - while (lb <= lbMax) - { - LineBrk lbNextToTry; - if (fInsertLB) - { - islotNewBreak = psstrmLB->InsertLineBreak(this, - *pislotPrevBreak, m_engst.m_fInsertedLB, islotStartTry, - lb, twsh, m_engst.m_cslotPreSeg, &lbNextToTry); - } - else - { - islotNewBreak = psstrmLB->MakeSegmentBreak(this, - *pislotPrevBreak, m_engst.m_fInsertedLB, islotStartTry, - lb, twsh, m_engst.m_cslotPreSeg, &lbNextToTry); - } - if (islotNewBreak > -1) - break; - if (lb >= lbMax) - break; - lb = IncLineBreak(lb); // relax the break weight - } - - if (islotNewBreak == -1) - { - return false; - } - - // We've successfully inserted a line break. - - if (fInsertLB) - m_engst.m_fInsertedLB = true; - - m_engst.m_fFinalLB = false; - - UnwindAndReinit(islotNewBreak); - - *pislotPrevBreak = islotNewBreak; - *plbMin = lb; // return the best break we were able to find, so we don't keep trying - // for a better one when we know now that we can't find it - *plbFound = lb; - - return true; -} - -/*---------------------------------------------------------------------------------------------- - This method is called after backtracking or removing trailing white-space. - Unwind the following slot streams as necessary depending on where the change was made. - - @param islotNewBreak - in output of (final) line-break pass -----------------------------------------------------------------------------------------------*/ -void GrTableManager::UnwindAndReinit(int islotNewBreak) -{ - OutputStream(m_cpassLB)->ZapCalculatedDirLevels(islotNewBreak); - - // Mark the passes before the line-break pass as fully written, so that if there - // isn't a line-break glyph to intercept, we don't keep trying to get more input - // from them. - int ipass; - for (ipass = 1; ipass < m_cpassLB + 1; ++ipass) - { - InputStream(ipass)->MarkFullyWritten(); - } - - // Unwind the passes to the changed positions. - // Note that we don't need to unwind pass 0, since all it does is generate glyph IDs. - // Also we don't need to unwind the line-break passes, because conceptually they happen - // before the break is inserted. - - int islotChgPos = islotNewBreak; - bool fFirst = true; - for (ipass = m_cpassLB + 1 ; ipass < m_cpass ; ++ipass) - { - islotChgPos = - Pass(ipass)->Unwind(this, islotChgPos, InputStream(ipass), OutputStream(ipass), - fFirst); - fFirst = false; - } - // For anything that may have been skipped in the final output: - OutputStream(m_cpass - 1)->SetReadPos(0); - OutputStream(m_cpass - 1)->SetReadPosMax(0); - Pass(m_cpass - 1)->UndoResyncSkip(); - OutputStream(m_cpass - 1)->ClearSlotsSkippedToResync(); - - m_engst.InitPosCache(); - - m_engst.m_dxsShrinkPossible = GrSlotState::kNotYetSet; // recalculate it -} - -/*---------------------------------------------------------------------------------------------- - Store information in the newly created segment that will allow us to reinitalize - the streams in order to process the next segment, appropriately handling any - cross-line-boundary contextuals. - - The information required is the number of glyphs in the first stream that must - be reprocessed, and a skip-offset between each stream indicating the beginning - of chunk boundaries. - - In most cases, where there are no cross-line-boundary contextuals, all these numbers - will be zero. - - The buffer generated is of the following format (all are 1 byte, unsigned): - end breakweight - previous strong directionality code - previous terminator dir code - restart backup - skip offsets for each pass - This format must match what is generated by InitializeStreams. - - @param pseg - newly created segment - @param islotUnderBreak - position of line break inserted in underlying stream (output - of glyph-generation pass--stream 0); -1 if we rendered to - the end of the range - @param islotSurfaceBreak - position of line break in surface stream; - -1 if we rendered to the end of the range - @param lbEnd - kind of line-break at the end of this segment - @param fNextSegNeedsContext - true if we need to remember the context for the next seg - @param pchstrm - character stream input for this segment - @param cbNextMax - amount of space available in the buffer - @param pbNextSegDat - buffer for initializing next segment - @param pcbNextSegDat - amount of space used in buffer -----------------------------------------------------------------------------------------------*/ -void GrTableManager::InitializeForNextSeg(Segment * pseg, - int islotUnderBreak, int islotSurfaceBreak, LineBrk lbEnd, - bool fNextSegNeedsContext, GrCharStream * pchstrm) -{ - byte pbNextSegDat[256]; - int cbNextSegDat; - int * pcbNextSegDat = &cbNextSegDat; - - std::vector<int> vcslotSkipOffsets; - vcslotSkipOffsets.resize(m_cpass); - - byte * pb = pbNextSegDat; - - if (!fNextSegNeedsContext) - { - // No contextualization between this segment and the next, whatever kind of renderer - // it might use. - *pcbNextSegDat = 0; - return; - } - - gid16 chwLB = LBGlyphID(); - - int islotUnderLim = islotUnderBreak; - if (!m_engst.m_fInsertedLB && !m_engst.m_fFinalLB) - // Then islotUnderBreak is the position of the last slot in the segment; increment - // to get the lim in stream zero. - islotUnderLim++; - - int islotSurfaceLim = islotSurfaceBreak; - if (islotSurfaceLim == -1) - islotSurfaceLim = OutputStream(m_cpass - 1)->FinalSegLim(); - - *pb++ = byte(lbEnd); - - // Find previous strong and terminator directionality codes. - - GrSlotStream * psstrm = OutputStream(m_cpass - 1); - DirCode dircStrong = kdircNeutral; - DirCode dircTerm = kdircNeutral; - int islot; - for (islot = islotSurfaceLim; islot-- > 0; ) - { - GrSlotState * pslot = psstrm->SlotAt(islot); - DirCode dirc = pslot->Directionality(); - if (dircTerm == kdircNeutral && dirc == kdircEuroTerm) - dircTerm = dirc; - if (StrongDir(dirc)) - { - dircStrong = dirc; - break; - } - } - *pb++ = byte(dircStrong); - *pb++ = byte(dircTerm); - - // Record how much of each pass to redo in the next segment. - // The basic algorithm is described in the "WR Data Transform Engine" document. - // But here we are doing a variation on what is described there. We are calculating - // the backup locations for BOTH the rule start locations and the necessary pre-contexts. - // It is the precontext values that are recorded for use by the following segment. But we - // also calculate the positions for the rule-start locations to make sure there is enough - // pre-context at each pass. - - int islotRS = islotSurfaceLim; // rule-start positions - int islotPC = islotRS; // to handle pre-context positions - - // If line-breaks are irrelevant to this font, we don't need to bother. - bool fGiveUp = !m_pgreng->LineBreakFlag(); - - int ipass; - for (ipass = m_cpass - 1; ipass >= 0 && !fGiveUp; --ipass) - { - GrSlotStream * psstrmIn = (ipass == 0) ? NULL : InputStream(ipass); - GrSlotStream * psstrmOut = OutputStream(ipass); - int islotBackupMin = (ipass == 0) ? 0 : psstrmOut->SegMin(); - if (ipass >= m_cpassLB && m_engst.m_fInitialLB) - islotBackupMin++; // how far we can back up--not before the start of this segment - - int islotPrevRS = 0; // corresponding slot in the previous stream for rule-start position - int islotPrevPC = 0; // same for pre-context position - - // Initially we have to include at least this many prior slots: - int cslotSkipOffset = 0; - - if (islotRS == psstrmOut->WritePos()) - { - islotPrevRS = (ipass == 0) ? pchstrm->Pos() : psstrmIn->ReadPos(); - } - else - { - // Ignore the final line-break, because it is explicitly inserted during - // the (final) line-break pass. -// if (ipass == m_cpassLB && psstrm->SlotAt(islotRS)->IsFinalLineBreak(chwLB)) -// { -// Assert(islotRS > 0); -// islotRS--; -// } - // Ignore the chunk in the pass that generated the line break that corresponds - // to the inserted line break being chunked with the previous glyph--we don't - // want to treat that as a cross-line-boundary contextual! - if (ipass == m_cpassLB && psstrmOut->SlotAt(islotRS)->IsFinalLineBreak(chwLB)) - { -// Assert(psstrm->ChunkInPrev(islotRS) == -1); - if (islotRS + 1 == psstrmOut->WritePos()) - islotPrevRS = (ipass == 0) ? pchstrm->SegOffset() : psstrmIn->ReadPos(); - else - islotPrevRS = psstrmOut->ChunkInPrev(islotRS + 1); - } - else - { - // Back up to the beginning of a chunk. - while (islotRS >= islotBackupMin && - (islotPrevRS = psstrmOut->ChunkInPrev(islotRS)) == -1) - { - --islotRS; - //++cslotSkipOffset; - } - } - } - if (islotPrevRS == -1 || islotRS < islotBackupMin) // hit the start of the segment - { - // In order to get enough context to be sure to run the same rules again, - // we'd have to back up into the previous segment. Too complicated, so give up. - fGiveUp = true; - break; - } - - int cslotPreContext = Pass(ipass)->MaxRulePreContext(); -LBackupPC: - if (islotPC == psstrmOut->WritePos()) - { - islotPrevPC = (ipass == 0) ? pchstrm->Pos() : psstrmIn->ReadPos(); - } - else - { - if (ipass == m_cpassLB && psstrmOut->SlotAt(islotPC)->IsFinalLineBreak(chwLB)) - { - if (islotPC+1 == psstrmOut->WritePos()) - islotPrevPC = (ipass == 0) ? pchstrm->SegOffset() : psstrmIn->ReadPos(); - else - islotPrevPC = psstrmOut->ChunkInPrev(islotPC+1); - } - else - { - // Back up to the beginning of a chunk; also make sure there are enough slots - // to handle the required pre-context for this pass. - while (islotPC >= islotBackupMin && - ((islotPrevPC = psstrmOut->ChunkInPrev(islotPC)) == -1 || - islotPrevRS - islotPrevPC < cslotPreContext)) - { - --islotPC; - ++cslotSkipOffset; - } - } - } - if (islotPC >= islotBackupMin && islotPrevRS - islotPrevPC < cslotPreContext) - { - --islotPC; - ++cslotSkipOffset; - goto LBackupPC; - } - if (islotPrevPC == -1 || islotPC < islotBackupMin) // hit the start of the segment - { - fGiveUp = true; - break; - } - - vcslotSkipOffsets[ipass] = cslotSkipOffset; - - islotRS = islotPrevRS; - islotPC = islotPrevPC; - - if (ipass == 0) - { - // Convert from underlying chars to stream-zero slots. - islotRS += m_engst.m_cslotPreSeg; - islotPC += m_engst.m_cslotPreSeg; - } - } - - // The following should be the case unless they tried to position contextually across - // the line break boundary, which is a very strange thing to do! - no longer true, - // because the pre-context is now included in this count, and it normal to have - // a pre-context in the final positioning pass. - //Assert(vcslotSkipOffsets[m_cpass-1] == 0); - - // Also no adjustments are made by the glyph-generation pass, so this should always - // be true: - Assert(vcslotSkipOffsets[0] == 0); - - // The number of slots in the underlying input previous to the line-break - // that must be reprocessed: - int cslotPreLB = islotUnderLim - islotPC; - - if (fGiveUp) - { - // We can't reasonably provide enough context, so don't try to do it at all. - cslotPreLB = 0; - for (ipass = 0; ipass < m_cpass; ipass++) - vcslotSkipOffsets[ipass] = 0; - } - - Assert(cslotPreLB >= 0); - Assert(cslotPreLB < 0xFF); - - *pb++ = byte(cslotPreLB); - for (ipass = 0; ipass < m_cpass; ipass++) - *pb++ = byte(vcslotSkipOffsets[ipass]); - - *pcbNextSegDat = 4 + m_cpass; - - pseg->RecordInitializationForNextSeg(*pcbNextSegDat, pbNextSegDat); -} -/*---------------------------------------------------------------------------------------------- - Make sure the final positions are set for every glyph. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::SetFinalPositions(Segment * pseg, bool fWidthIsCharCount) -{ - float xsTotalWidth, xsVisWidth; - -#ifdef OLD_TEST_STUFF - if (fWidthIsCharCount) - xsTotalWidth = xsVisWidth = 0; - else -#endif // OLD_TEST_STUFF - - // Make sure the final positions are set for every glyph. - CalcPositionsUpTo(m_cpass-1, reinterpret_cast<GrSlotState *>(NULL), - &xsTotalWidth, &xsVisWidth); - pseg->SetWidths(xsVisWidth, xsTotalWidth); -} - -/*---------------------------------------------------------------------------------------------- - Calculate the associations, and record the output slots in the segment. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::RecordAssocsAndOutput(Font * pfont, Segment * pseg, - TrWsHandling twsh, bool fParaRtl, int nDirDepth) -{ - int cchwUnderlying = pseg->stopCharacter() - pseg->startCharacter(); - GrSlotStream * psstrmFinal = OutputStream(m_cpass-1); - int csloutSurface = psstrmFinal->WritePos() - psstrmFinal->IndexOffset(); // # of output slots - - psstrmFinal->SetNeutralAssociations(LBGlyphID()); - - pseg->SetUpOutputArrays(pfont, this, psstrmFinal, cchwUnderlying, csloutSurface, LBGlyphID(), - twsh, fParaRtl, nDirDepth); - - // Set underlying-to-surface assocations in the segment. - CalculateAssociations(pseg, csloutSurface); -} - -/*---------------------------------------------------------------------------------------------- - Calculate the underlying-to-surface associations and ligature mappings. - Assumes the arrays have been properly initialized. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::CalculateAssociations(Segment * pseg, int csloutSurface) -{ - GrSlotStream * psstrmFinal = OutputStream(m_cpass-1); - - std::vector<int> vichwAssocs; - std::vector<int> vichwComponents; - - for (int islot = psstrmFinal->IndexOffset(); islot < psstrmFinal->WritePos(); islot++) - { - GrSlotState * pslot = psstrmFinal->SlotAt(islot); - int islout = islot - psstrmFinal->IndexOffset(); - if (!pslot->IsLineBreak(LBGlyphID())) - { - vichwAssocs.clear(); - pslot->AllAssocs(vichwAssocs); - - size_t iichw; - for (iichw = 0; iichw < vichwAssocs.size(); ++iichw) - { - pseg->RecordSurfaceAssoc(vichwAssocs[iichw], islout, 0); - } - - vichwComponents.clear(); - if (pslot->HasComponents()) - pslot->AllComponentRefs(vichwComponents); - - for (iichw = 0; iichw < vichwComponents.size(); iichw++) - { - pseg->RecordLigature(vichwComponents[iichw], islout, iichw); - } - } - } - - AdjustAssocsForOverlaps(pseg); - pseg->CleanUpAssocsVectors(); - -// pseg->AdjustForOverlapsWithPrevSeg(); // for any characters officially in the - // previous segment but rendered in this one, - // or vice versa - - // TODO SharonC: for all characters that are right-to-left in the underlying stream, - // reverse the before and after flags in the segment. -} - -/*---------------------------------------------------------------------------------------------- - For any slots associated with characters in the new segment but not rendered in the - segment, adjust the underlying-to-surface mappings accordingly. Ie, set the before - mapping to kNegInfinity for slots at the beginning of the streams, and set the - after mapping to kPosInfinity for slots at the end of the streams. - - TODO SharonC: Rework this method more carefully to handle each slot exactly once. The current - approach could possibly, for instance, process a slot that is inserted in one pass - and deleted in the next. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::AdjustAssocsForOverlaps(Segment * pseg) -{ - if (!m_engst.m_fInitialLB && !m_engst.m_fFinalLB && !m_engst.m_fInsertedLB) - // no cross-line contextualization possible - return; - - gid16 chwLB = LBGlyphID(); - std::vector<int> vichwAssocs; - - // Process any slots output by any substitution pass (or later) on either side of the - // line-breaks. These are the relevant slots that are rendered in the previous and - // following segments. - for (int ipass = m_cpass; ipass-- > m_cpassLB + 1; ) - { - GrSlotStream * psstrm = OutputStream(ipass); - int islotMin = (ipass == m_cpass - 1) ? psstrm->IndexOffset() : 0; - - if (m_engst.m_fInitialLB) - { - for (int islot = islotMin; ; islot++) - { - GrSlotState * pslot = psstrm->SlotAt(islot); - if (pslot->IsInitialLineBreak(chwLB)) - break; - Assert(!pslot->IsFinalLineBreak(chwLB)); - if (pslot->PassModified() != ipass) - continue; - - vichwAssocs.clear(); - pslot->AllAssocs(vichwAssocs); - for (size_t iichw = 0; iichw < vichwAssocs.size(); ++iichw) - pseg->MarkSlotInPrevSeg(vichwAssocs[iichw], islot); - } - } - - if ((m_engst.m_fFinalLB || m_engst.m_fInsertedLB) && ipass > m_cpassLB) - { - for (int islot = psstrm->WritePos(); islot-- > islotMin ; ) - { - GrSlotState * pslot = psstrm->SlotAt(islot); - if (pslot->IsFinalLineBreak(chwLB)) - break; - Assert(!pslot->IsInitialLineBreak(chwLB)); - if (pslot->PassModified() != ipass) - continue; - - vichwAssocs.clear(); - pslot->AllAssocs(vichwAssocs); - for (size_t iichw = 0; iichw < vichwAssocs.size(); ++iichw) - pseg->MarkSlotInNextSeg(vichwAssocs[iichw], islot); - } - } - } -} - -/*---------------------------------------------------------------------------------------------- - Initialize all the streams. In particular, process the information about the - skip-offsets to handle segments other than the first. - - @param cbPrev - number of bytes in the pbPrevSegDat buffer - @param pbPrevSegDat - buffer in the following format (all are 1 byte, unsigned): - prev seg's end breakweight - prev seg's previous strong directionality code - prev seg's previous terminator dir code - restart backup - skip offsets for each pass - This format must match what is generated by InitializeForNextSeg. -----------------------------------------------------------------------------------------------*/ -void EngineState::InitializeStreams(GrTableManager * ptman, - GrCharStream * pchstrm, - int cbPrev, byte * pbPrevSegDat, bool fNeedFinalBreak, int * pislotFinalBreak) -{ - int cpassLB = ptman->NumberOfLbPasses(); - int ipassPos1 = ptman->FirstPosPass(); - - CreateSlotStreams(); - - int cslotBackup = 0; - - InitForNewSegment(ptman); - - if (cbPrev == 0) - { - m_lbPrevEnd = klbNoBreak; - m_dircInitialStrongDir = kdircNeutral; - m_dircInitialTermDir = kdircNeutral; - for (int ipass = 0; ipass < m_cpass; ++ipass) - { - OutputStream(ipass)->Initialize(ipassPos1, false); - m_prgzpst[ipass].SetResyncSkip(0); - - if (ptman->LoggingTransduction()) - m_prgzpst[ipass].InitializeLogInfo(); - } - } - else - { - Assert(cbPrev >= 4); - byte * pb = pbPrevSegDat; - - m_lbPrevEnd = LineBrk(*pb++); - - // Directionality codes from the previous segment. - m_dircInitialStrongDir = DirCode((int)*pb++); - m_dircInitialTermDir = DirCode((int)*pb++); - - cslotBackup = (int)*pb++; - Assert((cbPrev == 4 || cslotBackup == 0) || cbPrev == m_cpass + 4); - - for (int ipass = 0; ipass < m_cpass; ++ipass) - { - OutputStream(ipass)->Initialize(ipassPos1, true); - if (cbPrev == 4) - m_prgzpst[ipass].SetResyncSkip(0); // different writing system - else - m_prgzpst[ipass].SetResyncSkip(*pb++); - - if (ptman->LoggingTransduction()) - m_prgzpst[ipass].InitializeLogInfo(); - } - - pchstrm->Backup(cslotBackup); - } - - if (cbPrev > 0 || pchstrm->StartLine()) - { - // Go ahead and run the initial line-break passes (if any), and then insert - // a line-break at the appropriate place where the new segment will begin. - int cslotToGet = cslotBackup; -LGetMore: - ptman->Pass(0)->ExtendGlyphIDOutput(ptman, pchstrm, OutputStream(0), - -1, 0, klbWordBreak, - cslotToGet, fNeedFinalBreak, m_twsh, pislotFinalBreak); - OutputStream(0)->SetSegMin(cslotBackup); - for (int ipass = 1; ipass <= cpassLB; ipass++) - { - if (cslotToGet > 0) - { - int nRet = kNextPass; - int cslotGot; - ptman->Pass(ipass)->ExtendOutput(ptman, - InputStream(ipass), OutputStream(ipass), - cslotToGet, m_twsh, &nRet, &cslotGot, pislotFinalBreak); - if (nRet != kNextPass) - { - cslotToGet = 1; - goto LGetMore; - } - } - OutputStream(ipass)->SetSegMin(cslotBackup); - } - Assert(OutputStream(cpassLB)->WritePos() >= cslotBackup); - m_cslotPreSeg = cslotBackup; - if (pchstrm->StartLine()) - { - OutputStream(cpassLB)->AppendLineBreak(ptman, pchstrm, m_lbPrevEnd, - (ptman->RightToLeft() ? kdircRlb : kdircLlb), cslotBackup, true, -1); - SetInitialLB(); - m_cslotPreSeg++; - if (cpassLB > 0 && *pislotFinalBreak > -1) - // See corresponding kludge in GrPass::ExtendGlyphIDOutput. - *pislotFinalBreak += 1; - } - else - { - OutputStream(cpassLB)->SetSegMin(cslotBackup); - } - OutputStream(cpassLB)->CalcIndexOffset(ptman); - } - - else - { - Assert(cslotBackup == 0); - OutputStream(0)->SetSegMin(0); - m_cslotPreSeg = 0; - } -} - -/*---------------------------------------------------------------------------------------------- - Reinitialize as we start to generate a new segment. -----------------------------------------------------------------------------------------------*/ -void EngineState::InitForNewSegment(GrTableManager * ptman) -{ - // Set up a fresh batch of slots. - DestroySlotBlocks(); - m_islotblkCurr = -1; - m_islotNext = kSlotBlockSize; - - m_fInitialLB = false; - m_fFinalLB = false; - m_fInsertedLB = false; - m_fExceededSpace = false; - m_fHitHardBreak = false; - m_fRemovedWhtsp = false; - InitPosCache(); - //////m_pgg = pgg; - - for (int ipass = 0; ipass < m_cpass; ipass++) - m_prgzpst[ipass].InitForNewSegment(ipass, ptman->Pass(ipass)->MaxRuleContext()); -} - -/*---------------------------------------------------------------------------------------------- - Calculate the position in stream zero of the given slot in the final stream, - based on the associations. (This will be the same as the position at the end of the - line-break passes, which is really what we want.) - - @param islotFinal - index of the final slot in the final stream -----------------------------------------------------------------------------------------------*/ -int EngineState::TraceStreamZeroPos(int islotFinal, int nTopDir) -{ - GrSlotStream * psstrmFinal = OutputStream(m_cpass - 1); - if (psstrmFinal->WritePos() == 0) - return -1; - - GrSlotState * pslot = psstrmFinal->SlotAt(islotFinal); - - // If we're in the middle of reordered bidi stuff, just use the end of the stream. - if (pslot->DirLevel() > nTopDir) - return -1; - - int islot = pslot->BeforeAssoc(); - if (islot == kPosInfinity || islot < 0) - return -1; - return islot + m_cslotPreSeg; -} - -/*---------------------------------------------------------------------------------------------- - Return the next higher (more relaxed, less desirable) line break weight. -----------------------------------------------------------------------------------------------*/ -LineBrk GrTableManager::IncLineBreak(LineBrk lb) -{ - Assert(lb != klbClipBreak); - return (LineBrk)((int)lb + 1); -} - -/*---------------------------------------------------------------------------------------------- - Return a pointer to a slot that is near the current position in the given stream. - Return NULL if no slots have been output at all. - This is used for initializing features of line-break slots. - @param ipassArg - pass at which to start looking - @param islot - slot to look for; -1 if considering the current position -----------------------------------------------------------------------------------------------*/ -GrSlotState * EngineState::AnAdjacentSlot(int ipassArg, int islot) -{ - int ipass = ipassArg; - while (ipass >= 0) - { - GrSlotStream * psstrm = OutputStream(ipass); - if (psstrm->NumberOfSlots() > 0) - { - if (islot == -1) - { - if (psstrm->AtEnd()) - return psstrm->SlotAt(psstrm->WritePos() - 1); - else - return psstrm->Peek(); - } - else - { - if (psstrm->WritePos() <= islot) - return psstrm->SlotAt(psstrm->WritePos() - 1); - else - return psstrm->SlotAt(islot); - } - } - ipass--; - } - return NULL; -} - -/*---------------------------------------------------------------------------------------------- - Simple access methods. -----------------------------------------------------------------------------------------------*/ -GrEngine * GrTableManager::Engine() -{ - return m_pgreng; -} - -EngineState * GrTableManager::State() -{ - return &m_engst; -} - -GrEngine * EngineState::Engine() -{ - return m_ptman->Engine(); -} - -GrTableManager * EngineState::TableManager() -{ - return m_ptman; -} - -/*---------------------------------------------------------------------------------------------- - Memory management for slots -----------------------------------------------------------------------------------------------*/ - -// standard for pass 0 slots -void EngineState::NewSlot( - gid16 gID, GrFeatureValues fval, int ipass, int ichwSegOffset, int nUnicode, - GrSlotState ** ppslotRet) -{ - NextSlot(ppslotRet); - (*ppslotRet)->Initialize(gID, Engine(), fval, ipass, ichwSegOffset, nUnicode); -} - -// line-break slots -void EngineState::NewSlot( - gid16 gID, GrSlotState * pslotFeat, int ipass, int ichwSegOffset, - GrSlotState ** ppslotRet) -{ - NextSlot(ppslotRet); - (*ppslotRet)->Initialize(gID, Engine(), pslotFeat, ipass, ichwSegOffset); -} - -// for inserting new slots after pass 0 (under-pos and unicode are irrelevant) -void EngineState::NewSlot( - gid16 gID, GrSlotState * pslotFeat, int ipass, - GrSlotState ** ppslotRet) -{ - NextSlot(ppslotRet); - (*ppslotRet)->Initialize(gID, Engine(), pslotFeat, ipass); -} - -// for making a new version of the slot initialized from the old -void EngineState::NewSlotCopy(GrSlotState * pslotCopyFrom, int ipass, - GrSlotState ** ppslotRet) -{ - NextSlot(ppslotRet); - (*ppslotRet)->InitializeFrom(pslotCopyFrom, ipass); -} - -void EngineState::NextSlot(GrSlotState ** ppslotRet) -{ - int cnExtraPerSlot = m_cUserDefn + (m_cCompPerLig * 2) + m_cFeat; - if (m_islotNext >= kSlotBlockSize) - { - // Allocate a new block of slots - GrSlotState * slotblkNew = new GrSlotState[kSlotBlockSize]; - u_intslot * prgnSlotBuf = new u_intslot[kSlotBlockSize * cnExtraPerSlot]; - - m_vslotblk.push_back(slotblkNew); - m_vprgnSlotVarLenBufs.push_back(prgnSlotBuf); - m_islotblkCurr++; - m_islotNext = 0; - Assert((unsigned)m_islotblkCurr == m_vslotblk.size()-1); - } - - *ppslotRet = m_vslotblk[m_islotblkCurr] + m_islotNext; - (*ppslotRet)->BasicInitialize(m_cUserDefn, m_cCompPerLig, m_cFeat, - (m_vprgnSlotVarLenBufs[m_islotblkCurr] + (m_islotNext * cnExtraPerSlot))); - m_islotNext++; -} - -/*---------------------------------------------------------------------------------------------- - Convert the number of font design units into source device logical units. -----------------------------------------------------------------------------------------------*/ -float GrTableManager::EmToLogUnits(int m) -{ - return m_engst.EmToLogUnits(m); -} - -float EngineState::EmToLogUnits(int m) -{ - if (m == 0) - return 0; - - float xysFontEmSquare; - m_pfont->getFontMetrics(NULL, NULL, &xysFontEmSquare); - - // mEmUnits should be equal to the design units in the font's em square - int mEmUnits = Engine()->GetFontEmUnits(); - if (mEmUnits <= 0) - { - Warn("Failed to obtain font em-units"); - return (float)m; - } - - return GrEngine::GrIFIMulDiv(m, xysFontEmSquare, mEmUnits); -} - -/*---------------------------------------------------------------------------------------------- - Convert the source device coordinates to font design units. -----------------------------------------------------------------------------------------------*/ -int GrTableManager::LogToEmUnits(float xys) -{ - return m_engst.LogToEmUnits(xys); -} - -int EngineState::LogToEmUnits(float xys) -{ - if (xys == 0) - return 0; - - float xysFontEmSquare; - m_pfont->getFontMetrics(NULL, NULL, &xysFontEmSquare); - - // mEmUnits should be equal to the design units in the font's em square - int mEmUnits = Engine()->GetFontEmUnits(); - if (mEmUnits < 0) - { - Warn("Failed to obtain font em-units"); - return (int)xys; - } - - return GrEngine::GrFIFMulDiv(xys, mEmUnits, xysFontEmSquare); -} - -/*---------------------------------------------------------------------------------------------- - Find the coordinates for a given glyph point. - Return true on success, false otherwise. -----------------------------------------------------------------------------------------------*/ -bool GrTableManager::GPointToXY(gid16 chwGlyphID, int nGPoint, float * pxs, float * pys) -{ - return m_engst.GPointToXY(chwGlyphID, nGPoint, pxs, pys); -} - -bool EngineState::GPointToXY(gid16 chwGlyphID, int nGPoint, float * pxs, float * pys) -{ - *pxs = INT_MIN; - *pys = INT_MIN; - Point pointRet; - m_pfont->getGlyphPoint(chwGlyphID, nGPoint, pointRet); - *pxs = pointRet.x; - *pys = pointRet.y; - - return true; -} - -/*---------------------------------------------------------------------------------------------- - Call the justification routines. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::CallJustifier(IGrJustifier * pgjus, int ipassCurr, - float dxUnjustified, float dxJustified, bool fEndLine) -{ - // Indicates the stream the justification routines will read and modify: - m_engst.m_ipassJustCalled = ipassCurr; - - int iGlyphMin = OutputStream(ipassCurr)->SegMin(); - int iGlyphLim = OutputStream(ipassCurr)->SegLimIfKnown(); - if (iGlyphLim == -1) - iGlyphLim = OutputStream(ipassCurr)->WritePos(); - - GrSlotStream * psstrm = OutputStream(ipassCurr); - if (m_pgreng->BasicJustification() && fEndLine) - UnstretchTrailingWs(psstrm, iGlyphLim); - - pgjus->adjustGlyphWidths(m_pgreng, iGlyphMin, iGlyphLim, dxUnjustified, dxJustified); - - // After returning, reading and modifying slot attributes is not permitted: - m_engst.m_ipassJustCalled = -1; -} - -/*---------------------------------------------------------------------------------------------- - For the basic justification approach, remove stretch from the trailing whitespace. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::UnstretchTrailingWs(GrSlotStream * psstrm, int iGlyphLim) -{ - int islot = iGlyphLim - 1; - while (islot >= 0) - { - GrSlotState * pslot = psstrm->SlotAt(islot); - if (pslot->IsLineBreak(LBGlyphID())) - { } // keep looking for the trailing space - else if (pslot->IsSpace(this)) - pslot->SetJStretch(0); // TODO: do this at level 0 - else - // something other than space--quit - return; - islot--; - } -} - -/*---------------------------------------------------------------------------------------------- - Determine how much shrink is permissible. - - This method is really used only for testing the shrink mechanism, since at this time - we don't allow low-end justification to do any shrinking. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::DetermineShrink(IGrJustifier * pgjus, int ipassCurr) -{ - if (m_engst.m_dxsShrinkPossible != GrSlotState::kNotYetSet) - return; - - if (m_engst.m_jmodi != kjmodiCanShrink || pgjus == NULL) - { - m_engst.m_dxsShrinkPossible = 0; - return; - } - - if (ipassCurr != m_ipassJust1 - 1) - return; - - GrSlotStream * psstrm = OutputStream(ipassCurr); - if (!psstrm->FullyWritten()) - return; - - // Normally just answer 0. To test shrinking, turn on the code below. - m_engst.m_dxsShrinkPossible = 0; - -#if TEST_SHRINK - int mTotal = 0; - int mShrink = 0; - int islotLim = psstrm->SegLimIfKnown(); - if (islotLim == -1) - islotLim = psstrm->WritePos(); - for ( ; islotLim >= 0; islotLim--) - { - // Trailing white space is not shrinkable. - GrSlotState * pslot = psstrm->SlotAt(islotLim - 1); - if (pslot->IsLineBreak(LBGlyphID())) - continue; - if (!pslot->IsSpace(this)) - break; - } - int islot; - for (islot = psstrm->SegMin(); islot < islotLim; islot++) - { - GrSlotState * pslot = psstrm->SlotAt(islot); - if (pslot->IsLineBreak(LBGlyphID())) - continue; - mTotal += pslot->AdvanceX(this); - mShrink += pslot->JShrink(); - } - - // Say that we are allowed to shrink up to 10% of the width of the segment. - mShrink = min(mShrink, mTotal/10); - m_engst.m_dxsShrinkPossible = EmToLogUnits(mShrink); -#endif // TEST_SHRINK -} - -/*---------------------------------------------------------------------------------------------- - Return the attribute of the given slot, back to the justification routine. Return - logical units. -----------------------------------------------------------------------------------------------*/ -GrResult EngineState::GetGlyphAttrForJustification(int iGlyph, int jgat, int nLevel, - float * pValueRet) -{ - GrResult res; - int valueRetInt = 0; - switch(jgat) - { - case kjgatWeight: - case kjgatStretchInSteps: - case kjgatBreak: - res = GetGlyphAttrForJustification(iGlyph, jgat, nLevel, &valueRetInt); - *pValueRet = (float)valueRetInt; - return res; - default: - break; - } - - if (m_ipassJustCalled == -1) - return kresUnexpected; - - if (nLevel != 1) - return kresInvalidArg; - - GrSlotStream * psstrm = OutputStream(m_ipassJustCalled); - - if (iGlyph < -1 || iGlyph >= psstrm->WritePos()) - return kresInvalidArg; - - GrSlotState * pslot = psstrm->SlotAt(iGlyph); - - // bool fConvertUnits = true; - - switch(jgat) - { - case kjgatStretch: - *pValueRet = EmToLogUnits(pslot->JStretch()); - break; - case kjgatShrink: - *pValueRet = EmToLogUnits(pslot->JShrink()); - break; - case kjgatStep: - *pValueRet = EmToLogUnits(pslot->JStep()); - break; - default: - return kresNotImpl; - } - return kresOk; -} - -GrResult EngineState::GetGlyphAttrForJustification(int iGlyph, int jgat, int nLevel, - int * pValueRet) -{ - GrResult res; - float valueRetFloat; - switch(jgat) - { - case kjgatStretch: - case kjgatShrink: - case kjgatStep: - res = GetGlyphAttrForJustification(iGlyph, jgat, nLevel, &valueRetFloat); - *pValueRet = GrEngine::RoundFloat(valueRetFloat); - return res; - default: - break; - } - - if (m_ipassJustCalled == -1) - return kresUnexpected; - - if (nLevel != 1) - return kresInvalidArg; - - GrSlotStream * psstrm = OutputStream(m_ipassJustCalled); - - if (iGlyph < -1 || iGlyph >= psstrm->WritePos()) - return kresInvalidArg; - - GrSlotState * pslot = psstrm->SlotAt(iGlyph); - - int mStretch, mStep; - //float xsStretch, xsStep; - - switch(jgat) - { - case kjgatWeight: - *pValueRet = pslot->JWeight(); - break; - case kjgatStretchInSteps: - // ???? should this be calculated in terms of logical units?? - // Probably doesn't matter, since the logical units are floating point, so the - // level of precision is about the same. - mStretch = pslot->JStretch(); - mStep = pslot->JStep(); - if (mStep == 0) - return kresUnexpected; - *pValueRet = int(mStretch / mStep); // round down - break; - //case kjgatStretchInSteps: - // xsStretch = EmToLogUnits(pslot->JStretch()); - // xsStep = EmToLogUnits(pslot->JStep()); - // if (xsStep == 0) - // return kresUnexpected; - // *pValueRet = int(xsStretch / xsStep); // round down - // break; - case kjgatBreak: - *pValueRet = pslot->BreakWeight(); - break; - default: - return kresNotImpl; - } - return kresOk; -} - -/*---------------------------------------------------------------------------------------------- - Set the attribute of the given slot, for the justification routine. -----------------------------------------------------------------------------------------------*/ -GrResult EngineState::SetGlyphAttrForJustification(int iGlyph, int jgat, int nLevel, - float value) -{ - GrResult res; - int valueInt; - switch(jgat) - { - case kjgatWeight: - case kjgatStretchInSteps: - case kjgatBreak: - valueInt = (int)value; - res = SetGlyphAttrForJustification(iGlyph, jgat, nLevel, valueInt); - return res; - default: - break; - } - - if (m_ipassJustCalled == -1) - return kresUnexpected; - - if (nLevel != 1) - return kresInvalidArg; - - GrSlotStream * psstrm = OutputStream(m_ipassJustCalled); - - if (iGlyph < -1 || iGlyph >= psstrm->WritePos()) - return kresInvalidArg; - - GrSlotState * pslot = psstrm->SlotAt(iGlyph); - - int mValue = LogToEmUnits(value); - mValue = min(mValue, 0xFFFF); // truncate to an unsigned short - - // Review: do we really want to allow them to set stretch/shrink/step/weight? The normal - // thing for them to do is set width. - switch(jgat) - { - case kjgatStretch: - pslot->SetJStretch(mValue); - break; - case kjgatShrink: - pslot->SetJShrink(mValue); - break; - case kjgatStep: - pslot->SetJStep(mValue); - break; - case kjgatWidth: - pslot->SetJWidth(mValue); - break; - default: - return kresNotImpl; - } - return kresOk; -} - -GrResult EngineState::SetGlyphAttrForJustification(int iGlyph, int jgat, int nLevel, - int value) -{ - GrResult res; - float valueFloat; - switch(jgat) - { - case kjgatStretch: - case kjgatShrink: - case kjgatStep: - case kjgatWidth: - valueFloat = (float)value; - res = SetGlyphAttrForJustification(iGlyph, jgat, nLevel, valueFloat); - return res; - default: - break; - } - - if (m_ipassJustCalled == -1) - return kresUnexpected; - - if (nLevel != 1) - return kresInvalidArg; - - GrSlotStream * psstrm = OutputStream(m_ipassJustCalled); - - if (iGlyph < -1 || iGlyph >= psstrm->WritePos()) - return kresInvalidArg; - - GrSlotState * pslot = psstrm->SlotAt(iGlyph); - - int mValue, cSteps; - switch(jgat) - { - case kjgatWeight: - pslot->SetJWeight(value); - break; - case kjgatWidthInSteps: - cSteps = value; - mValue = pslot->JStep(); - if (mValue == 0) - return kresUnexpected; - pslot->SetJWidth(mValue * cSteps); - break; - default: - return kresNotImpl; - } - return kresOk; -} - -//:>-------------------------------------------------------------------------------------------- -//:> Functions to forward to the engine. -//:>------------------------------------------------------------------------------------------*/ -gid16 GrTableManager::GetGlyphIDFromUnicode(int nUnicode) -{ - return m_pgreng->GetGlyphIDFromUnicode(nUnicode); -} - -/*--------------------------------------------------------------------------------------------*/ - -gid16 GrTableManager::ActualGlyphForOutput(utf16 chw) -{ - return m_pgreng->ActualGlyphForOutput(chw); -} - -/*--------------------------------------------------------------------------------------------*/ - -GrGlyphTable * GrTableManager::GlyphTable() -{ - return m_pgreng->GlyphTable(); -} - -/*--------------------------------------------------------------------------------------------*/ - -gid16 GrTableManager::LBGlyphID() -{ - return m_pgreng->LBGlyphID(); -} - -/*--------------------------------------------------------------------------------------------*/ - -gid16 GrTableManager::GetClassGlyphIDAt(int nClass, int nIndex) -{ - return m_pgreng->GetClassGlyphIDAt(nClass, nIndex); -} - -/*--------------------------------------------------------------------------------------------*/ - -int GrTableManager::GetIndexInGlyphClass(int nClass, gid16 chwGlyphID) -{ - return m_pgreng->GetIndexInGlyphClass(nClass, chwGlyphID); -} - -/*--------------------------------------------------------------------------------------------*/ - -size_t GrTableManager::NumberOfGlyphsInClass(int nClass) -{ - return m_pgreng->NumberOfGlyphsInClass(nClass); -} - -/*--------------------------------------------------------------------------------------------*/ - -void GrTableManager::SetSlotAttrsFromGlyphAttrs(GrSlotState * pslot) -{ - m_pgreng->SetSlotAttrsFromGlyphAttrs(pslot); -} - -/*--------------------------------------------------------------------------------------------*/ - -int GrTableManager::NumFeat() -{ - return m_pgreng->NumFeat(); -} - -/*--------------------------------------------------------------------------------------------*/ - -int GrTableManager::DefaultForFeatureAt(int ifeat) -{ - return m_pgreng->DefaultForFeatureAt(ifeat); -} - -/*--------------------------------------------------------------------------------------------*/ - -void GrTableManager::DefaultsForLanguage(isocode lgcode, - std::vector<featid> & vnFeats, std::vector<int> & vnValues) -{ - return m_pgreng->DefaultsForLanguage(lgcode, vnFeats, vnValues); -} - -/*--------------------------------------------------------------------------------------------*/ - -GrFeature * GrTableManager::FeatureWithID(featid nID, int * pifeat) -{ - return m_pgreng->FeatureWithID(nID, pifeat); -} - -/*--------------------------------------------------------------------------------------------*/ - -GrFeature * GrTableManager::Feature(int ifeat) -{ - return m_pgreng->Feature(ifeat); -} - -/*--------------------------------------------------------------------------------------------*/ - -bool GrTableManager::RightToLeft() -{ - if (m_engst.WhiteSpaceOnly()) - return m_engst.m_fParaRtl; - else - return m_pgreng->RightToLeft(); -} - -/*--------------------------------------------------------------------------------------------*/ - -int GrTableManager::TopDirectionLevel() -{ - return m_pgreng->TopDirectionLevel(); -} - -/*--------------------------------------------------------------------------------------------*/ - -float GrTableManager::VerticalOffset() -{ - return m_pgreng->VerticalOffset(); -} - -/*--------------------------------------------------------------------------------------------*/ - -int GrTableManager::NumUserDefn() -{ - return m_pgreng->NumUserDefn(); -} - -/*--------------------------------------------------------------------------------------------*/ - -int GrTableManager::NumCompPerLig() -{ - return m_pgreng->NumCompPerLig(); -} - -/*--------------------------------------------------------------------------------------------*/ - -int GrTableManager::ComponentIndexForGlyph(gid16 chwGlyphID, int nCompID) -{ - return m_pgreng->ComponentIndexForGlyph(chwGlyphID, nCompID); -} - -/*--------------------------------------------------------------------------------------------*/ - -int GrTableManager::GlyphAttrValue(gid16 chwGlyphID, int nAttrID) -{ - return m_pgreng->GlyphAttrValue(chwGlyphID, nAttrID); -} - -/*--------------------------------------------------------------------------------------------*/ - -bool GrTableManager::LoggingTransduction() -{ - return m_fLogging; - //return m_pgreng->LoggingTransduction(); -} - -/*---------------------------------------------------------------------------------------------- - Calculate the positions of the glyphs up to the given slot, within the output of the given - pass. If the slot is NULL, go all the way to the end of what has been generated. - - @param ipass - index of pass needing positioning; normally this will be the - final pass, but it could be another if positions are - requested by the rules themselves - @param pslotLast - last slot that needs to be positioned, or NULL - @param pxsWidth - return the total width used so far - @param psxVisibleWidth - return the visible width so far - - MOVE to EngineState -----------------------------------------------------------------------------------------------*/ -void GrTableManager::CalcPositionsUpTo(int ipass, GrSlotState * pslotLast, - float * pxsWidth, float * pxsVisibleWidth) -{ - Assert(ipass >= m_ipassPos1 - 1); - - int isstrm = ipass; - GrSlotStream * psstrm = OutputStream(isstrm); - Assert(psstrm->GotIndexOffset()); - if (psstrm->WritePos() <= psstrm->IndexOffset()) - { - Assert(psstrm->WritePos() == 0); - *pxsWidth = 0; - *pxsVisibleWidth = 0; - return; - } - if (!pslotLast) - { - pslotLast = psstrm->SlotAt(psstrm->WritePos() - 1); - } - Assert(pslotLast); - - // First set positions of all base slots. - - int islot = psstrm->IndexOffset(); - GrSlotState * pslot; - float xs = 0; - float ys = VerticalOffset(); - *pxsWidth = 0; - *pxsVisibleWidth = 0; - - bool fLast = false; - bool fLastBase = false; - - bool fFakeItalic = m_pgreng->FakeItalic(); - float fakeItalicRatio = 0; - if (fFakeItalic) - fakeItalicRatio = State()->GetFont()->fakeItalicRatio(); - bool fBasicJust = m_pgreng->BasicJustification(); - - // Figure out how to know when to stop. - // We need to calculate up to the base of the last leaf slot, if it happens - // to be later in the stream than the last actual slot passed in. - if (!psstrm->HasSlotAtPosPassIndex(pslotLast->AttachRootPosPassIndex())) - return; - GrSlotState * pslotLastBase = pslotLast->Base(psstrm); - - if (ipass == m_cpass - 1 && m_engst.m_islotPosNext > -1) - { - // For final pass, initialize from cache of previous calculations. - islot = m_engst.m_islotPosNext; - xs = m_engst.m_xsPosXNext; - ys = m_engst.m_ysPosYNext; - *pxsWidth = m_engst.m_dxsTotWidthSoFar; - *pxsVisibleWidth = m_engst.m_dxsVisWidthSoFar; - - if (psstrm->SlotsPresent() <= islot) - return; - - if (pslotLastBase->PosPassIndex() == GrSlotAbstract::kNotYetSet) - { - Assert(false); // I think this case is handled above - return; // can't position this slot yet; its base has not been processed - } - - if (pslotLastBase->PosPassIndex() + psstrm->IndexOffset() < islot) - { - fLastBase = true; - if (pslotLast == pslotLastBase) - fLast = true; - } - } - - std::vector<GrSlotState *> vpslotAttached; - - bool fRtl = RightToLeft(); - - while (!fLast || !fLastBase) - { - Assert(islot < psstrm->SlotsPresent()); - - pslot = (isstrm == ipass) ? psstrm->SlotAt(islot) : psstrm->OutputSlotAt(islot); - - if (!pslot->IsBase()) - { - // This slot is attached to another; it will be positioned strictly - // relative to that one. This happens in the loop below. - vpslotAttached.push_back(pslot); - } - else - { - // Base character. - - bool fLB = pslot->IsLineBreak(LBGlyphID()); - if (InternalJustificationMode() == kjmodiJustify && fBasicJust - && ipass == m_cpass - 1 && !fLB) - { - m_engst.AddJWidthToAdvance(psstrm, &pslot, islot, &pslotLast, &pslotLastBase); - } - - // Make sure the metrics are the complete ones. - pslot->CalcCompositeMetrics(this, psstrm, kPosInfinity, true); - - float xsInc = pslot->GlyphXOffset(psstrm, fakeItalicRatio); - float ysInc = pslot->GlyphYOffset(psstrm); - float xsAdvX = pslot->ClusterAdvWidth(psstrm); - float ysAdvY = (fLB) ? - 0 : - EmToLogUnits(pslot->AdvanceY(this)); - - if (fRtl) - { - xs -= xsAdvX; - ys -= ysAdvY; - pslot->SetXPos(xs + xsInc); - pslot->SetYPos(ys + ysInc); - } - else - { - pslot->SetXPos(xs + xsInc); - pslot->SetYPos(ys + ysInc); - xs += xsAdvX; - ys += ysAdvY; - } - - *pxsWidth = max(*pxsWidth, fabsf(xs)); - if (!IsWhiteSpace(pslot)) - *pxsVisibleWidth = *pxsWidth; - - if (isstrm == m_cpass - 1) - { - // For the final output pass, cache the results of the calculation so far. - // Only do this for slots that have actually been processed by the final - // pass, because others may have intermediate values that may be changed - // later. - m_engst.m_islotPosNext = pslot->PosPassIndex() + psstrm->IndexOffset() + 1; - m_engst.m_xsPosXNext = xs; - m_engst.m_ysPosYNext = ys; - m_engst.m_dxsTotWidthSoFar = *pxsWidth; - m_engst.m_dxsVisWidthSoFar = *pxsVisibleWidth; - } - } - - // Need to have calculated both the last leaf and the last base (if they happen to - // be different); if so, we're done. - if (pslot == pslotLast) - fLast = true; - if (pslot == pslotLastBase) - fLastBase = true; - - islot++; - } - - Assert(fLast); - Assert(fLastBase); - - // Now set positions of non-base slots, relative to their bases. - - for (size_t ipslot = 0; ipslot < vpslotAttached.size(); ipslot++) - { - GrSlotState * pslot = vpslotAttached[ipslot]; - GrSlotState * pslotBase = pslot->Base(psstrm); - if (pslotBase->XPosition() == kNegInfinity || pslotBase->YPosition() == kNegInfinity) - { - Assert(false); - continue; - } - float xsCluster = pslotBase->XPosition() - pslotBase->GlyphXOffset(psstrm, fakeItalicRatio); - float ysCluster = pslotBase->YPosition() - pslotBase->GlyphYOffset(psstrm); - float xsInc = pslot->GlyphXOffset(psstrm, fakeItalicRatio); - float ysInc = pslot->GlyphYOffset(psstrm); - pslot->SetXPos(xsCluster + xsInc); - pslot->SetYPos(ysCluster + ysInc); - - // My theory is that we don't need to adjust *pxsWidth here, because the width of - // any non-base slots should be factored into the advance width of their cluster - // base, which was handled above. - } -} - -/*---------------------------------------------------------------------------------------------- - Return true if the given slot is white space. -----------------------------------------------------------------------------------------------*/ -bool GrTableManager::IsWhiteSpace(GrSlotState * pslot) -{ - if (pslot->IsLineBreak(LBGlyphID())) - return true; - return pslot->IsSpace(this); -} - -/*---------------------------------------------------------------------------------------------- - When doing basic justification, apply the value of justify.width to the advance width. - This happens during the final positioning routine. -----------------------------------------------------------------------------------------------*/ -void EngineState::AddJWidthToAdvance(GrSlotStream * psstrm, GrSlotState ** ppslot, int islot, - GrSlotState ** ppslotLast, GrSlotState ** ppslotLastBase) -{ - Assert(psstrm->OutputOfPass() == m_cpass - 1); // only used for final stream - if ((*ppslot)->JWidth() > 0) - { - if ((*ppslot)->PassModified() != m_cpass - 1) - { - // Replace the slot with a new slot, so it gets marked properly with the - // pass in which it was modified. (Otherwise the debug log gets screwed up.) - GrSlotState * pslotNew; - NewSlotCopy((*ppslot), m_cpass - 1, &pslotNew); - psstrm->PutSlotAt(pslotNew, islot); - if (*ppslot == *ppslotLast) - *ppslotLast = pslotNew; - if (*ppslot == *ppslotLastBase) - *ppslotLastBase = pslotNew; - *ppslot = pslotNew; - } - (*ppslot)->AddJWidthToAdvance(TableManager()); - } -} - - -//:>******************************************************************************************** -//:> Debuggers and utilities -//:>******************************************************************************************** - -//:Ignore -#if 0 -void GrTableManager::TempDebug() -{ - for (int ipass = 0; ipass < m_cpass; ++ipass) - { - int wpos = OutputStream(ipass)->WritePos(); - int rpos = OutputStream(ipass)->ReadPos(); - GrSlotState * wslot = OutputStream(ipass)->LastSlotWritten(); - GrSlotState * rslot = OutputStream(ipass)->LastSlotRead(); - - } -} -#endif -/*---------------------------------------------------------------------------------------------- - Given a character index in the original string, locate the corresponding line-break slot - in the final surface stream. The character index must be one before which there is a - line-break (seg lim), or the beginning or the end of the string. - TODO SharonC: fix the bugs -----------------------------------------------------------------------------------------------*/ -int GrTableManager::SurfaceLineBreakSlot(int ichw, GrCharStream * pchstrm, bool fInitial) -{ - if (ichw == 0) - { - Assert(fInitial); - return -1; // no initial line break - } - if (ichw == pchstrm->Lim()) - { - Assert(!fInitial); - return -1; // no terminating line break - } - - int islotIn = pchstrm->SegOffset(ichw); - Assert(islotIn >= 0); - islotIn += (fInitial? m_engst.m_cslotPreSeg - 1: m_engst.m_cslotPreSeg); - - gid16 chwLBGlyphID = LBGlyphID(); - - // Now islotIn is the position in stream 0; - - for (int ipass = 1; ipass < m_cpass; ++ipass) - { - int islotChunkMin; - int islotChunkLim; - GrSlotStream * psstrmOut = OutputStream(ipass); - - GrSlotStream * psstrmIn = InputStream(ipass); - if (fInitial) - islotIn = max(islotIn, psstrmIn->PreChunk()); - int islotT = psstrmIn->ChunkInNextMin(islotIn); - islotChunkMin = psstrmIn->ChunkInNext(islotT); - islotChunkMin = (islotChunkMin == -1)? 0: islotChunkMin; - - islotT = psstrmIn->ChunkInNextLim(islotIn); - Assert(islotT <= psstrmIn->ReadPos()); - if (islotT == psstrmIn->ReadPos()) - islotChunkLim = psstrmOut->WritePos(); - else - islotChunkLim = psstrmIn->ChunkInNext(islotT); - - int islotOut; - for (islotOut = islotChunkMin; islotOut < islotChunkLim; ++islotOut) - { - gid16 chw = psstrmOut->GlyphIDAt(islotOut); - if (chw == chwLBGlyphID) - break; - } - Assert(psstrmOut->GlyphIDAt(islotOut) == chwLBGlyphID); - - islotIn = islotOut; - } - return islotIn; -} - -/*---------------------------------------------------------------------------------------------- - Generate a debugger string showing the chunk boundaries for the given stream. -----------------------------------------------------------------------------------------------*/ -std::wstring GrTableManager::ChunkDebugString(int ipass) -{ - GrSlotStream * psstrm = OutputStream(ipass); - std::wstring stuRet; - //utf16 chwN = '\\'; - //utf16 chwR = '^'; - - gid16 chwLBGlyphID = LBGlyphID(); - - for (int islot = 0; islot < psstrm->WritePos(); islot++) - { - if (psstrm->ChunkInPrev(islot) != -1) - { - if (psstrm->ChunkInNext(islot) != -1) - stuRet.append(L">"); - else - stuRet.append(L"\\"); - } - else if (psstrm->ChunkInNext(islot) != -1) - stuRet.append(L"/"); - else - stuRet.append(L" "); - -// if (islot == psstrm->ReadPos()) -// stuRet.Append(&chwR, 1); - - wchar_t chw = psstrm->SlotAt(islot)->GlyphID(); - if (chw == chwLBGlyphID) - stuRet.append(L"#"); - else - stuRet.append(&chw, 1); - } - return stuRet; -} - -} // namespace gr - -//:End Ignore diff --git a/Build/source/libs/graphite-engine/src/segment/GrTableManager.h b/Build/source/libs/graphite-engine/src/segment/GrTableManager.h deleted file mode 100644 index e0306c832c7..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/GrTableManager.h +++ /dev/null @@ -1,583 +0,0 @@ -/*--------------------------------------------------------------------*//*:Ignore this sentence. -Copyright (C) 1999 - 2008 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: GrTableManager.h -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - The GrTableManager class. -----------------------------------------------------------------------------------------------*/ -#ifdef _MSC_VER -#pragma once -#endif -#ifndef GR_TABLEMAN_INCLUDED -#define GR_TABLEMAN_INCLUDED - -#include <cassert> -//:End Ignore - -namespace gr -{ - -class Font; - -/*---------------------------------------------------------------------------------------------- - There is a single instance of Engine State that keeps track of the state of the processing - for a single segment generation. - - Hungarian: engst -----------------------------------------------------------------------------------------------*/ -class EngineState -{ - friend class GrTableManager; - friend class FontMemoryUsage; - -public: - EngineState(); - void Initialize(GrEngine *, GrTableManager *); - - ~EngineState(); - void DestroySlotBlocks(); - - void InitForNewSegment(GrTableManager * ptman); - - void CreateEmpty(); - - GrEngine * Engine(); - GrTableManager * TableManager(); - - void CreateSlotStreams(); - - GrSlotStream * InputStream(int ipass) - { - Assert(ipass > 0); // the char stream serves as input to the zeroth pass - return m_prgpsstrm[ipass - 1]; - } - - // Return the stream that serves as output to the given pass. - GrSlotStream * OutputStream(int ipass) - { - Assert(ipass < m_cpass); - return m_prgpsstrm[ipass]; - } - - GrSlotState * AnAdjacentSlot(int ipassArg, int islotArg); - - GrResult GetGlyphAttrForJustification(int iGlyph, int jgat, int nLevel, float * pxysValueRet); - GrResult GetGlyphAttrForJustification(int iGlyph, int jgat, int nLevel, int * pxysValueRet); - GrResult SetGlyphAttrForJustification(int iGlyph, int jgat, int nLevel, float xysValue); - GrResult SetGlyphAttrForJustification(int iGlyph, int jgat, int nLevel, int xysValue); - - enum { kSlotBlockSize = 50 }; // number of slots to allocate in a block - - void InitPosCache() - { - m_islotPosNext = -1; - m_xsPosXNext = 0; - m_ysPosYNext = 0; - m_dxsTotWidthSoFar = 0; - m_dxsVisWidthSoFar = 0; - } - - void SetFont(Font * pfont) - { - m_pfont = pfont; - } - Font * GetFont() - { - return m_pfont; - } - - bool StartLineContext() - { - return m_fStartLineContext; - } - bool EndLineContext() - { - return m_fEndLineContext; - } - void SetStartLineContext(bool f) - { - m_fStartLineContext = f; - } - void SetEndLineContext(bool f) - { - m_fEndLineContext = f; - } - - void SetInitialLB(bool f = true) - { - m_fInitialLB = f; - } - - void SetFinalLB(bool f = true) - { - m_fFinalLB = f; - } - - void SetInsertedLB(bool f = true) - { - m_fInsertedLB = f; - } - - bool HasInitialLB() - { - return m_fInitialLB; - } - bool HasInsertedLB() - { - return m_fInsertedLB; - } - bool HasFinalLB() - { - return m_fFinalLB; - } - - void SetExceededSpace(bool f = true) - { - m_fExceededSpace = f; - } - - bool ExceededSpace() - { - return m_fExceededSpace; - } - - void SetHitHardBreak(bool f = true) - { - m_fHitHardBreak = f; - } - - bool HitHardBreak() - { - return m_fHitHardBreak; - } - - void SetRemovedTrWhiteSpace(bool f = true) - { - m_fRemovedWhtsp = f; - } - - bool RemovedTrWhiteSpace() - { - return m_fRemovedWhtsp; - } - - bool WhiteSpaceOnly() - { - return (m_twsh == ktwshOnlyWs); - } - - bool ParaRightToLeft() - { - return m_fParaRtl; - } - - //int PrevPassMaxBackup(int ipass) - //{ - // if (ipass == 0) - // return 0; - // return Pass(ipass - 1)->MaxBackup(); - //} - - DirCode InitialStrongDir() - { - return m_dircInitialStrongDir; - } - DirCode InitialTermDir() - { - return m_dircInitialTermDir; - } - - void InitializeStreams(GrTableManager * ptman, GrCharStream * pchstrm, - int cbPrev, byte * pbPrevSegDat, bool fNeedFinalBreak, int * pislotFinalBreak); - int LbSlotToSegLim(int islot, GrCharStream * pchstrm, int cpassLB); - int TraceStreamZeroPos(int islotFinal, int nTopDir); - - float EmToLogUnits(int m); - int LogToEmUnits(float xys); - bool GPointToXY(gid16 chwGlyphID, int nGPoint, float * xs, float * ys); - - void AddJWidthToAdvance(GrSlotStream * psstrm, GrSlotState ** ppslot, int islot, - GrSlotState ** ppslotLast, GrSlotState ** ppslotLastBase); - - // Memory management for slots: - void NewSlot(gid16 gID, GrFeatureValues fval, int ipass, int ichwSegOffset, int nUnicode, - GrSlotState **); - void NewSlot(gid16 gID, GrSlotState * pslotFeat, int ipass, int ichwSegOffset, - GrSlotState **); - void NewSlot(gid16 gID, GrSlotState * pslotFeat, int ipass, GrSlotState **); - void NewSlotCopy(GrSlotState * pslotCopyFrom, int ipass, - GrSlotState ** pslotRet); -protected: - void NextSlot(GrSlotState ** ppslot); - -protected: - GrTableManager * m_ptman; - - int m_cFeat; - int m_cCompPerLig; - int m_cUserDefn; - - int m_jmodi; // justification mode - int m_ipassJustCalled; // pass after which justification routine was called; - // -1 if we are not in the midst of interacting with the - // GrJustifier - - // Pointer to font - Font * m_pfont; - - bool m_fStartLineContext; // true if there was a rule that ran over the initial LB - bool m_fEndLineContext; // true if there was a rule that ran over the final LB - - // the number of slots inserted in the first stream before the official beginning - // of the segment, including any initial line break - int m_cslotPreSeg; - - // List of allocated GrSlotStates; hungarian slotblk = prgslot - std::vector<GrSlotState *> m_vslotblk; - std::vector<u_intslot *> m_vprgnSlotVarLenBufs; // corresponding var-length blocks - int m_islotblkCurr; - int m_islotNext; - - // Directionality codes from previous segment; these are used by the bidi algorithm - // at the initial line-break character. - DirCode m_dircInitialStrongDir; - DirCode m_dircInitialTermDir; - - LineBrk m_lbPrevEnd; - - // All of the following 3 are true only when there is an actual LB glyph in the stream - bool m_fInitialLB; // is there is an initial LB (an actual LB glyph--in all streams) - bool m_fFinalLB; // is there is a final LB (in all streams--true when we've hit - // the end of the input and end-of-line is true) - bool m_fInsertedLB; // is there is a final LB inserted in the output of LB pass - // (true when we've backtracked) - - bool m_fExceededSpace; // true if we backtracked due to exceeding space; false if we - // haven't backtracked, or we did so for some other reason - // (eg, omitting trailing whitespace) - - bool m_fHitHardBreak; // true if we encountered a hard-break in the input stream - // (before the natural end of the segment) - - bool m_fRemovedWhtsp; // true if we've hit trailing whitespace characters that we've - // removed - - TrWsHandling m_twsh; // white-space handling - bool m_fParaRtl; // paragraph direction - - float m_dxsShrinkPossible; - - // The final positioning pass is where we are going to do most of the positioning. - // Cache the intermediate results so we don't have to calculate from the beginning of - // the segment every time. - int m_islotPosNext; // where to continue calculating positions in final output stream - // (one past the last base that was calculated) - float m_xsPosXNext; - float m_ysPosYNext; - float m_dxsTotWidthSoFar; - float m_dxsVisWidthSoFar; - - int m_cpass; // number of passes - - // array of pass-state objects - PassState * m_prgzpst; - - // array of slot streams which are output of passes (input of zeroth - // pass is the character stream, not a slot stream): - GrSlotStream ** m_prgpsstrm; - // For instance, a simple set of passes might look like this: - // CharStream - // GlyphGenPass pass 0 - // SlotStream stream 0 - // SubPass pass 1 - // SlotStream stream 1 - // PosPass pass 2 - // SlotStream stream 2 - // - // m_cpass = 3 - -}; // end of class EngineState - -/*---------------------------------------------------------------------------------------------- - There is a single instance of GrTableManager that handle the interactions between - passes, including the demand-pull mechanism. - - Hungarian: tman -----------------------------------------------------------------------------------------------*/ - -class GrTableManager { - friend class FontMemoryUsage; - -public: - // Constructor & destructor: - GrTableManager(GrEngine * pgreng) - : m_cpass(0), - m_fBidi(false), - m_prgppass(NULL), - m_pgreng(pgreng) - { - Assert(pgreng); - } - - ~GrTableManager(); - - bool CreateAndReadPasses(GrIStream & grstrm, int fxdSilfVersion, int fxdRuleVersion, - int cpassFont, long lSubTableStart, int * rgnPassOffsets, - int ipassSub1Font, int ipassPos1Font, int ipassJust1Font, byte ipassPostBidiFont); - - void CreateEmpty(); - - GrEngine * Engine(); - EngineState * State(); - - void Run(Segment * psegNew, Font * pfont, GrCharStream * pchstrm, - IGrJustifier * pgjus, int jmodi, - LayoutEnvironment & layout, - int ichStop, float dxWidth, float dxUnjustified, - bool fNeedFinalBreak, bool fMoreText, int ichFontLim, - bool fInfiniteWidth, bool fWidthIsCharCount, - int ichwCallerBtLim, - int nDirDepth, SegEnd estJ); - - GrPass* Pass(int ipass) - { - Assert(ipass >= 0); - return m_prgppass[ipass]; - } - - int NumberOfPasses() - { - return m_cpass; - } - - int NumberOfLbPasses() - { - return m_cpassLB; - } - - bool HasBidiPass() - { - return m_fBidi; - } - - int FirstPosPass() - { - return m_ipassPos1; - } - - void StorePassStates(PassState * rgzpst); - - // Return the stream that serves as input to the given pass. - GrSlotStream * InputStream(int ipass) - { - return m_engst.InputStream(ipass); - } - GrSlotStream * OutputStream(int ipass) - { - return m_engst.OutputStream(ipass); - } - - void UnwindAndReinit(int islotNewBreak); - -public: - int InternalJustificationMode() - { - return m_engst.m_jmodi; - } - - bool ShouldLogJustification() - { - return (m_engst.m_jmodi != kjmodiNormal); - } - - int PrevPassMaxBackup(int ipass) - { - if (ipass == 0) - return 0; - return Pass(ipass - 1)->MaxBackup(); - } - - // Forward to the engine itself - gid16 GetGlyphIDFromUnicode(int nUnicode); - gid16 ActualGlyphForOutput(utf16 chwGlyphID); - GrGlyphTable * GlyphTable(); - - gid16 LBGlyphID(); - - gid16 GetClassGlyphIDAt(int nClass, int nIndex); - int GetIndexInGlyphClass(int nClass, gid16 chwGlyphID); - size_t NumberOfGlyphsInClass(int nClass); - - void SetSlotAttrsFromGlyphAttrs(GrSlotState * pslot); - - int NumFeat(); - int DefaultForFeatureAt(int ifeat); - GrFeature * FeatureWithID(featid nID, int * pifeat); - GrFeature * Feature(int ifeat); - void DefaultsForLanguage(isocode lgcode, - std::vector<featid> & vnFeats, std::vector<int> & vnValues); - - bool RightToLeft(); - int TopDirectionLevel(); - - float VerticalOffset(); - - int NumUserDefn(); - int NumCompPerLig(); - - int ComponentIndexForGlyph(gid16 chwGlyphID, int nCompID); - int GlyphAttrValue(gid16 chwGlyphID, int nAttrID); - - // --- - - bool LoggingTransduction(); - - float EmToLogUnits(int m); - int LogToEmUnits(float xys); - bool GPointToXY(gid16 chwGlyphID, int nGPoint, float * xs, float * ys); - - void CalcPositionsUpTo(int ipass, GrSlotState * pslotLast, - float * pxsWidth, float * pxsVisibleWidth); - - void InitPosCache() - { - m_engst.InitPosCache(); - } - - bool IsWhiteSpace(GrSlotState * pslot); - - // For transduction logging: - bool WriteTransductionLog(std::ostream * pstrmLog, - GrCharStream * pchstrm, Segment * psegRet, int cbPrevSetDat, byte * pbPrevSegDat); - bool WriteAssociationLog(std::ostream * pstrmLog, - GrCharStream * pchstrm, Segment * psegRet); - bool WriteXmlLog(std::ostream * pstrmLog, - GrCharStream * pchstrm, Segment * psegRet, int cbPrevSegDat, byte * pbPrevSegDat); - bool WriteXmlAssocLog(std::ostream * pstrmLog, - GrCharStream * pchstrm, Segment * psegRet); - -#ifdef TRACING - void WriteXductnLog(std::ostream & strmOut, GrCharStream * pchstrm, Segment * psegRet, - int cbPrevSegDat, byte * pbPrevSegDat); - //bool LogFileName(std::string & staFile); - void LogUnderlying(std::ostream & strmOut, GrCharStream * pchstrm, int cchwBackup); - void LogPass1Input(std::ostream & strmOut); - void LogPassOutput(std::ostream & strmOut, int ipass, int cslotSkipped); - void LogAttributes(std::ostream & strmOut, int ipass, bool fJustWidths = false); - void LogFinalPositions(std::ostream & strmOut); - void LogUnderlyingHeader(std::ostream & strmOut, int ichwMin, - int ichwLim, int cchwBackup, int * prgichw16bit); - void LogSlotHeader(std::ostream & strmOut, int cslot, - int cspPerSlot, int cspLeading, int islotMin = 0); - void LogSlotGlyphs(std::ostream & strmOut, GrSlotStream * psstrm); - void SlotAttrsModified(int ipass, bool * rgfMods, bool fPreJust, int * pccomp, int *pcassoc); - void LogInTable(std::ostream & strmOut, int n); - void LogInTable(std::ostream & strmOut, float n); - void LogHexInTable(std::ostream & strmOut, gid16 chw, bool fPlus = false); - void LogDirCodeInTable(std::ostream & strmOut, int dirc); - void LogBreakWeightInTable(std::ostream & strmOut, int lb); - - void WriteXmlLogAux(std::ostream & strmOut, - GrCharStream * pchstrm, Segment * psegRet, int cbPrevSegDat, byte * pbPrevSegDat); - void LogXmlUnderlying(std::ostream & strmOut, GrCharStream * pchstrm, int cchwBackup, size_t nIndent); - void LogXmlUnderlyingAux(std::ostream & strmOut, GrCharStream * pchstrm, - int cch32Backup, int cch32Lim, size_t nIndent, - bool fLogText, bool fLogFeatures, bool fLogColor, bool fLogStrOff, bool fLogLig, bool fLogGlyphs); - void LogXmlPass(std::ostream & strmOut, int ipass, int cslotSkipped, int nIndent); - - void LogXmlTagOpen(std::ostream & strmOut, std::string strTag, size_t nIndent, bool fContent); - void LogXmlTagPostAttrs(std::ostream & strmOut, bool fContent); - void LogXmlTagClose(std::ostream & strmOut, std::string strTag, size_t nIndent, bool fContent); - void LogXmlTagAttr(std::ostream & strmOut, std::string strAttr, int nValue, size_t nIndent = 0); - void LogXmlTagAttr(std::ostream & strmOut, std::string strAttr, const char * szValue, size_t nIndent = 0); - void LogXmlTagAttrHex(std::ostream & strmOut, std::string strAttr, int nValue, size_t nIndent = 0); - std::string HexString(int n1, int n2, int n3, int n4, int n5, int n6); - std::string HexString(std::vector<int>); - void LogXmlTagColor(std::ostream & strmOut, std::string strAttr, int clrValue, bool fBack, - size_t nIndent = 0); - void LogXmlDirCode(std::ostream & strmOut, std::string strAttr, int dircValue, size_t nIndent = 0); - void LogXmlBreakWeight(std::ostream & strmOut, std::string strAttr, int dircValue, - size_t nIndent = 0); - void LogXmlComment(std::ostream & strmOut, std::string strComment, size_t nIndent = 0); - -#endif // TRACING - -protected: - void InitNewSegment(Segment * psegNew, Font * pfont, GrCharStream * pchstrm, IGrJustifier * pgjus, - int islotStream0Break, int islotSurfaceBreak, bool fStartLine, bool fEndLine, int ichFontLim, - LineBrk lbEnd, SegEnd est, int * dichSegLen); - - void InitSegmentAsEmpty(Segment * psegNew, Font * pfont, GrCharStream * pchstrm, - bool fStartLine, bool fEndLine); - - void InitSegmentToDelete(Segment * psegNew, Font * pfont, GrCharStream * pchstrm); - - int ChunkInPrev(int ipass, int islot, GrCharStream * pchstrm); - - bool Backtrack(int * islotPrevLB, - LineBrk * plbPref, LineBrk lbMax, TrWsHandling, bool fMoreText, - int ichwCallerBtLim, LineBrk * plbFound); - - LineBrk IncLineBreak(LineBrk lb); - - void InitializeForNextSeg(Segment* pseg, - int islotStream0Break, int islotSurfaceBreak, LineBrk lbEnd, - bool fNextSegNeedsContext, GrCharStream * pchstrm); - - void SetFinalPositions(Segment * pseg, bool fWidthIsCharCount); - void RecordAssocsAndOutput(Font * pfont, Segment * pseg, - TrWsHandling twsh, bool fParaRtl, int nDirDepth); - - void CalculateAssociations(Segment * pseg, int csloutSurface); - void AdjustAssocsForOverlaps(Segment * pseg); - - void UnstretchTrailingWs(GrSlotStream * psstrm, int iGlyphLim); - void CallJustifier(IGrJustifier * pgjus, int ipassCurr, float dxUnjustified, float dxJustified, - bool fEndLine); - - void DetermineShrink(IGrJustifier * pgjus, int ipass); - -protected: - // Instance variables: - - int m_cpass; // number of passes; zero-th pass is Unicode character -> glyph ID mapping; - // Note thatwe always have one positioning pass to measure things even - // if there are no tables to run. - - int m_cpassLB; // number of line-break passes - int m_ipassPos1; // first positioning pass - int m_ipassJust1; // first justification pass (== m_ipassPos1 if none) - - bool m_fBidi; // is there a bidi pass? - - // array of passes: - GrPass ** m_prgppass; - - // Pointer back to Graphite engine, to give access to global constants and tables. - GrEngine * m_pgreng; - - // State of processing. - EngineState m_engst; - - bool m_fLogging; - -public: - // For test procedures: - void SetUpTest(std::wstring); - -protected: - void TempDebug(); - int SurfaceLineBreakSlot(int ichw, GrCharStream * pchstrm, bool fInitial); - std::wstring ChunkDebugString(int ipass); -}; // end of class GrTableManager - -} // namespace gr - - -#endif // !GR_TABLEMAN_INCLUDED diff --git a/Build/source/libs/graphite-engine/src/segment/Main.h b/Build/source/libs/graphite-engine/src/segment/Main.h deleted file mode 100644 index da95af09ce8..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/Main.h +++ /dev/null @@ -1,181 +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: Main.h -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Main.header file for the Graphite engine. -----------------------------------------------------------------------------------------------*/ -#ifdef _MSC_VER -#pragma once -#endif -#ifndef GRAPHITE_H -#define GRAPHITE_H 1 - -//:End Ignore - -#define NO_EXCEPTIONS 1 - -// It's okay to use functions that were declared deprecated by VS 2005: -#ifdef _MSC_VER -#define _CRT_SECURE_NO_DEPRECATE -#pragma warning(disable: 4996) // warning: function was declared deprecated -#pragma warning(disable: 4702) // unreachable code -#endif - -#include "GrCommon.h" - -//:>******************************************************************************************** -//:> Interfaces. -//:>******************************************************************************************** -#include "GrData.h" - -//:>******************************************************************************************** -//:> Implementations. -//:>******************************************************************************************** - -#ifndef _WIN32 -#include "GrMstypes.h" -#ifndef HAVE_FABSF -float fabsf(float x); -#endif -#endif -#include "GrDebug.h" - -// For reading the font (FieldWorks's approach) and transduction logging: -#include <fstream> -#include <iostream> - -#include <vector> -////#include <algorithm> -#include <string> - -// gAssert should be used for any kind of assertions that can be caused by a corrupted font, -// particularly those that won't be caught when loading the tables. -#define gAssert(x) Assert(x) -// When testing the error mechanism (because the process of bringing up the assertion dialog -// interferes with FW repainting the invalid window: -////#define gAssert(x) if (!(x)) Warn("corrupted font?") - -// Internal headers. -#include "FileInput.h" - -// Public headers. -#include "GrResult.h" -//////#include "IGrGraphics.h" -#include "ITextSource.h" -#include "IGrJustifier.h" -#include "IGrEngine.h" -#include "GrConstants.h" -#include "GrFeature.h" - -// External helper classes. -#include "GrExt.h" - - -// Forward declarations. -namespace gr -{ - class GrTableManager; - class Segment; - class GrEngine; -} - -// Define after GrExt.h to avoid conflict with FW Rect class. -namespace gr -{ -/* -struct Point -{ - float x; - float y; - - Point() - { - x = y = 0; - } - - Point(POINT & p) - { - x = (float)p.x; - y = (float)p.y; - } -}; - - -struct Rect -{ - float top; - float bottom; - float left; - float right; - - Rect() - { - top = bottom = left = right = 0; - }; - - Rect(RECT & r) - { - top = (float)r.top; - bottom = (float)r.bottom; - left = (float)r.left; - right = (float)r.right; - }; -}; -*/ -}; // namespace gr - -#include "GrFeatureValues.h" -#include "GrSlotState.h" - -#include "SegmentAux.h" - -// Internal headers -#include "GrCharStream.h" -#include "GrGlyphTable.h" -#include "GrClassTable.h" -#include "GrPseudoMap.h" -#include "GrSlotStream.h" -#include "GrFSM.h" -#include "GrPass.h" -#include "GrTableManager.h" -#include "FontCache.h" - - -// Public headers -#include "Font.h" -#include "GraphiteProcess.h" -#include "GrEngine.h" -#include "FontFace.h" -#include "Segment.h" -#include "SegmentPainter.h" - -//#ifdef _WIN32 -//#include <hash_map> -//#include "WinFont.h" -//#include "WinSegmentPainter.h" -//#endif - -// Internal headers -#include "TtfUtil.h" -//#include "GrUtil.h" - -#include "GrWrappers.h" - -//#include "IGrDebug.h" -//#include "GrSegmentDebug.h" -//#include "GrEngineDebug.h" - -/////<<<<<<< .mine -// clashes with non gr stuff -// using namespace gr; -///////>>>>>>> .r98 - -#endif // GRAPHITE_H - diff --git a/Build/source/libs/graphite-engine/src/segment/Makefile.am b/Build/source/libs/graphite-engine/src/segment/Makefile.am deleted file mode 100644 index 59113aa924b..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/Makefile.am +++ /dev/null @@ -1,26 +0,0 @@ -segmentdir = $(top_srcdir)/src/segment - -libgraphite_la_SOURCES += $(segmentdir)/FileInput.cpp -libgraphite_la_SOURCES += $(segmentdir)/FontCache.cpp -libgraphite_la_SOURCES += $(segmentdir)/FontFace.cpp -libgraphite_la_SOURCES += $(segmentdir)/GrCharStream.cpp -libgraphite_la_SOURCES += $(segmentdir)/GrClassTable.cpp -libgraphite_la_SOURCES += $(segmentdir)/GrEngine.cpp -libgraphite_la_SOURCES += $(segmentdir)/GrFeature.cpp -libgraphite_la_SOURCES += $(segmentdir)/GrFSM.cpp -libgraphite_la_SOURCES += $(segmentdir)/GrGlyphTable.cpp -libgraphite_la_SOURCES += $(segmentdir)/GrPassActionCode.cpp -libgraphite_la_SOURCES += $(segmentdir)/GrPass.cpp -libgraphite_la_SOURCES += $(segmentdir)/GrSlotState.cpp -libgraphite_la_SOURCES += $(segmentdir)/GrSlotStream.cpp -libgraphite_la_SOURCES += $(segmentdir)/GrTableManager.cpp -libgraphite_la_SOURCES += $(segmentdir)/MemoryUsage.cpp -libgraphite_la_SOURCES += $(segmentdir)/Platform.cpp -libgraphite_la_SOURCES += $(segmentdir)/SegmentAux.cpp -libgraphite_la_SOURCES += $(segmentdir)/Segment.cpp -libgraphite_la_SOURCES += $(segmentdir)/TestFSM.cpp -libgraphite_la_SOURCES += $(segmentdir)/TestPasses.cpp -libgraphite_la_SOURCES += $(segmentdir)/TransductionLog.cpp - -EXTRA_DIST += $(segmentdir)/*.h - diff --git a/Build/source/libs/graphite-engine/src/segment/MemoryUsage.cpp b/Build/source/libs/graphite-engine/src/segment/MemoryUsage.cpp deleted file mode 100644 index 1fb3fc25282..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/MemoryUsage.cpp +++ /dev/null @@ -1,781 +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: MemoryUsage.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Calculates memory usage for the engine and segments. -----------------------------------------------------------------------------------------------*/ - -#pragma warning(disable: 4244) // conversion from wchar_t to char -#pragma warning(disable: 4702) // unreachable code - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** - -#include "GrCommon.h" -#include "GrData.h" -#ifndef _WIN32 -#include "GrMstypes.h" -#endif -#include "GrDebug.h" -//#include <fstream> -#include <iostream> -#include <cstring> -//#include <string> -// Forward declarations. - -#include "Main.h" - -//namespace gr -//{ -// class GrTableManager; -// class Segment; -// class GrEngine; -//} -// -//#include "GrTableManager.h" -//#include "GrFeatureValues.h" -//#include "GrSlotState.h" -//#include "SegmentAux.h" -//#include "Segment.h" -#include "MemoryUsage.h" - -//#ifndef _MSC_VER -//#include "config.h" -//#endif - -#ifdef _MSC_VER -#pragma hdrstop -#endif -#undef THIS_FILE -DEFINE_THIS_FILE - -//:End Ignore - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -const int stringOverhead = (3 * sizeof(int)) + (sizeof(void *)) + (8 * sizeof(short)); -const int vectorOverhead = 3 * sizeof(void *); - -namespace gr -{ - -//:>******************************************************************************************** -//:> Font/engine -//:>******************************************************************************************** - -void FontMemoryUsage::initialize() -{ - font = 0; - fontCache = 0; - fontFace = 0; - - eng_count = 0; - eng_overhead = 0; - eng_scalars = 0; - eng_strings = 0; - eng_pointers = 0; - eng_cmap = 0; - eng_nameTable = 0; - - pseudoMap = 0; - - clstbl_counters = 0; - clstbl_offsets = 0; - clstbl_glyphList = 0; - - glftbl_general = 0; - glftbl_compDefns = 0; - glftbl_attrTable = 0; - glftbl_attrOffsets = 0; - - lngtbl_general = 0; - lngtbl_entries = 0; - lngtbl_featureSets = 0; - - tman_general = 0; - - pass_count = 0; - pass_general = 0; - pass_fsm = 0; - pass_ruleExtras = 0; - pass_constraintOffsets = 0; - pass_constraintCode = 0; - pass_actionOffsets = 0; - pass_actionCode = 0; - - engst_general = 0; - engst_passState = 0; - - sstrm_count = 0; - sstrm_general = 0; - sstrm_chunkMapsUsed = 0; - sstrm_chunkMapsAlloc = 0; - sstrm_reprocBuf = 0; - - slot_count = 0; - slot_general = 0; - slot_abstract = 0; - slot_varLenBuf = 0; - slot_assocsUsed = 0; - slot_assocsAlloc = 0; - slot_attachUsed = 0; - slot_attachAlloc = 0; -} - -/*---------------------------------------------------------------------------------------------- - Return the total byte count. -----------------------------------------------------------------------------------------------*/ -int FontMemoryUsage::total() -{ - int grandTotal = 0; - grandTotal += font + fontCache + fontFace; - grandTotal += eng_overhead + eng_scalars + eng_strings + eng_pointers + eng_cmap + eng_nameTable; - grandTotal += pseudoMap; - grandTotal += clstbl_counters + clstbl_offsets + clstbl_glyphList; - grandTotal += glftbl_general + glftbl_compDefns + glftbl_attrTable + glftbl_attrOffsets; - grandTotal += lngtbl_general + lngtbl_entries + lngtbl_featureSets; - grandTotal += tman_general; - grandTotal += pass_general + pass_fsm + pass_ruleExtras - + pass_constraintOffsets + pass_constraintCode + pass_actionOffsets + pass_actionCode; - grandTotal += engst_general + engst_passState; - grandTotal += sstrm_general + sstrm_chunkMapsAlloc + sstrm_reprocBuf; - grandTotal += slot_general + slot_abstract + slot_varLenBuf + slot_assocsAlloc + slot_attachAlloc; - - return grandTotal; -} - -/*---------------------------------------------------------------------------------------------- - Add the results of two runs together. -----------------------------------------------------------------------------------------------*/ -void FontMemoryUsage::add(FontMemoryUsage & fmu) -{ - font += fmu.font; - fontCache += fmu.fontCache; - fontFace += fmu.fontFace; - - eng_count += fmu.eng_count; - eng_overhead += fmu.eng_overhead; - eng_scalars += fmu.eng_scalars; - eng_strings += fmu.eng_strings; - eng_pointers += fmu.eng_pointers; - eng_cmap += fmu.eng_cmap; - eng_nameTable += fmu.eng_nameTable; - - pseudoMap += fmu.pseudoMap; - - clstbl_counters += fmu.clstbl_counters; - clstbl_offsets += fmu.clstbl_offsets; - clstbl_glyphList += fmu.clstbl_glyphList; - - glftbl_general += fmu.glftbl_general; - glftbl_compDefns += fmu.glftbl_compDefns; - glftbl_attrTable += fmu.glftbl_attrTable; - glftbl_attrOffsets += fmu.glftbl_attrOffsets; - - lngtbl_general += fmu.lngtbl_general; - lngtbl_entries += fmu.lngtbl_entries; - lngtbl_featureSets += fmu.lngtbl_featureSets; - - tman_general += fmu.tman_general; - - pass_count += fmu.pass_count; - pass_general += fmu.pass_general; - pass_fsm += fmu.pass_fsm; - pass_ruleExtras += fmu.pass_ruleExtras; - pass_constraintOffsets += fmu.pass_constraintOffsets; - pass_constraintCode += fmu.pass_constraintCode; - pass_actionOffsets += fmu.pass_actionOffsets; - pass_actionCode += fmu.pass_actionCode; - - engst_general += fmu.engst_general; - engst_passState += fmu.engst_passState; - - sstrm_count += fmu.sstrm_count; - sstrm_general += fmu.sstrm_general; - sstrm_chunkMapsUsed += fmu.sstrm_chunkMapsUsed; - sstrm_chunkMapsAlloc += fmu.sstrm_chunkMapsAlloc; - sstrm_reprocBuf += fmu.sstrm_reprocBuf; - - slot_count += fmu.slot_count; - slot_general += fmu.slot_general; - slot_abstract += fmu.slot_abstract; - slot_varLenBuf += fmu.slot_varLenBuf; - slot_assocsUsed += fmu.slot_assocsUsed; - slot_assocsAlloc += fmu.slot_assocsAlloc; - slot_attachUsed += fmu.slot_attachUsed; - slot_attachAlloc += fmu.slot_attachAlloc; -} - -/*---------------------------------------------------------------------------------------------- - Add up the memory used by all the engines in the cache. -----------------------------------------------------------------------------------------------*/ -FontMemoryUsage Font::calculateMemoryUsage() -{ - FontMemoryUsage fmu; - FontFace::calculateAllMemoryUsage(fmu); - return fmu; -} - -void FontFace::calculateAllMemoryUsage(FontMemoryUsage & fmu) -{ - s_pFontCache->calculateMemoryUsage(fmu); -} - -void FontCache::calculateMemoryUsage(FontMemoryUsage & fmuTotal) -{ - fmuTotal.fontCache += sizeof(int) * 4; // m_cfci, m_cfciMax, m_cfface, m_flush - fmuTotal.fontCache += sizeof(void*); // m_prgfci; - - // Iterate through all the font faces in the cache. - for (int ifci = 0; ifci < m_cfci; ifci++) - { - CacheItem * pfci = m_prgfci + ifci; - char rgchFontName[32]; - memset(rgchFontName, 0, 32 * sizeof(char)); - std::copy(pfci->szFaceName, pfci->szFaceName + 32, rgchFontName); - std::string strFontName(rgchFontName); - fmuTotal.vstrFontNames.push_back(strFontName); - int cface = 0; - if (pfci->pffaceRegular) - { - FontMemoryUsage fmu; - pfci->pffaceRegular->calculateMemoryUsage(fmu); - fmuTotal.add(fmu); - fmuTotal.vFontTotalsReg.push_back(fmu.total()); - cface++; - } - else - fmuTotal.vFontTotalsReg.push_back(0); - - if (pfci->pffaceBold) - { - FontMemoryUsage fmu; - pfci->pffaceBold->calculateMemoryUsage(fmu); - fmuTotal.add(fmu); - fmuTotal.vFontTotalsBold.push_back(fmu.total()); - cface++; - } - else - fmuTotal.vFontTotalsBold.push_back(0); - - if (pfci->pffaceItalic) - { - FontMemoryUsage fmu; - pfci->pffaceItalic->calculateMemoryUsage(fmu); - fmuTotal.add(fmu); - fmuTotal.vFontTotalsItalic.push_back(fmu.total()); - cface++; - } - else - fmuTotal.vFontTotalsItalic.push_back(0); - - if (pfci->pffaceBI) - { - FontMemoryUsage fmu; - pfci->pffaceBI->calculateMemoryUsage(fmu); - fmuTotal.add(fmu); - fmuTotal.vFontTotalsBI.push_back(fmu.total()); - cface++; - } - else - fmuTotal.vFontTotalsBI.push_back(0); - - fmuTotal.vFaceCount.push_back(cface); - } -} - -void FontFace::calculateMemoryUsage(FontMemoryUsage & fmu) -{ - fmu.fontFace += sizeof(int); // m_cfonts - fmu.fontFace += sizeof(void *) * 2; // s_pFontCache, m_pgreng - - fmu.font += m_cfonts * sizeof(void*); // m_pfface - - fmu.addEngine(m_pgreng); -} - -void FontMemoryUsage::addEngine(GrEngine * pgreng) -{ - eng_count++; - - eng_overhead += sizeof(long); // m_cref - eng_scalars += sizeof(bool) * 6; // m_fBold, m_fItalic, m_fSmart... - eng_scalars += sizeof(bool) * 2; // m_fFakeItalicCache, m_fFakeBICache; - eng_strings += stringOverhead * 4; // m_strCtrlFileReg/Bold/Italic/BI - eng_strings += sizeof(wchar_t) * pgreng->m_strCtrlFileReg.length(); - eng_strings += sizeof(wchar_t) * pgreng->m_strCtrlFileBold.length(); - eng_strings += sizeof(wchar_t) * pgreng->m_strCtrlFileItalic.length(); - eng_strings += sizeof(wchar_t) * pgreng->m_strCtrlFileBI.length(); - eng_scalars += sizeof(bool); - eng_strings += stringOverhead * 6; // m_stuCtrlFile etc. - eng_strings += sizeof(wchar_t) * pgreng->m_stuCtrlFile.length(); - eng_strings += sizeof(wchar_t) * pgreng->m_stuInitError.length(); - eng_strings += sizeof(wchar_t) * pgreng->m_stuFaceName.length(); - eng_strings += sizeof(wchar_t) * pgreng->m_stuFeatures.length(); - eng_strings += sizeof(wchar_t) * pgreng->m_stuBaseFaceName.length(); - eng_scalars += sizeof(bool); // m_fUseSepBase - eng_scalars += sizeof(GrResult) * 2; // m_resFontRead, m_resFontValid - eng_scalars += sizeof(FontErrorCode); - eng_scalars += sizeof(int) * 3; // m_fxdBadVersion, m_nFontCheckSum, m_nScriptTag, m_grfsdc - eng_scalars += sizeof(bool); // m_fRightToLeft - eng_scalars += sizeof(int) * 2; // m_mXAscent, m_mXDescent - eng_scalars += sizeof(float); // m_dysOffset - eng_scalars += sizeof(bool); // m_fBasicJust - eng_scalars += sizeof(int); // m_cJLevels - eng_pointers += sizeof(void*) * 4; // m_ptman, m_pctbl, m_pgtbl, m_pfface - eng_scalars += sizeof(GrFeature) * kMaxFeatures; - eng_scalars += sizeof(int); // m_cfeat - eng_scalars += sizeof(size_t); // m_clcidFeatLabelLangs - eng_scalars += sizeof(short) * pgreng->m_clcidFeatLabelLangs; - // m_langtbl - eng_scalars += sizeof(bool); // m_fLineBreak - eng_scalars += sizeof(int) * 2; // m_cchwPreXlbContext, m_cchwPostXlbContext - eng_scalars += sizeof(data16) * 7; // m_chwPseudoAttr, etc. - eng_scalars += sizeof(gid16); // m_chwLBGlyphID - eng_scalars += sizeof(int) * 4; // m_cComponents, m_cnUserDefn, m_cnCompPerLig, m_mFontEmUnits - - pseudoMap += sizeof(int) * 3; - pseudoMap += sizeof(GrPseudoMap) * pgreng->m_cpsd; - - eng_cmap += sizeof(void*) * 2; - eng_cmap += sizeof(byte*); - eng_cmap += sizeof(bool); - if (pgreng->m_fCmapTblCopy) - eng_cmap += pgreng->m_cbCmapTbl; - - eng_nameTable += sizeof(byte *); - eng_nameTable += sizeof(bool); - if (pgreng->m_fNameTblCopy) - eng_nameTable += pgreng->m_cbNameTbl; - - eng_scalars += sizeof(bool) * 2; // m_fLogXductn, m_fInErrorState - - clstbl_counters += sizeof(int) * 2; // m_ccls, m_cclsLinear - clstbl_offsets += sizeof(data16) * (pgreng->m_pctbl->m_ccls + 1); - clstbl_glyphList += sizeof(data16) * (pgreng->m_pctbl->m_prgichwOffsets[pgreng->m_pctbl->m_ccls]); - - glftbl_general += sizeof(int) * 3; // m_cglf, m_cComponents, m_cgstbl - glftbl_general += vectorOverhead; // m_vpgstbl - GrGlyphSubTable * pgstbl = pgreng->m_pgtbl->m_vpgstbl[0]; - glftbl_general += sizeof(int) * 4; // m_fxdSilfVersion, m_nAttrIDLim, m_cComponents, m_cnCompPerLig - glftbl_general += sizeof(bool) * 2; // m_fHasDebugStrings, m_fGlocShort - glftbl_general += sizeof(data16) * 3; // m_chw...Attr - glftbl_compDefns += sizeof(int) * (pgstbl->m_cnCompPerLig + 1) * pgreng->m_pgtbl->m_cglf; - glftbl_attrTable += sizeof(int) * 2; // m_fxdSilfVersion, m_cbEntryBufLen - glftbl_attrTable += sizeof(byte) * pgstbl->m_pgatbl->m_cbEntryBufLen; - glftbl_attrOffsets += - (pgreng->m_pgtbl->m_cglf + 1) * ((pgstbl->m_fGlocShort) ? sizeof(data16) : sizeof(data32)); - - lngtbl_general += sizeof(size_t); // m_clang - lngtbl_general += sizeof(data16) * 3; // m_dilangInit, m_cLoop, m_ilangStart - lngtbl_general += sizeof(void*) * 2; // m_prglang, m_prgfset - lngtbl_general += sizeof(int); // m_cbOffset0 - lngtbl_entries += sizeof(GrLangTable::LangEntry) * pgreng->m_langtbl.m_clang; - lngtbl_featureSets += sizeof(GrLangTable::FeatSet) * pgreng->m_langtbl.m_cfset; - - GrTableManager * ptman = pgreng->m_ptman; - tman_general += sizeof(int) * 4; // m_cpass, m_cpassLB, m_ipassPos1, m_ipassJust1 - tman_general += sizeof(bool); // m_fBidi - tman_general += sizeof(void*) * 2; // m_prgppass, m_pgreng - tman_general += sizeof(void*) * ptman->m_cpass; // m_prgppass - tman_general += sizeof(bool); // m_fLogging - - pass_count += ptman->m_cpass; - for (int ipass = 0; ipass < ptman->m_cpass; ipass++) - { - GrPass * ppass = ptman->m_prgppass[ipass]; - pass_general = sizeof(GrPass); - - GrFSM * pfsm = ppass->m_pfsm; - if (pfsm) - { - pass_fsm += sizeof(int) * 5; // m_crow, m_crowFinal, m_rowFinalMin, m_crowNonAcpt, m_ccol - pass_fsm += sizeof(void*) * 3; // m_prgirulnMin, m_prgrulnMatched, m_prgrowTransitions - int crowSuccess = pfsm->m_crow - pfsm->m_crowNonAcpt; - pass_fsm += sizeof(data16) * (crowSuccess + 1); // m_prgirulnMin - pass_fsm += sizeof(data16) * (pfsm->m_crulnMatched); // m_prgrulnMatched - pass_fsm += sizeof(short) * ((pfsm->m_crow - pfsm->m_crowFinal) * pfsm->m_ccol); - pass_fsm += sizeof(data16); // m_dimcrInit, m_cLoop, m_imcrStart - pass_fsm += sizeof(int); // m_cmcr - pass_fsm += sizeof(void*); // m_prgmcr - pass_fsm += sizeof(GrFSMClassRange) * pfsm->m_cmcr; - pass_fsm += sizeof(int) * 2; // m_critMinRulePreContext, m_critMaxRulePreContext - pass_fsm += sizeof(void*); // m_prgrowStartStates - pass_fsm += sizeof(short) * (pfsm->m_critMaxRulePreContext - pfsm->m_critMinRulePreContext + 1); - } - - pass_ruleExtras = sizeof(data16) * ppass->m_crul; // m_prgchwRuleSortKeys - pass_ruleExtras = sizeof(byte*) * ppass->m_crul; // m_prgcritRulePreModContext - - pass_constraintOffsets += sizeof(data16) * (ppass->m_crul + 1); - pass_actionOffsets =+ sizeof(data16) * (ppass->m_crul + 1); - - pass_constraintCode += sizeof(byte) * ppass->m_cbConstraints; - pass_actionCode += sizeof(byte) * ppass->m_cbActions; - - pass_general += sizeof(bool) * ppass->m_crul; // m_prgfRuleOkay - pass_general += vectorOverhead; // m_vnStack - pass_general += sizeof(int) * ppass->m_vnStack.capacity(); - } - - engst_general += sizeof(EngineState); - engst_general += sizeof(void *) * ptman->m_engst.m_vslotblk.capacity(); - engst_general += sizeof(void *) * ptman->m_engst.m_vprgnSlotVarLenBufs.capacity(); - engst_general += sizeof(void *) * ptman->m_engst.m_cpass; // m_prgpsstrm - - engst_passState += sizeof(PassState) * ptman->m_engst.m_cpass; - - for (int isstrm = 0; isstrm < ptman->m_engst.m_cpass; isstrm++) - { - sstrm_count++; - GrSlotStream * psstrm = ptman->m_engst.m_prgpsstrm[isstrm]; - sstrm_general += sizeof(GrSlotStream); - sstrm_chunkMapsUsed += psstrm->m_vislotPrevChunkMap.size(); - sstrm_chunkMapsUsed += psstrm->m_vislotPrevChunkMap.size(); - sstrm_chunkMapsAlloc += psstrm->m_vislotPrevChunkMap.capacity(); - sstrm_chunkMapsAlloc += psstrm->m_vislotNextChunkMap.capacity(); - sstrm_reprocBuf += psstrm->m_vpslotReproc.capacity(); - sstrm_reprocBuf += sizeof(int) * 2; - sstrm_general -= sizeof(int) * 2; - } - - slot_general += ptman->m_engst.m_vslotblk.size() * EngineState::kSlotBlockSize - * (sizeof(GrSlotState) - sizeof(GrSlotAbstract)); - slot_abstract += ptman->m_engst.m_vslotblk.size() * EngineState::kSlotBlockSize - * sizeof(GrSlotAbstract); - int cnExtraPerSlot = ptman->m_engst.m_cUserDefn + (ptman->m_engst.m_cCompPerLig * 2) - + ptman->m_engst.m_cFeat; - slot_varLenBuf += EngineState::kSlotBlockSize * cnExtraPerSlot * sizeof(u_intslot); - for (size_t islotblk = 0; islotblk < ptman->m_engst.m_vslotblk.size(); islotblk++) - { - for (int islot = 0; islot < EngineState::kSlotBlockSize; islot++) - { - slot_count++; - GrSlotState * pslot = ptman->m_engst.m_vslotblk[islotblk] + islot; - slot_assocsUsed += pslot->m_vpslotAssoc.size(); - slot_assocsAlloc += pslot->m_vpslotAssoc.capacity(); - slot_attachUsed += pslot->m_vdislotAttLeaves.size(); - slot_attachAlloc += pslot->m_vdislotAttLeaves.capacity(); - } - } - -} - -/*---------------------------------------------------------------------------------------------- - Write out the memory usage onto a stream. -----------------------------------------------------------------------------------------------*/ -void FontMemoryUsage::prettyPrint(std::ostream & strm) -{ - int totalBytes = total(); - - strm << "Number of engines: " << eng_count << "\n"; - strm << "Number of passes: " << pass_count << "\n\n"; - - strm << "Number of slot streams: " << sstrm_count << "\n"; - strm << "Number of slots: " << slot_count << "\n\n"; - - int classTableTotal = clstbl_counters + clstbl_offsets + clstbl_glyphList; - int glyphTableTotal = glftbl_general + glftbl_compDefns + glftbl_attrTable + glftbl_attrOffsets; - int langTableTotal = lngtbl_general + lngtbl_entries + lngtbl_featureSets; - int passTotal = pass_general + pass_fsm + pass_ruleExtras + pass_constraintOffsets + pass_constraintCode - + pass_actionOffsets + pass_actionCode; - int engineTotal = eng_overhead + eng_scalars + eng_strings + eng_pointers + eng_cmap + eng_nameTable - + pseudoMap + classTableTotal + glyphTableTotal + langTableTotal + tman_general - + passTotal; - - strm << "BYTE COUNT TOTALS\n"; - strm << "Font: " << font << "\n"; - strm << "Font cache: " << fontCache << "\n"; - strm << "Font face: " << fontFace << "\n"; - strm << "Engine " << engineTotal << "\n"; - strm << " Overhead: " << eng_overhead << "\n"; - strm << " Scalars: " << eng_scalars << "\n"; - strm << " Strings: " << eng_strings << "\n"; - strm << " Pointers: " << eng_pointers << "\n"; - strm << " Cmap table: " << eng_cmap << "\n"; - strm << " Name table: " << eng_nameTable << "\n"; - strm << " Pseudo map: " << pseudoMap << "\n"; - strm << " Class table: " << classTableTotal << "\n"; - strm << " Counters: " << clstbl_counters << "\n"; - strm << " Offsets: " << clstbl_offsets << "\n"; - strm << " Glyph list: " << clstbl_glyphList << "\n"; - strm << " Glyph table: " << glyphTableTotal << "\n"; - strm << " General: " << glftbl_general << "\n"; - strm << " Component defns: " << glftbl_compDefns << "\n"; - strm << " Attr table: " << glftbl_attrTable << "\n"; - strm << " Attr offsets: " << glftbl_attrOffsets << "\n"; - strm << " Language table: " << langTableTotal << "\n"; - strm << " General: " << lngtbl_general << "\n"; - strm << " Entries: " << lngtbl_entries << "\n"; - strm << " Feature sets: " << lngtbl_featureSets << "\n"; - strm << " Table manager: " << tman_general << "\n"; - strm << " Passes: " << passTotal << "\n"; - strm << " General: " << pass_general << "\n"; - strm << " FSM: " << pass_fsm << "\n"; - strm << " Rule extras: " << pass_ruleExtras << "\n"; - strm << " Constraint offsets: " << pass_constraintOffsets << "\n\n"; - strm << " Constraint code: " << pass_constraintCode << "\n"; - strm << " Action offsets: " << pass_actionOffsets << "\n"; - strm << " Action code: " << pass_actionCode << "\n\n"; - - int slotTotal = slot_general + slot_abstract + slot_varLenBuf + slot_assocsAlloc + slot_attachAlloc; - int streamTotal = sstrm_general + sstrm_chunkMapsAlloc + sstrm_reprocBuf + slotTotal; - int engineStateTotal = engst_general + engst_passState + streamTotal; - - strm << " Engine State: " << engineStateTotal << "\n"; - strm << " General: " << engst_general << "\n"; - strm << " Pass states: " << engst_passState << "\n"; - strm << " Slot streams: " << streamTotal << "\n"; - strm << " General: " << sstrm_general << "\n"; - strm << " Chunk maps: " << sstrm_chunkMapsAlloc << " (" << sstrm_chunkMapsUsed << " used)\n"; - strm << " Reprocess buffer: " << sstrm_reprocBuf << "\n"; - strm << " Slots: " << slotTotal << "\n"; - strm << " General: " << slot_general << "\n"; - strm << " Abstract: " << slot_abstract << "\n"; - strm << " Var-length buf: " << slot_varLenBuf << "\n"; - strm << " Associations: " << slot_assocsAlloc << " (" << slot_assocsUsed << " used)\n"; - strm << " Attachments: " << slot_attachAlloc << " (" << slot_attachUsed << " used)\n\n"; - - strm << "Total bytes used: " << totalBytes << "\n\n"; - - strm << "TOTALS PER FONT\n"; - for (size_t ifont = 0; ifont < vstrFontNames.size(); ifont++) - { - strm << vstrFontNames[ifont].c_str() << "\n"; - strm << " Regular: " << vFontTotalsReg[ifont] << "\n"; - strm << " Bold: " << vFontTotalsBold[ifont] << "\n"; - strm << " Italic: " << vFontTotalsItalic[ifont] << "\n"; - strm << " Bold-italic: " << vFontTotalsBI[ifont] << "\n\n"; - } -} - - -//:>******************************************************************************************** -//:> Segment -//:>******************************************************************************************** - -/*---------------------------------------------------------------------------------------------- - Initialize the data structure. -----------------------------------------------------------------------------------------------*/ -void SegmentMemoryUsage::initialize() -{ - seg_count = 0; - overhead = 0; - pointers = 0; - scalars = 0; - strings = 0; - metrics = 0; - associations = 0; - init = 0; - obsolete = 0; - - slot_count = 0; - slot_abstract = 0; - slot_varLenBuf = 0; - slot_scalars = 0; - slot_clusterMembers = 0; - - glyphInfo_count = 0; - glyphInfo = 0; - - wastedVector = 0; -} - -/*---------------------------------------------------------------------------------------------- - Add the memory for the segemtn to the SegmentMemoryUsage data structure. -----------------------------------------------------------------------------------------------*/ -void Segment::calculateMemoryUsage(SegmentMemoryUsage & smu) -{ - smu.addSegment(*this); -} - - -void SegmentMemoryUsage::addSegment(Segment & seg) -{ - seg_count++; - - overhead += sizeof(long); // m_cref - pointers += sizeof(void*); // m_pgts - scalars += sizeof(int); // m_dichwLim - scalars += sizeof(int); // m_ichwMin - pointers += sizeof(void*); // m_pfont - pointers += sizeof(void*); // m_preneng - scalars += sizeof(bool); // m_fErroneous - pointers += sizeof(void*); // m_pgjus - scalars += sizeof(LayoutEnvironment); - scalars += sizeof(bool); // m_fWsRtl - scalars += sizeof(bool); // m_fParaRtl - scalars += sizeof(TrWsHandling); - scalars += sizeof(int); // m_nDirDepth - init += sizeof(byte*); // m_prgbNextSegDat - init += sizeof(int); // m_cbNextSegDat - init += sizeof(byte) * seg.m_cbNextSegDat; - init += sizeof(byte*); // m_prgInitDat - init += sizeof(int); // m_cbInitDat - init += sizeof(byte) * seg.m_cbInitDat; - init += sizeof(int); // m_dichPreContext -// obsolete += sizeof(void *); // m_psegPrev -// obsolete += sizeof(void *); // m_psegNext -// strings += stringOverhead * 2; -// strings += sizeof(wchar_t) * seg.m_stuFaceName.length(); -// strings += sizeof(wchar_t) * seg.m_stuBaseFaceName.length(); -// scalars += sizeof(bool); // m_fUseSepBase; -// scalars += sizeof(float); // m_pixHeight -// scalars += sizeof(bool); // m_fBold -// scalars += sizeof(bool); // m_fItalic - scalars += sizeof(LineBrk); // m_lbStart - scalars += sizeof(LineBrk); // m_lbEnd - scalars += sizeof(bool); // m_fStartLine - scalars += sizeof(bool); // m_fEndLine - scalars += sizeof(SegEnd); // m_est - metrics += sizeof(int); // m_mFontEmUnits - metrics += sizeof(float) * 17; // was 19, removed m_x/ysDPI - associations += sizeof(int); // m_ichwAssocsMin - associations += sizeof(int); // m_ichwAssocsLim - int dichw = seg.m_ichwAssocsLim - seg.m_ichwAssocsMin; - associations += sizeof(int*); // m_prgisloutBefore - associations += sizeof(int) * dichw; - associations += sizeof(int*); // m_prgisloutAfter - associations += sizeof(int) * dichw; - associations += sizeof(void*); // m_prgpvisloutAssocs - associations += sizeof(void*) * dichw; - for (int idichw = 0; idichw < dichw; idichw++) - { - std::vector<int> * pvisloutAssocs = seg.m_prgpvisloutAssocs[idichw]; - if (pvisloutAssocs) - { - associations += vectorOverhead; - associations += sizeof(int) * pvisloutAssocs->capacity(); - wastedVector += sizeof(int) * (pvisloutAssocs->capacity() - pvisloutAssocs->size()); - } - } - associations += sizeof(int*); // m_prgisloutLigature - associations += sizeof(int) * dichw; - associations += sizeof(sdata8*); // m_prgiComponent - associations += sizeof(sdata8) * dichw; -// obsolete += sizeof(void*); // m_psstrm - scalars += sizeof(int); // m_cslout - slot_count += seg.m_cslout; - for (int islout = 0; islout < seg.m_cslout; islout++) - { - GrSlotOutput * pslout = seg.m_prgslout + islout; - slot_abstract += sizeof(gid16) * 2; // m_chwGlyphID, m_chwActual - slot_abstract += sizeof(sdata8) * 4; // m_spsl, m_dirc, m_lb, m_nDirLevel -// slot_abstract += sizeof(float) * 8; // font/glyph metrics - slot_abstract += sizeof(short) * 5; // slot attributes - was 21 - slot_abstract += sizeof(int); // m_mJWidth0; - slot_abstract += sizeof(byte); // m_nJWeight0; - slot_abstract += sizeof(bool); // m_fInsertBefore - slot_abstract += sizeof(sdata8); // m_bIsSpace - slot_abstract += sizeof(byte); // m_cnCompPerLig - slot_abstract += sizeof(void*); // m_prgnVarLenBuf - slot_varLenBuf += pslout->CExtraSpaceSlout() * sizeof(u_intslot); - slot_abstract += sizeof(float); // m_xsPositionX, m_ysPositionY -// slot_abstract += sizeof(bool); // m_fAdvXSet, m_fAdvYSet - slot_scalars += sizeof(int) * 2; // m_ichwBefore/AfterAssoc - slot_scalars += sizeof(sdata8); // m_cComponents - slot_scalars += sizeof(int); // m_isloutClusterBase - slot_scalars += sizeof(sdata8); // m_disloutCluster - slot_scalars += sizeof(float) * 3; // m_xsClusterXOffset, m_xsClusterAdvance, m_xsAdvanceX - slot_scalars += sizeof(int); // m_igbb -// slot_scalars += sizeof(Rect); // m_rectBB - } - scalars += sizeof(int); // m_cnUserDefn - scalars += sizeof(int); // m_cnCompPerLig - scalars += sizeof(int); // m_cnFeat - glyphInfo_count += seg.m_cginf; - scalars += sizeof(int); // m_cginf; - scalars += sizeof(int); // m_isloutGinf0 - for (int iginf = 0; iginf < seg.m_cginf; iginf++) - { - ///GlyphInfo * pginf = seg.m_prgginf + iginf; - glyphInfo += sizeof(void *); // m_pseg - glyphInfo += sizeof(void *); // m_pslout - glyphInfo += sizeof(int); // m_islout - } - init += sizeof(int); // m_cslotRestartBackup - init += vectorOverhead; - init += sizeof(sdata8) * seg.m_vnSkipOffsets.capacity(); - wastedVector += sizeof(sdata8) * (seg.m_vnSkipOffsets.capacity() - seg.m_vnSkipOffsets.size()); - init += sizeof(DirCode); // m_dircPrevStrong - init += sizeof(DirCode); // m_dircPrevTerm - - //int grandTotal; - //grandTotal = overhead + pointers + scalars + strings + metrics + associations - // + init + obsolete + slot_count + slot_abstract + slot_varLenBuf + slot_scalars - // + slot_clusterMembers + glyphInfo_count + glyphInfo; - - //int totalPerSeg = grandTotal / seg_count; -} - -/*---------------------------------------------------------------------------------------------- - Write out the memory usage onto a stream. -----------------------------------------------------------------------------------------------*/ -void SegmentMemoryUsage::prettyPrint(std::ostream & strm) -{ - int totalBytes = overhead + pointers + scalars + strings + metrics + associations - + init + obsolete + slot_count + slot_abstract + slot_varLenBuf + slot_scalars - + slot_clusterMembers + glyphInfo_count + glyphInfo; - - int slotTotal = slot_abstract + slot_varLenBuf + slot_scalars + slot_clusterMembers; - - strm << "Number of segments: " << seg_count << "\n\n"; - - strm << "TOTALS\n"; - strm << "Overhead: " << overhead << "\n"; - strm << "Pointers: " << pointers << "\n"; - strm << "Scalars: " << scalars << "\n"; - strm << "Strings: " << strings << "\n"; - strm << "Metrics: " << metrics << "\n"; - strm << "Associations: " << associations << "\n"; - strm << "Obsolete: " << obsolete << "\n"; - strm << "Slot data: " << slotTotal << "\n"; - strm << " Abstract: " << slot_abstract << "\n"; - strm << " Var-length buffer: " << slot_varLenBuf << "\n"; - strm << " Scalars: " << slot_scalars << "\n"; - strm << " Cluster members: " << slot_clusterMembers << "\n"; - strm << "Glyph info: " << glyphInfo << "\n\n"; - - strm << "Wasted in vectors: " << wastedVector << "\n\n"; - - strm << "Total bytes used: " << totalBytes << "\n\n"; - - if (seg_count > 0) - { - strm << "AVERAGES\n"; - strm << "Overhead: " << overhead/seg_count << "\n"; - strm << "Pointers: " << pointers/seg_count << "\n"; - strm << "Scalars: " << scalars/seg_count << "\n"; - strm << "Strings: " << strings/seg_count << "\n"; - strm << "Metrics: " << metrics/seg_count << "\n"; - strm << "Associations: " << associations/seg_count << "\n"; - strm << "Obsolete: " << obsolete/seg_count << "\n"; - strm << "Slot data: " << slotTotal/seg_count << "\n"; - strm << " Abstract: " << slot_abstract/seg_count << "\n"; - strm << " Var-length buffer: " << slot_varLenBuf/seg_count << "\n"; - strm << " Scalars: " << slot_scalars/seg_count << "\n"; - strm << " Cluster members: " << slot_clusterMembers/seg_count << "\n"; - strm << "Glyph info: " << glyphInfo/seg_count << "\n\n"; - - strm << "Avg. bytes per segment: " << totalBytes / seg_count << "\n\n"; - - strm << "Avg. # of slots per segment: " << slot_count / seg_count << "\n\n"; - } -} - -} //namespace gr - diff --git a/Build/source/libs/graphite-engine/src/segment/Platform.cpp b/Build/source/libs/graphite-engine/src/segment/Platform.cpp deleted file mode 100644 index 30ec3f4bf1f..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/Platform.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "GrPlatform.h" - -#ifdef _WIN32 -#include "windows.h" - -namespace gr -{ - -size_t Platform_UnicodeToANSI(const utf16 * prgchwSrc, size_t cchwSrc, char * prgchsDst, size_t cchsDst) -{ - return ::WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)prgchwSrc, cchwSrc, prgchsDst, cchsDst, NULL, NULL); -} - -size_t Platform_AnsiToUnicode(const char * prgchsSrc, size_t cchsSrc, utf16 * prgchwDst, size_t cchwDst) -{ - return ::MultiByteToWideChar(CP_ACP, 0, prgchsSrc, cchsSrc, (LPWSTR)prgchwDst, cchwDst); -} - -size_t Platform_8bitToUnicode(int nCodePage, const char * prgchsSrc, int cchsSrc, - utf16 * prgchwDst, int cchwDst) -{ - return ::MultiByteToWideChar(nCodePage, 0, prgchsSrc, cchsSrc, (LPWSTR)prgchwDst, cchwDst); -} - -size_t utf8len(const char *s) -{ - return mbstowcs(NULL,s,0); -} - -utf16 *utf16cpy(utf16 *dest, const utf16 *src) -{ - return (utf16*)wcscpy((wchar_t*)dest, (const wchar_t*)src); -} - -utf16 *utf16ncpy(utf16 *dest, const utf16 *src, size_t n) -{ - return (utf16*)wcsncpy((wchar_t*)dest, (const wchar_t*)src, n); -} - -utf16 *utf16ncpy(utf16 *dest, const char *src, size_t n) -{ - #ifdef UTF16DEBUG - std::cerr << "utf16ncpy8: " << src << std::endl; - #endif - Platform_AnsiToUnicode(src, strlen(src), dest, n); - return dest; -} - - -size_t utf16len(const utf16 *s) -{ - return wcslen((const wchar_t*)s); -} - -int utf16cmp(const utf16 *s1, const utf16 *s2) -{ -return wcscmp((const wchar_t*)s1, (const wchar_t*)s2); -} - -int utf16ncmp(const utf16 *s1, const utf16 *s2, size_t n) -{ - return wcsncmp((const wchar_t*)s1, (const wchar_t*)s2, n); -} - -int utf16cmp(const utf16 *s1, const char *s2) -{ - while (*s1 && s2) - { - if (*s1 < *s2) - { - return -1; - } - if (*s1 > *s2) - { - return 1; - } - *s1++; - *s2++; - } - if (*s1) return -1; - else if (*s2) return 1; - return 0; -} - -} -#else // not _WIN32 - -#include <iostream> -#include <stdlib.h> -#include <string.h> - -#ifndef HAVE_FABSF -float fabsf(float x) -{ - return (x < 0.0f) ? -x : x; -} -#endif - -namespace gr -{ - -size_t utf16len(const utf16 *s) -{ - // assumes NULL terminated strings - const utf16 *start = s; - for (; *s; ++s); - - return s - start; -} - -} // namespace gr -#endif // _WIN32 - diff --git a/Build/source/libs/graphite-engine/src/segment/Segment.cpp b/Build/source/libs/graphite-engine/src/segment/Segment.cpp deleted file mode 100644 index b936b037a64..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/Segment.cpp +++ /dev/null @@ -1,3547 +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: Segment.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Implements a Graphite segment--a range of rendered text in one writing system, that can be - rendered with a single font, and that fits on a single line. --------------------------------------------------------------------------------*//*:End Ignore*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" -#ifdef _MSC_VER -#pragma hdrstop -#endif -// any other headers (not precompiled) -#include <math.h> -#ifndef _WIN32 -#include <stdlib.h> -#endif - -#undef THIS_FILE -DEFINE_THIS_FILE - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** -#if 0 // TODO remove -namespace -{ - -static bool g_fDrawing; - -} // namespace -#endif - - -static int g_csegTotal = 0; - -namespace gr -{ - -//:>******************************************************************************************** -//:> Segment methods -//:>******************************************************************************************** - - -int Segment::GetSegmentCount() /// TEMP -{ - return g_csegTotal; -} - - -/*---------------------------------------------------------------------------------------------- - Constructor: basic initialization. -----------------------------------------------------------------------------------------------*/ -Segment::Segment() : - m_pgts(NULL), - m_pfont(NULL), - m_preneng(NULL), - m_fErroneous(false), - m_pgjus(NULL), - m_prgbNextSegDat(NULL), - m_cbNextSegDat(0), - m_prgInitDat(NULL), - m_cbInitDat(0), -// m_fUseSepBase(0), - //m_psegAltEndLine(NULL), - m_prgisloutBefore(NULL), - m_prgisloutAfter(NULL), - m_prgpvisloutAssocs(NULL), - m_prgisloutLigature(NULL), - m_prgiComponent(NULL), -// m_psstrm(NULL), - m_cslout(0), - m_prgslout(NULL), - m_prgnSlotVarLenBuf(NULL), -// m_cnUserDefn(0), - m_cnCompPerLig(0), -// m_cnFeat(0), - m_cginf(0), - m_prgginf(NULL) -{ - m_cref = 1; - - g_csegTotal++; - -// m_stuFaceName.erase(); -// m_stuBaseFaceName.erase(); - m_vnSkipOffsets.clear(); -} - -/*---------------------------------------------------------------------------------------------- - Reference counting. -----------------------------------------------------------------------------------------------*/ - -long Segment::IncRefCount(void) -{ - AssertPtr(this); - return InterlockedIncrement(&m_cref); -} - -long Segment::DecRefCount(void) -{ - AssertPtr(this); - long cref = InterlockedDecrement(&m_cref); - if (cref == 0) { - m_cref = 1; - delete this; - } - return cref; -} - -/*---------------------------------------------------------------------------------------------- - Constructor to fit as much of the text on the line as possible, - finding a reasonable break point if necessary. -----------------------------------------------------------------------------------------------*/ -LineFillSegment::LineFillSegment( - Font * pfont, - ITextSource * pts, - LayoutEnvironment * playoutArg, - toffset ichStart, - toffset ichStop, - float xsMaxWidth, - bool fBacktracking) - : Segment() -{ - if (!pfont) - throw; - if (!pts) - throw; - - LayoutEnvironment layoutDefault; - LayoutEnvironment * playout = (!playoutArg) ? &layoutDefault : playoutArg; - - pfont->RenderLineFillSegment(this, pts, *playout, ichStart, ichStop, xsMaxWidth, - fBacktracking); -} - -/*---------------------------------------------------------------------------------------------- - Constructor to create a segment representing the given range of characters. -----------------------------------------------------------------------------------------------*/ -RangeSegment::RangeSegment( - Font * pfont, - ITextSource * pts, - LayoutEnvironment * playoutArg, - toffset ichStart, - toffset ichStop, - Segment * psegInitLike) - : Segment() -{ - if (!pfont) - throw; - if (!pts) - throw; - - LayoutEnvironment layoutDefault; - LayoutEnvironment * playout = (!playoutArg) ? &layoutDefault : playoutArg; - playout->setSegmentForInit(psegInitLike); - - pfont->RenderRangeSegment(this, pts, *playout, ichStart, ichStop); - - playout->setSegmentForInit(NULL); -} - -/*---------------------------------------------------------------------------------------------- - Constructor to create a justified segment. Private. -----------------------------------------------------------------------------------------------*/ -JustSegmentAux::JustSegmentAux( - Font * pfont, - ITextSource * pts, - LayoutEnvironment * playoutArg, - toffset ichStart, - toffset ichStop, - float xsNaturalWidth, - float xsJustifiedWidth, - Segment * psegInitLike) - : Segment() -{ - if (!pfont) - throw; - if (!pts) - throw; - - LayoutEnvironment layoutDefault; - LayoutEnvironment * playout = (!playoutArg) ? &layoutDefault : playoutArg; - playout->setSegmentForInit(psegInitLike); - - pfont->RenderJustifiedSegment(this, pts, *playout, ichStart, ichStop, - xsNaturalWidth, xsJustifiedWidth); - - playout->setSegmentForInit(NULL); -} - -//Segment::Segment(ITextSource * pgts, int ichwMin, int ichwLim, -// LineBrk lbStart, LineBrk lbEnd, -// bool fStartLine, bool fEndLine, bool fWsRtl) -//{ -// m_cref = 1; -// Initialize(pgts, ichwMin, ichwLim, lbStart, lbEnd, fStartLine, fEndLine, fWsRtl); -//} - -void Segment::Initialize(ITextSource * pgts, int ichwMin, int ichwLim, - LineBrk lbStart, LineBrk lbEnd, SegEnd est, - bool fStartLine, bool fEndLine, bool fWsRtl) -{ - AssertPtrN(pgts); - Assert(ichwMin >= 0); - Assert(ichwLim >= 0); - Assert(ichwMin <= ichwLim); - - //pgts->TextSrcObject(&m_pgts); // create a permanent wrapper, if necessary - // m_pgts->AddRef(); no, smart pointer - m_pgts = pgts; - - m_ichwMin = ichwMin; - m_dichwLim = ichwLim - ichwMin; - m_lbStart = lbStart; - m_lbEnd = lbEnd; - m_est = est; - m_dxsStretch = 0; - m_dxsWidth = -1; - m_dysAscent = -1; // to properly init, ComputeDimensions must be called - m_dysHeight = -1; - m_dysXAscent = -1; - m_dysXDescent = -1; - m_dysAscentOverhang = -1; - m_dysDescentOverhang = -1; - m_dxsLeftOverhang = -1; - m_dxsRightOverhang = -1; - m_dysOffset = 0; - m_fStartLine = fStartLine; - m_fEndLine = fEndLine; - m_fWsRtl = fWsRtl; - - m_dxsVisibleWidth = -1; - m_dxsTotalWidth = -1; - -// m_psstrm = NULL; - m_prgslout = NULL; - m_prgnSlotVarLenBuf = NULL; - m_prgisloutBefore = NULL; - m_prgisloutAfter = NULL; - m_prgpvisloutAssocs = NULL; - m_prgisloutLigature = NULL; - m_prgiComponent = NULL; - - m_prgbNextSegDat = NULL; - m_cbNextSegDat = 0; - - //m_psegAltEndLine = NULL; - -// m_stuFaceName.erase(); -// m_stuBaseFaceName.erase(); -// m_fUseSepBase = false; - -// m_psegPrev = NULL; // obsolete -// m_psegNext = NULL; - - //InitializePlatform(); -} - -/*---------------------------------------------------------------------------------------------- - Destructor. -----------------------------------------------------------------------------------------------*/ -Segment::~Segment() -{ - g_csegTotal--; - - DestroyContents(); -} - -void Segment::DestroyContents() -{ - delete m_pfont; - m_pfont = NULL; - - //if (m_pgts) - // // A specially-created wrapper object has to be deleted. - // m_pgts->DeleteTextSrcPtr(); - m_pgts = NULL; - - //if (m_pgjus) - // // A specially-created wrapper object has to be deleted. - // m_pgjus->DeleteJustifierPtr(); - m_pgjus = NULL; - - //if (m_psegAltEndLine) - //{ - // if (m_psegAltEndLine->m_psegAltEndLine == this) - // m_psegAltEndLine->m_psegAltEndLine = NULL; - // delete m_psegAltEndLine; - //} - - //for (int iginf = 0; iginf < m_cginf; iginf++) // DELETE - // delete m_prgginf[iginf].components; - - Assert((m_prgslout && m_prgnSlotVarLenBuf) || (!m_prgslout && !m_prgnSlotVarLenBuf)); - delete[] m_prgslout; - delete[] m_prgnSlotVarLenBuf; - delete[] m_prgisloutBefore; - delete[] m_prgisloutAfter; - for (int ichw = 0; ichw < m_ichwAssocsLim - m_ichwAssocsMin; ichw++) - { - if (m_prgpvisloutAssocs && m_prgpvisloutAssocs[ichw]) - delete m_prgpvisloutAssocs[ichw]; - } - delete[] m_prgpvisloutAssocs; - delete[] m_prgisloutLigature; - delete[] m_prgiComponent; - delete[] m_prgbNextSegDat; - delete[] m_prgInitDat; - delete[] m_prgginf; - m_cginf = 0; - - //DestroyContentsPlatform(); - - // ReleaseObj(m_pgts); automatic because smart pointer -} - -/*---------------------------------------------------------------------------------------------- - Factory method to create a new version of an existing segment with different - line-boundary flags. -----------------------------------------------------------------------------------------------*/ -Segment * Segment::LineContextSegment(Segment & seg, bool fStartLine, bool fEndLine) -{ - if (!seg.hasLineBoundaryContext()) - { - // Make an identical segment and just change the flags. - Segment * psegNew = new Segment(seg); - psegNew->InitLineContextSegment(fStartLine, fEndLine); - return psegNew; - } - else - { - // Rerun the processing. - LayoutEnvironment layout = seg.Layout(); - layout.setStartOfLine(fStartLine); - layout.setEndOfLine(fEndLine); - ITextSource & gts = seg.getText(); - Font & font = seg.getFont(); - return new RangeSegment(&font, >s, &layout, - seg.startCharacter(), seg.stopCharacter(), &seg); - } -} - -void Segment::InitLineContextSegment(bool fStartLine, bool fEndLine) -{ - // For RTL end-of-line segments, trailing white space hangs off the left of - // the origin of the segment. So when changing that flag - // shift appropriately. - bool fShift = ((m_nDirDepth % 2) && (m_fEndLine != fEndLine)); - - m_fStartLine = fStartLine; - m_fEndLine = fEndLine; - - m_layout.setStartOfLine(fStartLine); - m_layout.setEndOfLine(fEndLine); - - if (fShift) - { - (m_fEndLine) ? - ShiftGlyphs(m_dxsVisibleWidth - m_dxsTotalWidth) : // shift left - ShiftGlyphs(m_dxsTotalWidth - m_dxsVisibleWidth); // shift right - } - - m_dxsWidth = -1; -} - -/*---------------------------------------------------------------------------------------------- - A factory method to create a justified version of an existing segment. -----------------------------------------------------------------------------------------------*/ -Segment * Segment::JustifiedSegment(Segment & seg, float xsNewWidth) -{ - LayoutEnvironment layout(seg.Layout()); - ITextSource & gts = seg.getText(); - - // Why do we have to do this? - layout.setJustifier(seg.Justifier()); - Font & font = seg.getFont(); - return new JustSegmentAux(&font, >s, &layout, - seg.startCharacter(), seg.stopCharacter(), - seg.advanceWidth(), xsNewWidth, &seg); -} - -/*---------------------------------------------------------------------------------------------- - A factory method to create a new version of an existing trailing white-space segment - with a different direction. -----------------------------------------------------------------------------------------------*/ -Segment * Segment::WhiteSpaceSegment(Segment & seg, int nNewDepth) -{ - Segment * psegNew = new Segment(seg); - psegNew->InitWhiteSpaceSegment(nNewDepth); - return psegNew; -} - -void Segment::InitWhiteSpaceSegment(int nNewDepth) -{ - if (nNewDepth == m_nDirDepth) - { - return; - } - else if ((nNewDepth % 2) == (m_nDirDepth % 2)) - { - // Same direction, not much to change. - m_nDirDepth = nNewDepth; - return; - } - else if (m_twsh != ktwshOnlyWs) - return; // couldn't change it, oh, well - - // Otherwise, do the hard stuff: reverse the positions of the glyphs. - for (int islout = 0; islout < m_cslout; islout++) - { - OutputSlot(islout)->ShiftForDirDepthChange(m_dxsTotalWidth); - } - m_nDirDepth = nNewDepth; - - //SetDirectionDepthPlatform(nNewDepth); -} - -/*---------------------------------------------------------------------------------------------- - Basic copy method. -----------------------------------------------------------------------------------------------*/ -Segment::Segment(Segment & seg) -{ - int islout; - - m_pgts = seg.m_pgts; - m_dichwLim = seg.m_dichwLim; - m_ichwMin = seg.m_ichwMin; - m_pfont = seg.m_pfont->copyThis(); - m_preneng = seg.m_preneng; - m_fErroneous = seg.m_fErroneous; - m_pgjus = seg.m_pgjus; - m_fWsRtl = seg.m_fWsRtl; - m_fParaRtl = seg.m_fParaRtl; - m_twsh = seg.m_twsh; - m_nDirDepth = seg.m_nDirDepth; - m_cbNextSegDat = seg.m_cbNextSegDat; - m_prgbNextSegDat = new byte[m_cbNextSegDat]; - std::copy(seg.m_prgbNextSegDat, seg.m_prgbNextSegDat + m_cbNextSegDat, m_prgbNextSegDat); -// m_psegPrev = seg.m_psegPrev; -// m_psegNext = seg.m_psegNext; -// m_stuFaceName = seg.m_stuFaceName; -// m_stuBaseFaceName = seg.m_stuBaseFaceName; -// m_fUseSepBase = seg.m_fUseSepBase; -// m_pixHeight = seg.m_pixHeight; -// m_fBold = seg.m_fBold; -// m_fItalic = seg.m_fItalic; - m_lbStart = seg.m_lbStart; - m_lbEnd = seg.m_lbEnd; - m_fStartLine = seg.m_fStartLine; - m_fEndLine = seg.m_fEndLine; - m_est = seg.m_est; - m_mFontEmUnits = seg.m_mFontEmUnits; - m_dysFontAscent = seg.m_dysFontAscent; - m_dysFontDescent = seg.m_dysFontDescent; - m_xysEmSquare = seg.m_xysEmSquare; -// m_xsDPI = seg.m_xsDPI; -// m_ysDPI = seg.m_ysDPI; - m_dxsStretch = seg.m_dxsStretch; - m_dxsWidth = seg.m_dxsWidth; - m_dysHeight = seg.m_dysHeight; - m_dysAscent = seg.m_dysAscent; - m_dysXAscent = seg.m_dysXAscent; - m_dysXDescent = seg.m_dysXDescent; - m_dysAscentOverhang = seg.m_dysAscentOverhang; - m_dysDescentOverhang = seg.m_dysDescentOverhang; - m_dxsLeftOverhang = seg.m_dxsLeftOverhang; - m_dxsRightOverhang = seg.m_dxsRightOverhang; - m_dxsVisibleWidth = seg.m_dxsVisibleWidth; - m_dxsTotalWidth = seg.m_dxsTotalWidth; - m_isloutVisLim = seg.m_isloutVisLim; - m_dysOffset = seg.m_dysOffset; - - m_ichwAssocsMin = seg.m_ichwAssocsMin; - m_ichwAssocsLim = seg.m_ichwAssocsLim; - - int dichw = m_ichwAssocsLim - m_ichwAssocsMin; - m_prgisloutBefore = new int[dichw]; - std::copy(seg.m_prgisloutBefore, seg.m_prgisloutBefore + dichw, m_prgisloutBefore); - m_prgisloutAfter = new int[dichw]; - std::copy(seg.m_prgisloutAfter, seg.m_prgisloutAfter + dichw, m_prgisloutAfter); - m_prgpvisloutAssocs = new std::vector<int> * [dichw]; - for (int ivislout = 0; ivislout < dichw; ivislout++) - { - std::vector<int> * pvislout = seg.m_prgpvisloutAssocs[ivislout]; - if (pvislout) - { - std::vector<int> * pvisloutNew = new std::vector<int>; - m_prgpvisloutAssocs[ivislout] = pvisloutNew; - *pvisloutNew = *pvislout; // copy the vector - } - } - m_prgisloutLigature = new int[dichw]; - std::copy(seg.m_prgisloutLigature, seg.m_prgisloutLigature + dichw, m_prgisloutLigature); - m_prgiComponent = new sdata8[dichw]; - std::copy(seg.m_prgiComponent, seg.m_prgiComponent + dichw, m_prgiComponent); - - m_cslout = seg.m_cslout; - int cnExtraPerSlot = (m_cslout > 0) ? seg.m_prgslout[0].CExtraSpaceSlout() : 0; - m_prgnSlotVarLenBuf = new u_intslot[m_cslout * cnExtraPerSlot]; - m_prgslout = new GrSlotOutput[m_cslout]; - for (islout = 0; islout < m_cslout; islout++) - { - GrSlotOutput * psloutOrig = seg.m_prgslout + islout; - GrSlotOutput * psloutThis = m_prgslout + islout; - psloutThis->ExactCopyFrom(psloutOrig, - m_prgnSlotVarLenBuf + (islout * cnExtraPerSlot), // var-length buffer location - cnExtraPerSlot); - } - -// m_cnUserDefn = seg.m_cnUserDefn; - m_cnCompPerLig = seg.m_cnCompPerLig; -// m_cnFeat = seg.m_cnFeat; - m_cslotRestartBackup = seg.m_cslotRestartBackup; - std::copy(seg.m_prgnSlotVarLenBuf, seg.m_prgnSlotVarLenBuf + - (m_cslout * cnExtraPerSlot), m_prgnSlotVarLenBuf); - - m_cginf = seg.m_cginf; - m_isloutGinf0 = seg.m_isloutGinf0; - m_prgginf = new GlyphInfo[m_cginf]; - std::copy(seg.m_prgginf, seg.m_prgginf + m_cginf, m_prgginf); - for (int iginf = 0; iginf < m_cginf; iginf++) - { - m_prgginf[iginf].m_pseg = this; - m_prgginf[iginf].m_pslout = m_prgslout + m_prgginf[iginf].m_islout; - } - - // Platform-specific; remove eventually: - //m_cgstrm = seg.m_cgstrm; - //m_prggstrm = new GlyphStrm[m_cgstrm]; - //for (int igstrm = 0; igstrm < m_cgstrm; igstrm++) - //{ - // m_prggstrm[igstrm].gsk.ys = seg.m_prggstrm[igstrm].gsk.ys; - // m_prggstrm[igstrm].gsk.clrFore = seg.m_prggstrm[igstrm].gsk.clrFore; - // m_prggstrm[igstrm].gsk.clrBack = seg.m_prggstrm[igstrm].gsk.clrBack; - // m_prggstrm[igstrm].vchwGlyphId = seg.m_prggstrm[igstrm].vchwGlyphId; - // m_prggstrm[igstrm].vdxs = seg.m_prggstrm[igstrm].vdxs; - // m_prggstrm[igstrm].vigbb = seg.m_prggstrm[igstrm].vigbb; - // m_prggstrm[igstrm].xsStart = seg.m_prggstrm[igstrm].xsStart; - // m_prggstrm[igstrm].xsStartInt = seg.m_prggstrm[igstrm].xsStartInt; - //} - //m_cgbb = seg.m_cgbb; - //m_prggbb = new GlyphBb[m_cgbb]; - //memcpy(m_prggbb, seg.m_prggbb, m_cgbb * sizeof(GlyphBb)); - //------------------------------------- - - m_vnSkipOffsets = seg.m_vnSkipOffsets; - m_dircPrevStrong = seg.m_dircPrevStrong; - m_dircPrevTerm = seg.m_dircPrevTerm; - m_cbInitDat = seg.m_cbInitDat; - m_prgInitDat = new byte[m_cbInitDat]; - std::copy(seg.m_prgInitDat, seg.m_prgInitDat + m_cbInitDat, m_prgInitDat); -} - -/*---------------------------------------------------------------------------------------------- - Swap the guts of the two segments. - OBSOLETE -----------------------------------------------------------------------------------------------*/ -void Segment::SwapWith(Segment * pgrseg) -{ - int crefThis = m_cref; - int crefOther = pgrseg->m_cref; - - std::swap(*this, *pgrseg); - - m_cref = crefThis; - pgrseg->m_cref = crefOther; -} - -/*---------------------------------------------------------------------------------------------- - Delete the pointer to the alternate-end-of-line segment. -----------------------------------------------------------------------------------------------*/ -void Segment::ClearAltEndLineSeg() -{ - //if (m_psegAltEndLine) - //{ - // if (m_psegAltEndLine->m_psegAltEndLine == this) - // m_psegAltEndLine->m_psegAltEndLine = NULL; // so we don't get into a loop - // delete m_psegAltEndLine; - // m_psegAltEndLine = NULL; - //} -} - - -//:>******************************************************************************************** -//:> Interface methods -//:>******************************************************************************************** - -/*---------------------------------------------------------------------------------------------- - Return the font that was used to create this segment. - Note that in some implementations, the font may be invalid; eg, on Windows the font - may not contain a valid device context. -----------------------------------------------------------------------------------------------*/ -Font & Segment::getFont() -{ - return *m_pfont; -} - -/*---------------------------------------------------------------------------------------------- - Return the text-source that the segment is representing. -----------------------------------------------------------------------------------------------*/ -ITextSource & Segment::getText() -{ - return *m_pgts; -} - -/*---------------------------------------------------------------------------------------------- - The distance the drawing point should advance after drawing this segment. - Always positive, even for RtoL segments. -----------------------------------------------------------------------------------------------*/ -float Segment::advanceWidth() -{ - if (m_dxsWidth < 0) - { - ////SetUpGraphics(ichwBase, pgg, true); - ComputeDimensions(); - } - return m_dxsWidth; -} - -/*---------------------------------------------------------------------------------------------- - Compute the rectangle in destination coords which contains all the pixels drawn by - this segment. This should be a sufficient rectangle to invalidate if the segment is - about to be discarded. -----------------------------------------------------------------------------------------------*/ -Rect Segment::boundingRect() -{ - if (m_dxsWidth < 0) - { - ////SetUpGraphics(ichwBase, pgg, true); - ComputeDimensions(); - } - - Rect rectRet; - rectRet.top = m_dysAscent + m_dysAscentOverhang; - rectRet.bottom = (m_dysAscent - m_dysHeight) - m_dysDescentOverhang; - rectRet.left = m_dxsLeftOverhang; - rectRet.right = m_dxsVisibleWidth + m_dxsRightOverhang; - - return rectRet; -} - -/*---------------------------------------------------------------------------------------------- - Answer whether the primary direction of the segment is right-to-left. This is based - on the direction of the writing system, except for white-space-only segments, in - which case it is based on the main paragraph direction. -----------------------------------------------------------------------------------------------*/ -bool Segment::rightToLeft() -{ - if (m_twsh == ktwshOnlyWs) - { - // White-space-only segment: use main paragraph direction. - return (m_nDirDepth % 2); - } - - GrEngine * pgreng = EngineImpl(); - if (pgreng) - { - return pgreng->RightToLeft(); - } - return (m_pgts->getRightToLeft(m_ichwMin)); -} - -/*---------------------------------------------------------------------------------------------- - Get the depth of direction embedding used by this segment. It is presumably the same - for all runs of the segment, otherwise, some of them would use a different writing - system and therefore be part of a different segment. So just use the first. -----------------------------------------------------------------------------------------------*/ -int Segment::directionDepth(bool * pfWeak) -{ - if (pfWeak) - *pfWeak = (m_twsh == ktwshOnlyWs); - -// *pnDepth = m_pgts->getDirectionDepth(m_ichwLim); -// Assert(*pnDepth == m_nDirDepth); - - return m_nDirDepth; -} - -/*---------------------------------------------------------------------------------------------- - Change the direction of the segment. This is needed specifically for white-space-only - segments, which are initially created to be in the direction of the paragraph, but then - later are discovered to not be line-end after all, and need to be changed to use the - directionality of the writing system. - - @return kresFail for segments that do not have weak directionality and therefore - cannot be changed. -----------------------------------------------------------------------------------------------*/ -bool Segment::setDirectionDepth(int nNewDepth) -{ - Assert(false); - - if (nNewDepth == m_nDirDepth) - { - return true; - } - else if ((nNewDepth % 2) == (m_nDirDepth % 2)) - { - // Same direction, not much to change. - m_nDirDepth = nNewDepth; - return true; - } - else if (m_twsh != ktwshOnlyWs) - return false; - - // Otherwise, do the hard stuff: reverse the positions of the glyphs. - for (int islout = 0; islout < m_cslout; islout++) - { - OutputSlot(islout)->ShiftForDirDepthChange(m_dxsTotalWidth); - } - - //SetDirectionDepthPlatform(nNewDepth); - - return true; - -} - -/*---------------------------------------------------------------------------------------------- - The logical range of characters covered by the segment, relative to the beginning of - the segment. The stop character is the index of the first character beyond the end - of the segment. - - These values should be exact at a writing system or string boundary, - but may be somewhat fuzzy at a line-break, since characters may be re-ordered - across such boundaries. The renderer is free to apply any definition it likes of - where a line-break occurs. This should always be the same value obtained from the - renderer as pdichLimSeg. -----------------------------------------------------------------------------------------------*/ -int Segment::startCharacter() -{ - return m_ichwMin; -} - -int Segment::stopCharacter() -{ - return m_ichwMin + m_dichwLim; -} - -/*---------------------------------------------------------------------------------------------- - Returns an indication of why the segment ended. -----------------------------------------------------------------------------------------------*/ -bool Segment::startOfLine() -{ - return m_fStartLine; -} - -/*---------------------------------------------------------------------------------------------- - Returns an indication of why the segment ended. -----------------------------------------------------------------------------------------------*/ -bool Segment::endOfLine() -{ - return m_fEndLine; -} - -/*---------------------------------------------------------------------------------------------- - Returns true if this segment has something special happening at line boundaries. -----------------------------------------------------------------------------------------------*/ -bool Segment::hasLineBoundaryContext() -{ - return (EngineImpl()->LineBreakFlag()); -} - -/*---------------------------------------------------------------------------------------------- - Returns an indication of why the segment ended. -----------------------------------------------------------------------------------------------*/ -SegEnd Segment::segmentTermination() -{ - return m_est; -} - -/*---------------------------------------------------------------------------------------------- - Indicates the last character of interest to the segment, relative to the beginning - of the segment. The meaning of this is that no behavior of this segment will be - affected if characters beyond that change. This does not necessarily mean that - a different line break could not have been obtained by the renderer if characters - beyond that change, just that a segment with the boundaries of this one would - not behave differently. -----------------------------------------------------------------------------------------------*/ -//GrResult Segment::get_LimInterest(int ichwBase, int * pdichw) -//{ -// ChkGrOutPtr(pdichw); -// -// GrEngine * pgreng = EngineImpl(); -// Assert(pgreng); -// *pdichw = m_dichwLim + pgreng->PostXlbContext(); -// ReturnResult(kresOk); -//} - -/*---------------------------------------------------------------------------------------------- - Changes the end-of-line status of the segment. This is used after making the last segment - of a string if we want to attempt to put some more text after it (e.g., in another - writing system), or if we have reordered due to bidirectionality. - - ENHANCE: the current version handles switching back and forth when we are trying to - decide whether we can put more stuff on a line. So it assumes we are at the end of - the contextual run (ie, the next batch of stuff will be in a different ows). - This will not correctly handle the way this function could or possibly - should be used for bidirectional reordering. -----------------------------------------------------------------------------------------------*/ -/* -GrResult Segment::changeLineEnds(bool fNewStart, bool fNewEnd) -{ - if (m_fStartLine != fNewStart || m_fEndLine != fNewEnd) - { - if (EngineImpl()->LineBreakFlag()) - { - if (!m_psegAltEndLine) - { - int dichwLimSeg, dichwContext; - float dxWidth; - SegEnd est; - int cbNextSegDat; - byte rgbNextSegDat[256]; - OLECHAR rgchErrMsg[256]; - Segment * pseg; - - EngineImpl()->FindBreakPointAux(m_pfont, m_pgts, m_pgjus, - m_ichwMin, m_ichwMin + m_dichwLim, m_ichwMin + m_dichwLim, - false, fNewStart, fNewEnd, kPosInfFloat, false, - klbNoBreak, klbNoBreak, m_twsh, m_fParaRtl, - &pseg, - &dichwLimSeg, &dxWidth, &est, - m_cbInitDat, m_prgInitDat, 256, rgbNextSegDat, &cbNextSegDat, - &dichwContext, - NULL, - rgchErrMsg, 256); - // TODO: do something with the error message. This shouldn't really happen, - // since to get here we already created a segment with this font. - if (!pseg) - { - // Because we provide INT_MAX as the amount of space, there should - // always be enough room to generate the alternate segment. - Assert(false); - THROW(kresUnexpected); - } - Assert(cbNextSegDat == 0); - m_psegAltEndLine = pseg; - } - Assert(m_psegAltEndLine->m_fEndLine == fNewEnd); - Segment * pseg = m_psegAltEndLine; // save the value - SwapWith(m_psegAltEndLine); - m_psegAltEndLine = pseg; // reset it after swap - pseg->m_psegAltEndLine = this; - } - else - { - bool fShift = ((m_nDirDepth % 2) && (m_fEndLine != fNewEnd)); - m_fStartLine = fNewStart; - m_fEndLine = fNewEnd; - if (fShift) - { - (m_fEndLine) ? - ShiftGlyphs(m_dxsVisibleWidth - m_dxsTotalWidth) : // shift left - ShiftGlyphs(m_dxsTotalWidth - m_dxsVisibleWidth); // shift right - } - m_dxsWidth = -1; - } - } - - ReturnResult(kresOk); -} -*/ - -/*---------------------------------------------------------------------------------------------- - Get the type of break that occurs at the logical start of the segment. -----------------------------------------------------------------------------------------------*/ -LineBrk Segment::startBreakWeight() -{ - return m_lbStart; -} - -/*---------------------------------------------------------------------------------------------- - Get the type of break that occurs at the logical end of the segment. -----------------------------------------------------------------------------------------------*/ -LineBrk Segment::endBreakWeight() -{ - return m_lbEnd; -} - -/*---------------------------------------------------------------------------------------------- - Read the amount of stretch, that is, the difference between the actual and natural width. - If the segment has been shrunk, returns a negative number. - TODO: implement properly. -----------------------------------------------------------------------------------------------*/ -float Segment::stretch() -{ - return (float)m_dxsStretch; -} - -/*---------------------------------------------------------------------------------------------- - Return the maximum stretch possible. - TODO: implement properly. -----------------------------------------------------------------------------------------------*/ -float Segment::maxStretch() -{ - return 1000; -} - -/*---------------------------------------------------------------------------------------------- - Return the maximum shrink possible. - TODO: implement properly. -----------------------------------------------------------------------------------------------*/ -float Segment::maxShrink() -{ - return 0; -} - -/*---------------------------------------------------------------------------------------------- - Return iterators representing the complete range of glyphs in the segment. -----------------------------------------------------------------------------------------------*/ -std::pair<GlyphIterator, GlyphIterator> Segment::glyphs() -{ - return std::make_pair(GlyphIterator(*this, 0), GlyphIterator(*this, m_cginf)); -} - -/*---------------------------------------------------------------------------------------------- - Return iterators representing the set of glyphs for the given character. -----------------------------------------------------------------------------------------------*/ -std::pair<GlyphSetIterator, GlyphSetIterator> Segment::charToGlyphs(toffset ich) -{ - std::vector<int> vislout = UnderlyingToLogicalAssocs(ich); - - if (vislout.size() == 0) - return std::make_pair(GlyphSetIterator(), GlyphSetIterator()); - else - { - // Note that BOTH instances of GlyphSetIterator must use the same underlying vector, - // so that comparisons make sense. - RcVector * qvislout = new RcVector(vislout); - return std::make_pair( - GlyphSetIterator(*this, 0, qvislout), - GlyphSetIterator(*this, vislout.size(), qvislout)); - } -} - -/*---------------------------------------------------------------------------------------------- - Return the rendered glyphs and their x- and y-coordinates, in the order generated by - the final positioning pass, relative to the top-left of the segment. They are always - returned in (roughly) left-to-right order. Note: any of the arrays may be null. -----------------------------------------------------------------------------------------------*/ -/* -GrResult Segment::GetGlyphsAndPositions( - Rect rs, Rect rd, int cchMax, int * pcchRet, - utf16 * prgchGlyphs, float * prgxd, float * prgyd, float * prgdxdAdv) -{ - ChkGrOutPtr(pcchRet); - if (prgchGlyphs) - ChkGrArrayArg(prgchGlyphs, cchMax); - if (prgxd) - ChkGrArrayArg(prgxd, cchMax); - if (prgyd) - ChkGrArrayArg(prgyd, cchMax); - if (prgdxdAdv) - ChkGrArrayArg(prgdxdAdv, cchMax); - - GrResult res; - - //SetUpGraphics(ichwBase, pgg, true); - - Assert(m_dxsWidth >= 0); - Assert(m_dysAscent >= 0); - - *pcchRet = m_cginf; - if (cchMax < m_cginf) - { - res = (cchMax == 0) ? kresFalse : kresInvalidArg; - //RestoreFont(pgg); - ReturnResult(res); - } - - if (m_dxsWidth < 0) - ComputeDimensions(); - - float dysFontAscent = m_dysFontAscent; - //////res = GetFontAscentSourceUnits(pgg, &dysFontAscent); - //////if (ResultFailed(res)) - //////{ - ////// RestoreFont(pgg); - ////// ReturnResult(res); - //////} - - float xs = 0; - // Top of text that sits on the baseline, relative to top of segment: - float ys = m_dysAscent - dysFontAscent; - - float * prgxdLocal; - if (prgxd == NULL) - prgxdLocal = new float[cchMax]; - else - prgxdLocal = prgxd; - - res = GetGlyphsAndPositionsPlatform(xs, ys, rs, rd, - prgchGlyphs, prgxdLocal, prgyd, prgdxdAdv); - - if (!prgxd) - delete[] prgxdLocal; - - //RestoreFont(pgg); - - ReturnResult(res); -} -*/ - -/*---------------------------------------------------------------------------------------------- - For debugging. Return the characters in this segment. - OBSOLETE -----------------------------------------------------------------------------------------------*/ -GrResult Segment::GetCharData(int cchMax, utf16 * prgch, int * pcchRet) -{ - ChkGrArgPtr(prgch); - ChkGrOutPtr(pcchRet); - - int ichLimTmp = m_ichwMin + min(m_dichwLim, cchMax); - m_pgts->fetch(m_ichwMin, ichLimTmp - m_ichwMin, prgch); - *pcchRet = ichLimTmp - m_ichwMin; - ReturnResult(kresOk); -} - -/*---------------------------------------------------------------------------------------------- - Return either the first or last character that the the glyph corresponds to. The - index of the glyph matches what was returned by GetGlyphsAndPositions. - OBSOLETE -----------------------------------------------------------------------------------------------*/ -GrResult Segment::GlyphToChar(int iginf, bool fFirst, int * pich) -{ - Assert(m_dxsWidth >= 0); - Assert(m_dysAscent >= 0); - - *pich = PhysicalSurfaceToUnderlying(iginf, fFirst); - ReturnResult(kresOk); -} - -/*---------------------------------------------------------------------------------------------- - Return all the characters that the glyph corresponds to. Most commonly this will - be only one char, but ligatures, for instance, will have several. The index of the - glyph matches what was returned by GetGlyphsAndPositions. - OBSOLETE -----------------------------------------------------------------------------------------------*/ -GrResult Segment::GlyphToAllChars(int iginf, - int cichMax, int * prgich, int * pcichRet) -{ - Assert(m_dxsWidth >= 0); - Assert(m_dysAscent >= 0); - - std::vector<int> vich; - int ichFirst = PhysicalSurfaceToUnderlying(iginf, true); - int ichLast = PhysicalSurfaceToUnderlying(iginf, false); - Assert(ichFirst <= ichLast); - - if (ichFirst < ichLast) - { - // Loop over the range of characters that might be associated with this glyph - // and add any that actually are. - // TODO: we should probably use a method that gets us all the physical associations, - // but this should get us 99.5% of the way there for now. - for (int ich = ichFirst; ich <= ichLast; ich++) - { - int iginfFirst = UnderlyingToPhysicalSurface(ich, true); - int iginfLast = UnderlyingToPhysicalSurface(ich, false); - if (iginfFirst == iginf || iginfLast == iginf) - vich.push_back(ich); - } - } - else - vich.push_back(ichFirst); - - *pcichRet = vich.size(); - if (cichMax < signed(vich.size())) - { - GrResult res = (cichMax == 0 ? kresFalse : kresInvalidArg); - ReturnResult(res); - } - int * pi = prgich; - for (size_t i = 0; i < vich.size(); i++) - *pi++ = vich[i]; - - ReturnResult(kresOk); -} - -/*---------------------------------------------------------------------------------------------- - Return either the first or last glyph that corresponds to the character. The - index of the glyph matches what was returned by GetGlyphsAndPositions. - OBSOLETE -----------------------------------------------------------------------------------------------*/ -GrResult Segment::CharToGlyph(int ich, bool fFirst, int * pigbb) -{ - Assert(m_dxsWidth >= 0); - Assert(m_dysAscent >= 0); - - *pigbb = UnderlyingToPhysicalSurface(ich, fFirst); - ReturnResult(kresOk); -} - - -//:>******************************************************************************************** -//:> Non-FieldWorks interface methods -//:>******************************************************************************************** - -/*---------------------------------------------------------------------------------------------- - Return the breakweight for the given character. Returns the best value if the character is - mapped to glyphs with different values. -----------------------------------------------------------------------------------------------*/ -LineBrk Segment::getBreakWeight(int ich, bool fBreakBefore) -{ - LineBrk lbFirst, lbLast; - - int isloutFirst = UnderlyingToLogicalSurface(ich, true); - if (isloutFirst == kPosInfinity || isloutFirst == kNegInfinity) - return klbClipBreak; - GrSlotOutput * psloutFirst = m_prgslout + isloutFirst; - bool fNotFirst = false; - if ((psloutFirst->NumberOfComponents() > 0) - && psloutFirst->UnderlyingComponent(0) != ich) - { - // Not the first component of a ligature. - lbFirst = (LineBrk) ((int)klbClipBreak * -1); - fNotFirst = true; - } - else - { - lbFirst = (LineBrk) psloutFirst->BreakWeight(); - } - - int isloutLast = UnderlyingToLogicalSurface(ich, false); - if (isloutLast == kPosInfinity || isloutLast == kNegInfinity) - return klbClipBreak; - GrSlotOutput * psloutLast = m_prgslout + isloutLast; - bool fNotLast = false; - if ((psloutLast->NumberOfComponents() > 0) - && psloutLast->UnderlyingComponent(psloutLast->NumberOfComponents() - 1) != ich) - { - // Not the last component of a ligature. - lbLast = klbClipBreak; - fNotLast = true; - } - else - { - lbLast = (LineBrk) psloutLast->BreakWeight(); - } - - LineBrk lbRet; - if (fNotLast && fNotFirst) - // middle of a ligature - lbRet = klbClipBreak; - else if (fNotLast) - lbRet = (fBreakBefore) ? lbFirst : klbClipBreak; - else if (fNotFirst) - lbRet = (fBreakBefore) ? klbClipBreak : lbLast; - else - lbRet = (fBreakBefore) ? lbFirst : lbLast; - - return lbRet; -} - -/*---------------------------------------------------------------------------------------------- - Return the width of the range of characters. Line-boundary contextualization is handled - by the measure attributes on the glyphs. The width returned is equivalent to the sum of - the widths of any line-segments that would be needed to underline all the characters. - - Since this method is intended to be used on "measured" segments that include the entire - paragraph, it is not very smart about handling cross-line-boundary contextualization. - It basically ignores any glyphs that are rendered by this segment but not officially - part of the segment. -----------------------------------------------------------------------------------------------*/ -float Segment::getRangeWidth(int ichMin, int ichLim, - bool fStartLine, bool fEndLine, bool fSkipSpace) -{ - if (m_dxsWidth < 0) - { - ////SetUpGraphics(ichwBase, pgg, true); - ComputeDimensions(); - } - - Assert(m_dxsWidth >= 0); - Assert(m_dysAscent >= 0); - - //float xsSegRight = m_dxsTotalWidth; - - int ichMinRange = min(ichMin, ichLim); - int ichLimRange = max(ichMin, ichLim); - - //int ichMinSeg = max(ichMinRange, m_ichwMin + m_ichwAssocsMin); - //int ichLimSeg = min(ichLimRange, m_ichwMin + m_ichwAssocsLim); - int ichMinSeg = max(ichMinRange, m_ichwMin); - int ichLimSeg = min(ichLimRange, m_ichwMin + m_dichwLim); - - if (ichLimSeg < m_ichwMin) // not + m_ichwAssocsMin - return 0; - if (ichMinSeg >= m_ichwMin + m_dichwLim) // not m_ichwAssocsLim - return 0; - - if (fSkipSpace) - { - int islout = UnderlyingToLogicalSurface(ichLimSeg - 1, true); - GrSlotOutput * pslout = (islout == kNegInfinity || islout == kPosInfinity) ? - NULL : - OutputSlot(islout); - while (pslout && pslout->IsSpace()) - { - ichLimSeg--; - islout = UnderlyingToLogicalSurface(ichLimSeg - 1, true); -// pslout = OutputSlot(islout); - pslout = (islout == kNegInfinity || islout == kPosInfinity) ? - NULL : OutputSlot(islout); - } - } - - float xsWidth = 0; - SegmentNonPainter segp(this); // doesn't really need to paint - float rgxdLefts[100]; - float rgxdRights[100]; - size_t cxd = 0; - if (ichMinRange < ichLimRange) - cxd = segp.getUnderlinePlacement(ichMinSeg, ichLimSeg, fSkipSpace, - 100, rgxdLefts, rgxdRights, NULL); - for (size_t i = 0; i < cxd; i++) - xsWidth += rgxdRights[i] - rgxdLefts[i]; - - // Add in the line-boundary contextualization. - int isloutFirst = UnderlyingToLogicalSurface(ichMin, true); - int isloutLast = UnderlyingToLogicalSurface(ichLim - 1, false); - int mSol = 0; - int mEol = 0; - if (0 <= isloutFirst && isloutFirst < m_cslout) - mSol = m_prgslout[isloutFirst].MeasureSol(); - if (0 <= isloutLast && isloutLast < m_cslout) - mEol = m_prgslout[isloutLast].MeasureEol(); - float dxsSol = GrEngine::GrIFIMulDiv(mSol, m_xysEmSquare, m_mFontEmUnits); - float dxsEol = GrEngine::GrIFIMulDiv(mEol, m_xysEmSquare, m_mFontEmUnits); - xsWidth += dxsSol; - xsWidth += dxsEol; - - //RestoreFont(pgg); - - return xsWidth; -} - -/*---------------------------------------------------------------------------------------------- - Return the next reasonable breakpoint after ichStart resulting in range that fits in - the specified width. -----------------------------------------------------------------------------------------------*/ -int Segment::findNextBreakPoint(int ichStart, - LineBrk lbPref, LineBrk lbWorst, float dxMaxWidth, - float * pdxBreakWidth, bool fStartLine, bool fEndLine) -{ - ChkGrOutPtr(pdxBreakWidth); - - int ichBreak; - - // First make a rough estimation of how much will fit, using a binary chop approach. - int iginfStart = UnderlyingToPhysicalSurface(ichStart, !m_fWsRtl); - int iginfEnd = UnderlyingToPhysicalSurface(m_ichwMin + m_dichwLim - 1, m_fWsRtl); - int iginfLeft = min(iginfStart, iginfEnd); - int iginfRight= max(iginfStart, iginfEnd); - - int iginfMin = iginfLeft; - int iginfLim = iginfRight; - int ichFit; - if (m_fWsRtl) // right-to-left - { - float xRight = GlyphLeftEdge(iginfRight + 1); - float xLeftMost = xRight - dxMaxWidth; - while (GlyphLeftEdge(iginfLim) < xLeftMost) - { - if (iginfLim - iginfMin <= 1) - break; - int iginfMid = (iginfLim + iginfMin) >> 1; // divide by 2 - if (GlyphLeftEdge(iginfMid) < xLeftMost) - iginfLim = iginfMid; - else - iginfMin = iginfMid; - } - ichFit = PhysicalSurfaceToUnderlying(iginfLim, false); - } - else // left-to-right - { - float xLeft = GlyphLeftEdge(iginfLeft); - float xRightMost = dxMaxWidth - xLeft; // QUESTION: shouldn't this be +, not -? - iginfLim++; - while (GlyphLeftEdge(iginfLim) > xRightMost) - { - if (iginfLim - iginfMin <= 1) - break; - int iginfMid = (iginfLim + iginfMin) >> 1; // divide by 2 - if (GlyphLeftEdge(iginfMid) > xRightMost) - iginfLim = iginfMid; - else - iginfMin = iginfMid; - } - Assert(iginfLim <= m_cginf); - if (iginfLim >= m_cginf) iginfLim = m_cginf - 1; - ichFit = PhysicalSurfaceToUnderlying(iginfLim, false); - } - - // Breaking after ichFit should pretty much fit in the space. But make sure. - float dxWidthFit; - while (ichFit > ichStart) - { - dxWidthFit = getRangeWidth(ichStart, ichFit, fStartLine, fEndLine); - if (dxWidthFit <= dxMaxWidth) - break; - ichFit--; - } - - if (ichFit <= ichStart) - { - // Nothing will fit. - return ichStart - 1; - } - - // Now look for a good break. First look forward until the range doesn't fit anymore. - int ichTry = ichFit; - int nExtra = 2; - LineBrk lbBest = klbClipBreak; - int ichBestBreak = -1; - while (nExtra > 0 && ichTry < m_ichwMin + m_dichwLim) - { - float dxWTmp; - dxWTmp = getRangeWidth(ichStart, ichTry, fStartLine, fEndLine); - if (dxWTmp <= dxMaxWidth) - { - LineBrk lbTmp; - lbTmp = getBreakWeight(ichTry - 1, false); - if (lbTmp > 0 && lbTmp < lbWorst && max(lbTmp, lbPref) <= lbBest) - { - ichBestBreak = ichTry; - lbBest = max(lbTmp, lbPref); // any value better than lbPref is insignificant - } - else - { - lbTmp = getBreakWeight(ichTry - 1, true); - if (lbTmp < 0) - { - lbTmp = LineBrk(max(lbTmp * -1L, long(lbPref))); - if (lbTmp < lbWorst && lbTmp <= lbBest) - { - ichBestBreak = ichTry - 1; - lbBest = lbTmp; - } - } - } - } - else - { - // Didn't fit. But it is theoretically possible that actually adding another - // character will! Try a few more. - nExtra--; - } - ichTry++; - } - - if (ichTry >= m_ichwMin + m_dichwLim) - { - // Break at the end of the segment. - ichBreak = m_ichwMin + m_dichwLim; - *pdxBreakWidth = getRangeWidth(ichStart, m_dichwLim, fStartLine, fEndLine); - return ichBreak; - } - - if (ichBestBreak > -1 && lbBest <= lbPref) - { - // Found a reasonable break by looking forward; return it. - ichBreak = ichBestBreak;// + m_ichwMin; - *pdxBreakWidth = getRangeWidth(ichStart, ichBestBreak, fStartLine, fEndLine); - return ichBreak; - } - - // Didn't find a really good break point looking forward from our rough guess. - // Now look backward. - - ichTry = ichFit; - while (ichTry > ichStart) - { - LineBrk lbTmp; - lbTmp = getBreakWeight(ichTry - 1, false); - if (lbTmp > 0 && lbTmp < lbWorst && max(lbTmp, lbPref) < lbBest) - { - ichBestBreak = ichTry; - lbBest = max(lbTmp, lbPref); // any value better than lbPref is insignificant - } - else - { - lbTmp = getBreakWeight(ichTry - 1, true); - if (lbTmp < 0) - { - lbTmp = LineBrk(max(lbTmp * -1L, long(lbPref))); - if (lbTmp < lbWorst && lbTmp < lbBest) - { - ichBestBreak = ichTry - 1; - lbBest = lbTmp; - } - } - } - if (lbBest <= lbPref) - break; - - ichTry--; - } - - if (ichBestBreak > -1 && ichBestBreak > ichStart) - { - // Found a reasonable break by looking backward; return it. - ichBreak = ichBestBreak;// + m_ichwMin; - *pdxBreakWidth = getRangeWidth(ichStart, ichBestBreak, fStartLine, fEndLine); - return ichBreak; - } - - // No reasonable break. - return ichStart - 1; -} - -/*---------------------------------------------------------------------------------------------- - Private; used by findNextBreakPoint(). -----------------------------------------------------------------------------------------------*/ -float Segment::GlyphLeftEdge(int iginf) -{ - if (iginf >= m_cginf) - return m_prgginf[m_cginf - 1].origin() + m_prgginf[m_cginf - 1].advanceWidth(); -// return m_prgginf[m_cginf].origin() + m_prgginf[m_cginf].advanceWidth(); - else - return m_prgginf[iginf].origin(); -} - - -//:>******************************************************************************************** -//:> Other methods -//:>******************************************************************************************** - -/*---------------------------------------------------------------------------------------------- - Get the embedded string. For temporary use; AddRef is not automatically called. - Do not release unless you AddRef. -----------------------------------------------------------------------------------------------*/ -ITextSource * Segment::GetString() -{ - return m_pgts; -} - -/*---------------------------------------------------------------------------------------------- - Compute the ascent, height, width, and overhangs of the segment. - The ascent is the ascent of the font (distance from the baseline to the top) - plus any extra ascent height specified by the font. - The descent is distance from the baseline to the bottom of font, plus any extra descent - specified by the font (ExtraDescent). - The ascent overhang is the distance from the top of the font to the top of the highest - glyph, or zero if all the glyphs fit within the ascent. - The descent overhang is the distance from the bottom of the font to the bottom of the lowest - glyph, or zero if all the glyphs fit within the descent. - The height is the sum of the ascent and descent. -----------------------------------------------------------------------------------------------*/ -void Segment::ComputeDimensions() -{ - if (m_fEndLine) - m_dxsWidth = m_dxsVisibleWidth; // don't include trailing white space. - else - m_dxsWidth = m_dxsTotalWidth; - - if (m_dxsWidth == -1) - { - for (int iginf = 0; iginf < m_cginf; iginf++) - { - GlyphInfo * pginf = m_prgginf + iginf; - if (pginf->isSpace()) - continue; - m_dxsWidth = max(m_dxsWidth, (pginf->origin() + pginf->advanceWidth())); - } - } - - int dysNegFontDescent = (int)m_dysFontDescent * -1; - - // if there were no glyphs in the segment then there is sometimes no EngineImpl - if (!EngineImpl()) - { - Assert(m_cslout == 0); - Assert(m_cginf == 0); - m_dxsWidth = 0; - m_dysAscent = 0; // max(0.0, m_dysFontAscent); - m_dysHeight = 0; // max(0.0, m_dysAscent - dysNegFontDescent); - m_dysAscentOverhang = 0; - m_dysDescentOverhang = 0; - m_dxsLeftOverhang = 0; - m_dxsRightOverhang = 0; - return; - } - - // Calculate the extra ascent and descent. - int mXAscent = EngineImpl()->ExtraAscent(); - int mXDescent = EngineImpl()->ExtraDescent(); - - m_dysXAscent = GrEngine::GrIFIMulDiv(mXAscent, m_xysEmSquare, m_mFontEmUnits); - m_dysXDescent = GrEngine::GrIFIMulDiv(mXDescent, m_xysEmSquare, m_mFontEmUnits); - - m_dysAscent = m_dysFontAscent + m_dysXAscent; - float dysNegDescent = dysNegFontDescent - m_dysXDescent; // dysNegDescent < 0 - m_dysHeight = m_dysAscent - dysNegDescent; - - // Calculate the overhangs. - float dysVisAscent = m_dysAscent; - float dysNegVisDescent = dysNegDescent; - float dxsVisLeft = 0; - float dxsVisRight = m_dxsTotalWidth; - ComputeOverhangs(&dysVisAscent, &dysNegVisDescent, &dxsVisLeft, &dxsVisRight); - m_dysAscentOverhang = max(float(0), (dysVisAscent - m_dysAscent)); - m_dysDescentOverhang = max(float(0), (dysNegDescent - dysNegVisDescent)); - m_dxsLeftOverhang = min(float(0), dxsVisLeft); - m_dxsRightOverhang = max(float(0), dxsVisRight - m_dxsTotalWidth); - - m_dysOffset = EngineImpl()->VerticalOffset(); -} - -/*---------------------------------------------------------------------------------------------- - Compute the visible ascent and descent, based on how much the bounding box of any - glyph may extend beyond the ascent or descent of the font. - Also compute the left- and right-overhangs. -----------------------------------------------------------------------------------------------*/ -void Segment::ComputeOverhangs(float * pdysVisAscent, float * pdysNegVisDescent, - float * pdxsVisLeft, float * pdxsVisRight) -{ - for (int iginf = 0; iginf < m_cginf; iginf++) - { - *pdysVisAscent = max(*pdysVisAscent, m_prgginf[iginf].bb().top); - *pdysNegVisDescent = min(*pdysNegVisDescent, m_prgginf[iginf].bb().bottom); - - *pdxsVisLeft = min(*pdxsVisLeft, m_prgginf[iginf].bb().left); - *pdxsVisRight = max(*pdxsVisRight, m_prgginf[iginf].bb().right); - } -} - -/*---------------------------------------------------------------------------------------------- - Create the arrays to store the final output and association information. -----------------------------------------------------------------------------------------------*/ -void Segment::SetUpOutputArrays(Font * pfont, GrTableManager * ptman, - GrSlotStream * psstrmFinal, - int cchwInThisSeg, int csloutSurface, gid16 chwLB, - TrWsHandling twsh, bool fParaRtl, int nDirDepth, bool fEmpty) -{ - m_mFontEmUnits = EngineImpl()->GetFontEmUnits(); - - pfont->getFontMetrics(&m_dysFontAscent, &m_dysFontDescent, &m_xysEmSquare); -// m_xsDPI = (float)pfont->getDPIx(); -// m_ysDPI = (float)pfont->getDPIy(); - - // Note that storing both of these values is redundant; they should be the same. -// Assert(m_xysEmSquare == m_pixHeight); - - m_twsh = twsh; - m_fParaRtl = fParaRtl; - if (m_twsh == ktwshOnlyWs) - m_nDirDepth = (int)fParaRtl; - else if (fParaRtl && nDirDepth == 0) - m_nDirDepth = 2; - else - m_nDirDepth = nDirDepth; - - // Create association mappings and set up final versions of slots. - - Assert((psstrmFinal == NULL) == fEmpty); - - m_ichwAssocsMin = 0; - m_ichwAssocsLim = cchwInThisSeg; - - m_prgisloutBefore = new int[cchwInThisSeg]; - - m_prgisloutAfter = new int[cchwInThisSeg]; - - m_prgpvisloutAssocs = new std::vector<int> * [cchwInThisSeg]; - - m_prgisloutLigature = new int[cchwInThisSeg]; - - m_prgiComponent = new sdata8[cchwInThisSeg]; - - int cslot = 0; - //m_psstrm = psstrmFinal; // TODO: make a local variable - if (psstrmFinal) - cslot = psstrmFinal->FinalSegLim(); - else - Assert(fEmpty); - - float xsMin = 0; - int islot; - int islotMin = (psstrmFinal) ? psstrmFinal->IndexOffset() : 0; - for (islot = islotMin; islot < cslot; islot++) - xsMin = min(xsMin, psstrmFinal->SlotAt(islot)->XPosition()); - - // For right-to-left segments, the draw origin is at the left side of the visible - // portion of the text. So if necessary, scoot everything left so that the invisible - // trailing white-space is to the left of the draw position. - Assert(m_dxsTotalWidth > -1); - Assert(m_dxsVisibleWidth > -1); - float dxsInvisible = (m_fEndLine) ? m_dxsTotalWidth - m_dxsVisibleWidth : 0; - for (islot = islotMin; ((m_nDirDepth % 2) && (islot < cslot)); islot++) - { - GrSlotState * pslot = psstrmFinal->SlotAt(islot); - // int islout = islot - islotMin; - if (pslot->GlyphID() == chwLB) - continue; // skip over linebreak markers - if (m_nDirDepth % 2) // redundant test - { - // RTL will have descending neg values, adjust to be positive. Also make sure - // invisible trailing white space is to the left of the draw origin. - // Review: will changing this value have side affects? - pslot->SetXPos(pslot->XPosition() - xsMin - dxsInvisible); - } - } - - Assert(kPosInfinity > 0); - Assert(kNegInfinity < 0); - for (int ichw = 0; ichw < cchwInThisSeg; ++ichw) - { - m_prgisloutBefore[ichw] = kPosInfinity; - m_prgisloutAfter[ichw] = kNegInfinity; - m_prgpvisloutAssocs[ichw] = new std::vector<int>; - m_prgisloutLigature[ichw] = kNegInfinity; - m_prgiComponent[ichw] = 0; - } - - m_cslout = csloutSurface; - if (ptman->NumUserDefn() > 0 && ptman->NumCompPerLig() > 0) - { - int x; x = 3; - } - -// m_cnUserDefn = ptman->NumUserDefn(); - m_cnCompPerLig = ptman->NumCompPerLig(); -// m_cnFeat = ptman->NumFeat(); - // Normal buffers, plus underlying indices of ligature components, plus - // map from used components to defined components. -// int cnExtraPerSlot = m_cnUserDefn + (m_cnCompPerLig * 2) + m_cnFeat + (m_cnCompPerLig * 2); - - // We don't need to store the user-defined slot attributes or the features in the segment itself. - // What we need is: (1) component.ref attr settings, (2) slot-attribute indices, - // (3) underlying indicates of ligature components, and (4) map from used components - // to defined components - int cnExtraPerSlot = m_cnCompPerLig * 4; - m_prgslout = new GrSlotOutput[m_cslout]; - m_prgnSlotVarLenBuf = new u_intslot[m_cslout * cnExtraPerSlot]; - - m_isloutVisLim = 0; - if (psstrmFinal) - { - for (islot = islotMin; islot < psstrmFinal->FinalSegLim(); ++islot) - { - int isloutRel = islot - islotMin; - - GrSlotState * pslot = psstrmFinal->SlotAt(islot); - pslot->SetPosPassIndex(isloutRel, false); - pslot->EnsureCacheForOutput(ptman); - GrSlotOutput * pslout = OutputSlot(isloutRel); - pslout->SetBufferPtr(m_prgnSlotVarLenBuf + (isloutRel * cnExtraPerSlot)); - pslout->InitializeOutputFrom(pslot); - pslout->SetBeforeAssoc(pslot->BeforeAssoc()); - pslout->SetAfterAssoc(pslot->AfterAssoc()); - if (pslot->HasComponents()) - pslot->SetComponentRefsFor(pslout); - Assert(pslot->HasComponents() == (pslout->NumberOfComponents() > 0)); - //if (pslot->HasClusterMembers()) - //{ - //Assert(pslot->HasClusterMembers() || pslot->ClusterRootOffset() == 0); - pslout->SetClusterXOffset(pslot->ClusterRootOffset() * -1); - pslout->SetClusterAdvance(pslot->ClusterAdvWidthFrom(0)); - - //} - - if (!ptman->IsWhiteSpace(pslot)) - m_isloutVisLim = islot + 1; - } - } - - // Set up the clusters. - for (islot = islotMin; islot < m_cslout; islot++) - { - GrSlotState * pslot = psstrmFinal->SlotAt(islot); - int isloutAdj = islot - islotMin; - int isloutBaseIndex = pslot->Base(psstrmFinal)->PosPassIndex(); - if (!pslot->IsBase()) - { - OutputSlot(isloutBaseIndex)->AddClusterMember(isloutBaseIndex, pslot->PosPassIndex()); - OutputSlot(isloutAdj)->SetClusterBase(isloutBaseIndex); - } - else if (pslot->HasClusterMembers() && pslot->IsBase()) - { - Assert(isloutBaseIndex == islot - islotMin); - OutputSlot(isloutAdj)->SetClusterBase(isloutBaseIndex); - } - } - - ///AssertValidClusters(psstrmFinal); - -#ifdef OLD_TEST_STUFF - if (ptman->GlyphTable() == NULL) - return; // test procedures -#endif // OLD_TEST_STUFF - - // CalcPositionsUpTo() called on final pass already from Table Mgr - - // Final output for draw routines. - - SetUpGlyphInfo(ptman, psstrmFinal, chwLB, nDirDepth, islotMin, cslot); - - //SetUpOutputArraysPlatform(ptman, chwLB, nDirDepth, islotMin, cslot); - -} - -/*---------------------------------------------------------------------------------------------- - Set up the data structures that represent the actual rendered glyphs for the new segment. -----------------------------------------------------------------------------------------------*/ -void Segment::SetUpGlyphInfo(GrTableManager * ptman, GrSlotStream * psstrmFinal, - gid16 chwLB, int nDirDepth, int islotMin, int cslot) -{ - //int paraDirLevel = (ptman->State()->ParaRightToLeft()) ? 1 : 0; - - m_cginf = 0; - - int islot; - for (islot = islotMin; islot < cslot; islot++) - { - if (psstrmFinal->SlotAt(islot)->GlyphID() != chwLB) - { - m_cginf++; - } - } - - // For right-to-left segments, the draw origin will be at the left side of the visible - // portion of the text. So if necessary, scoot everything left so that the invisible - // trailing white-space is to the left of the draw position. - Assert(m_dxsTotalWidth > -1); - Assert(m_dxsVisibleWidth > -1); - //float dxsInvisible = (m_fEndLine) ? m_dxsTotalWidth - m_dxsVisibleWidth : 0; - - m_prgginf = new GlyphInfo [m_cginf]; - - m_isloutGinf0 = -1; - int iginf = 0; - for (int islot = islotMin; islot < cslot; islot++) - { - GrSlotState * pslot = psstrmFinal->SlotAt(islot); - - if (pslot->GlyphID() == chwLB) - { - continue; // skip over linebreak markers - } - - int islout = islot - islotMin; - GrSlotOutput * pslout = OutputSlot(islout); - - if (m_isloutGinf0 == -1) - m_isloutGinf0 = islout; - - m_prgginf[iginf].m_pslout = pslout; - m_prgginf[iginf].m_islout = islout; - m_prgginf[iginf].m_pseg = this; - - // Fill in stuff in the output slot that is needed by the GlyphInfo object. - pslout->m_xsAdvanceX = pslot->GlyphMetricLogUnits(ptman, kgmetAdvWidth); - //pslout->m_ysAdvanceY = pslot->GlyphMetricLogUnits(ptman, kgmetAdvHeight); - //pslout->m_rectBB.top - // = pslot->YPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbTop); - //pslout->m_rectBB.bottom - // = pslot->YPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbBottom); - //pslout->m_rectBB.left - // = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbLeft); - //if (pslot->IsSpace(ptman)) - // pslout->m_rectBB.right - // = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetAdvWidth); - //else - // pslout->m_rectBB.right - // = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbRight); - - iginf++; - } - - if (cslot - islotMin == 0) - m_isloutGinf0 = 0; - if (m_isloutGinf0 == -1) - { - Assert(m_cginf == 0); - m_isloutGinf0 = ((OutputSlot(0)->IsInitialLineBreak()) ? 1 : 0); - } - - Assert(m_isloutGinf0 == 0 || m_isloutGinf0 == 1); -} - -/* -// OLD VERSION -void Segment::SetUpGlyphInfo(GrTableManager * ptman, GrSlotStream * psstrmFinal, gid16 chwLB, int nDirDepth, - int islotMin, int cslot) -{ - int paraDirLevel = (ptman->State()->ParaRightToLeft()) ? 1 : 0; - - m_cginf = 0; - int islot; - for (islot = islotMin; islot < cslot; islot++) - { - if (psstrmFinal->SlotAt(islot)->GlyphID() != chwLB) - m_cginf++; - } - - // For right-to-left segments, the draw origin will be at the left side of the visible - // portion of the text. So if necessary, scoot everything left so that the invisible - // trailing white-space is to the left of the draw position. - Assert(m_dxsTotalWidth > -1); - Assert(m_dxsVisibleWidth > -1); - float dxsInvisible = (m_fEndLine) ? m_dxsTotalWidth - m_dxsVisibleWidth : 0; - - m_prgginf = new GlyphInfo [m_cginf]; - - // Fill in glyph information structures. - m_isloutGinf0 = -1; - for (islot = islotMin; islot < cslot; islot++) - { - GrSlotState * pslot = psstrmFinal->SlotAt(islot); - - int islout = islot - islotMin; - if (pslot->GlyphID() == chwLB) - { - continue; // skip over linebreak markers - } - if (m_isloutGinf0 == -1) - m_isloutGinf0 = islout; - - GrSlotOutput * pslout = OutputSlot(islout); - - int iginf = islout - m_isloutGinf0; - GlyphInfo & ginf = m_prgginf[iginf]; - - ginf.glyphID = pslot->ActualGlyphForOutput(ptman); - ginf.pseudoGlyphID = pslot->GlyphID(); - if (ginf.glyphID == ginf.pseudoGlyphID) - ginf.pseudoGlyphID = 0; - - ginf.isSpace = pslot->IsSpace(ptman); - - ginf.origin = pslot->XPosition(); - ginf.yOffset = pslot->YPosition(); - - ginf.bbLeft = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbLeft); - ginf.bbTop = pslot->YPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbTop); - if (ginf.isSpace) - { - ginf.bbRight = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetAdvWidth); - } - else - { - ginf.bbRight = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbRight); - } - ginf.bbBottom = pslot->YPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbBottom); - - ginf.advanceWidth = pslot->GlyphMetricLogUnits(ptman, kgmetAdvWidth); - ginf.advanceHeight = 0; - - if (pslot->AttachTo() == 0) // not attached - ginf.attachedTo = -1; - else - ginf.attachedTo = pslot->AttachTo() + islot; - - ginf.directionality = byte(pslot->Directionality()); - if (pslot->DirLevel() == -1) - ginf.directionLevel = paraDirLevel; - else - ginf.directionLevel = byte(pslot->DirLevel()); - - //ginf.firstChar = LogicalSurfaceToUnderlying(islout, true); - //ginf.lastChar = LogicalSurfaceToUnderlying(islout, false); - - if (pslot->HasComponents()) - { - SetUpLigInfo(ptman, ginf, pslout); - } - else - { - ginf.numberOfComponents = 0; - ginf.components = NULL; - } - - ginf.insertBefore = pslot->InsertBefore(); - - ginf.maxStretch[0] = ptman->EmToLogUnits(pslot->JStretch()); - ginf.maxShrink[0] = ptman->EmToLogUnits(pslot->JShrink()); - ginf.stretchStep[0]= ptman->EmToLogUnits(pslot->JStep()); - ginf.justWidth[0] = ptman->EmToLogUnits(pslot->JWidth()); - ginf.justWeight[0] = pslot->JWeight(); - - ginf.measureStartOfLine = pslout->MeasureSolLogUnits(); - ginf.measureEndOfLine = pslout->MeasureEolLogUnits(); - } -} -*/ - -/*---------------------------------------------------------------------------------------------- - Set up the data structures that represent the components of a ligature glyph. -----------------------------------------------------------------------------------------------*/ -/* -void Segment::SetUpLigInfo(GrTableManager * ptman, GlyphInfo & ginf, GrSlotOutput * pslout) -{ - GrGlyphTable * pgtbl = ptman->GlyphTable(); - - int ccomp = pslout->NumberOfComponents(); - ginf.numberOfComponents = ccomp; - ginf.components = new ComponentBox[ccomp]; - for (int icomp = 0; icomp < ccomp; icomp++) - { - ComponentBox & cb = ginf.components[icomp]; - - // TODO: Rework ComponentIndexForGlyph to take slati rather than iForGlyph. - float xsLeft, xsRight, ysTop, ysBottom; - int slati = pslout->ComponentId(icomp); - int iForGlyph = pgtbl->ComponentIndexForGlyph(pslout->GlyphID(), slati); - pgtbl->ComponentBoxLogUnits(m_xysEmSquare, pslout->GlyphID(), iForGlyph, - m_mFontEmUnits, m_dysAscent, - &xsLeft, &ysTop, &xsRight, &ysBottom, false); - - cb.firstChar = pslout->UnderlyingComponent(icomp); - cb.lastChar = cb.firstChar; // TODO: is this supported? - cb.left = xsLeft; - cb.right = xsRight; - cb.top = ysTop; - cb.bottom = ysBottom; - } -} -*/ - - -// --------- OBSOLETE - replaced by GrTableManager::AdjustAssocsForOverlaps() --------------- -#if 0 - -/*---------------------------------------------------------------------------------------------- - Now that this segment is finished and has its associations set, handle any overlaps in - the associations between the previous segment and this one. - - Review: Think about whether we need to distinguish between before==kPosInfinity meaning - that the glyph is in the next segment vs. there is no association at all. - OBSOLETE -----------------------------------------------------------------------------------------------*/ -void Segment::AdjustForOverlapsWithPrevSeg() -{ - if (m_psegPrev) - { - AdjustBeforeArrayFromPrevSeg(); - m_psegPrev->AdjustAfterArrayFromNextSeg(); - } -} - -/*---------------------------------------------------------------------------------------------- - For any characters that are officially in this segment but are rendered in - the previous segment, initialize this segment's before array appropriately. Specifically, - set this segment's before value to something invalid--negative infinity, which will - never be overwritten. - OBSOLETE - replaced by AdjustAfterArrayFromNextSeg -----------------------------------------------------------------------------------------------*/ -void Segment::InitBeforeArrayFromPrevSeg() -{ - Assert(m_psegPrev); - - int ichwPrevMin = m_psegPrev->m_ichwMin; - int ichwPrevLim = m_psegPrev->m_ichwLim; -// int ichwPrevContextLim = -// m_psegPrev->m_ichwAssocsLim - m_psegPrev->m_ichwAssocsMin + m_psegPrev->m_ichwMin; - int cchwPrevAssocsMin = m_psegPrev->m_ichwAssocsMin; - int cchwPrevAssocsLim = m_psegPrev->m_ichwAssocsLim; - - // Loop over associations appended to the end of the previous segment; - // ichwPrev and ichwThis are relative to the start of their respective segments. - for (int ichwPrev = ichwPrevLim - ichwPrevMin; ichwPrev < cchwPrevAssocsLim; ++ichwPrev) - { - int ichwThis = ichwPrev - (ichwPrevLim - ichwPrevMin); // relative to start of this seg - if (m_psegPrev->m_prgisloutBefore[ichwPrev - cchwPrevAssocsMin] < kPosInfinity) - // The "before" value is in the previous segment, so make this segment's - // before value invalid. - m_prgisloutBefore[ichwThis - m_ichwAssocsMin] = kNegInfinity; - } -} - -/*---------------------------------------------------------------------------------------------- - For any associations that overlap between the previous segment and this, adjust - this segment's before array appropriately. Specifically, for any characters that - are rendered in both, set this segment's before value to something invalid. - OBSOLETE -----------------------------------------------------------------------------------------------*/ -void Segment::AdjustBeforeArrayFromPrevSeg() -{ - Assert(m_psegPrev); - - int ichwPrevMin = m_psegPrev->m_ichwMin; - int ichwPrevLim = m_psegPrev->m_ichwLim; - int ichwPrevAssocsMin = m_psegPrev->m_ichwAssocsMin; - int ichwPrevAssocsLim = m_psegPrev->m_ichwAssocsLim; - - // Loop over associations appended to the end of the previous segment - // (ie, rendered in the previous segment but officially in this one); - // ichwPrev and ichwThis are relative to the start of their respective segments. - for (int ichwPrev = ichwPrevLim - ichwPrevMin; ichwPrev < ichwPrevAssocsLim; ++ichwPrev) - { - int ichwThis = ichwPrev - (ichwPrevLim - ichwPrevMin); // relative to start of this seg - if (m_psegPrev->m_prgisloutBefore[ichwPrev - ichwPrevAssocsMin] < kPosInfinity) - // The "before" value is in the previous segment, so make this segment's - // before value invalid. - m_prgisloutBefore[ichwThis - m_ichwAssocsMin] = kNegInfinity; - } - // Loop over associations prepended to the start of this segment - // (ie, rendered in this segment but officially in the previous one); - // ichwPrev and ichwThis are relative to the start of their respective segments. - for (int ichwThis = m_ichwAssocsMin; ichwThis < 0; ++ichwThis) - { - int ichwPrev = ichwThis + (ichwPrevLim - ichwPrevMin); - if (m_psegPrev->m_prgisloutBefore[ichwPrev - ichwPrevAssocsMin] < kPosInfinity) - // The "before" value is in the previous segment, so make this segment's - // before value invalid. - m_prgisloutBefore[ichwThis - m_ichwAssocsMin] = kNegInfinity; - } -} - -/*---------------------------------------------------------------------------------------------- - For any associations that overlap between this segment and the next, adjust - this segment's after array appropriately. Specifically, for any characters that - are rendered in both, set this segment's after value to something invalid. - OBSOLETE -----------------------------------------------------------------------------------------------*/ -void Segment::AdjustAfterArrayFromNextSeg() -{ - Assert(m_psegNext); - - int ichwNextMin = m_psegNext->m_ichwMin; - int ichwNextContextMin = ichwNextMin + m_psegNext->m_ichwAssocsMin; - int ichwNextAssocsMin = m_psegNext->m_ichwAssocsMin; - - // Loop over associations prepended to the beginning of the following segment - // (ie, rendered in the next segment but officially in this one); - // ichwThis and ichwNext are relative to the start of their respective segments. - for (int ichwNext = cchwNextAssocsMin; ichwNext < 0; ++ichwNext) - { - int ichwThis = ichwNext + (m_ichwLim - m_ichwMin); - if (m_psegNext->m_prgisloutAfter[ichwNext - ichwNextAssocsMin] > kNegInfinity) - // The "after" value is in the next segment, so make this segment's - // after value invalid. - m_prgisloutAfter[ichwThis - m_ichwAssocsMin] = kPosInfinity; - } - - // Loop over associations appended to the end of this segment - // (ie, rendered in this segment but officially in the next one); - // ichwThis and ichwNext are relative to the start of their respective segments. - for (int ichwThis = m_ichwLim - m_ichwMin; ichwThis < m_cchwAssocsLim; ++ichwThis) - { - int ichwNext = ichwThis - (m_ichwLim - m_ichwMin); - if (m_psegNext->m_prgisloutAfter[ichwNext - ichwNextAssocsMin] > kNegInfinity) - // The "after" value is in the next segment, so make this segment's - // after value invalid. - m_prgisloutAfter[ichwThis - m_ichwAssocsMin] = kPosInfinity; - } -} - -#endif // -------------------------- END OF OBSOLETE CODE ---------------------------------- - - -/*---------------------------------------------------------------------------------------------- - Generate a list of all the glyphs that are attached to the base with the given index. - Note that we want to generate glyph indices, not slot indices. - - @param disloutCluster - indicates how far on either side of the base to look. -----------------------------------------------------------------------------------------------*/ -void Segment::ClusterMembersForGlyph(int isloutBase, int disloutCluster, - std::vector<int> & visloutRet) -{ - for (int islout = max(0, isloutBase - disloutCluster); - islout < min(m_cslout, isloutBase + disloutCluster + 1); - islout++) - { - if (islout == isloutBase) - continue; // don't include the base itself - GrSlotOutput * pslout = m_prgslout + islout; - if (pslout->ClusterBase() == isloutBase) - { - visloutRet.push_back(islout); - } - } -} - -/*---------------------------------------------------------------------------------------------- - Record an underlying-to-surface association mapping, based on the fact that there is - a corresponding surface-to-underlying association in the streams. - - @param ichwUnder - character index relative to the official beginning of the segment - @param islotSurface - surface glyph it maps to -----------------------------------------------------------------------------------------------*/ -void Segment::RecordSurfaceAssoc(int ichwUnder, int islotSurface, int nDir) -{ - // If we are recording an association across the line boundary, make sure there - // is space for it. - EnsureSpaceAtLineBoundaries(ichwUnder); - - // For left-to-right chars, the before-value is the minimum of the previous - // and new values, and the after-value is the maximum. - if (nDir % 2 == 0) - { - // left-to-right - m_prgisloutBefore[ichwUnder - m_ichwAssocsMin] = - min(m_prgisloutBefore[ichwUnder - m_ichwAssocsMin], islotSurface); - m_prgisloutAfter[ ichwUnder - m_ichwAssocsMin] = - max(m_prgisloutAfter[ ichwUnder - m_ichwAssocsMin], islotSurface); - } - else - { - // right-to-left: the before-value is the max and the after-value is the min - m_prgisloutBefore[ichwUnder - m_ichwAssocsMin] = - max(m_prgisloutBefore[ichwUnder - m_ichwAssocsMin], islotSurface); - m_prgisloutAfter[ ichwUnder - m_ichwAssocsMin] = - min(m_prgisloutAfter[ ichwUnder - m_ichwAssocsMin], islotSurface); - } - - m_prgpvisloutAssocs[ichwUnder - m_ichwAssocsMin]->push_back(islotSurface); -} - -/*---------------------------------------------------------------------------------------------- - Record an underlying-to-surface ligature mapping, based on the fact that there is - a component.ref attribute in the surface stream. Note that if there was a previous - ligature value there, it will be overwritten. - - @param ichwUnder - character index relative to the official beginning of the segment - @param islotSurface - surface glyph it maps to - @param iComponent - which component this glyph represents -----------------------------------------------------------------------------------------------*/ -void Segment::RecordLigature(int ichwUnder, int islotSurface, int iComponent) -{ - // If we are recording a mapping across the line boundary, make sure there - // is space for it. - EnsureSpaceAtLineBoundaries(ichwUnder); - - Assert(m_prgisloutLigature[ichwUnder - m_ichwAssocsMin] == kNegInfinity); - - m_prgisloutLigature[ichwUnder - m_ichwAssocsMin] = islotSurface; - Assert(iComponent < kMaxComponentsPerGlyph); - m_prgiComponent[ ichwUnder - m_ichwAssocsMin] = sdata8(iComponent); -} - -/*---------------------------------------------------------------------------------------------- - The given slot is one that is rendered in the previous segment. - If it is associated with a character officially in this segment, mark the - before-association kNegInfinity. - - @param ichwUnder - character index relative to the official beginning of the segment - @param islot - processed glyph it maps to -----------------------------------------------------------------------------------------------*/ -void Segment::MarkSlotInPrevSeg(int ichwUnder, int islot) -{ - if (ichwUnder >= m_ichwAssocsMin) - m_prgisloutBefore[ichwUnder - m_ichwAssocsMin] = kNegInfinity; -} - -/*---------------------------------------------------------------------------------------------- - The given slot is one that is rendered in the following segment. - If it is associated with a character officially in this segment, mark the - after-association kPosInfinity. - - @param ichwUnder - character index relative to the official beginning of the segment - @param islot - processed glyph it maps to -----------------------------------------------------------------------------------------------*/ -void Segment::MarkSlotInNextSeg(int ichwUnder, int islot) -{ - if (ichwUnder < m_ichwAssocsLim) - m_prgisloutAfter[ichwUnder - m_ichwAssocsMin] = kPosInfinity; -} - -/*---------------------------------------------------------------------------------------------- - If we are recording an association across the line boundary (in either direction), - make sure there is space for it. This involves adding space to the beginning or - the end of the association arrays, and adjusting the min and lim indicators. -----------------------------------------------------------------------------------------------*/ -void Segment::EnsureSpaceAtLineBoundaries(int ichwUnder) -{ - int cchwNewMin = min(ichwUnder, m_ichwAssocsMin); - int cchwNewLim = max(ichwUnder+1, m_ichwAssocsLim); - if (cchwNewMin < m_ichwAssocsMin || cchwNewLim > m_ichwAssocsLim) - { - // Make space either at the beginning or the end of the arrays. - int cchwPreAdd = m_ichwAssocsMin - cchwNewMin; - int cchwPostAdd = cchwNewLim - m_ichwAssocsLim; - - int * prgisloutTmp = m_prgisloutBefore; - m_prgisloutBefore = new int[cchwNewLim - cchwNewMin]; - std::copy(prgisloutTmp, prgisloutTmp + (m_ichwAssocsLim - m_ichwAssocsMin), - m_prgisloutBefore + cchwPreAdd); - delete[] prgisloutTmp; - - prgisloutTmp = m_prgisloutAfter; - m_prgisloutAfter = new int[cchwNewLim - cchwNewMin]; - std::copy(prgisloutTmp, prgisloutTmp + (m_ichwAssocsLim - m_ichwAssocsMin), - m_prgisloutAfter + cchwPreAdd); - delete[] prgisloutTmp; - - std::vector<int> ** ppvisloutTmp = m_prgpvisloutAssocs; - m_prgpvisloutAssocs = new std::vector<int> * [cchwNewLim - cchwNewMin]; - std::swap_ranges(m_prgpvisloutAssocs + cchwPreAdd, - m_prgpvisloutAssocs + cchwPreAdd + - (m_ichwAssocsLim - m_ichwAssocsMin), ppvisloutTmp); - delete[] ppvisloutTmp; - - prgisloutTmp = m_prgisloutLigature; - m_prgisloutLigature = new int[cchwNewLim - cchwNewMin]; - std::copy(prgisloutTmp, prgisloutTmp + (m_ichwAssocsLim - m_ichwAssocsMin), - m_prgisloutLigature + cchwPreAdd); - delete[] prgisloutTmp; - - sdata8 * prgiCompTmp = m_prgiComponent; - m_prgiComponent = new sdata8[cchwNewLim - cchwNewMin]; - std::copy(prgiCompTmp, prgiCompTmp + (m_ichwAssocsLim - m_ichwAssocsMin), - m_prgiComponent + cchwPreAdd); - delete[] prgiCompTmp; - - // Initialize new slots. - int i; - for (i = 0; i < cchwPreAdd; ++i) - { - m_prgisloutBefore[i] = kPosInfinity; - m_prgisloutAfter[i] = kNegInfinity; - m_prgpvisloutAssocs[i] = new std::vector<int>; - m_prgisloutLigature[i] = kNegInfinity; - m_prgiComponent[i] = 0; - } - for (i = m_ichwAssocsLim - m_ichwAssocsMin + cchwPreAdd; - i < m_ichwAssocsLim - m_ichwAssocsMin + cchwPreAdd + cchwPostAdd; - ++i) - { - m_prgisloutBefore[i] = kPosInfinity; - m_prgisloutAfter[i] = kNegInfinity; - m_prgpvisloutAssocs[i] = new std::vector<int>; - m_prgisloutLigature[i] = kNegInfinity; - m_prgiComponent[i] = 0; - } - m_ichwAssocsMin = cchwNewMin; - m_ichwAssocsLim = cchwNewLim; - } -} - -/*---------------------------------------------------------------------------------------------- - Return the given output slot. -----------------------------------------------------------------------------------------------*/ -GrSlotOutput * Segment::OutputSlot(int islout) -{ - return m_prgslout + islout; -} - -/*---------------------------------------------------------------------------------------------- - Set the rendering engine to the current one. -----------------------------------------------------------------------------------------------*/ -void Segment::SetEngine(GrEngine * pgreng) -{ - //if (m_preneng) - // m_preneng->DecRefCount(); - m_preneng = pgreng; - //if (m_preneng) - // m_preneng->IncRefCount(); -} - -/*---------------------------------------------------------------------------------------------- - Set the font. -----------------------------------------------------------------------------------------------*/ -void Segment::SetFont(Font * pfont) -{ - m_pfont = pfont->copyThis(); - -// m_fBold = pfont->bold(); -// m_fItalic = pfont->italic(); - // Note that we store the character height (which does not include the internal leading), - // not the actual font height, ie, ascent + descent. This is what is used in the LOGFONT. - pfont->getFontMetrics(NULL, NULL, &m_xysEmSquare); // m_xysEmSquare = m_pixHeight -} - -/*---------------------------------------------------------------------------------------------- - Switch the font out. - ??? Do we need to change the member variables too? -----------------------------------------------------------------------------------------------*/ -void Segment::SwitchFont(Font * pfont) -{ - m_pfont = pfont; -} - -/*---------------------------------------------------------------------------------------------- - Return the engine implementation if it is a proper GrEngine, or NULL otherwise. -----------------------------------------------------------------------------------------------*/ -GrEngine * Segment::EngineImpl() -{ - return m_preneng; -} - -/*---------------------------------------------------------------------------------------------- - Set the justification agent, in case this segment will ever need to be stretched - or shrunk. -----------------------------------------------------------------------------------------------*/ -void Segment::SetJustifier(IGrJustifier * pgjus) -{ - m_pgjus = pgjus; - //if (pgjus) - // pgjus->JustifierObject(&m_pgjus); - //else - // m_pgjus = NULL; -} - -/*---------------------------------------------------------------------------------------------- - Set the graphics object to use the base font. -----------------------------------------------------------------------------------------------*/ -//void Segment::SetToBaseFont(IGrGraphics * pgg) -//{ -// if (m_fUseSepBase) -// EngineImpl()->SwitchGraphicsFont(pgg, true); -//} - -/*---------------------------------------------------------------------------------------------- - Restore the graphics object to use the font that it originally had when passed in to - the interface method. -----------------------------------------------------------------------------------------------*/ -//void Segment::RestoreFont(IGrGraphics * pgg) -//{ -// if (m_fUseSepBase) -// EngineImpl()->SwitchGraphicsFont(pgg, false); -//} - -/*---------------------------------------------------------------------------------------------- - Given a logical surface location, return the underlying position (relative to the - beginning of the string). NOTE that we are returning the index of the closest charater - (plus an indication of which side the click was on), not a position between characters. - - @param islout - output slot - @param xsOffset - x coordinate of physical click, relative to left of glyph; - kPosInfinity means all the way to the right; - kNegInfinity means all the way to the left - @param ysOffset - y coordinate of physical click, relative to TOP of segment (NOT - upwards from baseline); kPosInfinity means all the way at - the top; kNegInfinity means all the way at the bottom - @param dxsGlyphWidth - width of glyph clicked on, or 0 if irrelevant - @param dysGlyphHeight - actually line height -- CURRENTLY NOT USED - @param pfAfter - return true if they clicked on trailing side; possibly NULL -----------------------------------------------------------------------------------------------*/ -int Segment::LogicalSurfaceToUnderlying(int islout, float xsOffset, float ysClick, - float dxsGlyphWidth, float dysGlyphHeight, bool * pfAfter) -{ - Assert(islout >= 0); - Assert(islout < m_cslout); - - GrSlotOutput * pslout = OutputSlot(islout); - bool fGlyphRtl = SlotIsRightToLeft(pslout); - - int dichw; - bool fAfter, fRight; - - float ysForGlyph = pslout->YPosition(); - - float dysFontAscent = m_dysFontAscent; - ////GrResult res = GetFontAscentSourceUnits(pgg, &dysFontAscent); - ////if (ResultFailed(res)) - //// THROW(WARN(res)); - dysFontAscent += m_dysXAscent; - - float dysOffset = ysClick - (m_dysAscent - dysFontAscent); // relative to top of 0-baseline text - - // If the slot has components, see if the offset falls within one of them. - - if (pslout->NumberOfComponents() > 0) - { - GrEngine * pgreng = EngineImpl(); - if (!pgreng) - goto LNotLigature; - - GrGlyphTable * pgtbl = pgreng->GlyphTable(); - - for (int icomp = 0; icomp < pslout->NumberOfComponents(); icomp++) - { - float xsLeft, xsRight, ysTop, ysBottom; - - // TODO: Rework ComponentIndexForGlyph to take slati rather than iForGlyph. - int slati = pslout->ComponentId(icomp); - int iForGlyph = pgtbl->ComponentIndexForGlyph(pslout->GlyphID(), slati); - if (!pgtbl->ComponentBoxLogUnits(m_xysEmSquare, pslout->GlyphID(), iForGlyph, - m_mFontEmUnits, m_dysAscent, - &xsLeft, &ysTop, &xsRight, &ysBottom)) - { - continue; // component not defined - } - Assert(xsLeft <= xsRight); - Assert(ysTop <= ysBottom); - if (xsOffset < xsLeft || xsOffset > xsRight) - continue; - if ((dysOffset - ysForGlyph) < ysTop || (dysOffset - ysForGlyph) > ysBottom) - continue; - - // Click was within the component's box. - - dichw = pslout->UnderlyingComponent(icomp); - Assert(m_ichwMin + dichw >= 0); - Assert(dichw < m_dichwLim); - - fRight = (xsOffset - xsLeft > xsRight - xsOffset); - fAfter = (fGlyphRtl) ? !fRight : fRight; - if (pfAfter) - *pfAfter = fAfter; - - Assert(GrCharStream::AtUnicodeCharBoundary(m_pgts, m_ichwMin + dichw)); - - return m_ichwMin + dichw; - } - } - -LNotLigature: - - // No relevant ligature component. - // If the x-offset is less than half way across, - // answer the before-association; otherwise answer the after-association. - - if (xsOffset == kPosInfinity) - fRight = true; - else if (xsOffset == kNegInfinity) - fRight = false; - else - fRight = (xsOffset > (dxsGlyphWidth / 2)); - - fAfter = (fGlyphRtl) ? !fRight : fRight; - - int diCharAdj = 0; - if (fAfter) - { - dichw = pslout->AfterAssoc(); - if (pfAfter) - *pfAfter = true; - // The following should not be necessary because of the way associations are set up: - //while (!GrCharStream::AtUnicodeCharBoundary(m_pgts, ichwBase + dichw + diCharAdj)) - // diCharAdj++; - } - else - { - dichw = pslout->BeforeAssoc(); - if (pfAfter) - *pfAfter = false; - // The following should not be necessary because of the way associations are set up: - //while (!GrCharStream::AtUnicodeCharBoundary(m_pgts, ichwBase + dichw + diCharAdj)) - // diCharAdj--; - } - - if (dichw == kNegInfinity || dichw == kPosInfinity) - return dichw; - - // This should be true because of the way the associations are set up: - Assert(GrCharStream::AtUnicodeCharBoundary(m_pgts, m_ichwMin + dichw)); // + diCharAdj)); - - return m_ichwMin + dichw + diCharAdj; -} - -/*--------------------------------------------------------------------------------------------*/ - -int Segment::LogicalSurfaceToUnderlying(int islout, bool fBefore) -{ - if (fBefore) - return LogicalSurfaceToUnderlying(islout, kNegInfFloat, kNegInfFloat); - else - return LogicalSurfaceToUnderlying(islout, kPosInfFloat, kPosInfFloat); -} - -/*---------------------------------------------------------------------------------------------- - Given a physical surface location (an index into the glyph boxes), - return the underlying position, relative to the beginning of the string. - - @param igbb - index of glyph - @param xsOffset - relative to left side of glyph - @param ysOffset - downwards from top of segment (not upwards from baseline) -----------------------------------------------------------------------------------------------*/ -int Segment::PhysicalSurfaceToUnderlying( - int iginf, float xsOffset, float ysOffset, - float dxsGlyphWidth, float dysGlyphHeight, bool * pfAfter) -{ - int islout = iginf + m_isloutGinf0; - return LogicalSurfaceToUnderlying(islout, xsOffset, ysOffset, - dxsGlyphWidth, dysGlyphHeight, pfAfter); -} - -/*--------------------------------------------------------------------------------------------*/ - -int Segment::PhysicalSurfaceToUnderlying(int iginf, bool fBefore) -{ - int islout = iginf + m_isloutGinf0; - bool fGlyphRtl = SlotIsRightToLeft(OutputSlot(islout)); - if (fBefore == fGlyphRtl) - return PhysicalSurfaceToUnderlying(iginf, kPosInfFloat, kPosInfFloat); - else - return PhysicalSurfaceToUnderlying(iginf, kNegInfFloat, kNegInfFloat); -} - -/*---------------------------------------------------------------------------------------------- - Given an underlying position (relative to the beginning of the string), - return the logical surface location (ignoring right-to-left). - NOTE that ichw indicates a CHARACTER, not a location between characters. So ichw = 3, - fBefore = false indicates a selection between characters 3 and 4. - For surrogates, it indicates the FIRST of the pair of 16-bit chars. -----------------------------------------------------------------------------------------------*/ -int Segment::UnderlyingToLogicalSurface(int ichw, bool fBefore) -{ - int ichwSegOffset = ichw - m_ichwMin; - - if (ichwSegOffset < m_ichwAssocsMin) - return kNegInfinity; // probably rendered in previous segment - - - // if the buffers aren't even allocated, then it probably means there - // wasn't room for any glyphs, so the following segment is most likely -// else if (ichwSegOffset >= m_ichwAssocsLim) - else if (ichwSegOffset >= m_ichwAssocsLim || !m_prgisloutBefore || !m_prgisloutAfter) - return kPosInfinity; // probably rendered in following segment - - else if (fBefore) - { - int isloutRet; - int ichw = ichwSegOffset; - // If no association has been made, loop forward to the next slot - // we are before. As a last resort, answer kPosInfinity, meaning we - // aren't before anything. - do - { - isloutRet = m_prgisloutBefore[ichw - m_ichwAssocsMin]; - do { ++ichw; } - while (!GrCharStream::AtUnicodeCharBoundary(m_pgts, ichw)); - } while (isloutRet == kPosInfinity && ichw < m_ichwAssocsLim); - return isloutRet; - } - else - { - int isloutRet; - int ichw = ichwSegOffset; - // If no association has been made, loop backward to the previous slot - // we are after. As a last resort, answer kNegInfinity, meaning we - // aren't after anything. - do - { - isloutRet = m_prgisloutAfter[ichw - m_ichwAssocsMin]; - do { --ichw; } - while (!GrCharStream::AtUnicodeCharBoundary(m_pgts, ichw)); - } while (isloutRet == kNegInfinity && ichw >= 0); - return isloutRet; - } - Assert(false); // should never reach here -} - -/*---------------------------------------------------------------------------------------------- - Given an underlying position (relative to the beginning of the string), - return the physical surface location, the index into m_prgginf. -----------------------------------------------------------------------------------------------*/ -int Segment::UnderlyingToPhysicalSurface(int ichw, bool fBefore) -{ - int islout = UnderlyingToLogicalSurface(ichw, fBefore); - return LogicalToPhysicalSurface(islout); -} - -/*---------------------------------------------------------------------------------------------- - Given a logical position (index into output slots), return the physical position, - the index into the list of glyphs (m_prgginf). -----------------------------------------------------------------------------------------------*/ -int Segment::LogicalToPhysicalSurface(int islout) -{ - if (islout == kNegInfinity || islout == kPosInfinity) - return islout; - - Assert(m_prgginf[islout - m_isloutGinf0].logicalIndex() == (unsigned)(islout - m_isloutGinf0)); - - return islout - m_isloutGinf0; -} - -/*---------------------------------------------------------------------------------------------- - Given an underlying position (relative to the beginning of the string), - return the physical surface locations of all the associated surface glyphs. - OBSOLETE -----------------------------------------------------------------------------------------------*/ -#if 0 -void Segment::UnderlyingToPhysicalAssocs(int ichw, std::vector<int> & viginf) -{ - int ichwSegOffset = ichw - m_ichwMin; - - if (ichwSegOffset < m_ichwAssocsMin) - return; // possibly rendered in previous segment - - else if (ichwSegOffset >= m_ichwAssocsLim) - return; // possibly rendered in following segment - - else - { - std::vector<int> * pvisloutTmp = &(m_prgvisloutAssocs[ichwSegOffset - m_ichwAssocsMin]); - - for (size_t i = 0; i < pvisloutTmp->size(); i++) - { - int islout = (*pvisloutTmp)[i]; - Assert(islout != kNegInfinity); - Assert(islout != kPosInfinity); - viginf.push_back(LogicalToPhysicalSurface(islout)); - } - } -} -#endif - -/*---------------------------------------------------------------------------------------------- - Given an underlying character position (relative to the beginning of the string), - return a pointer to the vector containing the logical surface locations of - all the associated surface glyphs. - - Returns an empty vector (not something containing infinities) if the character is - "invisible." -----------------------------------------------------------------------------------------------*/ -std::vector<int> Segment::UnderlyingToLogicalAssocs(int ichw) -{ - std::vector<int> vnEmpty; - vnEmpty.clear(); - Assert(vnEmpty.size() == 0); - - int ichwSegOffset = ichw - m_ichwMin; - - if (ichwSegOffset < m_ichwAssocsMin) - return vnEmpty; // probably rendered in previous segment - - else if (ichwSegOffset >= m_ichwAssocsLim) - return vnEmpty; // probably rendered in following segment - - else if (m_prgpvisloutAssocs[ichwSegOffset - m_ichwAssocsMin] == NULL) - { - // Create a vector using the before and after values. - std::vector<int> visloutRet; - int isloutBefore = m_prgisloutBefore[ichwSegOffset - m_ichwAssocsMin]; - int isloutAfter = m_prgisloutAfter[ichwSegOffset - m_ichwAssocsMin]; - if (isloutBefore != kPosInfinity && isloutBefore != kNegInfinity) - visloutRet.push_back(isloutBefore); - if (isloutAfter != kPosInfinity && isloutAfter != kNegInfinity && isloutBefore != isloutAfter) - { - visloutRet.push_back(isloutAfter); - } - return visloutRet; - } - else - { - std::vector<int> * pvisloutRet = m_prgpvisloutAssocs[ichwSegOffset - m_ichwAssocsMin]; - return *pvisloutRet; - } -} - -/*---------------------------------------------------------------------------------------------- - Given an underlying character position (relative to the beginning of the string), - return an index of a slot in this segment that can used to test things like - InsertBefore. Don't return kNegInfinity or kPosInfinity except as a last resort. -----------------------------------------------------------------------------------------------*/ -int Segment::UnderlyingToLogicalInThisSeg(int ichw) -{ - int isloutTest = kNegInfinity; - std::vector<int> vislout = UnderlyingToLogicalAssocs(ichw); - for (size_t iislout = 0; iislout < vislout.size(); iislout++) - { - isloutTest = vislout[iislout]; - if (isloutTest != kNegInfinity && isloutTest != kPosInfinity) - return isloutTest; - } - return isloutTest; -} - -/*---------------------------------------------------------------------------------------------- - Return true if the two characters map to exactly the same set of glyphs. -----------------------------------------------------------------------------------------------*/ -bool Segment::SameSurfaceGlyphs(int ichw1, int ichw2) -{ - std::vector<int> vislout1 = UnderlyingToLogicalAssocs(ichw1); - std::vector<int> vislout2 = UnderlyingToLogicalAssocs(ichw2); - - bool fRet = true; - if (vislout1.size() == 0 || vislout2.size() == 0) - fRet = false; - else if (vislout1.size() != vislout2.size()) - fRet = false; - else - { - for (size_t islout = 0; islout < vislout1.size(); islout++) - { - if (vislout1[islout] != vislout2[islout]) - { - fRet = false; - break; - } - } - } - return fRet; -} - -/*---------------------------------------------------------------------------------------------- - Return the direction level of the given character. -----------------------------------------------------------------------------------------------*/ -int Segment::DirLevelOfChar(int ichw, bool fBefore) -{ - if (m_twsh == ktwshOnlyWs) - return m_nDirDepth; - int islot = UnderlyingToLogicalSurface(ichw, fBefore); - if (islot == kNegInfinity || islot == kPosInfinity) - return 0; - int nDir = OutputSlot(islot)->DirLevel(); - if (nDir == -1) - // Not calculated: assume to be the top direction level. - nDir = TopDirLevel(); - - return nDir; -} - -/*---------------------------------------------------------------------------------------------- - Return whether the given character is right-to-left. -----------------------------------------------------------------------------------------------*/ -int Segment::CharIsRightToLeft(int ichw, bool fBefore) -{ - int nDir = DirLevelOfChar(ichw, fBefore); - return ((nDir % 2) != 0); -} - -/*---------------------------------------------------------------------------------------------- - Return whether the given slot is right-to-left. -----------------------------------------------------------------------------------------------*/ -int Segment::SlotIsRightToLeft(GrSlotOutput * pslout) -{ - if (m_twsh == ktwshOnlyWs) - return (m_nDirDepth % 2); - int nDir = pslout->DirLevel(); - if (nDir == -1) - nDir = TopDirLevel(); - return (nDir % 2); -} - -/*---------------------------------------------------------------------------------------------- - Check to make sure that the attachments are valid. Specifically, for every glyph that - is part of a cluster, all glyphs between that glyph and its root must (ultimately) have - that root glyph as one of its roots. - OBSOLETE -----------------------------------------------------------------------------------------------*/ -void Segment::AssertValidClusters(GrSlotStream * psstrm) -{ -#ifdef _DEBUG - for (int islot = 0; islot < psstrm->WritePos(); islot++) - { - GrSlotState * pslotThis = psstrm->SlotAt(islot); - GrSlotState * pslotRoot = pslotThis->AttachRoot(psstrm); - if (!pslotRoot) - continue; - Assert(pslotRoot != pslotThis); - - int inc = (pslotThis->PosPassIndex() > pslotRoot->PosPassIndex()) ? -1 : 1; - - for (int islot2 = pslotThis->PosPassIndex() + inc; - islot2 != pslotRoot->PosPassIndex(); - islot2 += inc) - { - GrSlotState * pslotMid = psstrm->SlotAt(islot2); - Assert(pslotMid->HasAsRoot(psstrm, pslotRoot)); - } - } -#endif // _DEBUG -} - -/*---------------------------------------------------------------------------------------------- - Return information about (editing) clusters as appropriate for Uniscribe, ie, consistent - with the ScriptShape funciton. - A cluster includes all attachments, all clumps of characters created by insert = false, - and clumps of reordered glyphs. - - prgiginfFirstOfCluster returns the first glyph of the cluster for each CHARACTER - (glyph indices returned are zero-based and refer to physical order--left-to-right, etc.). - pfClusterStart returns a flag for each GLYPH indicating whether it is the first (left-most) - of a cluster. - Both arrays are optional. - CORRECTION: for now we use strictly logical order. It's not clear whether physical - order is needed for right-to-left text or not. See note below. - - TODO: convert from GlyphInfo objects which are RTL. -----------------------------------------------------------------------------------------------*/ -GrResult Segment::getUniscribeClusters( - int * prgiginfFirstOfCluster, int cchMax, int * pcch, - bool * pfClusterStart, int cfMax, int * pcf) -{ - ChkGrOutPtr(pcch); - if (prgiginfFirstOfCluster) - ChkGrArrayArg(prgiginfFirstOfCluster, cchMax); - ChkGrOutPtr(pcf); - if (pfClusterStart) - ChkGrArrayArg(pfClusterStart, cfMax); - - GrResult res = kresOk; - - //SetUpGraphics(ichwBase, pgg, true); - - if (m_dxsWidth == -1) - ComputeDimensions(); - - Assert(m_dxsWidth >= 0); - Assert(m_dysAscent >= 0); - - if (pcch) - *pcch = m_dichwLim; - if (pcf) - *pcf = m_cginf; - if (cchMax < m_dichwLim) - { - if (cchMax == 0 && cfMax == 0) - res = kresFalse; // just asking for size information - else if (prgiginfFirstOfCluster || cchMax > 0) - res = kresInvalidArg; // not enough space - } - if (cfMax < m_cginf) - { - if (cchMax == 0 && cfMax == 0) - res = kresFalse; - else if (pfClusterStart || cfMax > 0) - res = kresInvalidArg; - } - if (res != kresOk) - { - //RestoreFont(pgg); - ReturnResult(res); - } - - // Generate a pair of arrays, indicating the first and last (logical) slots - // of the cluster for each character. Initially clusters are based just on - // character-to-glyph associations, but they expand as we process - // insert=false settings, attachments, and reordering. - - std::vector<int> visloutBefore; - std::vector<int> visloutAfter; - visloutBefore.resize(m_dichwLim); - visloutAfter.resize(m_dichwLim); - - int ich; - for (ich = 0; ich < m_dichwLim; ich++) - { - visloutBefore[ich] = m_prgisloutBefore[ich - m_ichwAssocsMin]; - visloutAfter[ich] = m_prgisloutAfter[ich - m_ichwAssocsMin]; - } - - if (m_dichwLim == 1) - { - // Only one character, therefore only one cluster. - visloutBefore[0] = m_isloutGinf0; - visloutAfter[0] = max(m_cginf - 1, 0) + m_isloutGinf0; - } - else - { - // Make all glyphs attached to each other part of a cluster, or glyphs where - // insertion is not allowed. - for (ich = 0; ich < m_dichwLim; ich++) - { - std::vector<int> vislout = UnderlyingToLogicalAssocs(ich + m_ichwMin); - - if (vislout.size() == 0) - { - // No glyphs represent this character. Merge it with the previous - // character. - visloutBefore[ich] = (ich == 0) ? visloutBefore[ich + 1] : visloutBefore[ich - 1]; - visloutAfter[ich] = (ich == 0) ? visloutAfter[ich + 1] : visloutAfter[ich - 1]; - continue; - } - - size_t iislout; - for (iislout = 0; iislout < vislout.size(); iislout++) - { - int islout = vislout[iislout]; - if (!m_prgslout[islout].InsertBefore()) - { - // This glyph does not allow insertion before it; make its character part - // of the same cluster as the previous character. - MergeUniscribeCluster(visloutBefore, visloutAfter, ich - 1, ich); -/* -+ // Keith Stribley's fix: -+ // NOTE: this is NOT always the same as the previous character, so -+ // check whether the next character actually has a glyph before this -+ // one -+ if ((ich == m_dichwLim - 1) || -+ (std::min(visloutBefore[ich + 1], visloutAfter[ich + 1]) > -+ std::max(visloutBefore[ich], visloutAfter[ich]))) -+ { -+ MergeUniscribeCluster(visloutBefore, visloutAfter, ich - 1, ich); -+ } -+ else -+ MergeUniscribeCluster(visloutBefore, visloutAfter, ich, ich + 1); -*/ - } - else if (m_prgslout[islout].ClusterBase() != -1 - && m_prgslout[islout].ClusterBase() != islout) - { - // This glyph is attached to something; make them part of the same cluster. - int isloutBase = m_prgslout[islout].ClusterBase(); - int ichBase = LogicalSurfaceToUnderlying(isloutBase, false) - m_ichwMin; - MergeUniscribeCluster(visloutBefore, visloutAfter, - ich, ichBase); - int ichBase1 = LogicalSurfaceToUnderlying(isloutBase, false) - m_ichwMin; - if (ichBase1 != ichBase) - MergeUniscribeCluster(visloutBefore, visloutAfter, - ich, ichBase1); - } - } - } - - // Handle reordering. Whenever the islout values get out of order, we need to - // merge into a single cluster. - for (ich = 0; ich < m_dichwLim - 1; ich++) - { - Assert(visloutBefore[ich] <= visloutAfter[ich]); - Assert(visloutBefore[ich] != kPosInfinity); - Assert(visloutBefore[ich] != kNegInfinity); - Assert(visloutAfter[ich] != kPosInfinity); - Assert(visloutAfter[ich] != kNegInfinity); - const int b1 = visloutBefore[ich]; - const int a1 = visloutAfter[ich]; - const int b2 = visloutBefore[ich + 1]; - const int a2 = visloutAfter[ich + 1]; - if (b1 == b2 && a1 == a2) - continue; // already a cluster - - if (std::min(b2, a2) <= std::max(b1, a1)) - { - MergeUniscribeCluster(visloutBefore, visloutAfter, ich, ich + 1); - } - } - } - - if (pfClusterStart) - { - // Initialize. - int iginf; - for (iginf = 0; iginf < m_cginf; iginf++) - pfClusterStart[iginf] = false; - } - - // To skip line-break slots; remember that the number of output slots equals the - // number of gbbs plus initial and/or final line-break slots if any. - // In this case the beginning of the first cluster indicates the first real glyph. - int isloutFirstReal = (m_dichwLim) ? ((m_fWsRtl)? visloutAfter[0] : visloutBefore[0]) : 0; - - // Kludge to make assertions below easier: - if (m_dichwLim > 0) - { - visloutBefore.push_back(visloutAfter.back() + 1); - visloutAfter.push_back(visloutAfter.back() + 1); - } - - // Convert (logical) slots to actual glyphs. - for (ich = 0; ich < m_dichwLim; ich++) - { - // NOTE: to treat the first of the cluster as the left-most, use visloutAfter for - // right-to-left situations. - - if (prgiginfFirstOfCluster) - prgiginfFirstOfCluster[ich] - = LogicalToPhysicalSurface((m_fWsRtl) ? visloutAfter[ich] : visloutBefore[ich]); - int clusterStartPos = ((m_fWsRtl) ? visloutAfter[ich] : visloutBefore[ich]) - isloutFirstReal; - if (pfClusterStart) - pfClusterStart[clusterStartPos] = true; - - Assert((visloutBefore[ich] == visloutBefore[ich + 1] && - visloutAfter[ich] == visloutAfter[ich + 1]) - || (visloutBefore[ich] <= visloutAfter[ich] && - visloutAfter[ich] < visloutBefore[ich + 1])); - } - - //RestoreFont(pgg); - - return kresOk; -} - - -// suppress GCC 4.3 warning for optimized min()/max() when called with (ich, ich+1) or similar -#pragma GCC diagnostic ignored "-Wstrict-overflow" - -/*---------------------------------------------------------------------------------------------- - Merge the given characters into the same Uniscribe cluster. This means merging any - intervening characters as well. -----------------------------------------------------------------------------------------------*/ -void Segment::MergeUniscribeCluster( - std::vector<int> & visloutBefore, std::vector<int> & visloutAfter, - int ich1, int ich2) -{ - int ichStartOrig = min(ich1, ich2); - int ichStopOrig = max(ich1, ich2); - - int isloutMin = visloutBefore[ichStopOrig]; - int isloutMax = visloutAfter[ichStartOrig]; - - int ichStart = ichStopOrig; - int ichStop = ichStartOrig; - // Find the beginning of the cluster. - while (ichStart > 0 && - (ichStart > ichStartOrig - || visloutBefore[ichStart - 1] >= visloutBefore[ichStopOrig] - || visloutBefore[ichStart - 1] == visloutBefore[ichStart])) - { - ichStart--; - isloutMin = std::min(isloutMin, visloutBefore[ichStart]); - isloutMax = std::max(isloutMax, visloutAfter[ichStart]); - } - // Find end of cluster. - while (ichStop < m_dichwLim - 1 && - (ichStop < ichStopOrig - || visloutAfter[ichStop + 1] <= visloutAfter[ichStartOrig] - || visloutAfter[ichStop + 1] == visloutAfter[ichStop])) - { - ichStop++; - isloutMin = std::min(isloutMin, visloutBefore[ichStop]); - isloutMax = std::max(isloutMax, visloutAfter[ichStop]); - } - - int ich; - for (ich = ichStart; ich <= ichStop; ich++) - { - visloutBefore[ich] = isloutMin; - visloutAfter[ich] = isloutMax; - } -} - -/*---------------------------------------------------------------------------------------------- - Return information about the positioning of glyphs as appropriate for Uniscribe. - The advance widths returned are the natural ones (what would be applied if no smart - rendering were happening), and the x-offsets are the difference between the - natural location of the glyph and what is produced by Graphite. The y-offset - is the same as GetGlyphsAndPositions. - - This is an experimental method. Its behavior may change signficantly in the future. -----------------------------------------------------------------------------------------------*/ -/* -GrResult Segment::GetUniscribePositions( - Rect rs, Rect rd, int cgidMax, int *pcgidRet, - float * prgxd, float * prgyd, float * prgdxdAdv) -{ - ChkGrOutPtr(pcgidRet); - ChkGrArrayArg(prgxd, cgidMax); - ChkGrArrayArg(prgyd, cgidMax); - ChkGrArrayArg(prgdxdAdv, cgidMax); - - GrResult res; - - //SetUpGraphics(ichBase, pgg, true); - - Assert(m_dxsWidth >= 0); - Assert(m_dysAscent >= 0); - - *pcgidRet = m_cginf; - if (cgidMax < m_cginf) - { - res = (cgidMax == 0) ? kresFalse : kresInvalidArg; - //RestoreFont(pgg); - ReturnResult(res); - } - - if (m_dxsWidth < 0) - ComputeDimensions(); - - float * rgxdTmp = new float[cgidMax]; - float * rgdxdAdvTmp = new float[cgidMax]; - res = GetGlyphsAndPositions(rs, rd, cgidMax, pcgidRet, - NULL, rgxdTmp, prgyd, rgdxdAdvTmp); - if (ResultFailed(res)) - { - delete[] rgxdTmp; - delete[] rgdxdAdvTmp; - //RestoreFont(pgg); - ReturnResult(res); - } - - float xdLeft = SegmentPainter::ScaleX(0, rs, rd); - float xdXPosNatural = xdLeft; - for (int iginf = 0; iginf < *pcgidRet; iginf++) - { - int islout = iginf + m_isloutGinf0; - GrSlotOutput * pslout = OutputSlot(islout); - float dxsAdvNatural = pslout->AdvanceXMetric(); - float dxdAdvNatural = SegmentPainter::ScaleX(dxsAdvNatural, rs, rd) - xdLeft; - prgdxdAdv[iginf] = dxdAdvNatural; - prgxd[iginf] = rgxdTmp[iginf] - xdXPosNatural; - - xdXPosNatural += dxdAdvNatural; - } - - delete[] rgxdTmp; - delete[] rgdxdAdvTmp; - - //RestoreFont(pgg); - - ReturnResult(res); - -} -*/ - -/*---------------------------------------------------------------------------------------------- - Return information about the positioning of glyphs as appropriate for Uniscribe. - The advance widths returned are the natural ones (what would be applied if no smart - rendering were happening), and the x-offsets are the difference between the - natural location of the glyph and what is produced by Graphite. The y-offset - is the same as GetGlyphsAndPositions. - - This is an experimental method. Its behavior may change signficantly in the future. -----------------------------------------------------------------------------------------------*/ -/* -GrResult Segment::GetUniscribeGlyphsAndPositions( - Rect rs, Rect rd, int cgidMax, int *pcgidRet, utf16 * prgchGlyphs, - float * prgxd, float * prgyd, float * prgdxdAdv) -{ - ChkGrOutPtr(pcgidRet); - ChkGrArrayArg(prgxd, cgidMax); - ChkGrArrayArg(prgyd, cgidMax); - ChkGrArrayArg(prgdxdAdv, cgidMax); - - GrResult res; - - //SetUpGraphics(ichBase, pgg, true); - - Assert(m_dxsWidth >= 0); - Assert(m_dysAscent >= 0); - - *pcgidRet = m_cginf; - if (cgidMax < m_cginf) - { - res = (cgidMax == 0) ? kresFalse : kresInvalidArg; - //RestoreFont(pgg); - ReturnResult(res); - } - - if (m_dxsWidth < 0) - ComputeDimensions(); - - float * rgxdTmp = new float[cgidMax]; - float * rgdxdAdvTmp = new float[cgidMax]; - res = GetGlyphsAndPositions(rs, rd, cgidMax, pcgidRet, - prgchGlyphs, rgxdTmp, prgyd, rgdxdAdvTmp); - if (ResultFailed(res)) - { - delete[] rgxdTmp; - delete[] rgdxdAdvTmp; - //RestoreFont(pgg); - ReturnResult(res); - } - - float xdLeft = SegmentPainter::ScaleX(0, rs, rd); - float xdXPosNatural = xdLeft; - for (int iginf = 0; iginf < *pcgidRet; iginf++) - { - int islout = iginf + m_isloutGinf0; - GrSlotOutput * pslout = OutputSlot(islout); - float dxsAdvNatural = pslout->AdvanceXMetric(); - float dxdAdvNatural = SegmentPainter::ScaleX(dxsAdvNatural, rs, rd) - xdLeft; - prgdxdAdv[iginf] = dxdAdvNatural; - prgxd[iginf] = rgxdTmp[iginf] - xdXPosNatural; - - xdXPosNatural += dxdAdvNatural; - } - - delete[] rgxdTmp; - delete[] rgdxdAdvTmp; - - //RestoreFont(pgg); - - ReturnResult(res); -} -*/ - -/*---------------------------------------------------------------------------------------------- - Return the visual box for the given ligature component. Return (0,0,0,0) if the component - is not defined. -----------------------------------------------------------------------------------------------*/ -Rect Segment::ComponentRect(GrSlotOutput * pslout, int icomp) -{ - Rect rectRet; - rectRet.top = rectRet.bottom = rectRet.left = rectRet.right = 0; - if (icomp < 0 || icomp > pslout->NumberOfComponents()) - return rectRet; - - GrEngine * pgreng = EngineImpl(); - if (!pgreng) - return rectRet; - GrGlyphTable * pgtbl = pgreng->GlyphTable(); - if (!pgtbl) - return rectRet; - - float xsLeft, xsRight, ysTop, ysBottom; - - // TODO: Rework ComponentIndexForGlyph to take slati rather than iForGlyph. - int slati = pslout->ComponentId(icomp); - int iForGlyph = pgtbl->ComponentIndexForGlyph(pslout->GlyphID(), slati); - if (!pgtbl->ComponentBoxLogUnits(m_xysEmSquare, pslout->GlyphID(), iForGlyph, - m_mFontEmUnits, m_dysAscent, - &xsLeft, &ysTop, &xsRight, &ysBottom, - false)) // origin is baseline - { - return rectRet; - } - rectRet.top = ysTop; - rectRet.bottom = ysBottom; - rectRet.left = xsLeft; - rectRet.right = xsRight; - - return rectRet; -} - -/*---------------------------------------------------------------------------------------------- - Shift the glyphs physically by the given amount. This happens when a right-to-left - segment is changed from being end-of-line to not, so we have to account for the fact - that the trailing white-space was previous invisible but is now visible. -----------------------------------------------------------------------------------------------*/ -void Segment::ShiftGlyphs(float dxsShift) -{ - for (int islout = 0; islout < m_cslout; islout++) - { - GrSlotOutput * pslout = OutputSlot(islout); - pslout->AdjustPosXBy(dxsShift); - } - - //ShiftGlyphsPlatform(dxsShift); -} - -/*---------------------------------------------------------------------------------------------- - Find the glyph that best matches the given click location. - - @param xsClick - relative to start of segment - @param ysClick - relative to segment baseline -----------------------------------------------------------------------------------------------*/ -int Segment::GlyphHit(float xsClick, float ysClick) -{ - float xsLeft = kPosInfFloat; - float xsRight = kNegInfFloat; - - int iginf; - for (iginf = 0; iginf < m_cginf; iginf++) - { - GlyphInfo * pginf = m_prgginf + iginf; - xsLeft = min(xsLeft, pginf->origin()); - xsRight = max(xsRight, pginf->origin() + pginf->advanceWidth()); - } - - if (xsClick < xsLeft) - return m_fWsRtl ? m_cginf - 1 : 0; - else if (xsClick > xsRight) - return m_fWsRtl ? 0 : m_cginf - 1; - - int iginfHit; - std::vector<int> viginfNear; - std::vector<int> viginfHit; - std::vector<int> viginfInside; - - // Find glyph which might contain click point. - - for (iginfHit = m_cginf; iginfHit-- > 0; ) - { - if (m_fWsRtl) - { - if (m_prgginf[iginfHit].bb().right >= xsClick) - break; - } - else - { - if (m_prgginf[iginfHit].bb().left <= xsClick) - break; - } - } - if (iginfHit < 0) // click within lsb of first glyph - { - return 0; - } - - // Find all BB that OVERLAP the click point (bb.left < XClick < bb.right). - for (iginf = iginfHit; iginf >= 0; iginf--) - { - Rect rectBB = m_prgginf[iginf].bb(); - if (rectBB.left <= xsClick && xsClick <= rectBB.right) - { - viginfNear.push_back(iginf); - } - } - - // Find all BB that CONTAIN the click point (considering the click's Y coor too). - int iiginf; - for (iiginf = 0; iiginf < (int)viginfNear.size(); iiginf++) - { - Rect rectBB = m_prgginf[viginfNear[iiginf]].bb(); - if (rectBB.bottom <= ysClick && ysClick <= rectBB.top) - { - viginfHit.push_back(viginfNear[iiginf]); - } - } - - if (viginfNear.size() > 2 && viginfHit.size() == 0) - { - // No hit along y-axis; find the closest thing. - float dy = float(10000000.0); - for (int iiginf2 = 0; iiginf2 < (int)viginfNear.size(); iiginf2++) - { - Rect rectBB = m_prgginf[viginfNear[iiginf2]].bb(); - if (fabsf(rectBB.top - ysClick) < dy) - { - dy = fabsf(rectBB.top - ysClick); - viginfHit.clear(); - viginfHit.push_back(viginfNear[iiginf2]); - } - if (fabsf(rectBB.bottom - ysClick) < dy) - { - dy = fabsf(rectBB.bottom - ysClick); - viginfHit.clear(); - viginfHit.push_back(viginfNear[iiginf2]); - } - } - } - - // Find all BB for which the click is within their advance width, if any. - for (iiginf = 0; iiginf < (int)viginfHit.size(); iiginf++) - { - //Rect rectBB = m_prgginf[viginfHit[iiginf]].bb(); -- ?? this tests the bounding box again :-/ - //if (rectBB.left <= xsClick && xsClick <= rectBB.right) - gr::GlyphInfo * pginf = m_prgginf + viginfHit[iiginf]; - if (pginf->advanceWidth() == 0 // advance width is irrelevant - || (pginf->origin() < xsClick && xsClick <= pginf->origin() + pginf->advanceWidth())) - { - viginfInside.push_back(viginfHit[iiginf]); - } - } - - // If no BB coincides in any way with the click point, take the BB whose leading edge - // is closest to the click point. - // There could be more than one BB with the same leading x coor. - if (viginfHit.size() == 0 && viginfNear.size() == 0 && viginfInside.size() == 0) - { - float xsLeading; - if (iginfHit + 1 == m_cginf) - { - viginfNear.push_back(iginfHit); - } - else if (!m_fWsRtl) - { - // Left-to-right: - xsLeading = m_prgginf[iginfHit + 1].bb().left; - for (iginf = iginfHit + 1; iginf < m_cginf; iginf++) - { - if (m_prgginf[iginf].bb().left == xsLeading) - viginfNear.push_back(iginf); - } - } - else - { - // Right-to-left: - xsLeading = m_prgginf[iginfHit].bb().right; - for (iginf = iginfHit; iginf < m_cginf; iginf++) - { - if (m_prgginf[iginf].bb().right == xsLeading) - viginfNear.push_back(iginf); - } - } - } - - Assert(viginfNear.size()); - - int iginfLoc; - - // Select the BB based on its leading edge, offset from baseline, position in final pass. - if (viginfInside.size()) - iginfLoc = SelectBb(viginfInside, m_fWsRtl); - else if (viginfHit.size()) - iginfLoc = SelectBb(viginfHit, m_fWsRtl); - else - iginfLoc = SelectBb(viginfNear, m_fWsRtl); - - return iginfLoc; -} - -/*---------------------------------------------------------------------------------------------- - Select the bounding box we will use for a mouse hit. - First select any glyph with a significantly smaller bounding box. - Then, select the BB with the left-most (LTR) or right-most (RTL) edge. - If more than one BB has same edge of interest, select the one that is closest to the - the baseline. - If that is a tie, select the one with the lowest islout. - - @param vigbb - list of indexes into m_prggbb - @param fRTL - writing system direction -----------------------------------------------------------------------------------------------*/ -int Segment::SelectBb(std::vector<int> & viginf, bool fRTL) -{ - if (!viginf.size()) - { - Assert(false); - return -1; - } - - if (viginf.size() == 1) - return viginf[0]; - - // Find a glyph that has a signficantly smaller bounding box. - // The idea is that it is going to be harder to hit than the bigger glyph. - float smallestArea = float(1000000000.0); - float largestArea = 0.0; - size_t iiginfSmallest = 0; - size_t iiginf; - for (iiginf = 0; iiginf < viginf.size(); iiginf++) - { - gr::GlyphInfo * pginf = m_prgginf + viginf[iiginf]; - Rect rectBB = pginf->bb(); - float thisArea = (rectBB.right - rectBB.left) * (rectBB.top - rectBB.bottom); - if (smallestArea > thisArea) - { - smallestArea = thisArea; - iiginfSmallest = iiginf; - } - largestArea = max(largestArea, thisArea); - } - if (smallestArea * 2.0 < largestArea) - return viginf[iiginfSmallest]; - - // Find appropriate x coor of leading edge. - float xsLeading; - if (!fRTL) - xsLeading = m_prgginf[viginf[0]].bb().left; - else - xsLeading = m_prgginf[viginf[0]].bb().right; - - for (iiginf = 1; iiginf < viginf.size(); iiginf++) - { - Rect rectBB = m_prgginf[viginf[iiginf]].bb(); - if (!fRTL) - xsLeading = min(xsLeading, rectBB.left); - else - xsLeading = max(xsLeading, rectBB.right); - } - - // Find BBs with the leading edge. - std::vector<int> viginfSameEdge; - for (iiginf = 0; iiginf < viginf.size(); iiginf++) - { - Rect rectBB = m_prgginf[viginf[iiginf]].bb(); - if (!fRTL) - { - if (rectBB.left == xsLeading) - viginfSameEdge.push_back(viginf[iiginf]); - } - else - { - if (rectBB.right == xsLeading) - viginfSameEdge.push_back(viginf[iiginf]); - } - } - - if (viginfSameEdge.size() == 1) - return viginfSameEdge[0]; - - // Find minimum distance from baseline. - float ysMin = fabsf(m_prgginf[viginfSameEdge[0]].yOffset()); - for (iiginf = 1; iiginf < viginfSameEdge.size(); iiginf++) - { - float ysThis = fabsf(m_prgginf[viginfSameEdge[iiginf]].yOffset()); - ysMin = min(ysMin, ysThis); - } - - // Find BBs with minimum distance from baseline. - std::vector<int> viginfSameY; - for (iiginf = 0; iiginf < viginfSameEdge.size(); iiginf++) - { - if (fabsf(m_prgginf[viginfSameEdge[iiginf]].yOffset()) == ysMin) - viginfSameY.push_back(viginfSameEdge[iiginf]); - } - - if (viginfSameY.size() == 1) - return viginfSameY[0]; - - // Find minimum index of current candidates. - int islout = m_prgginf[viginfSameY[0]].logicalIndex(); - for (iiginf = 1; iiginf < viginfSameY.size(); iiginf++) - { - int isloutThis = m_prgginf[viginfSameY[iiginf]].logicalIndex(); - islout = min(islout, isloutThis); - } - - // Find BB with minimum islout - islout should be unique for all glyphs. - for (iiginf = 0; iiginf < viginfSameY.size(); iiginf++) - { - if (m_prgginf[viginfSameY[iiginf]].logicalIndex() == (unsigned)islout) - return viginfSameY[iiginf]; - } - - Assert(false); - return -1; // needed to stop compiler warning -} - -/*---------------------------------------------------------------------------------------------- - Return the right-most glyph on the physical surface. If there are ties, it will - prefer the one that is logically closest to the edge. -----------------------------------------------------------------------------------------------*/ -int Segment::RightMostGlyph() -{ - float xsRight = kNegInfFloat; - int iginfRet = -1; - for (int iginf = 0; iginf < m_cginf; iginf++) - { - float xsThis = m_prgginf[iginf].bb().right; - // For RTL, we prefer the glyph that is logically first; for LTR we prefer logically last. - if (xsThis > xsRight || (!m_fWsRtl && xsRight == xsThis)) - { - xsRight = xsThis; - iginfRet = iginf; - } - } - return iginfRet; -} - -/*---------------------------------------------------------------------------------------------- - Return the left-most glyph on the physical surface. If there are ties, it will - prefer the one that is logically closest to the edge. -----------------------------------------------------------------------------------------------*/ -int Segment::LeftMostGlyph() -{ - float xsLeft = kPosInfFloat; - int iginfRet = -1; - for (int iginf = 0; iginf < m_cginf; iginf++) - { - float xsThis = m_prgginf[iginf].bb().left; - // For RTL, we prefer the glyph that is logically last; for LTR we prefer logically first. - if (xsThis < xsLeft || (m_fWsRtl && xsLeft == xsThis)) - { - xsLeft = xsThis; - iginfRet = iginf; - } - } - return iginfRet; -} - -/*---------------------------------------------------------------------------------------------- - Convert from em-units to logical units. -----------------------------------------------------------------------------------------------*/ -float Segment::EmToLogUnits(int m) -{ - return GrEngine::GrIFIMulDiv(m, m_xysEmSquare, m_mFontEmUnits); -} - -/*---------------------------------------------------------------------------------------------- - Return the line-break pseudo glyph ID. -----------------------------------------------------------------------------------------------*/ -gid16 Segment::LBGlyphID() -{ - return m_preneng->LBGlyphID(); -} - -} // namespace gr diff --git a/Build/source/libs/graphite-engine/src/segment/SegmentAux.cpp b/Build/source/libs/graphite-engine/src/segment/SegmentAux.cpp deleted file mode 100644 index 9191e8724d5..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/SegmentAux.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/*--------------------------------------------------------------------*//*:Ignore this sentence. -Copyright (C) 2005 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: SegmentAux.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Implements auxiliary class that work with Segment: - - GlyphInfo - - GlyphIterator - - LayoutEnvironment --------------------------------------------------------------------------------*//*:End Ignore*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" -#ifdef _MSC_VER -#pragma hdrstop -#endif -// any other headers (not precompiled) -#ifndef _WIN32 -#include <stdlib.h> -#endif - -#undef THIS_FILE -DEFINE_THIS_FILE - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -namespace gr -{ - -//:>******************************************************************************************** -//:> GlyphInfo methods -//:>******************************************************************************************** - -gid16 GlyphInfo::glyphID() -{ - return m_pslout->m_chwActual; -} - -gid16 GlyphInfo::pseudoGlyphID() -{ - if (m_pslout->m_chwActual == m_pslout->m_chwGlyphID) - return 0; // not a pseudo-glyph - return m_pslout->m_chwGlyphID; -} - -bool GlyphInfo::isAttached() const throw() -{ - return m_pslout->IsPartOfCluster(); -} - -gr::GlyphIterator GlyphInfo::attachedClusterBase() const throw() -{ - const int islout = m_pslout->ClusterBase(); - - // Since we are not passing an array, the constructor expects a ginf index, not a slout index. - return GlyphIterator(*m_pseg, ((islout >= 0) ? islout : m_islout) - m_pseg->m_isloutGinf0); -} - -float GlyphInfo::attachedClusterAdvance() const throw() -{ - return m_pslout->ClusterAdvance(); -} - -std::pair<gr::GlyphSetIterator, gr::GlyphSetIterator> GlyphInfo::attachedClusterGlyphs() const -{ - std::vector<int> visloutClusterMembers; - m_pslout->ClusterMembers(m_pseg, m_islout, visloutClusterMembers); - RcVector * qvislout = new RcVector(visloutClusterMembers); - return std::make_pair( - GlyphSetIterator(*m_pseg, 0, qvislout), - GlyphSetIterator(*m_pseg, visloutClusterMembers.size(), qvislout)); -} - -size_t GlyphInfo::logicalIndex() -{ - if (m_pseg->OutputSlot(0)->IsLineBreak()) - return m_islout - 1; - else - return m_islout; -} - -float GlyphInfo::origin() -{ - return m_pslout->XPosition(); -} - -float GlyphInfo::advanceWidth() // logical units -{ - return m_pslout->m_xsAdvanceX; -} - -float GlyphInfo::advanceHeight() // logical units; zero for horizontal fonts -{ - Font & font = m_pseg->getFont(); - return m_pslout->GlyphMetricLogUnits(&font, kgmetAdvHeight); -} - -float GlyphInfo::yOffset() -{ - return m_pslout->YPosition(); -} - -Rect GlyphInfo::bb() // logical units -{ - return m_pslout->BoundingBox(m_pseg->getFont()); -} - -bool GlyphInfo::isSpace() -{ - return m_pslout->IsSpace(); -} - -// first char associated with this glyph, relative to start of the text-source -toffset GlyphInfo::firstChar() -{ - return m_pseg->LogicalSurfaceToUnderlying(m_islout, true); -} - -// last char associated with this glyph, relative to start of the text-source -toffset GlyphInfo::lastChar() -{ - return m_pseg->LogicalSurfaceToUnderlying(m_islout, false); -} - -unsigned int GlyphInfo::directionality() -{ - return m_pslout->Directionality(); -} - -// Embedding depth -unsigned int GlyphInfo::directionLevel() -{ - return m_pslout->DirLevel(); -} - -bool GlyphInfo::insertBefore() -{ - return m_pslout->InsertBefore(); -} - -int GlyphInfo::breakweight() -{ - return m_pslout->BreakWeight(); -} - -float GlyphInfo::maxStretch(size_t level) -{ - return m_pslout->MaxStretch(m_pseg, (int)level); -} - -float GlyphInfo::maxShrink(size_t level) -{ - return m_pslout->MaxShrink(m_pseg, (int)level); -} - -float GlyphInfo::stretchStep(size_t level) -{ - return m_pslout->StretchStep(m_pseg, (int)level); -} - -byte GlyphInfo::justWeight(size_t level) -{ - return byte(m_pslout->JustWeight((int)level)); -} - -float GlyphInfo::justWidth(size_t level) -{ - return m_pslout->JustWidth(m_pseg, (int)level); -} - -float GlyphInfo::measureStartOfLine() -{ - return m_pslout->MeasureSolLogUnits(m_pseg); -} - -float GlyphInfo::measureEndOfLine() -{ - return m_pslout->MeasureEolLogUnits(m_pseg); -} - -size_t GlyphInfo::numberOfComponents() -{ - return m_pslout->NumberOfComponents(); -} - -Rect GlyphInfo::componentBox(size_t icomp) -{ - return m_pseg->ComponentRect(m_pslout, icomp); -} - -toffset GlyphInfo::componentFirstChar(size_t icomp) -{ - Assert((int)icomp < m_pslout->NumberOfComponents()); - return m_pslout->UnderlyingComponent(icomp) + m_pseg->startCharacter(); -} -toffset GlyphInfo::componentLastChar(size_t icomp) -{ - Assert((int)icomp < m_pslout->NumberOfComponents()); - return m_pslout->UnderlyingComponent(icomp) + m_pseg->startCharacter(); -} - -bool GlyphInfo::erroneous() -{ - return m_pseg->Erroneous(); -} - - -//:>******************************************************************************************** -//:> GlyphIterator methods -//:>******************************************************************************************** - -// Constructor -GlyphIterator::GlyphIterator(Segment & seg, size_t iginf) -: m_pginf(seg.m_prgginf + iginf) -{} - -// Copy constructor. -// Check if the incoming iterator is null, as we cannot dereference -// it to get the segment, and create a null GlyphIterator. -// Technically this might better be an assert as converting a null -// GlyphSetIterator into a null GlyphIterator is pointless and suggests -// some kind of error. -GlyphIterator::GlyphIterator(const GlyphSetIterator & sit) -: m_pginf((sit == GlyphSetIterator()) - ? 0 - : sit->segment().m_prgginf + sit->logicalIndex()) -{} - -/*---------------------------------------------------------------------------------------------- - Dereference the iterator, returning a GlyphInfo object. -----------------------------------------------------------------------------------------------*/ - -GlyphSetIterator::reference GlyphSetIterator::operator*() const -{ - assert(m_pseg != 0); - assert(m_vit != std::vector<int>::const_iterator()); - // in the case of a non-contiguous list - return m_pseg->m_prgginf[(*m_vit) - m_pseg->m_isloutGinf0]; -} - - -} // namespace gr diff --git a/Build/source/libs/graphite-engine/src/segment/TestFSM.cpp b/Build/source/libs/graphite-engine/src/segment/TestFSM.cpp deleted file mode 100644 index 6dad1dc9dc8..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/TestFSM.cpp +++ /dev/null @@ -1,3416 +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: TestFSM.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Hard-coded FSMs for test procedures. --------------------------------------------------------------------------------*//*:End Ignore*/ - -//:Ignore - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" - -#ifdef _MSC_VER -#pragma hdrstop -#endif -#undef THIS_FILE -DEFINE_THIS_FILE - -#ifdef OLD_TEST_STUFF - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -namespace gr -{ - -//:>******************************************************************************************** -//:> Methods -//:>******************************************************************************************** - -#ifndef _DEBUG - -bool GrLineBreakPass::RunTestRules(GrTableManager * ptman, int ruln, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - return false; -} - -bool GrSubPass::RunTestRules(GrTableManager * ptman, int ruln, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - return false; -} - -bool GrPosPass::RunTestRules(GrTableManager * ptman, int ruln, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - return false; -} -#endif // !_DEBUG - - -#ifdef _DEBUG - -/*---------------------------------------------------------------------------------------------- - Call the appropriate test function. -----------------------------------------------------------------------------------------------*/ - -bool GrLineBreakPass::RunTestRules(GrTableManager * ptman, int ruln, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - return false; -} - -bool GrSubPass::RunTestRules(GrTableManager * ptman, int ruln, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - if (m_staBehavior == "SimpleFSM") - return RunSimpleFSMTest(ptman, ruln, psstrmInput, psstrmOutput); - else if (m_staBehavior == "RuleAction") - return false; - else if (m_staBehavior == "RuleAction2") - return false; - else if (m_staBehavior == "Assoc") - return false; - else - return false; -} - -bool GrPosPass::RunTestRules(GrTableManager * ptman, int ruln, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - return false; -} - - -/*---------------------------------------------------------------------------------------------- - A simple FSM. - - Rules: - r1. clsCons clsVowel clsDiacrAcute - r2. clsCons clsVowelAE clsDiacr - r3. clsCons clsVowelI - r4. clsCons clsVowelI clsDiacrGrave - r5. clsCons clsVowelI clsDiacr - - Machine classes: - mcCons: b,c,d / f,g,h / j,k,l,m,n / p,q,r,s,t / v,w,x,y,z - mcVae: a 97/ e 101 - mcVi: i 105 - mcVou: o 111 / u 117 - mcDa: acute '/' 47 - mcDg: grave '\' 92 - mcDct: other diacritics-circumflex '^' 94 / tilde '~' 126 - - - FSM: (T=transition, F=final, A=accepting, NA=non-accepting) - - | mcCons mcVae mcVi mcVou mcDa mcDg mcDct - --------------------------------------------------------------------------- - T NA s0 | s1 - | - - - - - - - - T NA s1 | s2 s4 s3 - | - - - - - - - - T NA s2 | s5 s6 s6 - | - - - - - - - - T NA s3 | s10 - | - - - - - - - - T A s4 | s7 s8 s9 - | - - - - - - - - F A s5 | - | - - - - - - - - F A s6 | - | - - - - - - - - F A s7 | - | - - - - - - - - F A s8 | - | - - - - - - - - F A s9 | - | - - - - - - - - F A s10 | - | - - - - - - - - - Rules Matched: - s4: r3 - s5: r1, r2 - s6: r2 - s7: r1, r5 - s8: r4, r5 - s9: r5 - s10: r1 - -----------------------------------------------------------------------------------------------*/ - -void GrSubPass::SetUpSimpleFSMTest() -{ - m_nMaxRuleContext = m_nMaxChunk = 3; - m_nMaxRuleLoop = 2; - m_staBehavior = "SimpleFSM"; - - m_pfsm = new GrFSM(); - Assert(m_pfsm); - m_pfsm->SetUpSimpleFSMTest(); -} - -void GrFSM::SetUpSimpleFSMTest() -{ - // Create machine class ranges. - m_cmcr = 14; - m_prgmcr = new GrFSMClassRange[14]; - m_prgmcr[0].m_chwFirst = 47; // forward slash (acute): mcDa - m_prgmcr[0].m_chwLast = 47; - m_prgmcr[0].m_col = 4; - - m_prgmcr[1].m_chwFirst = 92; // backslash: mcDg - m_prgmcr[1].m_chwLast = 92; - m_prgmcr[1].m_col = 5; - - m_prgmcr[2].m_chwFirst = 94; // caret: mcDct - m_prgmcr[2].m_chwLast = 94; - m_prgmcr[2].m_col = 6; - - m_prgmcr[3].m_chwFirst = 97; // a: mcVae - m_prgmcr[3].m_chwLast = 97; - m_prgmcr[3].m_col = 1; - - m_prgmcr[4].m_chwFirst = 98; // b - d: mcCons - m_prgmcr[4].m_chwLast = 100; - m_prgmcr[4].m_col = 0; - - m_prgmcr[5].m_chwFirst = 101; // e: mcVae - m_prgmcr[5].m_chwLast = 101; - m_prgmcr[5].m_col = 1; - - m_prgmcr[6].m_chwFirst = 102; // f - h: mcCons - m_prgmcr[6].m_chwLast = 104; - m_prgmcr[6].m_col = 0; - - m_prgmcr[7].m_chwFirst = 105; // i: mcVi - m_prgmcr[7].m_chwLast = 105; - m_prgmcr[7].m_col = 2; - - m_prgmcr[8].m_chwFirst = 106; // j - n: mcCons - m_prgmcr[8].m_chwLast = 110; - m_prgmcr[8].m_col = 0; - - m_prgmcr[9].m_chwFirst = 111; // o: mcVou - m_prgmcr[9].m_chwLast = 111; - m_prgmcr[9].m_col = 3; - - m_prgmcr[10].m_chwFirst = 112; // p - t: mcCons - m_prgmcr[10].m_chwLast = 116; - m_prgmcr[10].m_col = 0; - - m_prgmcr[11].m_chwFirst = 117; // u: mcVou - m_prgmcr[11].m_chwLast = 117; - m_prgmcr[11].m_col = 3; - - m_prgmcr[12].m_chwFirst = 118; // v - z: mcCons - m_prgmcr[12].m_chwLast = 122; - m_prgmcr[12].m_col = 0; - - m_prgmcr[13].m_chwFirst = 126; // tilde: mcDct - m_prgmcr[13].m_chwLast = 126; - m_prgmcr[13].m_col = 6; - - m_dimcrInit = 8; // (max power of 2 <= m_cmcr); - m_cLoop = 3; // log2(max power of 2 <= m_cmcr); - m_imcrStart = m_cmcr - m_dimcrInit; - - - m_crow = 11; - m_crowNonAcpt = 4; - m_crowFinal = 6; - m_rowFinalMin = m_crow - m_crowFinal; - m_ccol = 7; - - // Set up transition table. - m_prgrowTransitions = new short[35]; // 35 = (m_crow-m_crowFinal) * m_ccol - short * psn = m_prgrowTransitions; - *psn++ = 1; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 2; *psn++ = 4; *psn++ = 3; *psn++ = 0; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 5; *psn++ = 6; *psn++ = 6; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ =10; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 7; *psn++ = 8; *psn++ = 9; - - // Set up matched-rules tables. - m_prgrulnMatched = new data16[10]; // 10 = sum of rules matched for each accepting state - m_prgirulnMin = new data16[7+1]; // 7 = m_crow - m_crowNonAcpt - - m_prgirulnMin[0] = 0; // s4: r3 - m_prgrulnMatched[0] = 3; - - m_prgirulnMin[1] = 1; // s5: r1, r2 - m_prgrulnMatched[1] = 1; - m_prgrulnMatched[2] = 2; - - m_prgirulnMin[2] = 3; // s6: r2 - m_prgrulnMatched[3] = 2; - - m_prgirulnMin[3] = 4; // s7: r1, r5 - m_prgrulnMatched[4] = 1; - m_prgrulnMatched[5] = 5; - - m_prgirulnMin[4] = 6; // s8: r4, r5 - m_prgrulnMatched[6] = 4; - m_prgrulnMatched[7] = 5; - - m_prgirulnMin[5] = 8; // s9: r5 - m_prgrulnMatched[8] = 5; - - m_prgirulnMin[6] = 9; // s10: r1 - m_prgrulnMatched[9] = 1; - - m_prgirulnMin[7] = 10; -} - - -/*---------------------------------------------------------------------------------------------- - The "rule" does something silly: just inserts *'s--the number equals the number of the - rule. -----------------------------------------------------------------------------------------------*/ -bool GrSubPass::RunSimpleFSMTest(GrTableManager * ptman, int ruln, GrSlotStream * psstrmInput, - GrSlotStream * psstrmOutput) -{ - int cslotMatched = (ruln == 3)? 2: 3; - - GrSlotState * pslot0 = psstrmInput->Peek(0); - - for (int islot = 0; islot < cslotMatched; islot++) - psstrmOutput->CopyOneSlotFrom(psstrmInput); - - for (islot = 0; islot < ruln; islot++) - { - GrSlotState * pslot; - ptman->NewSlot('*', pslot0, NULL, m_ipass, &pslot); - pslot->Associate(pslot0); - psstrmOutput->NextPut(pslot); - } - - return true; -} - - -/*---------------------------------------------------------------------------------------------- - A simple set of rules with actions. - - Rules: - r0. clsDigit gSlash clsDigit _ > @3 _ @1 gTilde; // tilde = 126 - r1. _ clsDigit gBackSlash clsDigit > gDollar @4 _ @2; // dollar sign = 36 - - Machine classes: - mcDigit: '0' - '9' 48 - 57 - mcSlash: '/' 47 - mcBSlash: '\' 92 - - - FSM: (T=transition, F=final, A=accepting, NA=non-accepting) - - | clsDig mcSlash mcBSlash - ------------------------------------------------------ - T NA s0 | s1 - | - - - - T NA s1 | s2 s3 - | - - - - T NA s2 | s4 - | - - - - T NA s3 | s5 - | - - - - F A s4 | - | - - - - F A s5 | - | - - - - - Rules Matched: - s4: r0 - s5: r1 - -----------------------------------------------------------------------------------------------*/ -void GrEngine::SetUpRuleActionTest() -{ - if (m_pctbl) - delete m_pctbl; - - m_pctbl = new GrClassTable(); - m_pctbl->SetUpRuleActionTest(); -} - -void GrClassTable::SetUpRuleActionTest() -{ - m_ccls = 2; // number of classes - m_cclsLinear = 2; // number of classes in linear format - - m_prgchwBIGGlyphList = new data16[100]; - - m_prgichwOffsets = new data16[2+1]; - - gid16 * pchw = m_prgchwBIGGlyphList; - - // Output class 0: tilde - m_prgichwOffsets[0] = 0; - *pchw++ = msbf(data16(126)); // '~' - - // Output class 1: dollar - m_prgichwOffsets[1] = 1; - *pchw++ = msbf(data16(36)); // '$' - - m_prgichwOffsets[2] = 2; -} - -void GrSubPass::SetUpRuleActionTest() -{ - m_nMaxRuleContext = m_nMaxChunk = 3; - m_nMaxRuleLoop = 2; - m_staBehavior = "RuleAction"; - - m_pfsm = new GrFSM(); - Assert(m_pfsm); - m_pfsm->SetUpRuleActionTest(); - - m_crul = 2; - - // Set up constraint code--succeed trivially. - m_prgbConstraintBlock = new byte[3]; - byte * pb = m_prgbConstraintBlock; - *pb++ = kopPushByte; *pb++ = 1; // Push true - *pb++ = kopPopRet; // PopAndRet - - m_prgibConstraintStart = new data16[m_crul]; - m_prgibConstraintStart[0] = 0; - m_prgibConstraintStart[1] = 0; - - // Set up rule action code. - m_prgbActionBlock = new byte[30]; - pb = m_prgbActionBlock; - - // Rule 1: clsDigit gSlash clsDigit _ > @3 _ @1 gTilde; - - *pb++ = kopPutCopy; *pb++ = 2; // PutCopy 2 - *pb++ = kopNext; // Next - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopPutCopy; *pb++ = -2; // PutCopy -2 - *pb++ = kopNext; // Next - *pb++ = kopInsert; // Insert - *pb++ = kopPutGlyph8bitObs; *pb++ = 0; // PutGlyph 0 ('~' = 126) - *pb++ = kopNext; // Next - *pb++ = kopPushByte; *pb++ = 0; // Push 0 - *pb++ = kopPopRet; // PopAndRet - - // Rule 2: _ clsDigit gBackSlash clsDigit > gDollar @4 _ @2; - - *pb++ = kopInsert; // Insert - *pb++ = kopPutGlyph8bitObs; *pb++ = 1; // PutGlyph 1 ('$' = 36) - *pb++ = kopNext; // Next - *pb++ = kopPutCopy; *pb++ = 2; // PutCopy 2 - *pb++ = kopNext; // Next - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopPutCopy; *pb++ = -2; // PutCopy -2 - *pb++ = kopNext; // Next - *pb++ = kopPushByte; *pb++ = 0; // Push 0 - *pb++ = kopPopRet; // PopAndRet - - m_prgibActionStart = new data16[m_crul]; - m_prgibActionStart[0] = 0; - m_prgibActionStart[1] = 15; -} - -void GrFSM::SetUpRuleActionTest() -{ - // Create machine class ranges. - m_cmcr = 3; - m_prgmcr = new GrFSMClassRange[3]; - m_prgmcr[0].m_chwFirst = 47; // forward slash: mcSlash - m_prgmcr[0].m_chwLast = 47; - m_prgmcr[0].m_col = 1; - - m_prgmcr[1].m_chwFirst = 48; // 0 - 9: mcDigit - m_prgmcr[1].m_chwLast = 57; - m_prgmcr[1].m_col = 0; - - m_prgmcr[2].m_chwFirst = 92; // backslash - m_prgmcr[2].m_chwLast = 92; - m_prgmcr[2].m_col = 2; - - - m_dimcrInit = 2; // (max power of 2 <= m_cmcr); - m_cLoop = 1; // log2(max power of 2 <= m_cmcr); - m_imcrStart = m_cmcr - m_dimcrInit; - - - m_crow = 6; - m_crowNonAcpt = 4; - m_crowFinal = 2; - m_rowFinalMin = m_crow - m_crowFinal; - m_ccol = 3; - - // Set up transition table. - m_prgrowTransitions = new short[12]; // 12 = (m_crow-m_crowFinal) * m_ccol - short * psn = m_prgrowTransitions; - *psn++ = 1; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 2; *psn++ = 3; - *psn++ = 4; *psn++ = 0; *psn++ = 0; - *psn++ = 5; *psn++ = 0; *psn++ = 0; - - // Set up matched-rules tables. - m_prgrulnMatched = new data16[2]; // 2 = sum of rules matched for each accepting state - m_prgirulnMin = new data16[2+1]; // 2 = m_crow - m_crowNonAcpt - - m_prgirulnMin[0] = 0; // s4: r0 - m_prgrulnMatched[0] = 0; - - m_prgirulnMin[1] = 1; // s5: r1 - m_prgrulnMatched[1] = 1; - - m_prgirulnMin[2] = 2; -} - -/*---------------------------------------------------------------------------------------------- - A more complicated set of rules with actions. - - PASS 1: - r0. clsDigit > @1 {dir = DIR_RIGHT} / ^ _ {dir == DIR_LEFT}; - r1. clsSpecial > @2 {dir = DIR_ARABNUMBER} / clsDigit {dir != DIR_LEFT} ^ _; - r2. clsSpecial > @2 {dir = @1.dir} / clsSpecial ^ _; - - Pass 1 machine classes: - mcDigit: '0' - '9' 48 - 57 - mcSpecial: '-', '_', '=', '~' 45, 95, 61, 126 - - Pass 1 FSM: (T=transition, F=final, A=accepting, NA=non-accepting) - - | mcDigit mcSpecial - ------------------------------------------ - T NA s0 | s2 s1 - | - _ - T NA s1 | s4 - | - - - T A s2 | s3 - | - - - F A s3 | - | - - - F A s4 | - | - - - - Rules Matched: - s2: r0 - s3: r1 - s4: r2 - - PASS 2: - r0. clsVowel gCaret > clsCirumVowel _; - r1. clsVowel gSlash > _ clsAcuteVowel$1; - - Pass 2 machine classes: - mcVowel - mcCaret: '^' 94 - mcSlash: '/' 47 - - - Pass 2 FSM: - | mcVowel mcCaret mcSlash - ----------------------------------------------------- - T NA s0 | s1 - | - _ - T NA s1 | s2 s3 - | - - - F A s2 | - | - - - F A s3 | - | - - - - Rules matched: - s2: r0 - s3: r1 - - - PASS 3: - r0. clsLeft > clsRight {dir = @1.dir} / _ clsDir {dir==DIR_RIGHT}; - r1. clsRight > clsLeft {dir = @1.dir} / clsDir {dir==DIR_RIGHT} _; - - Pass 3 machine classes: - mcDir: (clsDigit, clsSpecial) - mcLeft: '(', '[', '{' 40, 91, 123 - mcRight: ')', ']', '}' 41, 93, 125 - - Pass 3 FSM: - | mcDir mcLeft mcRight - ----------------------------------------------------- - T NA s0 | s2 s1 - | - _ - T NA s1 | s3 - | - - - T NA s2 | s4 - | - - - F A s3 | - | - - - F A s4 | - | - - - - Rules matched: - s3: r0 - s4: r1 - - -----------------------------------------------------------------------------------------------*/ -void GrEngine::SetUpRuleAction2Test() -{ - if (m_pctbl) - delete m_pctbl; - - m_pctbl = new GrClassTable(); - m_pctbl->SetUpRuleAction2Test(); -} - -void GrClassTable::SetUpRuleAction2Test() -{ - m_ccls = 7; // number of classes - m_cclsLinear = 4; // number of classes in linear format - - m_prgchwBIGGlyphList = new data16[70]; - - m_prgichwOffsets = new data16[7+1]; - - data16 * pchw = m_prgchwBIGGlyphList; - - // Output class 0: clsCirumVowel - m_prgichwOffsets[0] = 0; - *pchw++ = msbf(data16(226)); // a - *pchw++ = msbf(data16(234)); // e - *pchw++ = msbf(data16(238)); // i - *pchw++ = msbf(data16(244)); // o - *pchw++ = msbf(data16(251)); // u - *pchw++ = msbf(data16(194)); // A - *pchw++ = msbf(data16(202)); // E - *pchw++ = msbf(data16(206)); // I - *pchw++ = msbf(data16(212)); // O - *pchw++ = msbf(data16(219)); // U - - // Output class 1: clsAcuteVowel - m_prgichwOffsets[1] = 10; - *pchw++ = msbf(data16(225)); // a - *pchw++ = msbf(data16(233)); // e - *pchw++ = msbf(data16(237)); // i - *pchw++ = msbf(data16(243)); // o - *pchw++ = msbf(data16(250)); // u - *pchw++ = msbf(data16(193)); // A - *pchw++ = msbf(data16(201)); // E - *pchw++ = msbf(data16(205)); // I - *pchw++ = msbf(data16(211)); // O - *pchw++ = msbf(data16(218)); // U - - // Output class 2: clsLeft - m_prgichwOffsets[2] = 10 + 10; - *pchw++ = msbf(data16(40)); // ( - *pchw++ = msbf(data16(91)); // [ - *pchw++ = msbf(data16(123)); // { - - // Output class 3: clsRight - m_prgichwOffsets[3] = 20 + 3; - *pchw++ = msbf(data16(41)); // ) - *pchw++ = msbf(data16(93)); // ] - *pchw++ = msbf(data16(125)); // } - - // Input class 4: clsVowel - m_prgichwOffsets[4] = 23 + 3; // 26 - *pchw++ = msbf(data16(10)); - *pchw++ = msbf(data16(8)); *pchw++ = msbf(data16(3)); *pchw++ = msbf(data16(10-8)); - *pchw++ = msbf(data16(65)); *pchw++ = msbf(data16(5)); // A - *pchw++ = msbf(data16(69)); *pchw++ = msbf(data16(6)); // E - *pchw++ = msbf(data16(73)); *pchw++ = msbf(data16(7)); // I - *pchw++ = msbf(data16(79)); *pchw++ = msbf(data16(8)); // O - *pchw++ = msbf(data16(85)); *pchw++ = msbf(data16(9)); // U - *pchw++ = msbf(data16(97)); *pchw++ = msbf(data16(0)); // a - *pchw++ = msbf(data16(101)); *pchw++ = msbf(data16(1)); // e - *pchw++ = msbf(data16(105)); *pchw++ = msbf(data16(2)); // i - *pchw++ = msbf(data16(111)); *pchw++ = msbf(data16(3)); // o - *pchw++ = msbf(data16(117)); *pchw++ = msbf(data16(4)); // u - - // Input class 5: clsLeft - m_prgichwOffsets[5] = 26 + 4 + 10*2; // 50 - *pchw++ = msbf(data16(3)); - *pchw++ = msbf(data16(2)); *pchw++ = msbf(data16(1)); *pchw++ = msbf(data16(3-2)); - *pchw++ = msbf(data16(40)); *pchw++ = msbf(data16(0)); // ( - *pchw++ = msbf(data16(91)); *pchw++ = msbf(data16(1)); // [ - *pchw++ = msbf(data16(123)); *pchw++ = msbf(data16(2)); // { - - // Input class 6: clsRight - m_prgichwOffsets[6] = 50 + 4 + 3*2; // 60 - *pchw++ = msbf(data16(3)); - *pchw++ = msbf(data16(2)); *pchw++ = msbf(data16(1)); *pchw++ = msbf(data16(3-2)); - *pchw++ = msbf(data16(41)); *pchw++ = msbf(data16(0)); // ) - *pchw++ = msbf(data16(93)); *pchw++ = msbf(data16(1)); // ] - *pchw++ = msbf(data16(125)); *pchw++ = msbf(data16(2)); // } - - m_prgichwOffsets[7] = 60 + 4 + 3*2; // 70 -} - -void GrSubPass::SetUpRuleAction2Test() -{ - if (m_ipass == 1) - { - m_nMaxRuleContext = m_nMaxChunk = 2; - m_nMaxRuleLoop = 5; - m_staBehavior = "RuleAction2"; - - m_pfsm = new GrFSM(); - Assert(m_pfsm); - m_pfsm->SetUpRuleAction2Test(m_ipass); - - m_crul = 3; - - // Set up constraint code. - m_prgbConstraintBlock = new byte[1 + 10 + 10]; - byte * pb = m_prgbConstraintBlock; - *pb++ = kopRetTrue; // RetTrue - - *pb++ = kopCntxtItem; *pb++ = 0; // ContextItem 0 - *pb++ = kopPushSlotAttr; *pb++= kslatDir; // PushSlotAttr dir 0 - *pb++ = 0; - *pb++ = kopPushByte; *pb++ = kdircL; // Push DIR_LEFT - *pb++ = kopEqual; // Equal - *pb++ = kopOr; // Or - *pb++ = kopPopRet; // PopAndRet - - *pb++ = kopCntxtItem; *pb++ = 0; // ContextItem 0 - *pb++ = kopPushSlotAttr; *pb++= kslatDir; // PushSlotAttr dir 0 - *pb++ = 0; - *pb++ = kopPushByte; *pb++ = kdircL; // Push DIR_LEFT - *pb++ = kopNotEq; // NotEqual - *pb++ = kopOr; // Or - *pb++ = kopPopRet; // PopAndRet - - m_prgibConstraintStart = new data16[m_crul]; - m_prgibConstraintStart[0] = 1; - m_prgibConstraintStart[1] = 11; - m_prgibConstraintStart[2] = 0; - - // Set up rule action code. - m_prgbActionBlock = new byte[10 + 11 + 12]; - pb = m_prgbActionBlock; - - // Rule 0: clsDigit > @1 {dir = DIR_RIGHT} / ^ _ {dir == DIR_LEFT}; - - *pb++ = kopPutCopy; *pb++ = 0; // PutCopy 0 - *pb++ = kopPushByte; *pb++ = kdircR; // PushByte DIR_RIGHT - *pb++ = kopAttrSet; *pb++ = kslatDir; // AttrSet dir - *pb++ = kopNext; // Next - *pb++ = kopPushByte; *pb++ = -1; // Push -1 - *pb++ = kopPopRet; // PopAndRet - - // Rule 1: clsSpecial > @2 {dir = DIR_ARABNUMBER} / clsDigit {dir != DIR_LEFT} ^ _; - - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopPutCopy; *pb++ = 0; // PutCopy 0 - *pb++ = kopPushByte; *pb++ = kdircArabNum; // Push DIR_ARABNUMBER - *pb++ = kopAttrSet; *pb++ = kslatDir; // AttrSet dir - *pb++ = kopNext; // Next - *pb++ = kopPushByte; *pb++ = -1; // Push -1 - *pb++ = kopPopRet; // PopAndRet - - // Rule 2: clsSpecial > @2 {dir = @1.dir} / clsSpecial ^ _; - - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopPutCopy; *pb++ = 0; // PutCopy 0 - *pb++ = kopPushSlotAttr;*pb++ = kslatDir; // PushSlotAttr dir -1 - *pb++ = -1; - *pb++ = kopAttrSet; *pb++ = kslatDir; // AttrSet dir - *pb++ = kopNext; // Next - *pb++ = kopPushByte; *pb++ = -1; // Push -1 - *pb++ = kopPopRet; // PopAndRet - - m_prgibActionStart = new data16[m_crul]; - m_prgibActionStart[0] = 0; - m_prgibActionStart[1] = 10; - m_prgibActionStart[2] = 10 + 11; - } - else if (m_ipass == 2) - { - m_nMaxRuleContext = m_nMaxChunk = 2; - m_nMaxRuleLoop = 3; - m_staBehavior = "RuleAction2"; - - m_pfsm = new GrFSM(); - Assert(m_pfsm); - m_pfsm->SetUpRuleAction2Test(m_ipass); - - m_crul = 2; - - // Set up constraint code--succeed trivially. - m_prgbConstraintBlock = new byte[1]; - byte * pb = m_prgbConstraintBlock; - *pb++ = kopRetTrue; // RetTrue - - m_prgibConstraintStart = new data16[m_crul]; - m_prgibConstraintStart[0] = 0; - m_prgibConstraintStart[1] = 0; - - // Set up rule action code. - m_prgbActionBlock = new byte[16]; - pb = m_prgbActionBlock; - - // Rule 0: clsVowel gCaret > clsCirumVowel _; - - *pb++ = kopPutSubs8bitObs; *pb++ = 0; // PutSubs 0 clsVowel clsCircumVowel - *pb++ = 4; *pb++ = 0; - *pb++ = kopNext; // Next - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - // Rule 1: clsVowel gSlash > _ clsAcuteVowel$1; - - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopPutSubs8bitObs; *pb++ = -1; // PutSubs -1 clsVowel clsAcuteVowel - *pb++ = 4; *pb++ = 1; - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - m_prgibActionStart = new data16[m_crul]; - m_prgibActionStart[0] = 0; - m_prgibActionStart[1] = 8; - } - else if (m_ipass == 3) - { - m_nMaxRuleContext = m_nMaxChunk = 2; - m_nMaxRuleLoop = 3; - m_staBehavior = "RuleAction2"; - - m_pfsm = new GrFSM(); - Assert(m_pfsm); - m_pfsm->SetUpRuleAction2Test(m_ipass); - - m_crul = 2; - - // Set up constraint code. - m_prgbConstraintBlock = new byte[1 + 10 + 10]; - byte * pb = m_prgbConstraintBlock; - *pb++ = kopRetTrue; // RetTrue - - *pb++ = kopCntxtItem; *pb++ = 1; // ContextItem 1 - *pb++ = kopPushSlotAttr;*pb++ = kslatDir; // PushSlotAttr dir 0 - *pb++ = 0; - *pb++ = kopPushByte; *pb++ = kdircR; // Push DIR_RIGHT - *pb++ = kopEqual; // Equal - *pb++ = kopOr; // Or - *pb++ = kopPopRet; // PopAndRet - - *pb++ = kopCntxtItem; *pb++ = 0; // ContextItem 0 - *pb++ = kopPushSlotAttr;*pb++ = kslatDir; // PushSlotAttr dir 0 - *pb++ = 0; - *pb++ = kopPushByte; *pb++ = kdircR; // Push DIR_RIGHT - *pb++ = kopEqual; // Equal - *pb++ = kopOr; // Or - *pb++ = kopPopRet; // PopAndRet - - m_prgibConstraintStart = new data16[m_crul]; - m_prgibConstraintStart[0] = 1; - m_prgibConstraintStart[1] = 1 + 10; - - // Set up rule action code. - m_prgbActionBlock = new byte[23]; - pb = m_prgbActionBlock; - - // Rule 0: clsLeft > clsRight {dir = @1.dir} / _ clsDir {dir == DIR_RIGHT}; - - *pb++ = kopPutSubs8bitObs; *pb++ = 0; // PutSubs 0 clsLeft clsRight - *pb++ = 5; *pb++ = 3; - *pb++ = kopPushSlotAttr;*pb++ = kslatDir; // PushSlotAttr dir 1 - *pb++ = 1; - *pb++ = kopAttrSet; *pb++ = kslatDir; // AttrSet dir - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - // Rule 1: clsRight > clsLeft {dir = @1.dir} / clsDir {dir == DIR_RIGHT} _; - - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopPutSubs8bitObs; *pb++ = 0; // PutSubs 0 clsRight clsLeft - *pb++ = 6; *pb++ = 2; - *pb++ = kopPushSlotAttr;*pb++ = kslatDir; // PushSlotAttr dir -1 - *pb++ = -1; - *pb++ = kopAttrSet; *pb++ = kslatDir; // AttrSet dir - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - m_prgibActionStart = new data16[m_crul]; - m_prgibActionStart[0] = 0; - m_prgibActionStart[1] = 11; - } -} - - -void GrFSM::SetUpRuleAction2Test(int ipass) -{ - if (ipass == 1) - { - // Create machine class ranges. - m_cmcr = 5; - m_prgmcr = new GrFSMClassRange[5]; - m_prgmcr[0].m_chwFirst = 45; // hyphen - m_prgmcr[0].m_chwLast = 45; - m_prgmcr[0].m_col = 1; - - m_prgmcr[1].m_chwFirst = 48; // 0 - 9: mcDigit - m_prgmcr[1].m_chwLast = 57; - m_prgmcr[1].m_col = 0; - - m_prgmcr[2].m_chwFirst = 61; // equals sign - m_prgmcr[2].m_chwLast = 61; - m_prgmcr[2].m_col = 1; - - m_prgmcr[3].m_chwFirst = 95; // underscore - m_prgmcr[3].m_chwLast = 95; - m_prgmcr[3].m_col = 1; - - m_prgmcr[4].m_chwFirst = 126; // tilde - m_prgmcr[4].m_chwLast = 126; - m_prgmcr[4].m_col = 1; - - m_dimcrInit = 4; // (max power of 2 <= m_cmcr); - m_cLoop = 2; // log2(max power of 2 <= m_cmcr); - m_imcrStart = m_cmcr - m_dimcrInit; - - - m_crow = 5; - m_crowNonAcpt = 2; - m_crowFinal = 2; - m_rowFinalMin = m_crow - m_crowFinal; - m_ccol = 2; - - // Set up transition table. - m_prgrowTransitions = new short[6]; // 6 = (m_crow-m_crowFinal) * m_ccol - short * psn = m_prgrowTransitions; - *psn++ = 2; *psn++ = 1; - *psn++ = 0; *psn++ = 4; - *psn++ = 0; *psn++ = 3; - - // Set up matched-rules tables. - m_prgrulnMatched = new data16[3]; // 3 = sum of rules matched for each accepting state - m_prgirulnMin = new data16[3+1]; // 3 = m_crow - m_crowNonAcpt - - m_prgirulnMin[0] = 0; // s2: r0 - m_prgrulnMatched[0] = 0; - - m_prgirulnMin[1] = 1; // s3: r1 - m_prgrulnMatched[1] = 1; - - m_prgirulnMin[2] = 2; // s3: r2 - m_prgrulnMatched[2] = 2; - - m_prgirulnMin[3] = 3; - } - else if (ipass == 2) - { - // Create machine class ranges. - m_cmcr = 12; - m_prgmcr = new GrFSMClassRange[12]; - m_prgmcr[0].m_chwFirst = 47; // slash - m_prgmcr[0].m_chwLast = 47; - m_prgmcr[0].m_col = 2; - - m_prgmcr[1].m_chwFirst = 65; // A - m_prgmcr[1].m_chwLast = 65; - m_prgmcr[1].m_col = 0; - - m_prgmcr[2].m_chwFirst = 69; // E - m_prgmcr[2].m_chwLast = 69; - m_prgmcr[2].m_col = 0; - - m_prgmcr[3].m_chwFirst = 73; // I - m_prgmcr[3].m_chwLast = 73; - m_prgmcr[3].m_col = 0; - - m_prgmcr[4].m_chwFirst = 79; // O - m_prgmcr[4].m_chwLast = 79; - m_prgmcr[4].m_col = 0; - - m_prgmcr[5].m_chwFirst = 85; // U - m_prgmcr[5].m_chwLast = 85; - m_prgmcr[5].m_col = 0; - - m_prgmcr[6].m_chwFirst = 94; // caret - m_prgmcr[6].m_chwLast = 94; - m_prgmcr[6].m_col = 1; - - m_prgmcr[7].m_chwFirst = 97; // a - m_prgmcr[7].m_chwLast = 97; - m_prgmcr[7].m_col = 0; - - m_prgmcr[8].m_chwFirst = 101; // e - m_prgmcr[8].m_chwLast = 101; - m_prgmcr[8].m_col = 0; - - m_prgmcr[9].m_chwFirst = 105; // i - m_prgmcr[9].m_chwLast = 105; - m_prgmcr[9].m_col = 0; - - m_prgmcr[10].m_chwFirst = 111; // o - m_prgmcr[10].m_chwLast = 111; - m_prgmcr[10].m_col = 0; - - m_prgmcr[11].m_chwFirst = 117; // u - m_prgmcr[11].m_chwLast = 117; - m_prgmcr[11].m_col = 0; - - m_dimcrInit = 8; // (max power of 2 <= m_cmcr); - m_cLoop = 3; // log2(max power of 2 <= m_cmcr); - m_imcrStart = m_cmcr - m_dimcrInit; - - - m_crow = 4; - m_crowNonAcpt = 2; - m_crowFinal = 2; - m_rowFinalMin = m_crow - m_crowFinal; - m_ccol = 3; - - // Set up transition table. - m_prgrowTransitions = new short[6]; // 6 = (m_crow-m_crowFinal) * m_ccol - short * psn = m_prgrowTransitions; - *psn++ = 1; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 2; *psn++ = 3; - - // Set up matched-rules tables. - m_prgrulnMatched = new data16[2]; // 2 = sum of rules matched for each accepting state - m_prgirulnMin = new data16[2+1]; // 2 = m_crow - m_crowNonAcpt - - m_prgirulnMin[0] = 0; // s1: r0 - m_prgrulnMatched[0] = 0; - - m_prgirulnMin[1] = 1; // s2: r1 - m_prgrulnMatched[1] = 1; - - m_prgirulnMin[2] = 2; - } - else if (ipass == 3) - { - // Create machine class ranges. - m_cmcr = 11; - m_prgmcr = new GrFSMClassRange[11]; - m_prgmcr[0].m_chwFirst = 40; // ( - m_prgmcr[0].m_chwLast = 40; - m_prgmcr[0].m_col = 1; - - m_prgmcr[1].m_chwFirst = 41; // ) - m_prgmcr[1].m_chwLast = 41; - m_prgmcr[1].m_col = 2; - - m_prgmcr[2].m_chwFirst = 45; // hyphen - m_prgmcr[2].m_chwLast = 45; - m_prgmcr[2].m_col = 0; - - m_prgmcr[3].m_chwFirst = 48; // 0 - 9: mcDigit - m_prgmcr[3].m_chwLast = 57; - m_prgmcr[3].m_col = 0; - - m_prgmcr[4].m_chwFirst = 61; // = - m_prgmcr[4].m_chwLast = 61; - m_prgmcr[4].m_col = 0; - - m_prgmcr[5].m_chwFirst = 91; // [ - m_prgmcr[5].m_chwLast = 91; - m_prgmcr[5].m_col = 1; - - m_prgmcr[6].m_chwFirst = 93; // ] - m_prgmcr[6].m_chwLast = 93; - m_prgmcr[6].m_col = 2; - - m_prgmcr[7].m_chwFirst = 95; // underscore - m_prgmcr[7].m_chwLast = 95; - m_prgmcr[7].m_col = 0; - - m_prgmcr[8].m_chwFirst = 123; // { - m_prgmcr[8].m_chwLast = 123; - m_prgmcr[8].m_col = 1; - - m_prgmcr[9].m_chwFirst = 125; // } - m_prgmcr[9].m_chwLast = 125; - m_prgmcr[9].m_col = 2; - - m_prgmcr[10].m_chwFirst = 126; // tilde - m_prgmcr[10].m_chwLast = 126; - m_prgmcr[10].m_col = 0; - - m_dimcrInit = 8; // (max power of 2 <= m_cmcr); - m_cLoop = 3; // log2(max power of 2 <= m_cmcr); - m_imcrStart = m_cmcr - m_dimcrInit; - - - m_crow = 5; - m_crowNonAcpt = 3; - m_crowFinal = 2; - m_rowFinalMin = m_crow - m_crowFinal; - m_ccol = 3; - - // Set up transition table. - m_prgrowTransitions = new short[9]; // 9 = (m_crow-m_crowFinal) * m_ccol - short * psn = m_prgrowTransitions; - *psn++ = 2; *psn++ = 1; *psn++ = 0; - *psn++ = 3; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ = 4; - - // Set up matched-rules tables. - m_prgrulnMatched = new data16[2]; // 2 = sum of rules matched for each accepting state - m_prgirulnMin = new data16[2+1]; // 2 = m_crow - m_crowNonAcpt - - m_prgirulnMin[0] = 0; // s3: r0 - m_prgrulnMatched[0] = 0; - - m_prgirulnMin[1] = 1; // s4: r1 - m_prgrulnMatched[1] = 1; - - m_prgirulnMin[2] = 2; - } -} - - -/*---------------------------------------------------------------------------------------------- - Tests of various kinds of assocations. - - PASS 1 (line-break): - r0. gX / # _ ^ ; // do nothing - r1. gX {break = -2}; - - Pass 1 machine classes: - mcX: 'x' 120 - mcLB: 35 - - Pass 1 FSM: (T=transition, F=final, A=accepting, NA=non-accepting) - - | gX gLB - -------------------------------- - T NA s0 | s2 s1 - | - T NA s1 | s3 - | - F A s2 | - | - F A s3 | - - - Rules Matched: - s2: r1 - s3: r0 - - - - PASS 2: - r0. clsOA clsE > clsELig:(1 2) _; - r1. clsLC _ _ gX > @1 @5 @1 @5 / _ _ # {break==2} _ _ ; - r2. _ clsFraction _ > clsNumerator:2 gSlash:2 clsDenom:2; - - Pass 2 machine classes: - mcOA: O A 79 65 - mcOAlc: o a 111 97 - mcE E e 69 101 - mcFraction: 188 189 190 - mcX: x 120 - mcLCother - mcLB: 35 - - - Pass 2 FSM: mcLC - | mcOA mcOAlc mcE mcElc other mcX mcFractn mcLB - ----------------------------------------------------------------------------------------- - T NA s0 | s1 s2 s4 s3 s3 s6 - | - - - - - - - - T NA s1 | s7 - | - - - - - - - - T NA s2 | s7 s5 - | - - - - - - - - T NA s3 | s5 - | - - - - - - - - T NA s4 | s5 - | - - - - - - - - T NA s5 | s8 - | - - - - - - - - F A s6 | - | - - - - - - - F A s7 | - | - - - - - - - F A s8 | - | - - - - - - - - Rules matched: - s6: r2 - s7: r0 - s8: r1 - - - PASS 3: - r0. _ > gHyphen / _ # {break == 2} ^; - - Pass 3 machine classes: - mcLB: 35 - - Pass 3 FSM: - - | gLB - -------------------------------- - T NA s0 | s1 - | - F A s1 | - | - - Rules Matched: - s1: r0 -----------------------------------------------------------------------------------------------*/ -void GrEngine::SetUpAssocTest() -{ - if (m_pctbl) - delete m_pctbl; - - m_pctbl = new GrClassTable(); - m_pctbl->SetUpAssocTest(); - - m_fLineBreak = true; - m_cchwPreXlbContext = 1; - m_cchwPostXlbContext = 1; -} - -void GrClassTable::SetUpAssocTest() -{ - m_ccls = 11; // number of classes - m_cclsLinear = 5; // number of classes in linear format (output classes) - - m_prgchwBIGGlyphList = new data16[143]; - - m_prgichwOffsets = new data16[m_ccls+1]; - - data16 * pchw = m_prgchwBIGGlyphList; - - // Output class 0: clsELig - m_prgichwOffsets[0] = 0; - *pchw++ = msbf(data16(140)); // OE - *pchw++ = msbf(data16(198)); // AE - *pchw++ = msbf(data16(156)); // oe - *pchw++ = msbf(data16(230)); // ae - - // Output class 1: clsNumerator - m_prgichwOffsets[1] = 4; - *pchw++ = msbf(data16(49)); // 1 - *pchw++ = msbf(data16(49)); // 1 - *pchw++ = msbf(data16(51)); // 3 - - // Output class 2: clsDenom - m_prgichwOffsets[2] = 4 + 3; - *pchw++ = msbf(data16(52)); // 4 - *pchw++ = msbf(data16(50)); // 2 - *pchw++ = msbf(data16(52)); // 4 - - // Output class 3: gSlash - m_prgichwOffsets[3] = 7 + 3; - *pchw++ = msbf(data16(47)); // '/' - - // Output class 4: gHyphen - m_prgichwOffsets[4] = 10 + 1; - *pchw++ = msbf(data16(45)); // '-' - - // Input class 5: clsOA - m_prgichwOffsets[5] = 11 + 1; - *pchw++ = msbf(data16(4)); - *pchw++ = msbf(data16(4)); *pchw++ = msbf(data16(2)); *pchw++ = msbf(data16(0)); - *pchw++ = msbf(data16(65)); *pchw++ = msbf(data16(1)); // A - *pchw++ = msbf(data16(79)); *pchw++ = msbf(data16(0)); // O - *pchw++ = msbf(data16(97)); *pchw++ = msbf(data16(3)); // a - *pchw++ = msbf(data16(111)); *pchw++ = msbf(data16(2)); // o - - // Input class 6: clsE - m_prgichwOffsets[6] = 12 + 4 + 4*2; // 24 - *pchw++ = msbf(data16(3)); - *pchw++ = msbf(data16(2)); *pchw++ = msbf(data16(1)); *pchw++ = msbf(data16(3-2)); - *pchw++ = msbf(data16(40)); *pchw++ = msbf(data16(0)); // E - *pchw++ = msbf(data16(91)); *pchw++ = msbf(data16(1)); // e - - // Input class 7: clsLC - m_prgichwOffsets[7] = 24 + 4 + 2*2; // 32 - *pchw++ = msbf(data16(26)); - *pchw++ = msbf(data16(16)); *pchw++ = msbf(data16(4)); *pchw++ = msbf(data16(26-16)); - for (int i = 0; i < 26; ++i) - { - *pchw++ = msbf(data16(97+i)); *pchw++ = msbf(data16(i)); - } - - // Input class 8: gX - m_prgichwOffsets[8] = 32 + 4 + 26*2; // 88 - *pchw++ = msbf(data16(1)); - *pchw++ = msbf(data16(1)); *pchw++ = msbf(data16(0)); *pchw++ = msbf(data16(0)); - *pchw++ = msbf(data16(120)); *pchw++ = msbf(data16(0)); - - // Input class 9: clsFraction - m_prgichwOffsets[9] = 88 + 4 + 1*2; // 127 - *pchw++ = msbf(data16(3)); - *pchw++ = msbf(data16(2)); *pchw++ = msbf(data16(1)); *pchw++ = msbf(data16(3-2)); - *pchw++ = msbf(data16(188)); *pchw++ = msbf(data16(0)); // 1/4 - *pchw++ = msbf(data16(189)); *pchw++ = msbf(data16(1)); // 1/2 - *pchw++ = msbf(data16(190)); *pchw++ = msbf(data16(2)); // 3/4 - - // Input class 10: # - m_prgichwOffsets[10] = 127 + 4 + 3*2; // 137 - *pchw++ = msbf(data16(1)); - *pchw++ = msbf(data16(1)); *pchw++ = msbf(data16(0)); *pchw++ = msbf(data16(0)); - *pchw++ = msbf(data16(35)); *pchw++ = msbf(data16(0)); // 1/4 - - m_prgichwOffsets[11] = 137 + 4 + 1*2; // 143 -} - -void GrLineBreakPass::SetUpAssocTest() -{ - m_nMaxRuleContext = m_nMaxChunk = 1; - m_nMaxRuleLoop = 5; - m_staBehavior = "Assoc"; - - m_pfsm = new GrFSM(); - Assert(m_pfsm); - m_pfsm->SetUpAssocTest(m_ipass); - - m_crul = 2; - - // Set up constraint code--succeed trivially. - m_prgbConstraintBlock = new byte[1]; - byte * pb = m_prgbConstraintBlock; - *pb++ = kopRetTrue; // RetTrue - - m_prgibConstraintStart = new data16[m_crul]; - m_prgibConstraintStart[0] = 0; - m_prgibConstraintStart[1] = 0; - - // Set up rule action code. - m_prgbActionBlock = new byte[7 + 8]; - pb = m_prgbActionBlock; - - // Rule 0: gX / # _ ^ ; // do nothing - - *pb++ = kopPutCopy; *pb++ = 0; // PutCopy 0 - *pb++ = kopNext; // Next - *pb++ = kopPutCopy; *pb++ = 0; // PutCopy 0 - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - // Rule 1: gX {break = -2}; - - *pb++ = kopPutCopy; *pb++ = 0; // PutCopy 0 - *pb++ = kopPushByte; *pb++ = -2; // PushByte -2 - *pb++ = kopAttrSet; *pb++ = kslatBreak; // AttrSet breakweight - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - m_prgibActionStart = new data16[m_crul]; - m_prgibActionStart[0] = 0; - m_prgibActionStart[1] = 7; -} - -void GrSubPass::SetUpAssocTest() -{ - if (m_ipass == 2) - { - m_nMaxRuleContext = m_nMaxChunk = 3; - m_nMaxRuleLoop = 5; - m_staBehavior = "Assoc"; - - m_pfsm = new GrFSM(); - Assert(m_pfsm); - m_pfsm->SetUpAssocTest(m_ipass); - - m_crul = 3; - - // Set up constraint code. - m_prgbConstraintBlock = new byte[1 + 10]; - byte * pb = m_prgbConstraintBlock; - *pb++ = kopRetTrue; // RetTrue - - *pb++ = kopCntxtItem; *pb++ = 1; // ContextItem 1 - *pb++ = kopPushSlotAttr;*pb++ = kslatBreak; // PushSlotAttr break 0 - *pb++ = 0; - *pb++ = kopPushByte; *pb++ = 2; // Push 2 - *pb++ = kopEqual; // Equal - *pb++ = kopOr; // Or - *pb++ = kopPopRet; // PopAndRet - - m_prgibConstraintStart = new data16[m_crul]; - m_prgibConstraintStart[0] = 0; - m_prgibConstraintStart[1] = 1; - m_prgibConstraintStart[2] = 0; - - // Set up rule action code. - m_prgbActionBlock = new byte[12 + 12 + 22]; - pb = m_prgbActionBlock; - - // Rule 0: clsOA clsE > clsELig:(1 2) _ ; - - *pb++ = kopPutSubs8bitObs; *pb++ = 0; // PutSubs 0 clsOA clsELig - *pb++ = 5; *pb++ = 0; - *pb++ = kopAssoc; *pb++ = 2; // Assoc 2 0 1 - *pb++ = 0; *pb++ = 1; - *pb++ = kopNext; // Next - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - // Rule 1: clsLC _ _ gX > @1 @5 @1 @5 / _ _ # {break==2} _ _ ; - - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopInsert; // Insert - *pb++ = kopPutCopy; *pb++ = 2; // PutCopy 2 - *pb++ = kopNext; // Next - *pb++ = kopCopyNext; // CopyNext - line break - *pb++ = kopInsert; // Insert - *pb++ = kopPutCopy; *pb++ = -1; // PutCopy -1 - *pb++ = kopNext; // Next - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopRetZero; // RetZero - - // Rule 2: _ clsFraction _ > clsNumerator:2 gSlash:2 clsDenom:2; - - *pb++ = kopInsert; // Insert - *pb++ = kopPutSubs8bitObs; *pb++ = 1; // PutSubs 1 clsFraction clsNumerator - *pb++ = 9; *pb++ = 1; - *pb++ = kopAssoc; *pb++ = 1; // Assoc 1 1 - *pb++ = 1; - *pb++ = kopNext; // Next - *pb++ = kopPutGlyph8bitObs; *pb++ = 3; // PutGlyph gSlash - *pb++ = kopNext; // Next - *pb++ = kopInsert; // Insert - *pb++ = kopPutSubs8bitObs; *pb++ = 0; // PutSubs 0 clsFraction clsDenom - *pb++ = 9; *pb++ = 2; - *pb++ = kopAssoc; *pb++ = 1; // Assoc 1 0 - *pb++ = 0; - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - m_prgibActionStart = new data16[m_crul]; - m_prgibActionStart[0] = 0; - m_prgibActionStart[1] = 12; - m_prgibActionStart[2] = 12 + 12; - } - else if (m_ipass == 3) - { - m_nMaxRuleContext = m_nMaxChunk = 1; - m_nMaxRuleLoop = 3; - m_staBehavior = "Assoc"; - - m_pfsm = new GrFSM(); - Assert(m_pfsm); - m_pfsm->SetUpAssocTest(m_ipass); - - m_crul = 1; - - // Set up constraint code. - m_prgbConstraintBlock = new byte[1 + 10]; - byte * pb = m_prgbConstraintBlock; - *pb++ = kopRetTrue; // RetTrue - - *pb++ = kopCntxtItem; *pb++ = 0; // ContextItem 0 - *pb++ = kopPushSlotAttr;*pb++ = kslatBreak; // PushSlotAttr break 0 - *pb++ = 0; - *pb++ = kopPushByte; *pb++ = 2; // Push 2 - *pb++ = kopEqual; // Equal - *pb++ = kopOr; // Or - *pb++ = kopPopRet; // PopAndRet - - m_prgibConstraintStart = new data16[m_crul]; - m_prgibConstraintStart[0] = 1; - - m_prgbActionBlock = new byte[7]; - pb = m_prgbActionBlock; - - // Rule 0: _ > gHyphen / _ # {break == 2} ^; - - *pb++ = kopInsert; // Insert - *pb++ = kopPutGlyph8bitObs; *pb++ = 4; // PutGlyph 4 ('-' = 45) - *pb++ = kopNext; // Next - *pb++ = kopPushByte; *pb++ = 1; // Push 1 - *pb++ = kopPopRet; // PopAndRet - - m_prgibActionStart = new data16[m_crul]; - m_prgibActionStart[0] = 0; - } - else - Assert(false); -} - - -void GrFSM::SetUpAssocTest(int ipass) -{ - if (ipass == 1) - { - // Create machine class ranges. - m_cmcr = 2; - m_prgmcr = new GrFSMClassRange[m_cmcr]; - m_prgmcr[0].m_chwFirst = 35; // # - m_prgmcr[0].m_chwLast = 35; - m_prgmcr[0].m_col = 1; - - m_prgmcr[1].m_chwFirst = 120; // x - m_prgmcr[1].m_chwLast = 120; - m_prgmcr[1].m_col = 0; - - m_dimcrInit = 2; // (max power of 2 <= m_cmcr); - m_cLoop = 1; // log2(max power of 2 <= m_cmcr); - m_imcrStart = m_cmcr - m_dimcrInit; - - - m_crow = 4; - m_crowNonAcpt = 2; - m_crowFinal = 2; - m_rowFinalMin = m_crow - m_crowFinal; - m_ccol = 2; - - // Set up transition table. - m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 4 - short * psn = m_prgrowTransitions; - *psn++ = 2; *psn++ = 1; - *psn++ = 3; *psn++ = 0; - - // Set up matched-rules tables. - m_prgrulnMatched = new data16[2]; // 2 = sum of rules matched for each accepting state - m_prgirulnMin = new data16[m_crow - m_crowNonAcpt + 1]; - - m_prgirulnMin[0] = 0; // s2: r1 - m_prgrulnMatched[0] = 1; - - m_prgirulnMin[1] = 1; // s3: r0 - m_prgrulnMatched[1] = 0; - - m_prgirulnMin[2] = 2; - } - else if (ipass == 2) - { - // Create machine class ranges. - m_cmcr = 13; - m_prgmcr = new GrFSMClassRange[m_cmcr]; - m_prgmcr[0].m_chwFirst = 35; // # - m_prgmcr[0].m_chwLast = 35; - m_prgmcr[0].m_col = 7; - - m_prgmcr[1].m_chwFirst = 65; // A - m_prgmcr[1].m_chwLast = 65; - m_prgmcr[1].m_col = 0; - - m_prgmcr[2].m_chwFirst = 69; // E - m_prgmcr[2].m_chwLast = 69; - m_prgmcr[2].m_col = 2; - - m_prgmcr[3].m_chwFirst = 79; // O - m_prgmcr[3].m_chwLast = 79; - m_prgmcr[3].m_col = 0; - - m_prgmcr[4].m_chwFirst = 97; // a - m_prgmcr[4].m_chwLast = 97; - m_prgmcr[4].m_col = 1; - - m_prgmcr[5].m_chwFirst = 98; // b - d - m_prgmcr[5].m_chwLast = 100; - m_prgmcr[5].m_col = 4; - - m_prgmcr[6].m_chwFirst = 101; // e - m_prgmcr[6].m_chwLast = 101; - m_prgmcr[6].m_col = 3; - - m_prgmcr[7].m_chwFirst = 102; // f - n - m_prgmcr[7].m_chwLast = 110; - m_prgmcr[7].m_col = 4; - - m_prgmcr[8].m_chwFirst = 111; // o - m_prgmcr[8].m_chwLast = 111; - m_prgmcr[8].m_col = 1; - - m_prgmcr[9].m_chwFirst = 112; // p - w - m_prgmcr[9].m_chwLast = 119; - m_prgmcr[9].m_col = 4; - - m_prgmcr[10].m_chwFirst = 120; // x - m_prgmcr[10].m_chwLast = 120; - m_prgmcr[10].m_col = 5; - - m_prgmcr[11].m_chwFirst = 121; // y - z - m_prgmcr[11].m_chwLast = 122; - m_prgmcr[11].m_col = 4; - - m_prgmcr[12].m_chwFirst = 188; // 1/4, 1/2, 3/4 - m_prgmcr[12].m_chwLast = 190; - m_prgmcr[12].m_col = 6; - - - m_dimcrInit = 8; // (max power of 2 <= m_cmcr); - m_cLoop = 3; // log2(max power of 2 <= m_cmcr); - m_imcrStart = m_cmcr - m_dimcrInit; - - - m_crow = 9; - m_crowNonAcpt = 6; - m_crowFinal = 3; - m_rowFinalMin = m_crow - m_crowFinal; - m_ccol = 8; - - // Set up transition table. - m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 48 - short * psn = m_prgrowTransitions; - *psn++ = 1; *psn++ = 2; *psn++ = 0; *psn++ = 4; *psn++ = 3; *psn++ = 3; *psn++ = 6; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ = 7; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 7; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 5; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 5; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 5; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 8; *psn++ = 0; *psn++ = 0; - - // Set up matched-rules tables. - m_prgrulnMatched = new data16[3]; // 3 = sum of rules matched for each accepting state - m_prgirulnMin = new data16[3+1]; // 3 = m_crow - m_crowNonAcpt - - m_prgirulnMin[0] = 0; // s6: r2 - m_prgrulnMatched[0] = 2; - - m_prgirulnMin[1] = 1; // s7: r0 - m_prgrulnMatched[1] = 0; - - m_prgirulnMin[2] = 2; // s8: r1 - m_prgrulnMatched[2] = 1; - - m_prgirulnMin[3] = 3; - } - else if (ipass == 3) - { - // Create machine class ranges. - m_cmcr = 1; - m_prgmcr = new GrFSMClassRange[m_cmcr]; - m_prgmcr[0].m_chwFirst = 35; // # - m_prgmcr[0].m_chwLast = 35; - m_prgmcr[0].m_col = 0; - - m_dimcrInit = 1; // (max power of 2 <= m_cmcr); - m_cLoop = 0; // log2(max power of 2 <= m_cmcr); - m_imcrStart = m_cmcr - m_dimcrInit; - - - m_crow = 2; - m_crowNonAcpt = 1; - m_crowFinal = 1; - m_rowFinalMin = m_crow - m_crowFinal; - m_ccol = 1; - - // Set up transition table. - m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 1 - short * psn = m_prgrowTransitions; - *psn++ = 1; - - // Set up matched-rules tables. - m_prgrulnMatched = new data16[1]; // 1 = sum of rules matched for each accepting state - m_prgirulnMin = new data16[m_crow - m_crowNonAcpt + 1]; - - m_prgirulnMin[0] = 0; // s1: r0 - m_prgrulnMatched[0] = 0; - - m_prgirulnMin[1] = 1; - } -} - - -/*---------------------------------------------------------------------------------------------- - Second batch of association tests. - - PASS 1: - r0. clsSymbol _ > _ @1 / _ gNumber gHyphen # gNumber _; - r1. clsSymbol _ > _ @1 / _ gHyphen # _; - r2. _ clsSymbol > @6 _ / _ gNumber gHyphen # gNumber _; - r3. _ clsSymbol > @4 _ / _ gHyphen # _; - r4. clsLeft _ > @1 clsRight$1:1 / _ clsLetter gHyphen # _ gSpace; - r5. clsLeft _ > @1 clsRight$1:1 / _ clsLetter gHyphen # clsLetter _ gSpace; - r6. clsLeft _ > @1 clsRight$1:1 / _ clsLetter _ gSpace; - r7. clsLeft _ > @1 clsRight$1:1 / _ clsLetter clsLetter _ gSpace; - - Pass 1 machine classes: - mcSym: @, $, %, & 64, 36, 37, 38 - mcNum: 48-57 - mcHyphen: 45 - mcSpace: 32 - mcLet: 97-122 - mcLeft: ( [ { 40, 91, 123 - mcRight: ) ] } 41, 93, 125 - - Pass 1 FSM: (T=transition, F=final, A=accepting, NA=non-accepting) - - | mcSym mcNum mcHyph mcSpace mcLet mcLeft mcLB - ---------------------------------------------------------------------------------- - T NA s0 | s1 s2 s3 s4 - | - T NA s1 | s5 s6 - | - T NA s2 | s7 - | - T NA s3 | s8 - | - T NA s4 | s9 - | - T NA s5 | s10 - | - T NA s6 | s18 - | - T NA s7 | s11 - | - T NA s8 | s19 - | - T NA s9 | s12 s20 s13 - | - T NA s10 | s14 - | - T NA s11 | s15 - | - T NA s12 | s16 - | - T NA s13 | s21 - | - T NA s14 | s22 - | - T NA s15 | s23 - | - T NA s16 | s24 s17 - | - T NA s17 | s25 - | - F A s18 | - | - F A s19 | - | - F A s20 | - | - F A s21 | - | - F A s22 | - | - F A s23 | - | - F A s24 | - | - F A s25 | - - - Rules Matched: - s18: r1 - s19: r3 - s20: r6 - s21: r7 - s22: r0 - s23: r2 - s24: r4 - s25: r5 -----------------------------------------------------------------------------------------------*/ -void GrEngine::SetUpAssoc2Test() -{ - if (m_pctbl) - delete m_pctbl; - - m_pctbl = new GrClassTable(); - m_pctbl->SetUpAssoc2Test(); - - m_fLineBreak = true; - m_cchwPreXlbContext = 3; - m_cchwPostXlbContext = 2; -} - -void GrClassTable::SetUpAssoc2Test() -{ - m_ccls = 2; // number of classes - m_cclsLinear = 1; // number of classes in linear format (output classes) - - m_prgchwBIGGlyphList = new data16[13]; - - m_prgichwOffsets = new data16[m_ccls+1]; - - data16 * pchw = m_prgchwBIGGlyphList; - - // Output class 0: clsRight - m_prgichwOffsets[0] = 0; - *pchw++ = msbf(data16(41)); // ) - *pchw++ = msbf(data16(93)); // ] - *pchw++ = msbf(data16(125)); // } - - // Input class 1: clsLeft - m_prgichwOffsets[1] = 3; - *pchw++ = msbf(data16(3)); - *pchw++ = msbf(data16(2)); *pchw++ = msbf(data16(1)); *pchw++ = msbf(data16(3-2)); - *pchw++ = msbf(data16(40)); *pchw++ = msbf(data16(0)); // ( - *pchw++ = msbf(data16(91)); *pchw++ = msbf(data16(1)); // [ - *pchw++ = msbf(data16(123)); *pchw++ = msbf(data16(2)); // { - - m_prgichwOffsets[2] = 3 + 4 + 3*2; // 13 -} - -void GrSubPass::SetUpAssoc2Test() -{ - m_nMaxRuleContext = m_nMaxChunk = 6; - m_nMaxRuleLoop = 5; - m_staBehavior = "Assoc2"; - - m_pfsm = new GrFSM(); - Assert(m_pfsm); - m_pfsm->SetUpAssoc2Test(m_ipass); - - m_crul = 8; - - // Set up constraint code. - m_prgbConstraintBlock = new byte[1]; - byte * pb = m_prgbConstraintBlock; - *pb++ = kopRetTrue; // RetTrue - - m_prgibConstraintStart = new data16[m_crul]; - m_prgibConstraintStart[0] = 0; - m_prgibConstraintStart[1] = 0; - m_prgibConstraintStart[2] = 0; - m_prgibConstraintStart[3] = 0; - m_prgibConstraintStart[4] = 0; - m_prgibConstraintStart[5] = 0; - m_prgibConstraintStart[6] = 0; - m_prgibConstraintStart[7] = 0; - - // Set up rule action code. - m_prgbActionBlock = new byte[11 + 9 + 11 + 9 + 14 + 15 + 12 + 13]; - pb = m_prgbActionBlock; - - // Rule 0: clsSymbol _ > _ @1 / _ gNumber gHyphen # gNumber _; - - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopInsert; // Insert - *pb++ = kopPutCopy; *pb++ = -4; // PutCopy -4 - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - // Rule 1: clsSymbol _ > _ @1 / _ gHyphen # _; - - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopInsert; // Insert - *pb++ = kopPutCopy; *pb++ = -2; // PutCopy -2 - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - // Rule 2: _ clsSymbol > @6 _ / _ gNumber gHyphen # gNumber _; - - *pb++ = kopInsert; // Insert - *pb++ = kopPutCopy; *pb++ = 5; // PutCopy 5 - *pb++ = kopNext; // Next - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - // Rule 3: _ clsSymbol > @4 _ / _ gHyphen # _; - - *pb++ = kopInsert; // Insert - *pb++ = kopPutCopy; *pb++ = 3; // PutCopy 3 - *pb++ = kopNext; // Next - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - // Rule 4: clsLeft _ > @1 clsRight$1 / _ clsLetter gHyphen # _ gSpace; - - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopInsert; // Insert - *pb++ = kopPutSubs8bitObs; *pb++ = -3; // PutSubs -3 1 0 - *pb++ = 1; *pb++ = 0; - *pb++ = kopAssoc; *pb++ = 1; // Assoc 1 -3 - *pb++ = -3; - *pb++ = kopNext; // Next; - *pb++ = kopRetZero; // RetZero - - // Rule 5: clsLeft _ > @1 clsRight$1 / _ clsLetter gHyphen # clsLetter _ gSpace; - - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopInsert; // Insert - *pb++ = kopPutSubs8bitObs; *pb++ = -4; // PutSubs -4 1 0 - *pb++ = 1; *pb++ = 0; - *pb++ = kopAssoc; *pb++ = 1; // Assoc 1 -4 - *pb++ = -4; - *pb++ = kopNext; // Next; - *pb++ = kopRetZero; // RetZero - - // Rule 6: clsLeft _ > @1 clsRight$1 / _ clsLetter _ gSpace; - - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopInsert; // Insert - *pb++ = kopPutSubs8bitObs; *pb++ = -1; // PutSubs -1 1 0 - *pb++ = 1; *pb++ = 0; - *pb++ = kopAssoc; *pb++ = 1; // Assoc 1 -1 - *pb++ = -1; - *pb++ = kopNext; // Next; - *pb++ = kopRetZero; // RetZero - - // Rule 7: clsLeft _ > @1 clsRight$1 / _ clsLetter clsLetter _ gSpace; - - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopInsert; // Insert - *pb++ = kopPutSubs8bitObs; *pb++ = -2; // PutSubs -2 1 0 - *pb++ = 1; *pb++ = 0; - *pb++ = kopAssoc; *pb++ = 1; // Assoc 1 -2 - *pb++ = -2; - *pb++ = kopNext; // Next; - *pb++ = kopRetZero; // RetZero - - - m_prgibActionStart = new data16[m_crul]; - m_prgibActionStart[0] = 0; - m_prgibActionStart[1] = 11; - m_prgibActionStart[2] = 11 + 9; - m_prgibActionStart[3] = 20 + 11; - m_prgibActionStart[4] = 31 + 9; - m_prgibActionStart[5] = 40 + 14; - m_prgibActionStart[6] = 54 + 15; - m_prgibActionStart[7] = 69 + 12; -} - - -void GrFSM::SetUpAssoc2Test(int ipass) -{ - // Create machine class ranges. - m_cmcr = 10; - m_prgmcr = new GrFSMClassRange[m_cmcr]; - m_prgmcr[0].m_chwFirst = 32; // space - m_prgmcr[0].m_chwLast = 32; - m_prgmcr[0].m_col = 3; - - m_prgmcr[1].m_chwFirst = 35; // # - m_prgmcr[1].m_chwLast = 35; - m_prgmcr[1].m_col = 6; - - m_prgmcr[2].m_chwFirst = 36; // $, %, & - m_prgmcr[2].m_chwLast = 38; - m_prgmcr[2].m_col = 0; - - m_prgmcr[3].m_chwFirst = 40; // ( - m_prgmcr[3].m_chwLast = 40; - m_prgmcr[3].m_col = 5; - - m_prgmcr[4].m_chwFirst = 45; // - - m_prgmcr[4].m_chwLast = 45; - m_prgmcr[4].m_col = 2; - - m_prgmcr[5].m_chwFirst = 48; // 0 - 9 - m_prgmcr[5].m_chwLast = 57; - m_prgmcr[5].m_col = 1; - - m_prgmcr[6].m_chwFirst = 64; // @ - m_prgmcr[6].m_chwLast = 64; - m_prgmcr[6].m_col = 0; - - m_prgmcr[7].m_chwFirst = 91; // [ - m_prgmcr[7].m_chwLast = 91; - m_prgmcr[7].m_col = 5; - - m_prgmcr[8].m_chwFirst = 97; // a - z - m_prgmcr[8].m_chwLast = 122; - m_prgmcr[8].m_col = 4; - - m_prgmcr[9].m_chwFirst = 123; // { - m_prgmcr[9].m_chwLast = 123; - m_prgmcr[9].m_col = 5; - - - m_dimcrInit = 8; // (max power of 2 <= m_cmcr); - m_cLoop = 3; // log2(max power of 2 <= m_cmcr); - m_imcrStart = m_cmcr - m_dimcrInit; - - - m_crow = 26; - m_crowNonAcpt = 18; - m_crowFinal = 8; - m_rowFinalMin = m_crow - m_crowFinal; - m_ccol = 7; - - // Set up transition table. - m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 126 - short * psn = m_prgrowTransitions; - *psn++ = 1; *psn++ = 2; *psn++ = 3; *psn++ = 0; *psn++ = 0; *psn++ = 4; *psn++ = 0; - *psn++ = 0; *psn++ = 5; *psn++ = 6; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ = 7; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 8; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 9; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ =10; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ =18; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ =11; - *psn++ =19; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ =12; *psn++ =20; *psn++ =13; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ =14; - *psn++ = 0; *psn++ =15; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ =16; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ =21; *psn++ = 0; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ =22; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; - *psn++ =23; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ =24; *psn++ =17; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ =25; *psn++ = 0; *psn++ = 0; *psn++ = 0; - - // Set up matched-rules tables. - m_prgrulnMatched = new data16[8]; // 3 = sum of rules matched for each accepting state - m_prgirulnMin = new data16[m_crow - m_crowNonAcpt + 1]; - - m_prgirulnMin[0] = 0; // s18: r1 - m_prgrulnMatched[0] = 1; - - m_prgirulnMin[1] = 1; // s19: r3 - m_prgrulnMatched[1] = 3; - - m_prgirulnMin[2] = 2; // s20: r6 - m_prgrulnMatched[2] = 6; - - m_prgirulnMin[3] = 3; // s21: r7 - m_prgrulnMatched[3] = 7; - - m_prgirulnMin[4] = 4; // s22: r0 - m_prgrulnMatched[4] = 0; - - m_prgirulnMin[5] = 5; // s23: r2 - m_prgrulnMatched[5] = 2; - - m_prgirulnMin[6] = 6; // s24: r4 - m_prgrulnMatched[6] = 4; - - m_prgirulnMin[7] = 7; // s25: r5 - m_prgrulnMatched[7] = 5; - - m_prgirulnMin[8] = 8; -} - -/*---------------------------------------------------------------------------------------------- - Test of default associations - - PASS 1: - r0. gDollar _ > @1 gEquals; - r1. gAtSign > _ ; - - Pass 1 machine classes: - mcDollar: $ 36 - mcAt: @ 64 - - Pass 1 FSM: (T=transition, F=final, A=accepting, NA=non-accepting) - - | mcDollar mcAt - -------------------------------------- - T NA s0 | s1 s2 - | - F A s1 | - | - F A s2 | - - - Rules Matched: - s1: r0 - s2: r1 -----------------------------------------------------------------------------------------------*/ -void GrEngine::SetUpDefaultAssocTest() -{ - if (m_pctbl) - delete m_pctbl; - - m_pctbl = new GrClassTable(); - m_pctbl->SetUpDefaultAssocTest(); -} - -void GrClassTable::SetUpDefaultAssocTest() -{ - m_ccls = 1; // number of classes - m_cclsLinear = 1; // number of classes in linear format - - m_prgchwBIGGlyphList = new data16[1]; - - m_prgichwOffsets = new data16[m_ccls+1]; - - data16 * pchw = m_prgchwBIGGlyphList; - - // Output class 0: gEquals - m_prgichwOffsets[0] = 0; - *pchw++ = msbf(data16(61)); - - m_prgichwOffsets[1] = 1; -} - -void GrSubPass::SetUpDefaultAssocTest() -{ - m_nMaxRuleContext = m_nMaxChunk = 1; - m_nMaxRuleLoop = 5; - m_staBehavior = "DefaultAssoc"; - - m_pfsm = new GrFSM(); - Assert(m_pfsm); - m_pfsm->SetUpDefaultAssocTest(); - - m_crul = 2; - - // Set up constraint code. - m_prgbConstraintBlock = new byte[1]; - byte * pb = m_prgbConstraintBlock; - *pb++ = kopRetTrue; - - m_prgibConstraintStart = new data16[m_crul]; - m_prgibConstraintStart[0] = 0; - m_prgibConstraintStart[1] = 0; - - // Set up rule action code. - m_prgbActionBlock = new byte[6 + 3]; - pb = m_prgbActionBlock; - - // Rule 0: gDollar _ > @1 gEquals; - - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopInsert; // Insert - *pb++ = kopPutGlyph8bitObs; *pb++ = 0; // PutGlyph 0 - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - // Rule 1: gAtSign > _ ; - - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - m_prgibActionStart = new data16[m_crul]; - m_prgibActionStart[0] = 0; - m_prgibActionStart[1] = 6; -} - - -void GrFSM::SetUpDefaultAssocTest() -{ - // Create machine class ranges. - m_cmcr = 2; - m_prgmcr = new GrFSMClassRange[m_cmcr]; - m_prgmcr[0].m_chwFirst = 36; // $ - m_prgmcr[0].m_chwLast = 36; - m_prgmcr[0].m_col = 0; - - m_prgmcr[1].m_chwFirst = 64; // @ - m_prgmcr[1].m_chwLast = 64; - m_prgmcr[1].m_col = 1; - - - m_dimcrInit = 2; // (max power of 2 <= m_cmcr); - m_cLoop = 1; // log2(max power of 2 <= m_cmcr); - m_imcrStart = m_cmcr - m_dimcrInit; - - - m_crow = 3; - m_crowNonAcpt = 1; - m_crowFinal = 2; - m_rowFinalMin = m_crow - m_crowFinal; - m_ccol = 2; - - // Set up transition table. - m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 2 - short * psn = m_prgrowTransitions; - *psn++ = 1; *psn++ = 2; - - // Set up matched-rules tables. - m_prgrulnMatched = new data16[2]; // 2 = sum of rules matched for each accepting state - m_prgirulnMin = new data16[m_crow - m_crowNonAcpt + 1]; - - m_prgirulnMin[0] = 0; // s1: r0 - m_prgrulnMatched[0] = 0; - - m_prgirulnMin[1] = 1; // s2: r1 - m_prgrulnMatched[1] = 1; - - m_prgirulnMin[2] = 2; -} - -/*---------------------------------------------------------------------------------------------- - Test of features. The ID of "theFeature" == 234, its index is 0. The default value is 1. - - PASS 1: - if (theFeature == 0) // * -> $ - r0. gAsterisk > gDollar ; - else if (theFeature == 1) // * -> % - r1. gAsterisk > gPercent ; - else // * -> @ - r2. gAsterisk > gAt ; - - Pass 1 machine classes: - mcAsterisk: * 42 - - Pass 1 FSM: (T=transition, F=final, A=accepting, NA=non-accepting) - - | mcAsterisk - -------------------------------- - T NA s0 | s1 - | - F A s1 | - - - Rules Matched: - s1: r0, r1, r2 -----------------------------------------------------------------------------------------------*/ -void GrEngine::SetUpFeatureTest() -{ - AddFeature(234, 0, 1, 1); - - if (m_pctbl) - delete m_pctbl; - - m_pctbl = new GrClassTable(); - m_pctbl->SetUpFeatureTest(); -} - -void GrClassTable::SetUpFeatureTest() -{ - m_ccls = 4; // number of classes - m_cclsLinear = 4; // number of classes in linear format - - m_prgchwBIGGlyphList = new data16[4]; - - m_prgichwOffsets = new data16[m_ccls + 1]; - - data16 * pchw = m_prgchwBIGGlyphList; - - m_prgichwOffsets[0] = 0; - *pchw++ = msbf(data16(36)); // $ - - m_prgichwOffsets[1] = 1; - *pchw++ = msbf(data16(37)); // % - - m_prgichwOffsets[2] = 2; - *pchw++ = msbf(data16(64)); // @ - - m_prgichwOffsets[3] = 3; - *pchw++ = msbf(data16(42)); // * - - m_prgichwOffsets[4] = 4; -} - -void GrSubPass::SetUpFeatureTest() -{ - m_nMaxRuleContext = m_nMaxChunk = 1; - m_nMaxRuleLoop = 5; - m_staBehavior = "Feature"; - - m_pfsm = new GrFSM(); - Assert(m_pfsm); - m_pfsm->SetUpFeatureTest(); - - m_crul = 3; - - // Set up constraint code. - m_prgbConstraintBlock = new byte[1 + 6 + 12 + 12]; - byte * pb = m_prgbConstraintBlock; - *pb++ = kopRetTrue; - - // (theFeature == 0) - *pb++ = kopPushFeat; *pb++ = 0; // PushFeat 0 - *pb++ = kopPushByte; *pb++ = 0; // PushByte 0 - *pb++ = kopEqual; // Equal - *pb++ = kopPopRet; // PopAndRet - - // (theFeature != 0 && theFeature == 1) - *pb++ = kopPushFeat; *pb++ = 0; // PushFeat 0 - *pb++ = kopPushByte; *pb++ = 0; // PushByte 0 - *pb++ = kopNotEq; // NotEq - *pb++ = kopPushFeat; *pb++ = 0; // PushFeat 0 - *pb++ = kopPushByte; *pb++ = 1; // PushByte 1 - *pb++ = kopEqual; // Equal - *pb++ = kopAnd; // And - *pb++ = kopPopRet; // PopAndRet - - // (theFeature != 0 && theFeature != 1) - *pb++ = kopPushFeat; *pb++ = 0; // PushFeat 0 - *pb++ = kopPushByte; *pb++ = 0; // PushByte 0 - *pb++ = kopNotEq; // NotEq - *pb++ = kopPushFeat; *pb++ = 0; // PushFeat 0 - *pb++ = kopPushByte; *pb++ = 1; // PushByte 1 - *pb++ = kopNotEq; // NotEq - *pb++ = kopAnd; // And - *pb++ = kopPopRet; // PopAndRet - - m_prgibConstraintStart = new data16[m_crul]; - m_prgibConstraintStart[0] = 1; - m_prgibConstraintStart[1] = 1 + 6; - m_prgibConstraintStart[2] = 1 + 6 + 12; - - // Set up rule action code. - m_prgbActionBlock = new byte[4 + 4 + 4]; - pb = m_prgbActionBlock; - - // Rule 0: gAsterisk > gDollar ; - - *pb++ = kopPutGlyph8bitObs; *pb++ = 0; // PutGlyph 0 - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - // Rule 1: gAsterisk > gPercent ; - - *pb++ = kopPutGlyph8bitObs; *pb++ = 1; // PutGlyph 1 - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - // Rule 2: gAsterisk > gAt ; - - *pb++ = kopPutGlyph8bitObs; *pb++ = 2; // PutGlyph 2 - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - m_prgibActionStart = new data16[m_crul]; - m_prgibActionStart[0] = 0; - m_prgibActionStart[1] = 4; - m_prgibActionStart[2] = 4 + 4; -} - - -void GrFSM::SetUpFeatureTest() -{ - // Create machine class ranges. - m_cmcr = 1; - m_prgmcr = new GrFSMClassRange[m_cmcr]; - m_prgmcr[0].m_chwFirst = 42; // * - m_prgmcr[0].m_chwLast = 42; - m_prgmcr[0].m_col = 0; - - - m_dimcrInit = 1; // (max power of 2 <= m_cmcr); - m_cLoop = 0; // log2(max power of 2 <= m_cmcr); - m_imcrStart = m_cmcr - m_dimcrInit; - - - m_crow = 2; - m_crowNonAcpt = 1; - m_crowFinal = 1; - m_rowFinalMin = m_crow - m_crowFinal; - m_ccol = 1; - - // Set up transition table. - m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 1 - short * psn = m_prgrowTransitions; - *psn++ = 1; - - // Set up matched-rules tables. - m_prgrulnMatched = new data16[3]; // 3 = sum of rules matched for each accepting state - m_prgirulnMin = new data16[m_crow - m_crowNonAcpt + 1]; - - m_prgirulnMin[0] = 0; // s1: r0, r1, r2 - m_prgrulnMatched[0] = 0; - m_prgrulnMatched[1] = 1; - m_prgrulnMatched[2] = 2; - - m_prgirulnMin[1] = 3; -} - - -/*---------------------------------------------------------------------------------------------- - Tests of ligatures and components. - - PASS 1 (line-break): - r0. clsLetter { break = 2 } - - Pass 1 machine classes: - mcLetter: a - z 97 - 122 - - Pass 1 FSM: (T=transition, F=final, A=accepting, NA=non-accepting) - - | clsLetter - -------------------------------- - T NA s0 | s1 - | - F A s1 | - - - Rules Matched: - s1: r0 - - - PASS 2 (substitution): - r0. gX gY gZ > gCapX:(1 2 4) { comp {X.ref=@1; Y.ref=@2; Z.ref=@4 }} _ _ - / _ _ # {break==2} _; - r1. gX gY gZ > _ _ gCapZ:(1 3 4) { comp {X.ref=@1; Y.ref=@3; Z.ref=@4 }} - / _ # {break==2} _ _; - r2. gX gY gZ > _ gCapY:(1 2 3) { comp {X.ref=@1; Y.ref=@2; Z.ref=@3 }} gPlus; - - Pass 2 machine classes: - mcX: x 120 - mcY: y 121 - mcZ: z 122 - mcLB: 35 - - - Pass 2 FSM: - | mcX mcY mcZ mcLB - ---------------------------------------------------- - T NA s0 | s1 - | - - - - T NA s1 | s2 s3 - | - - - - T NA s2 | s6 s4 - | - - - - T NA s3 | s5 - | - - - - T NA s4 | s7 - | - - - - T NA s5 | s8 - | - - - - F A s6 | - | - - - - F A s7 | - | - - - - F A s8 | - | - - - - - Rules matched: - s6: r2 - s7: r0 - s8: r1 -----------------------------------------------------------------------------------------------*/ -void GrEngine::SetUpLigatureTest() -{ - if (m_pctbl) - delete m_pctbl; - - m_pctbl = new GrClassTable(); - m_pctbl->SetUpLigatureTest(); - - m_pgtbl = new GrGlyphTable(); - m_pgtbl->SetUpLigatureTest(); - - m_fLineBreak = true; - m_cchwPreXlbContext = 2; - m_cchwPostXlbContext = 2; -} - -void GrClassTable::SetUpLigatureTest() -{ - m_ccls = 7; // number of classes - m_cclsLinear = 7; // number of classes in linear format (all classes are single-item) - - m_prgchwBIGGlyphList = new data16[7]; - - m_prgichwOffsets = new data16[m_ccls+1]; - - data16 * pchw = m_prgchwBIGGlyphList; - - // Class 0: gCapX - m_prgichwOffsets[0] = 0; - *pchw++ = msbf(data16(88)); // X - - // Class 1: gCapY - m_prgichwOffsets[1] = 1; - *pchw++ = msbf(data16(89)); // Y - - // Class 2: gCapZ - m_prgichwOffsets[2] = 2; - *pchw++ = msbf(data16(90)); // Z - - // Class 3: gPlus - m_prgichwOffsets[3] = 3; - *pchw++ = msbf(data16(43)); // + - - // Class 4: gX - m_prgichwOffsets[4] = 4; - *pchw++ = msbf(data16(120)); // x - - // Class 5: gY - m_prgichwOffsets[5] = 5; - *pchw++ = msbf(data16(121)); // y - - // Class 6: gZ - m_prgichwOffsets[6] = 6; - *pchw++ = msbf(data16(122)); // z - - m_prgichwOffsets[7] = 7; -} - -void GrGlyphTable::SetUpLigatureTest() -{ - SetNumberOfGlyphs(128); - SetNumberOfStyles(1); - - GrGlyphSubTable * pgstbl = new GrGlyphSubTable(); - Assert(pgstbl); - - pgstbl->Initialize(1, 0, 128, 10, 4); - SetSubTable(0, pgstbl); - - SetNumberOfComponents(4); // comp.w, comp.x, comp.y, comp.z - - pgstbl->SetUpLigatureTest(); -} - -/*********************************************************************************************** - TODO: This method is BROKEN because m_prgibBIGAttrValues has been changed. It is no - longer a data16 *. The Gloc table can contain 16-bit or 32-bit entries and must be - accessed accordingly. -***********************************************************************************************/ -void GrGlyphSubTable::SetUpLigatureTest() -{ - m_nAttrIDLim = 20; - - m_pgatbl = new GrGlyphAttrTable(); - m_pgatbl->Initialize(0, 102); - - for (int i = 0; i < 88; i++) - m_prgibBIGAttrValues[i] = (byte)msbf(data16(0)); - - m_prgibBIGAttrValues[88] = (byte)msbf(data16(0)); - m_prgibBIGAttrValues[89] = (byte)msbf(data16(34)); - m_prgibBIGAttrValues[90] = (byte)msbf(data16(68)); - - for (i = 91; i < 128; i++) - m_prgibBIGAttrValues[i] = (byte)msbf(data16(102)); - - m_pgatbl->SetUpLigatureTest(); -} - -void GrGlyphAttrTable::SetUpLigatureTest() -{ - // Glyph 88 'X' (2 runs; offset = 0): - // 0 = 0 comp.w undefined - // 1 = 8 comp.x: (0,0, 25,100) - // 2 = 12 comp.y: (25,0, 75,100) - // 3 = 16 comp.z: (75,0, 100,100) - // 4-7 = 0 comp.w box corners - // 8 = 100 comp.x. top - // 9 = 0 bottom - // 10= 0 left - // 11= 25 right - // 12= 100 comp.y. top - // 13= 0 bottom - // 14= 25 left - // 15= 75 right - // 16= 100 comp.z. top - // 17= 0 bottom - // 18= 75 left - // 19= 100 right - // - // Glyph 89 (2 runs; offset = 34): - // 0 = 0 comp.w undefined - // 1 = 8 comp.x: (0,0, 33,100) - // 2 = 12 comp.y: (33,0, 67,100) - // 3 = 16 comp.z: (67,0, 100,100) - // 4-7 = 0 comp.w box corners - // 8 = 100 comp.x. top - // 9 = 0 bottom - // 10= 0 left - // 11= 33 right - // 12= 100 comp.y. top - // 13= 0 bottom - // 14= 33 left - // 15= 67 right - // 16= 100 comp.z. top - // 17= 0 bottom - // 18= 67 left - // 19= 100 right - // - // Glyph 90 (2 runs; offset = 68): - // 0 = 0 comp.w undefined - // 1 = 8 comp.x: (0,0, 10,100) - // 2 = 12 comp.y: (10,0, 90,100) - // 3 = 16 comp.z: (90,0, 100,100) - // 4-7 = 0 comp.w box corners - // 8 = 100 comp.x. top - // 9 = 0 bottom - // 10= 0 left - // 11= 10 right - // 12= 100 comp.y. top - // 13= 0 bottom - // 14= 10 left - // 15= 90 right - // 16= 100 comp.z. top - // 17= 0 bottom - // 18= 90 left - // 19= 100 right - - byte * pbBIG = m_prgbBIGEntries; - - GrGlyphAttrRun gatrun; - - // Glyph 88 'X' - gatrun.m_bMinAttrID = 1; - gatrun.m_cAttrs = 3; - gatrun.m_rgchwBIGValues[0] = msbf(data16(8)); - gatrun.m_rgchwBIGValues[1] = msbf(data16(12)); - gatrun.m_rgchwBIGValues[2] = msbf(data16(16)); - memcpy(pbBIG, &gatrun, 8); // 8 = 3*2 + 2 - pbBIG += 8; - gatrun.m_bMinAttrID = 8; // comp.x.top - gatrun.m_cAttrs = 12; - gatrun.m_rgchwBIGValues[0] = msbf(data16(100)); - gatrun.m_rgchwBIGValues[1] = msbf(data16(0)); - gatrun.m_rgchwBIGValues[2] = msbf(data16(0)); - gatrun.m_rgchwBIGValues[3] = msbf(data16(25)); - gatrun.m_rgchwBIGValues[4] = msbf(data16(100)); - gatrun.m_rgchwBIGValues[5] = msbf(data16(0)); - gatrun.m_rgchwBIGValues[6] = msbf(data16(25)); - gatrun.m_rgchwBIGValues[7] = msbf(data16(75)); - gatrun.m_rgchwBIGValues[8] = msbf(data16(100)); - gatrun.m_rgchwBIGValues[9] = msbf(data16(0)); - gatrun.m_rgchwBIGValues[10] = msbf(data16(75)); - gatrun.m_rgchwBIGValues[11] = msbf(data16(100)); - memcpy(pbBIG, &gatrun, 26); // 26 = 12*2 + 2 - pbBIG += 26; - - // Glyph 89 'Y' - gatrun.m_bMinAttrID = 1; - gatrun.m_cAttrs = 3; - gatrun.m_rgchwBIGValues[0] = msbf(data16(8)); - gatrun.m_rgchwBIGValues[1] = msbf(data16(12)); - gatrun.m_rgchwBIGValues[2] = msbf(data16(16)); - memcpy(pbBIG, &gatrun, 8); // 8 = 3*2 + 2 - pbBIG += 8; - gatrun.m_bMinAttrID = 8; // comp.x.top - gatrun.m_cAttrs = 12; - gatrun.m_rgchwBIGValues[0] = msbf(data16(100)); - gatrun.m_rgchwBIGValues[1] = msbf(data16(0)); - gatrun.m_rgchwBIGValues[2] = msbf(data16(0)); - gatrun.m_rgchwBIGValues[3] = msbf(data16(33)); - gatrun.m_rgchwBIGValues[4] = msbf(data16(100)); - gatrun.m_rgchwBIGValues[5] = msbf(data16(0)); - gatrun.m_rgchwBIGValues[6] = msbf(data16(33)); - gatrun.m_rgchwBIGValues[7] = msbf(data16(67)); - gatrun.m_rgchwBIGValues[8] = msbf(data16(100)); - gatrun.m_rgchwBIGValues[9] = msbf(data16(0)); - gatrun.m_rgchwBIGValues[10] = msbf(data16(67)); - gatrun.m_rgchwBIGValues[11] = msbf(data16(100)); - memcpy(pbBIG, &gatrun, 26); // 26 = 12*2 + 2 - pbBIG += 26; - - // Glyph 90 'Z' - gatrun.m_bMinAttrID = 1; - gatrun.m_cAttrs = 3; - gatrun.m_rgchwBIGValues[0] = msbf(data16(8)); - gatrun.m_rgchwBIGValues[1] = msbf(data16(12)); - gatrun.m_rgchwBIGValues[2] = msbf(data16(16)); - memcpy(pbBIG, &gatrun, 8); // 8 = 3*2 + 2 - pbBIG += 8; - gatrun.m_bMinAttrID = 8; // comp.x.top - gatrun.m_cAttrs = 12; - gatrun.m_rgchwBIGValues[0] = msbf(data16(100)); - gatrun.m_rgchwBIGValues[1] = msbf(data16(0)); - gatrun.m_rgchwBIGValues[2] = msbf(data16(0)); - gatrun.m_rgchwBIGValues[3] = msbf(data16(10)); - gatrun.m_rgchwBIGValues[4] = msbf(data16(100)); - gatrun.m_rgchwBIGValues[5] = msbf(data16(0)); - gatrun.m_rgchwBIGValues[6] = msbf(data16(10)); - gatrun.m_rgchwBIGValues[7] = msbf(data16(90)); - gatrun.m_rgchwBIGValues[8] = msbf(data16(100)); - gatrun.m_rgchwBIGValues[9] = msbf(data16(0)); - gatrun.m_rgchwBIGValues[10] = msbf(data16(90)); - gatrun.m_rgchwBIGValues[11] = msbf(data16(100)); - memcpy(pbBIG, &gatrun, 26); // 26 = 12*2 + 2 - pbBIG += 26; - - Assert(pbBIG == m_prgbBIGEntries + 102); -} - -void GrLineBreakPass::SetUpLigatureTest() -{ - m_nMaxRuleContext = m_nMaxChunk = 1; - m_nMaxRuleLoop = 5; - m_staBehavior = "Ligatures"; - - m_pfsm = new GrFSM(); - Assert(m_pfsm); - m_pfsm->SetUpLigatureTest(m_ipass); - - m_crul = 1; - - // Set up constraint code--succeed trivially. - m_prgbConstraintBlock = new byte[1]; - byte * pb = m_prgbConstraintBlock; - *pb++ = kopRetTrue; // RetTrue - - m_prgibConstraintStart = new data16[m_crul]; - m_prgibConstraintStart[0] = 0; - - // Set up rule action code. - m_prgbActionBlock = new byte[8]; - pb = m_prgbActionBlock; - - // Rule 0: clsLetter { break = 2 } - - *pb++ = kopPutCopy; *pb++ = 0; // PutCopy 0 - *pb++ = kopPushByte; *pb++ = 2; // PushByte 2 - *pb++ = kopAttrSet; *pb++ = kslatBreak; // AttrSet breakweight - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - m_prgibActionStart = new data16[m_crul]; - m_prgibActionStart[0] = 0; -} - -void GrSubPass::SetUpLigatureTest() -{ - if (m_ipass == 2) - { - m_nMaxRuleContext = m_nMaxChunk = 4; - m_nMaxRuleLoop = 5; - m_staBehavior = "Ligatures"; - - m_pfsm = new GrFSM(); - Assert(m_pfsm); - m_pfsm->SetUpLigatureTest(m_ipass); - - m_crul = 3; - - // Set up constraint code. - m_prgbConstraintBlock = new byte[1 + 10 + 10]; - byte * pb = m_prgbConstraintBlock; - *pb++ = kopRetTrue; // RetTrue - - *pb++ = kopCntxtItem; *pb++ = 2; // ContextItem 2 - *pb++ = kopPushSlotAttr;*pb++ = kslatBreak; // PushSlotAttr break 0 - *pb++ = 0; - *pb++ = kopPushByte; *pb++ = 2; // Push 2 - *pb++ = kopEqual; // Equal - *pb++ = kopOr; // Or - *pb++ = kopPopRet; // PopAndRet - - *pb++ = kopCntxtItem; *pb++ = 1; // ContextItem 1 - *pb++ = kopPushSlotAttr;*pb++ = kslatBreak; // PushSlotAttr break 0 - *pb++ = 0; - *pb++ = kopPushByte; *pb++ = 2; // Push 2 - *pb++ = kopEqual; // Equal - *pb++ = kopOr; // Or - *pb++ = kopPopRet; // PopAndRet - - m_prgibConstraintStart = new data16[m_crul]; - m_prgibConstraintStart[0] = 1; - m_prgibConstraintStart[1] = 11; - m_prgibConstraintStart[2] = 0; - - // Set up rule action code. - m_prgbActionBlock = new byte[29 + 29 + 29]; - pb = m_prgbActionBlock; - - // Rule 0: gX gY gZ > gCapX:(1 2 4) { comp {X.ref=@1; Y.ref=@2; Z.ref=@4 }} _ _ - // / _ _ # {break==2} _; - - *pb++ = kopPutGlyph8bitObs; *pb++ = 0; // PutGlyph 0 (gCapX) - *pb++ = kopAssoc; *pb++ = 3; // Assoc 3 0 1 3 - *pb++ = 0; *pb++ = 1; *pb++ = 3; - *pb++ = kopPushByte; *pb++ = 0; // Push 0 - *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref x - *pb++ = kslatCompRef; *pb++ = 1; - *pb++ = kopPushByte; *pb++ = 1; // Push 1 - *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref y - *pb++ = kslatCompRef; *pb++ = 2; - *pb++ = kopPushByte; *pb++ = 3; // Push 3 - *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref z - *pb++ = kslatCompRef; *pb++ = 3; - *pb++ = kopNext; // Next - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - // Rule 1: gX gY gZ > _ _ gCapZ:(1 3 4) { comp {X.ref=@1; Y.ref=@3; Z.ref=@4 }} - // / _ # {break==2} _ _; - - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopCopyNext; // CopyNext - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopPutGlyph8bitObs; *pb++ = 2; // PutGlyph 2 (gCapZ) - *pb++ = kopAssoc; *pb++ = 3; // Assoc 3 -3 -1 0 - *pb++ = -3; *pb++ = -1; *pb++ = 0; - *pb++ = kopPushByte; *pb++ = -3; // Push -3 - *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref x - *pb++ = kslatCompRef; *pb++ = 1; - *pb++ = kopPushByte; *pb++ = -1; // Push -1 - *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref y - *pb++ = kslatCompRef; *pb++ = 2; - *pb++ = kopPushByte; *pb++ = 0; // Push 0 - *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref z - *pb++ = kslatCompRef; *pb++ = 3; - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - // Rule 2: gX gY gZ > _ gCapY:(1 2 3) { comp {X.ref=@1; Y.ref=@2; Z.ref=@3 }} gPlus; - - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopPutGlyph8bitObs; *pb++ = 1; // PutGlyph 1 (gCapY) - *pb++ = kopAssoc; *pb++ = 3; // Assoc 3 -1 0 1 - *pb++ = -1; *pb++ = 0; *pb++ = 1; - *pb++ = kopPushByte; *pb++ = -1; // Push -1 - *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref x - *pb++ = kslatCompRef; *pb++ = 1; - *pb++ = kopPushByte; *pb++ = 0; // Push 0 - *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref y - *pb++ = kslatCompRef; *pb++ = 2; - *pb++ = kopPushByte; *pb++ = 1; // Push 1 - *pb++ = kopIAttrSetSlot; // IAttrSetSlot comp_ref z - *pb++ = kslatCompRef; *pb++ = 3; - *pb++ = kopNext; // Next - *pb++ = kopPutGlyph8bitObs; *pb++ = 3; // PutGlyph 3 (gPlus) - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - m_prgibActionStart = new data16[m_crul]; - m_prgibActionStart[0] = 0; - m_prgibActionStart[1] = 29; - m_prgibActionStart[2] = 29 + 29; - } - else - Assert(false); -} - - -void GrFSM::SetUpLigatureTest(int ipass) -{ - if (ipass == 1) - { - // Create machine class ranges. - m_cmcr = 1; - m_prgmcr = new GrFSMClassRange[m_cmcr]; - m_prgmcr[0].m_chwFirst = 97; // a - z - m_prgmcr[0].m_chwLast = 122; - m_prgmcr[0].m_col = 0; - - m_dimcrInit = 1; // (max power of 2 <= m_cmcr); - m_cLoop = 0; // log2(max power of 2 <= m_cmcr); - m_imcrStart = m_cmcr - m_dimcrInit; - - - m_crow = 2; - m_crowNonAcpt = 1; - m_crowFinal = 1; - m_rowFinalMin = m_crow - m_crowFinal; - m_ccol = 1; - - // Set up transition table. - m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 1 - short * psn = m_prgrowTransitions; - *psn++ = 1; - - // Set up matched-rules tables. - m_prgrulnMatched = new data16[1]; // 1 = sum of rules matched for each accepting state - m_prgirulnMin = new data16[m_crow - m_crowNonAcpt + 1]; - - m_prgirulnMin[0] = 0; // s1: r0 - m_prgrulnMatched[0] = 0; - - m_prgirulnMin[1] = 1; - } - else if (ipass == 2) - { - // Create machine class ranges. - m_cmcr = 4; - m_prgmcr = new GrFSMClassRange[m_cmcr]; - m_prgmcr[0].m_chwFirst = 35; // # - m_prgmcr[0].m_chwLast = 35; - m_prgmcr[0].m_col = 3; - - m_prgmcr[1].m_chwFirst = 120; // x - m_prgmcr[1].m_chwLast = 120; - m_prgmcr[1].m_col = 0; - - m_prgmcr[2].m_chwFirst = 121; // y - m_prgmcr[2].m_chwLast = 121; - m_prgmcr[2].m_col = 1; - - m_prgmcr[3].m_chwFirst = 122; // z - m_prgmcr[3].m_chwLast = 123; - m_prgmcr[3].m_col = 2; - - - m_dimcrInit = 4; // (max power of 2 <= m_cmcr); - m_cLoop = 2; // log2(max power of 2 <= m_cmcr); - m_imcrStart = m_cmcr - m_dimcrInit; - - - m_crow = 9; - m_crowNonAcpt = 6; - m_crowFinal = 3; - m_rowFinalMin = m_crow - m_crowFinal; - m_ccol = 4; - - // Set up transition table. - m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 24 - short * psn = m_prgrowTransitions; - *psn++ = 1; *psn++ = 0; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 2; *psn++ = 0; *psn++ = 3; - *psn++ = 0; *psn++ = 0; *psn++ = 6; *psn++ = 4; - *psn++ = 0; *psn++ = 5; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ = 7; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ = 8; *psn++ = 0; - - // Set up matched-rules tables. - m_prgrulnMatched = new data16[3]; // 3 = sum of rules matched for each accepting state - m_prgirulnMin = new data16[3+1]; // 3 = m_crow - m_crowNonAcpt - - m_prgirulnMin[0] = 0; // s6: r2 - m_prgrulnMatched[0] = 2; - - m_prgirulnMin[1] = 1; // s7: r0 - m_prgrulnMatched[1] = 0; - - m_prgirulnMin[2] = 2; // s8: r1 - m_prgrulnMatched[2] = 1; - - m_prgirulnMin[3] = 3; - } -} - - -/*---------------------------------------------------------------------------------------------- - Tests of ligatures and components where the components are modified glyphs. - - PASS 1: - r0. gX gI > @2 @1; - r1. clsPlainVowel gAcute > clsVowelAcute:(1 2) _; - r2. clsPlainVowel gGrave > clsVowelGrave:(1 2) _; - - Pass 1 machine classes: - mcX: x 120 - mcI: i 105 - mcPV: a e o u 97 101 111 117 - mcAcute: / 47 - mcGrave: \ 92 - - Pass 1 FSM: (T=transition, F=final, A=accepting, NA=non-accepting) - - | mcX mcPV mcI mcAcute mcGrave - --------------------------------------------------------------- - T NA s0 | s1 s2 s2 - | - - - - - T NA s1 | s3 - | - - - - - T NA s2 | s4 s5 - | - - - - - F A s3 | - | - - - - - F A s4 | - | - - - - - F A s5 | - | - - - - - - - Rules Matched: - s3: r0 - s4: r1 - s5: r2 - - - PASS 2: - r0. clsVowel gI > clsCapVowel:(1 2) { comp {v.ref = @1; i.ref = @2}} _; - - Pass 2 machine classes: - mcV: 97 101 111 117 - 224 225 232 233 236 237 242 243 249 250 - mcI: i 105 - - - Pass 2 FSM: - | mcV mcI - ---------------------------------------------------- - T NA s0 | s1 s1 - | - - T NA s1 | s2 - | - - F A s2 | - | - - - Rules matched: - s2: r0 -----------------------------------------------------------------------------------------------*/ -void GrEngine::SetUpLigature2Test() -{ - if (m_pctbl) - delete m_pctbl; - - m_pctbl = new GrClassTable(); - m_pctbl->SetUpLigature2Test(); - - m_pgtbl = new GrGlyphTable(); - m_pgtbl->SetUpLigature2Test(); -} - -void GrClassTable::SetUpLigature2Test() -{ - m_ccls = 5; // number of classes - m_cclsLinear = 3; // number of classes in linear format - - m_prgchwBIGGlyphList = new data16[73]; - - m_prgichwOffsets = new data16[m_ccls+1]; - - data16 * pchw = m_prgchwBIGGlyphList; - - // Output class 0: clsVowelAcute - m_prgichwOffsets[0] = 0; - *pchw++ = msbf(data16(225)); // a-acute - *pchw++ = msbf(data16(233)); // e-acute - *pchw++ = msbf(data16(237)); // i-acute - *pchw++ = msbf(data16(243)); // o-acute - *pchw++ = msbf(data16(250)); // u-acute - - // Output class 1: clsVowelGrave - m_prgichwOffsets[1] = 5; - *pchw++ = msbf(data16(224)); // a-grave - *pchw++ = msbf(data16(232)); // e-grave - *pchw++ = msbf(data16(236)); // i-grave - *pchw++ = msbf(data16(242)); // o-grave - *pchw++ = msbf(data16(249)); // u-grave - - // Output class 2: clsCapVowel - m_prgichwOffsets[2] = 5 + 5; // 10 - *pchw++ = msbf(data16(65)); // A - *pchw++ = msbf(data16(69)); // E - *pchw++ = msbf(data16(73)); // I - *pchw++ = msbf(data16(79)); // O - *pchw++ = msbf(data16(85)); // U - *pchw++ = msbf(data16(193)); // A-acute - *pchw++ = msbf(data16(201)); // E-acute - *pchw++ = msbf(data16(205)); // I-acute - *pchw++ = msbf(data16(211)); // O-acute - *pchw++ = msbf(data16(218)); // U-acute - *pchw++ = msbf(data16(192)); // A-grave - *pchw++ = msbf(data16(200)); // E-grave - *pchw++ = msbf(data16(204)); // I-grave - *pchw++ = msbf(data16(210)); // O-grave - *pchw++ = msbf(data16(217)); // U-grave - - // Input class 3: clsPlainVowel - m_prgichwOffsets[3] = 10 + 15; // 25 - *pchw++ = msbf(data16(5)); - *pchw++ = msbf(data16(4)); *pchw++ = msbf(data16(2)); *pchw++ = msbf(data16(5-4)); - *pchw++ = msbf(data16(97)); *pchw++ = msbf(data16(0)); // a - *pchw++ = msbf(data16(101)); *pchw++ = msbf(data16(1)); // e - *pchw++ = msbf(data16(105)); *pchw++ = msbf(data16(2)); // i - *pchw++ = msbf(data16(111)); *pchw++ = msbf(data16(3)); // o - *pchw++ = msbf(data16(117)); *pchw++ = msbf(data16(4)); // u - - // Input class 4: clsVowel - m_prgichwOffsets[4] = 25 + 4+(5*2); // 39 - *pchw++ = msbf(data16(15)); - *pchw++ = msbf(data16(8)); *pchw++ = msbf(data16(3)); *pchw++ = msbf(data16(15-8)); - *pchw++ = msbf(data16(97)); *pchw++ = msbf(data16(0)); // a - *pchw++ = msbf(data16(101)); *pchw++ = msbf(data16(1)); // e - *pchw++ = msbf(data16(105)); *pchw++ = msbf(data16(2)); // i - *pchw++ = msbf(data16(111)); *pchw++ = msbf(data16(3)); // o - *pchw++ = msbf(data16(117)); *pchw++ = msbf(data16(4)); // u - *pchw++ = msbf(data16(224)); *pchw++ = msbf(data16(10)); // a-grave - *pchw++ = msbf(data16(225)); *pchw++ = msbf(data16(5)); // a-acute - *pchw++ = msbf(data16(232)); *pchw++ = msbf(data16(11)); // e-grave - *pchw++ = msbf(data16(233)); *pchw++ = msbf(data16(6)); // e-acute - *pchw++ = msbf(data16(236)); *pchw++ = msbf(data16(12)); // i-grave - *pchw++ = msbf(data16(237)); *pchw++ = msbf(data16(7)); // i-acute - *pchw++ = msbf(data16(242)); *pchw++ = msbf(data16(13)); // o-grave - *pchw++ = msbf(data16(243)); *pchw++ = msbf(data16(8)); // o-acute - *pchw++ = msbf(data16(249)); *pchw++ = msbf(data16(14)); // u-grave - *pchw++ = msbf(data16(250)); *pchw++ = msbf(data16(9)); // u-acute - - m_prgichwOffsets[5] = 39 + 4+(15*2); // 73 -} - -void GrGlyphTable::SetUpLigature2Test() -{ - SetNumberOfGlyphs(256); - SetNumberOfStyles(1); - - GrGlyphSubTable * pgstbl = new GrGlyphSubTable(); - Assert(pgstbl); - - pgstbl->Initialize(1, 0, 256, 10, 4); - SetSubTable(0, pgstbl); - - SetNumberOfComponents(2); // comp.base, comp.i - - pgstbl->SetUpLigature2Test(); -} - -/*********************************************************************************************** - TODO: This method is BROKEN because m_prgibBIGAttrValues has been changed. It is no - longer a data16 *. The Gloc table can contain 16-bit or 32-bit entries and must be - accessed accordingly. -***********************************************************************************************/ -void GrGlyphSubTable::SetUpLigature2Test() -{ - m_nAttrIDLim = 10; - - m_pgatbl = new GrGlyphAttrTable(); - m_pgatbl->Initialize(0, 330); - - for (int i = 0; i <= 65; i++) // A - m_prgibBIGAttrValues[i] = (byte)msbf(data16(0)); - - for (i = 66; i <= 69; i++) // E - m_prgibBIGAttrValues[i] = (byte)msbf(data16(22)); - - for (i = 70; i <= 73; i++) // I - m_prgibBIGAttrValues[i] = (byte)msbf(data16(44)); - - for (i = 74; i <= 79; i++) // O - m_prgibBIGAttrValues[i] = (byte)msbf(data16(66)); - - for (i = 80; i <= 85; i++) // U - m_prgibBIGAttrValues[i] = (byte)msbf(data16(88)); - - for (i = 86; i <= 192; i++) // A-grave - m_prgibBIGAttrValues[i] = (byte)msbf(data16(110)); - - m_prgibBIGAttrValues[193] = (byte)msbf(data16(132)); // A-acute - - for (i = 194; i <= 200; i++) // E-grave - m_prgibBIGAttrValues[i] = (byte)msbf(data16(154)); - - m_prgibBIGAttrValues[201] = (byte)msbf(data16(176)); // E-acute - - for (i = 202; i <= 204; i++) // I-grave - m_prgibBIGAttrValues[i] = (byte)msbf(data16(198)); - - m_prgibBIGAttrValues[205] = (byte)msbf(data16(220)); // I-acute - - for (i = 206; i <= 210; i++) // O-grave - m_prgibBIGAttrValues[i] = (byte)msbf(data16(242)); - - m_prgibBIGAttrValues[211] = (byte)msbf(data16(264)); // O-acute - - for (i = 212; i <= 217; i++) // U-grave - m_prgibBIGAttrValues[i] = (byte)msbf(data16(286)); - - m_prgibBIGAttrValues[218] = (byte)msbf(data16(308)); // O-acute - - for (i = 219; i < 256; i++) - m_prgibBIGAttrValues[i] = (byte)msbf(data16(330)); - - m_pgatbl->SetUpLigature2Test(); -} - -void GrGlyphAttrTable::SetUpLigature2Test() -{ - // All ligatures have the following defined: - // - // 0 = 2 comp.base (0,30, 100,100) - // 1 = 6 comp.i (0,0, 100,30) - // 2= 100 comp.base.top - // 3= 30 bottom - // 4= 0 left - // 5= 100 right - // 6 = 30 comp.i.top - // 7 = 0 bottom - // 8= 0 left - // 9= 100 right - - byte * pbBIG = m_prgbBIGEntries; - - GrGlyphAttrRun gatrun; - - for (int i = 0; i < 15; i++) - { - gatrun.m_bMinAttrID = 0; - gatrun.m_cAttrs = 10; - gatrun.m_rgchwBIGValues[0] = msbf(data16(2)); - gatrun.m_rgchwBIGValues[1] = msbf(data16(6)); - gatrun.m_rgchwBIGValues[2] = msbf(data16(100)); - gatrun.m_rgchwBIGValues[3] = msbf(data16(30)); - gatrun.m_rgchwBIGValues[4] = msbf(data16(0)); - gatrun.m_rgchwBIGValues[5] = msbf(data16(100)); - gatrun.m_rgchwBIGValues[6] = msbf(data16(30)); - gatrun.m_rgchwBIGValues[7] = msbf(data16(0)); - gatrun.m_rgchwBIGValues[8] = msbf(data16(0)); - gatrun.m_rgchwBIGValues[9] = msbf(data16(100)); - memcpy(pbBIG, &gatrun, 22); // 22 = 10*2 + 2 - pbBIG += 22; - } - - Assert(pbBIG == m_prgbBIGEntries + (22 * 15)); -} - -void GrSubPass::SetUpLigature2Test() -{ - if (m_ipass == 1) - { - m_nMaxRuleContext = m_nMaxChunk = 2; - m_nMaxRuleLoop = 5; - m_staBehavior = "Ligatures2"; - - m_pfsm = new GrFSM(); - Assert(m_pfsm); - m_pfsm->SetUpLigature2Test(m_ipass); - - m_crul = 3; - - // Set up constraint code. - m_prgbConstraintBlock = new byte[1]; - byte * pb = m_prgbConstraintBlock; - *pb++ = kopRetTrue; // RetTrue - - m_prgibConstraintStart = new data16[m_crul]; - m_prgibConstraintStart[0] = 0; - m_prgibConstraintStart[1] = 0; - m_prgibConstraintStart[2] = 0; - - // Set up rule action code. - m_prgbActionBlock = new byte[7 + 12 + 12]; - pb = m_prgbActionBlock; - - // Rule 0: gX gI > @2 @1; - - *pb++ = kopPutCopy; *pb++ = 1; // PutCopy 1 - *pb++ = kopNext; // Next - *pb++ = kopPutCopy; *pb++ = -1; // PutCopy -1 - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - // Rule 1: clsPlainVowel gAcute > clsVowelAcute:(1 2) _; - - *pb++ = kopPutSubs8bitObs; *pb++ = 0; // PutSubs 0 3 0 - *pb++ = 3; *pb++ = 0; - *pb++ = kopAssoc; *pb++ = 2; // Assoc 2 0 1 - *pb++ = 0; *pb++ = 1; - *pb++ = kopNext; // Next - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - // Rule 2: clsPlainVowel gGrave > clsVowelGrave:(1 2) _; - - *pb++ = kopPutSubs8bitObs; *pb++ = 0; // PutSubs 0 3 1 - *pb++ = 3; *pb++ = 1; - *pb++ = kopAssoc; *pb++ = 2; // Assoc 2 0 1 - *pb++ = 0; *pb++ = 1; - *pb++ = kopNext; // Next - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - m_prgibActionStart = new data16[m_crul]; - m_prgibActionStart[0] = 0; - m_prgibActionStart[1] = 7; - m_prgibActionStart[2] = 7 + 12; - } - else if (m_ipass == 2) - { - m_nMaxRuleContext = m_nMaxChunk = 2; - m_nMaxRuleLoop = 5; - m_staBehavior = "Ligatures2"; - - m_pfsm = new GrFSM(); - Assert(m_pfsm); - m_pfsm->SetUpLigature2Test(m_ipass); - - m_crul = 1; - - // Set up constraint code. - m_prgbConstraintBlock = new byte[1]; - byte * pb = m_prgbConstraintBlock; - *pb++ = kopRetTrue; // RetTrue - - m_prgibConstraintStart = new data16[m_crul]; - m_prgibConstraintStart[0] = 0; - - // Set up rule action code. - m_prgbActionBlock = new byte[7 + 12 + 12]; - pb = m_prgbActionBlock; - - // Rule 0: clsVowel gI > clsCapVowel:(1 2) { comp {v.ref = @1; i.ref = @2}} _; - - *pb++ = kopPutSubs8bitObs; *pb++ = 0; // PutSubs 0 4 2 - *pb++ = 4; *pb++ = 2; - *pb++ = kopAssoc; *pb++ = 2; // Assoc 2 0 1 - *pb++ = 0; *pb++ = 1; - *pb++ = kopPushByte; *pb++ = 0; // Push 0 - *pb++ = kopIAttrSetSlot; // IAttrSetSlot compRef v - *pb++ = kslatCompRef; *pb++ = 0; - *pb++ = kopPushByte; *pb++ = 1; // Push 1 - *pb++ = kopIAttrSetSlot; // IAttrSetSlot compRef i - *pb++ = kslatCompRef; *pb++ = 1; - *pb++ = kopNext; // Next - *pb++ = kopDelete; // Delete - *pb++ = kopNext; // Next - *pb++ = kopRetZero; // RetZero - - m_prgibActionStart = new data16[m_crul]; - m_prgibActionStart[0] = 0; - } - else - Assert(false); -} - - -void GrFSM::SetUpLigature2Test(int ipass) -{ - if (ipass == 1) - { - // Create machine class ranges. - m_cmcr = 8; - m_prgmcr = new GrFSMClassRange[m_cmcr]; - m_prgmcr[0].m_chwFirst = 47; // acute - m_prgmcr[0].m_chwLast = 47; - m_prgmcr[0].m_col = 3; - - m_prgmcr[1].m_chwFirst = 92; // grave - m_prgmcr[1].m_chwLast = 92; - m_prgmcr[1].m_col = 4; - - m_prgmcr[2].m_chwFirst = 97; // a - m_prgmcr[2].m_chwLast = 97; - m_prgmcr[2].m_col = 1; - - m_prgmcr[3].m_chwFirst = 101; // e - m_prgmcr[3].m_chwLast = 101; - m_prgmcr[3].m_col = 1; - - m_prgmcr[4].m_chwFirst = 105; // i - m_prgmcr[4].m_chwLast = 105; - m_prgmcr[4].m_col = 2; - - m_prgmcr[5].m_chwFirst = 111; // o - m_prgmcr[5].m_chwLast = 111; - m_prgmcr[5].m_col = 1; - - m_prgmcr[6].m_chwFirst = 117; // u - m_prgmcr[6].m_chwLast = 117; - m_prgmcr[6].m_col = 1; - - m_prgmcr[7].m_chwFirst = 120; // x - m_prgmcr[7].m_chwLast = 120; - m_prgmcr[7].m_col = 0; - - m_dimcrInit = 8; // (max power of 2 <= m_cmcr); - m_cLoop = 3; // log2(max power of 2 <= m_cmcr); - m_imcrStart = m_cmcr - m_dimcrInit; - - - m_crow = 6; - m_crowNonAcpt = 3; - m_crowFinal = 3; - m_rowFinalMin = m_crow - m_crowFinal; - m_ccol = 5; - - // Set up transition table. - m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 15 - short * psn = m_prgrowTransitions; - *psn++ = 1; *psn++ = 2; *psn++ = 2; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ = 3; *psn++ = 0; *psn++ = 0; - *psn++ = 0; *psn++ = 0; *psn++ = 0; *psn++ = 4; *psn++ = 5; - - // Set up matched-rules tables. - m_prgrulnMatched = new data16[3]; // 3 = sum of rules matched for each accepting state - m_prgirulnMin = new data16[3+1]; // 3 = m_crow - m_crowNonAcpt - - m_prgirulnMin[0] = 0; // s3: r0 - m_prgrulnMatched[0] = 0; - - m_prgirulnMin[1] = 1; // s4: r1 - m_prgrulnMatched[1] = 1; - - m_prgirulnMin[2] = 2; // s5: r2 - m_prgrulnMatched[2] = 2; - - m_prgirulnMin[3] = 3; - } - else if (ipass == 2) - { - // Create machine class ranges. - m_cmcr = 10; - m_prgmcr = new GrFSMClassRange[m_cmcr]; - m_prgmcr[0].m_chwFirst = 97; // a - m_prgmcr[0].m_chwLast = 97; - m_prgmcr[0].m_col = 0; - - m_prgmcr[1].m_chwFirst = 101; // e - m_prgmcr[1].m_chwLast = 101; - m_prgmcr[1].m_col = 0; - - m_prgmcr[2].m_chwFirst = 105; // i - m_prgmcr[2].m_chwLast = 105; - m_prgmcr[2].m_col = 1; - - m_prgmcr[3].m_chwFirst = 111; // o - m_prgmcr[3].m_chwLast = 111; - m_prgmcr[3].m_col = 0; - - m_prgmcr[4].m_chwFirst = 117; // u - m_prgmcr[4].m_chwLast = 117; - m_prgmcr[4].m_col = 0; - - m_prgmcr[5].m_chwFirst = 224; // a-grave, a-acute - m_prgmcr[5].m_chwLast = 225; - m_prgmcr[5].m_col = 0; - - m_prgmcr[6].m_chwFirst = 232; // e-grave, e-acute - m_prgmcr[6].m_chwLast = 233; - m_prgmcr[6].m_col = 0; - - m_prgmcr[7].m_chwFirst = 236; // i-grave, i-acute - m_prgmcr[7].m_chwLast = 237; - m_prgmcr[7].m_col = 0; - - m_prgmcr[8].m_chwFirst = 242; // o-grave, o-acute - m_prgmcr[8].m_chwLast = 243; - m_prgmcr[8].m_col = 0; - - m_prgmcr[9].m_chwFirst = 249; // u-grave, u-acute - m_prgmcr[9].m_chwLast = 250; - m_prgmcr[9].m_col = 0; - - - m_dimcrInit = 8; // (max power of 2 <= m_cmcr); - m_cLoop = 3; // log2(max power of 2 <= m_cmcr); - m_imcrStart = m_cmcr - m_dimcrInit; - - - m_crow = 3; - m_crowNonAcpt = 2; - m_crowFinal = 1; - m_rowFinalMin = m_crow - m_crowFinal; - m_ccol = 2; - - // Set up transition table. - m_prgrowTransitions = new short[(m_crow-m_crowFinal) * m_ccol]; // 4 - short * psn = m_prgrowTransitions; - *psn++ = 1; *psn++ = 1; - *psn++ = 0; *psn++ = 2; - - // Set up matched-rules tables. - m_prgrulnMatched = new data16[1]; // 1 = sum of rules matched for each accepting state - m_prgirulnMin = new data16[1+1]; // 1 = m_crow - m_crowNonAcpt - - m_prgirulnMin[0] = 0; // s2: r0 - m_prgrulnMatched[0] = 0; - - m_prgirulnMin[1] = 1; - } -} - -#endif // _DEBUG - -} // namespace gr - -#endif // OLD_TEST_STUFF - -//:End Ignore diff --git a/Build/source/libs/graphite-engine/src/segment/TestPasses.cpp b/Build/source/libs/graphite-engine/src/segment/TestPasses.cpp deleted file mode 100644 index a85e6c56207..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/TestPasses.cpp +++ /dev/null @@ -1,1005 +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: TestPasses.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Hard-coded passes for test procedures. --------------------------------------------------------------------------------*//*:End Ignore*/ - -//:Ignore - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" - -#ifdef _MSC_VER -#pragma hdrstop -#endif -#undef THIS_FILE -DEFINE_THIS_FILE - -#ifdef OLD_TEST_STUFF - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -namespace gr -{ - -//:>******************************************************************************************** -//:> Methods -//:>******************************************************************************************** - -/*---------------------------------------------------------------------------------------------- - For release version. -----------------------------------------------------------------------------------------------*/ -#ifndef _DEBUG - -bool GrLineBreakPass::RunTestRules(GrTableManager * ptman, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - return false; -} - -bool GrSubPass::RunTestRules(GrTableManager * ptman, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - return false; -} - -bool GrPosPass::RunTestRules(GrTableManager * ptman, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - return false; -} - -#endif // !_DEBUG - - -#ifdef _DEBUG - -/*---------------------------------------------------------------------------------------------- - Set up a table manager for testing. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::SetUpTest(std::wstring stuRendBehavior) -{ - if (stuRendBehavior == L"NoRules") - { - m_cpass = 2; - m_cpassLB = 0; - m_ipassPos1 = 1; - m_fBidi = false; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrPosPass(1); - - m_prgppass[0]->SetUpTestData(); - m_prgppass[1]->SetUpTestData(); - } - else if (stuRendBehavior == L"JustReorder" || stuRendBehavior == "RightToLeftLayout") - { - m_cpass = 4; - m_cpassLB = 0; - m_ipassPos1 = 3; - m_fBidi = true; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrSubPass(1); - m_prgppass[2] = new GrBidiPass(2); - m_prgppass[3] = new GrPosPass(3); - - m_prgppass[0]->SetUpTestData(); - m_prgppass[1]->SetUpReverseNumbersTest(); - m_prgppass[2]->SetUpTestData(); - m_prgppass[3]->SetUpTestData(); - - m_prgppass[2]->SetTopDirLevel(TopDirectionLevel()); - } - else if (stuRendBehavior == L"CrossLineContext") - { - m_cpass = 4; - m_cpassLB = 1; - m_ipassPos1 = 3; - m_fBidi = false; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrLineBreakPass(1); - m_prgppass[2] = new GrSubPass(2); - m_prgppass[3] = new GrPosPass(3); - - m_prgppass[0]->SetUpTestData(); - m_prgppass[1]->SetUpCrossLineContextTest(); - m_prgppass[2]->SetUpCrossLineContextTest(); - m_prgppass[3]->SetUpTestData(); - } - else if (stuRendBehavior == L"Reprocess") - { - m_cpass = 6; - m_cpassLB = 1; - m_ipassPos1 = 5; - m_fBidi = true; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrLineBreakPass(1); - m_prgppass[2] = new GrSubPass(2); - m_prgppass[3] = new GrSubPass(3); - m_prgppass[4] = new GrBidiPass(4); - m_prgppass[5] = new GrPosPass(5); - - m_prgppass[0]->SetUpTestData(); // glyph-gen pass - m_prgppass[1]->SetUpReprocessTest(); // line-break pass - m_prgppass[2]->SetUpReverseNumbersTest(); // sub pass 1 - m_prgppass[3]->SetUpReprocessTest(); // sub pass 2 - m_prgppass[4]->SetUpTestData(); // bidi pass - m_prgppass[5]->SetUpTestData(); // pos pass - - m_prgppass[4]->SetTopDirLevel(TopDirectionLevel()); - } - else if (stuRendBehavior == L"LineEdgeContext") - { - m_cpass = 4; - m_cpassLB = 0; - m_ipassPos1 = 3; - m_fBidi = false; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrSubPass(1); - m_prgppass[2] = new GrSubPass(2); - m_prgppass[3] = new GrPosPass(3); - - m_prgppass[0]->SetUpTestData(); - m_prgppass[1]->SetUpLineEdgeContextTest(1); - m_prgppass[2]->SetUpLineEdgeContextTest(2); - m_prgppass[3]->SetUpTestData(); - } - else if (stuRendBehavior == L"BidiAlgorithm") - { - m_cpass = 4; - m_cpassLB = 0; - m_ipassPos1 = 3; - m_fBidi = true; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrSubPass(1); - m_prgppass[2] = new GrBidiPass(2); - m_prgppass[3] = new GrPosPass(3); - - m_prgppass[0]->SetUpTestData(); - m_prgppass[1]->SetUpBidiAlgorithmTest(); - m_prgppass[2]->SetUpBidiAlgorithmTest(); - m_prgppass[3]->SetUpTestData(); - - m_prgppass[2]->SetTopDirLevel(TopDirectionLevel()); - } - else if (stuRendBehavior == L"PseudoGlyphs") - { - m_cpass = 3; - m_cpassLB = 0; - m_ipassPos1 = 2; - m_fBidi = false; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrSubPass(1); - m_prgppass[2] = new GrPosPass(2); - - m_prgppass[0]->SetUpTestData(); - m_prgppass[1]->SetUpPseudoGlyphsTest(); - m_prgppass[2]->SetUpTestData(); - } - else if (stuRendBehavior == L"SimpleFSM") - { - m_cpass = 3; - m_cpassLB = 0; - m_ipassPos1 = 2; - m_fBidi = false; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrSubPass(1); - m_prgppass[2] = new GrPosPass(2); - - m_prgppass[0]->SetUpTestData(); - m_prgppass[1]->SetUpSimpleFSMTest(); - m_prgppass[2]->SetUpTestData(); - } - else if (stuRendBehavior == L"RuleAction") - { - m_cpass = 3; - m_cpassLB = 0; - m_ipassPos1 = 2; - m_fBidi = false; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrSubPass(1); - m_prgppass[2] = new GrPosPass(2); - - m_prgppass[0]->SetUpTestData(); - m_prgppass[1]->SetUpRuleActionTest(); - m_prgppass[2]->SetUpTestData(); - } - else if (stuRendBehavior == L"RuleAction2") - { - m_cpass = 6; - m_cpassLB = 0; - m_ipassPos1 = 5; - m_fBidi = true; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrSubPass(1); - m_prgppass[2] = new GrSubPass(2); - m_prgppass[3] = new GrSubPass(3); - m_prgppass[4] = new GrBidiPass(4); - m_prgppass[5] = new GrPosPass(5); - - m_prgppass[0]->SetUpTestData(); // glyph-gen pass - m_prgppass[1]->SetUpRuleAction2Test(); // sub pass 1 - m_prgppass[2]->SetUpRuleAction2Test(); // sub pass 2 - m_prgppass[3]->SetUpRuleAction2Test(); // sub pass 3 - m_prgppass[4]->SetUpTestData(); // bidi pass - m_prgppass[5]->SetUpTestData(); // pos pass - - m_prgppass[4]->SetTopDirLevel(TopDirectionLevel()); - } - else if (stuRendBehavior == L"Assoc") - { - m_cpass = 5; - m_cpassLB = 1; - m_ipassPos1 = 4; - m_fBidi = false; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrLineBreakPass(1); - m_prgppass[2] = new GrSubPass(2); - m_prgppass[3] = new GrSubPass(3); - m_prgppass[4] = new GrPosPass(4); - - m_prgppass[0]->SetUpTestData(); - m_prgppass[1]->SetUpAssocTest(); - m_prgppass[2]->SetUpAssocTest(); - m_prgppass[3]->SetUpAssocTest(); - m_prgppass[4]->SetUpTestData(); - } - else if (stuRendBehavior == L"Assoc2") - { - m_cpass = 3; - m_cpassLB = 0; - m_ipassPos1 = 2; - m_fBidi = false; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrSubPass(1); - m_prgppass[2] = new GrPosPass(2); - - m_prgppass[0]->SetUpTestData(); - m_prgppass[1]->SetUpAssoc2Test(); - m_prgppass[2]->SetUpTestData(); - } - else if (stuRendBehavior == L"DefaultAssoc") - { - m_cpass = 3; - m_cpassLB = 0; - m_ipassPos1 = 2; - m_fBidi = false; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrSubPass(1); - m_prgppass[2] = new GrPosPass(2); - - m_prgppass[0]->SetUpTestData(); - m_prgppass[1]->SetUpDefaultAssocTest(); - m_prgppass[2]->SetUpTestData(); - } - else if (stuRendBehavior == L"BidiNumbers") - { - m_cpass = 4; - m_cpassLB = 0; - m_ipassPos1 = 3; - m_fBidi = true; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrSubPass(1); - m_prgppass[2] = new GrBidiPass(2); - m_prgppass[3] = new GrPosPass(3); - - m_prgppass[0]->SetUpTestData(); - m_prgppass[1]->SetUpBidiNumbersTest(); - m_prgppass[2]->SetUpBidiNumbersTest(); - m_prgppass[3]->SetUpTestData(); - - m_prgppass[2]->SetTopDirLevel(TopDirectionLevel()); - } - else if (stuRendBehavior == L"Feature") - { - m_cpass = 3; - m_cpassLB = 0; - m_ipassPos1 = 2; - m_fBidi = false; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrSubPass(1); - m_prgppass[2] = new GrPosPass(2); - - m_prgppass[0]->SetUpTestData(); - m_prgppass[1]->SetUpFeatureTest(); - m_prgppass[2]->SetUpTestData(); - } - else if (stuRendBehavior == L"Ligatures") - { - m_cpass = 4; - m_cpassLB = 1; - m_ipassPos1 = 3; - m_fBidi = false; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrLineBreakPass(1); - m_prgppass[2] = new GrSubPass(2); - m_prgppass[3] = new GrPosPass(3); - - m_prgppass[0]->SetUpTestData(); - m_prgppass[1]->SetUpLigatureTest(); - m_prgppass[2]->SetUpLigatureTest(); - m_prgppass[3]->SetUpTestData(); - } - else if (stuRendBehavior == L"Ligatures2") - { - m_cpass = 4; - m_cpassLB = 1; - m_ipassPos1 = 3; - m_fBidi = false; - - m_prgppass = new GrPass*[m_cpass]; - m_prgppass[0] = new GrGlyphGenPass(0); - m_prgppass[1] = new GrSubPass(1); - m_prgppass[2] = new GrSubPass(2); - m_prgppass[3] = new GrPosPass(3); - - m_prgppass[0]->SetUpTestData(); - m_prgppass[1]->SetUpLigature2Test(); - m_prgppass[2]->SetUpLigature2Test(); - m_prgppass[3]->SetUpTestData(); - } - else - Assert(false); - - m_engst.m_prgpsstrm = new GrSlotStream*[m_cpass]; - for (int ipass = 0; ipass < m_cpass; ++ipass) - m_engst.m_prgpsstrm[ipass] = new GrSlotStream(ipass); -} - - -/*---------------------------------------------------------------------------------------------- - Set the pass variables that normally will be read from the ECF. -----------------------------------------------------------------------------------------------*/ - -void GrPass::SetUpTestData() -{ - m_nMaxRuleContext = m_nMaxChunk = 2; - m_nMaxRuleLoop = 2; -} - -//void GrBidiPass::SetUpTestData() -//{ -// m_nMaxRuleContext = m_nMaxChunk = 1; -// m_nMaxRuleLoop = 2; -//} - -/*---------------------------------------------------------------------------------------------- - Call the appropriate test function. -----------------------------------------------------------------------------------------------*/ - -bool GrLineBreakPass::RunTestRules(GrTableManager * ptman, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - if (m_staBehavior == "Reprocess") - return RunReprocessTest(ptman, psstrmInput, psstrmOutput); - else if (m_staBehavior == "CrossLineContext") - return RunCrossLineContextTest(ptman, psstrmInput, psstrmOutput); - else - return false; -} - -bool GrSubPass::RunTestRules(GrTableManager * ptman, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - if (m_staBehavior == "ReverseNumbers") - return RunReverseNumbersTest(ptman, psstrmInput, psstrmOutput); - else if (m_staBehavior == "CrossLineContext") - return RunCrossLineContextTest(ptman, psstrmInput, psstrmOutput); - else if (m_staBehavior == "Reprocess") - return RunReprocessTest(ptman, psstrmInput, psstrmOutput); - else if (m_staBehavior == "LineEdgeContext") - return RunLineEdgeContextTest(ptman, psstrmInput, psstrmOutput); - else if (m_staBehavior == "BidiAlgorithm") - return RunBidiAlgorithmTest(ptman, psstrmInput, psstrmOutput); - else if (m_staBehavior == "PseudoGlyphs") - return RunPseudoGlyphsTest(ptman, psstrmInput, psstrmOutput); - else if (m_staBehavior == "BidiNumbers") - return RunBidiNumbersTest(ptman, psstrmInput, psstrmOutput); - else - return false; -} - -bool GrPosPass::RunTestRules(GrTableManager * ptman, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - return false; -} - -/*---------------------------------------------------------------------------------------------- - A substitution pass that causes numbers to be reversed. Used by both the JustReorder test - and the Reprocess test. -----------------------------------------------------------------------------------------------*/ - -void GrSubPass::SetUpReverseNumbersTest() -{ - m_nMaxRuleContext = m_nMaxChunk = 1; - m_nMaxRuleLoop = 2; - m_staBehavior = "ReverseNumbers"; -} - -bool GrSubPass::RunReverseNumbersTest(GrTableManager * ptman, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - data16 chw0; - - // clsDigit { dir = DIR_RIGHT }; - if (psstrmInput->SlotsPending() >= 1) - { - bool fRtl = ptman->RightToLeft(); - chw0 = psstrmInput->Peek(0)->GlyphID(); - if ((chw0 >= '0') && (chw0 <= '9')) - { - GrSlotState * pslot0 = psstrmInput->NextGet(); -// GrFeatureValues fval0; -// pslot0->GetFeatureValues(&fval0); - - GrSlotState * pslotNew; - ptman->NewSlotCopy(pslot0, m_ipass, &pslotNew); - pslotNew->SetDirectionality(fRtl ? kdircArabNum : kdircR); - pslotNew->Associate(pslot0); - psstrmOutput->NextPut(pslotNew); - - return true; - } - else - { - GrSlotState * pslot0 = psstrmInput->NextGet(); -// GrFeatureValues fval0; -// pslot0->GetFeatureValues(&fval0); - - GrSlotState * pslotNew; - ptman->NewSlotCopy(pslot0, m_ipass, &pslotNew); - if (chw0 == 32) - pslotNew->SetDirectionality(kdircWhiteSpace); - else if (chw0 == '.') - pslotNew->SetDirectionality(kdircComSep); - else - pslotNew->SetDirectionality(fRtl ? kdircR : kdircL); - pslotNew->Associate(pslot0); - psstrmOutput->NextPut(pslotNew); - - return true; - } - } - else - return false; -} - -/*---------------------------------------------------------------------------------------------- - A substitution pass that will do some hard-coded actions resulting in cross-line-boundary - contextuals. -----------------------------------------------------------------------------------------------*/ -void GrEngine::SetUpCrossLineContextTest() -{ - m_fLineBreak = true; - m_cchwPreXlbContext = 2; - m_cchwPostXlbContext = 0; -} - -void GrLineBreakPass::SetUpCrossLineContextTest() -{ - m_nMaxRuleContext = m_nMaxChunk = 1; - m_nMaxRuleLoop = 2; - m_staBehavior = "CrossLineContext"; -} - -void GrSubPass::SetUpCrossLineContextTest() -{ - m_nMaxRuleContext = m_nMaxChunk = 3; - m_nMaxRuleLoop = 2; - m_staBehavior = "CrossLineContext"; -} - -bool GrLineBreakPass::RunCrossLineContextTest(GrTableManager * ptman, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - // '=' { break = intra }; - if ((psstrmInput->SlotsPending() >= 1) && - (psstrmInput->Peek(0)->GlyphID() == 61)) - { - GrSlotState * pslotNew0; - ptman->NewSlotCopy(psstrmInput->NextGet(), m_ipass, &pslotNew0); - pslotNew0->SetBreakWeight(int(klbHyphenBreak)); - psstrmOutput->NextPut(pslotNew0); - - psstrmOutput->SetPosForNextRule(0, psstrmInput, false); - - return true; - } - else - return false; -} - -bool GrSubPass::RunCrossLineContextTest(GrTableManager * ptman, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - // any '=' _ _ > any '=' '=':2 any:1 / _ _ # _ _ - if ((psstrmInput->SlotsPending() >= 3) && - (psstrmInput->Peek(1)->GlyphID() == 61) && - (psstrmInput->Peek(2)->GlyphID() == ptman->LBGlyphID())) - { - GrSlotState * pslot0 = psstrmInput->Peek(0); - GrSlotState * pslot1 = psstrmInput->Peek(1); - gid16 chw0 = pslot0->GlyphID(); -// GrFeatureValues fval0; -// pslot0->GetFeatureValues(&fval0); -// GrFeatureValues fval1; -// pslot1->GetFeatureValues(&fval1); - - // copy the first 3 slots - psstrmOutput->CopyOneSlotFrom(psstrmInput); - psstrmOutput->CopyOneSlotFrom(psstrmInput); - psstrmOutput->CopyOneSlotFrom(psstrmInput); - - // insert 2 more - GrSlotState * pslot3; - ptman->NewSlot(61, pslot1, NULL, m_ipass, &pslot3); - pslot3->Associate(pslot1); - psstrmOutput->NextPut(pslot3); - - GrSlotState * pslot4; - ptman->NewSlot(chw0, pslot0, NULL, m_ipass, &pslot4); - pslot4->Associate(pslot0); - psstrmOutput->NextPut(pslot4); - - return true; - } - else - return false; -} - -/*---------------------------------------------------------------------------------------------- - Line break and substitution passes that cause intra-pass reprocessing (ie, the ^ mechanism). -----------------------------------------------------------------------------------------------*/ - -void GrLineBreakPass::SetUpReprocessTest() -{ - m_nMaxRuleContext = m_nMaxChunk = 2; - m_nMaxRuleLoop = 2; - m_staBehavior = "Reprocess"; -} - -bool GrLineBreakPass::RunReprocessTest(GrTableManager * ptman, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - gid16 chw; - - // '^' {lb=2} / _ lc - if ((psstrmInput->SlotsPending() >=2) && - (psstrmInput->Peek(0)->GlyphID() == '^') && - (((chw = psstrmInput->Peek(1)->GlyphID()) >= 'a') && - (chw <= 'z'))) - { - GrSlotState * pslotNew0; - ptman->NewSlotCopy(psstrmInput->NextGet(), m_ipass, &pslotNew0); - pslotNew0->SetBreakWeight(int(klbHyphenBreak)); - psstrmOutput->NextPut(pslotNew0); - - psstrmOutput->SetPosForNextRule(0, psstrmInput, false); - - return true; - } - else - return false; -} - - -void GrSubPass::SetUpReprocessTest() -{ - m_nMaxRuleContext = m_nMaxChunk = 3; - m_nMaxRuleLoop = 2; - m_staBehavior = "Reprocess"; -} - -bool GrSubPass::RunReprocessTest(GrTableManager * ptman, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - gid16 chw; - gid16 chwLB = ptman->LBGlyphID(); - - // symbol > @2 {dir = DIR_ARABNUMBER} / any {dir != DIR_LEFT} ^ _ - if ((psstrmInput->SlotsPending() >= 2) && - (psstrmInput->Peek(0)->Directionality() != kdircL) && - (((chw = psstrmInput->Peek(1)->GlyphID()) == '@') || - (chw == '@') || (chw == '$') || (chw == '%') || - (chw == '^') || (chw == '&') || (chw == '*'))) - { - psstrmOutput->CopyOneSlotFrom(psstrmInput); - GrSlotState * pslotNew1; - ptman->NewSlotCopy(psstrmInput->NextGet(), m_ipass, &pslotNew1); - pslotNew1->SetDirectionality(kdircArabNum); - psstrmOutput->NextPut(pslotNew1); - - psstrmOutput->SetPosForNextRule(-1, psstrmInput, false); - - return true; - } - - // '^' lc > @1 uc - else if ((psstrmInput->SlotsPending() >= 2) && - (psstrmInput->Peek(0)->GlyphID() == '^') && - (((chw = psstrmInput->Peek(1)->GlyphID()) >= 'a') && - (chw <= 'z'))) - { - psstrmOutput->CopyOneSlotFrom(psstrmInput); - - gid16 chwNew = chw - 'a' + 'A'; - GrSlotState * pslotNew1; - ptman->NewSlotCopy(psstrmInput->NextGet(), m_ipass, &pslotNew1); - pslotNew1->SetGlyphID(chwNew); - psstrmOutput->NextPut(pslotNew1); - - psstrmOutput->SetPosForNextRule(0, psstrmInput, false); - - return true; - } - - // '^' lc > @1 uc / _ # _ - else if ((psstrmInput->SlotsPending() >= 3) && - (psstrmInput->Peek(0)->GlyphID() == '^') && - (psstrmInput->Peek(1)->IsLineBreak(chwLB)) && - (((chw = psstrmInput->Peek(2)->GlyphID()) >= 'a') && - (chw <= 'z'))) - { - psstrmOutput->CopyOneSlotFrom(psstrmInput); - psstrmOutput->CopyOneSlotFrom(psstrmInput); - - gid16 chwNew = chw - 'a' + 'A'; - GrSlotState * pslotNew1; - ptman->NewSlotCopy(psstrmInput->NextGet(), m_ipass, &pslotNew1); - pslotNew1->SetGlyphID(chwNew); - psstrmOutput->NextPut(pslotNew1); - - psstrmOutput->SetPosForNextRule(0, psstrmInput, false); - - return true; - } - - else - return false; -} - - -/*---------------------------------------------------------------------------------------------- - Substitution passes that create contextual forms at the line breaks; also a cross-line- - boundary contextual. -----------------------------------------------------------------------------------------------*/ - -void GrSubPass::SetUpLineEdgeContextTest(int ipass) -{ - m_nMaxRuleContext = (ipass == 2)? 5: 2; - m_nMaxChunk = m_nMaxRuleContext; - m_nMaxRuleLoop = 2; - m_staBehavior = "LineEdgeContext"; -} - -bool GrSubPass::RunLineEdgeContextTest(GrTableManager * ptman, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - gid16 chwLB = ptman->LBGlyphID(); - - // any _ _ > @1 '-' '-' / _ _ _ # - if ((m_ipass == 1) && - (psstrmInput->SlotsPending() >= 2) && - (psstrmInput->Peek(1)->IsLineBreak(chwLB))) - { - GrSlotState * pslot0 = psstrmInput->Peek(0); -// GrFeatureValues fval; -// pslot0->GetFeatureValues(&fval); - - psstrmOutput->CopyOneSlotFrom(psstrmInput); - - GrSlotState * pslotNew1; - ptman->NewSlot('-', pslot0, NULL, m_ipass, &pslotNew1); - pslotNew1->Associate(pslot0); - psstrmOutput->NextPut(pslotNew1); - - GrSlotState * pslotNew2; - ptman->NewSlot('-', pslot0, NULL, m_ipass, &pslotNew2); - pslotNew2->Associate(pslot0); - psstrmOutput->NextPut(pslotNew2); - - return true; - } - - // _ _ any > '+' '+' @4 / # _ _ _ - else if ((m_ipass == 1) && - (psstrmInput->SlotsPending() >= 2) && - (psstrmInput->Peek(0)->IsLineBreak(chwLB))) - { - GrSlotState * pslot2 = psstrmInput->Peek(1); -// GrFeatureValues fval; -// pslot2->GetFeatureValues(&fval); - - psstrmOutput->CopyOneSlotFrom(psstrmInput); - - GrSlotState * pslotNew0; - ptman->NewSlot('+', pslot2, NULL, m_ipass, &pslotNew0); - pslotNew0->Associate(pslot2); - psstrmOutput->NextPut(pslotNew0); - - GrSlotState * pslotNew1; - ptman->NewSlot('+', pslot2, NULL, m_ipass, &pslotNew1); - pslotNew1->Associate(pslot2); - psstrmOutput->NextPut(pslotNew1); - - psstrmOutput->CopyOneSlotFrom(psstrmInput); - - return true; - } - - // '-' '-' '+' '+' > @1 _ _ @4 / _ _ # _ _ - else if ((m_ipass == 2) && - (psstrmInput->SlotsPending() >= 5) && - (psstrmInput->Peek(0)->GlyphID() == '-') && - (psstrmInput->Peek(1)->GlyphID() == '-') && - (psstrmInput->Peek(2)->IsLineBreak(chwLB)) && - (psstrmInput->Peek(3)->GlyphID() == '+') && - (psstrmInput->Peek(4)->GlyphID() == '+')) - { - psstrmOutput->CopyOneSlotFrom(psstrmInput); - psstrmInput->Skip(1); - psstrmOutput->CopyOneSlotFrom(psstrmInput); - psstrmInput->Skip(1); - psstrmOutput->CopyOneSlotFrom(psstrmInput); - - return true; - } - - else - return false; -} - -/*---------------------------------------------------------------------------------------------- - Substitution passes that do something special with pseudo glyphs. -----------------------------------------------------------------------------------------------*/ - -void GrSubPass::SetUpPseudoGlyphsTest() -{ - m_nMaxRuleContext = m_nMaxChunk = 3; - m_nMaxRuleLoop = 2; - m_staBehavior = "PseudoGlyphs"; -} - -bool GrSubPass::RunPseudoGlyphsTest(GrTableManager * ptman, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - gid16 chwLB = ptman->LBGlyphID(); - - // pseudo > uppercase / _ ' ' - if ((psstrmInput->SlotsPending() >= 2) && - (psstrmInput->Peek(0)->GlyphID() > 1000) && // pseudo - (psstrmInput->Peek(1)->GlyphID() == 32)) - { - GrSlotState * pslot0 = psstrmInput->NextGet(); -// GrFeatureValues fval; -// pslot0->GetFeatureValues(&fval); - - GrSlotState * pslotNew; - ptman->NewSlotCopy(pslot0, m_ipass, &pslotNew); - pslotNew->SetGlyphID(pslot0->GlyphID() - 1000); - pslotNew->Associate(pslot0); - psstrmOutput->NextPut(pslotNew); - - psstrmOutput->SetPosForNextRule(0, psstrmInput, false); - - return true; - } - - // pseudo > uppercase / _ | - // pseudo > uppercase / _ # - else if ((psstrmInput->SlotsPending() <= 2) && - (psstrmInput->Peek(0)->GlyphID() > 1000) && // pseudo - (psstrmInput->SlotsPending() < 2 || psstrmInput->Peek(1)->GlyphID() == 35)) - { - GrSlotState * pslot0 = psstrmInput->NextGet(); -// GrFeatureValues fval; -// pslot0->GetFeatureValues(&fval); - - GrSlotState * pslotNew; - ptman->NewSlotCopy(pslot0, m_ipass, &pslotNew); - pslotNew->SetGlyphID(pslot0->GlyphID() - 1000); - pslotNew->Associate(pslot0); - psstrmOutput->NextPut(pslotNew); - - psstrmOutput->SetPosForNextRule(0, psstrmInput, false); - - return true; - } - - // pseudo any _ > lowercase:1 @2 @1 / _ _ ^ _; - else if ((psstrmInput->SlotsPending() >= 3) && - (psstrmInput->Peek(0)->GlyphID() > 1000)) // pseudo - { - GrSlotState * pslot0 = psstrmInput->NextGet(); -// GrFeatureValues fval; -// pslot0->GetFeatureValues(&fval); - - GrSlotState * pslotNew0; - ptman->NewSlot(pslot0->GlyphID()-1000-65+97, pslot0, NULL, m_ipass, &pslotNew0); - pslotNew0->Associate(pslot0); - psstrmOutput->NextPut(pslotNew0); - - psstrmOutput->CopyOneSlotFrom(psstrmInput); - - GrSlotState * pslotNew2; - ptman->NewSlot(pslot0->GlyphID(), pslot0, NULL, m_ipass, &pslotNew2); - pslotNew2->Associate(pslot0); - psstrmOutput->NextPut(pslotNew2); - - psstrmOutput->SetPosForNextRule(-1, psstrmInput, false); - - return true; - } - else - return false; -} - -/*---------------------------------------------------------------------------------------------- - Substitution pass that tests reversing numbers. -----------------------------------------------------------------------------------------------*/ -void GrSubPass::SetUpBidiNumbersTest() -{ - m_nMaxRuleContext = m_nMaxChunk = 1; - m_nMaxRuleLoop = 2; - m_staBehavior = "BidiNumbers"; -} - -bool GrSubPass::RunBidiNumbersTest(GrTableManager * ptman, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - gid16 chw0; - - // clsDigit > clsDigit { dir = DIR_ARABNUMBER }; - if ((psstrmInput->SlotsPending() >= 1) && - (((chw0 = psstrmInput->Peek(0)->GlyphID()) >= '0' && chw0 <= '9') || - (chw0 >= 'A' && chw0 <= 'Z') || (chw0 >= 'a' && chw0 <= 'z'))) - { - GrSlotState * pslot0 = psstrmInput->NextGet(); -// GrFeatureValues fval0; -// pslot0->GetFeatureValues(&fval0); - - GrSlotState * pslotNew; - ptman->NewSlot(chw0, pslot0, NULL, m_ipass, &pslotNew); - if (chw0 >= '0' && chw0 <= '9') - pslotNew->SetDirectionality(kdircArabNum); - else // a-z and A-Z - pslotNew->SetDirectionality(kdircR); - pslotNew->Associate(pslot0); - psstrmOutput->NextPut(pslotNew); - - return true; - } - else - return false; -} - -void GrBidiPass::SetUpBidiNumbersTest() -{ - m_nMaxRuleContext = m_nMaxChunk = 1; - m_nMaxRuleLoop = 2; - m_nTopDirection = 1; -} - -/*---------------------------------------------------------------------------------------------- - Substitution pass that tests the bidi algorithm thoroughly. -----------------------------------------------------------------------------------------------*/ -void GrSubPass::SetUpBidiAlgorithmTest() -{ - m_nMaxRuleContext = m_nMaxChunk = 1; - m_nMaxRuleLoop = 2; - m_staBehavior = "BidiAlgorithm"; -} - -bool GrSubPass::RunBidiAlgorithmTest(GrTableManager * ptman, - GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput) -{ - gid16 chw0; - - if (psstrmInput->SlotsPending() >= 1) - { - chw0 = psstrmInput->Peek(0)->GlyphID(); - - DirCode dircNew; - - if (chw0 >= '0' && chw0 <= '9') - dircNew = kdircEuroNum; - else if (chw0 >= 'a' && chw0 <= 'z') - dircNew = kdircL; - else if (chw0 >= 'A' && chw0 <= 'M') - dircNew = kdircR; - else if (chw0 >= 'N' && chw0 <= 'T') - dircNew = kdircRArab; - else if (chw0 >= 'U' && chw0 <= 'Z') - dircNew = kdircArabNum; - else if (chw0 == '$' || chw0 == '%') - dircNew = kdircEuroTerm; - else if (chw0 == '.' || chw0 == '*' || chw0 == '+') - dircNew = kdircEuroSep; - else if (chw0 == '@') - dircNew = kdircComSep; - else if (chw0 == '_' || chw0 == '=') - dircNew = kdircNeutral; - else if (chw0 == ':') - dircNew = kdircNSM; - else - return false; - - GrSlotState * pslot0 = psstrmInput->NextGet(); -// GrFeatureValues fval0; -// pslot0->GetFeatureValues(&fval0); - - GrSlotState * pslotNew; - ptman->NewSlot(chw0, pslot0, NULL, m_ipass, &pslotNew); - pslotNew->SetDirectionality(dircNew); - pslotNew->Associate(pslot0); - psstrmOutput->NextPut(pslotNew); - - return true; - } - else - return false; -} - -void GrBidiPass::SetUpBidiAlgorithmTest() -{ - m_nMaxRuleContext = m_nMaxChunk = 1; - m_nMaxRuleLoop = 2; - m_nTopDirection = 0; -} - - -#endif // _DEBUG - -} // namespace gr - -#endif // OLD_TEST_STUFF - -//:End Ignore diff --git a/Build/source/libs/graphite-engine/src/segment/TransductionLog.cpp b/Build/source/libs/graphite-engine/src/segment/TransductionLog.cpp deleted file mode 100644 index 73273ae3feb..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/TransductionLog.cpp +++ /dev/null @@ -1,2091 +0,0 @@ -/*--------------------------------------------------------------------*//*:Ignore this sentence. -Copyright (C) 2000 - 2008 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: TransductionLog.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Contains the functions for writing a log of the transduction process. -----------------------------------------------------------------------------------------------*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" - -#ifdef _MSC_VER -#pragma hdrstop -#endif - -#include <math.h> - -#undef THIS_FILE -DEFINE_THIS_FILE - -//:End Ignore - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -namespace gr -{ - -//:>******************************************************************************************** -//:> Methods -//:>******************************************************************************************** - -#define SP_PER_SLOT 7 -#define LEADING_SP 15 -#define MAX_SLOTS 128 - -/*---------------------------------------------------------------------------------------------- - Output a file showing a log of the transduction process and the resulting segment. -----------------------------------------------------------------------------------------------*/ -//bool GrTableManager::WriteTransductionLog(GrCharStream * pchstrm, Segment * psegRet, -// int cbPrevSegDat, byte * pbPrevSegDat, byte * pbNextSegDat, int * pcbNextSegDat) -//{ -//#ifdef TRACING -// std::string staFile; -// if (!LogFileName(staFile)) -// return false; -// -// std::ofstream strmOut; -// if (cbPrevSegDat > 0) -// strmOut.open(staFile.c_str(), std::ios::app); // append -// else -// strmOut.open(staFile.c_str()); -// if (strmOut.fail()) -// return false; -// -// WriteXductnLog(strmOut, pchstrm, psegRet, cbPrevSegDat, pbPrevSegDat); -// -// strmOut.close(); -// return true; -//#else -// return false; -//#endif // TRACING -//} - -bool GrTableManager::WriteTransductionLog(std::ostream * pstrmLog, - GrCharStream * pchstrm, Segment * psegRet, int cbPrevSegDat, byte * pbPrevSegDat) -{ -#ifdef TRACING - if (!pstrmLog) - return false; - std::ostream & strmOut = *pstrmLog; - WriteXductnLog(strmOut, pchstrm, psegRet, cbPrevSegDat, pbPrevSegDat); - return true; -#else - return false; -#endif // TRACING -} - -/*---------------------------------------------------------------------------------------------- - Append to the file, showing the surface/underlying mappings. This must be done after - figuring out all the associations. - - Also write the final glyph positions, since they are now determined. -----------------------------------------------------------------------------------------------*/ -//bool GrTableManager::WriteAssociationLog(GrCharStream * pchstrm, Segment * psegRet) -//{ -//#ifdef TRACING -// std::string staFile; -// if (!LogFileName(staFile)) -// return false; -// -// std::ofstream strmOut; -// strmOut.open(staFile.c_str(), std::ios::app); // append -// if (strmOut.fail()) -// return false; -// -// LogFinalPositions(strmOut); -// -// strmOut << "\n\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n"; -// -// psegRet->LogUnderlyingToSurface(this, strmOut, pchstrm); -// psegRet->LogSurfaceToUnderlying(this, strmOut); -// -// strmOut << "\n\n=======================================================================\n\n"; -// -// strmOut.close(); -// return true; -//#else -// return false; -//#endif // TRACING -//} - - -bool GrTableManager::WriteAssociationLog(std::ostream * pstrmLog, - GrCharStream * pchstrm, Segment * psegRet) -{ -#ifdef TRACING - if (!pstrmLog) - return false; - - std::ostream & strmOut = *pstrmLog; - - psegRet->LogUnderlyingToSurface(this, strmOut, pchstrm); - psegRet->LogSurfaceToUnderlying(this, strmOut); - - strmOut << "\n\n=======================================================================\n\n"; - - return true; -#else - return false; -#endif // TRACING -} - -#ifdef TRACING - -/*---------------------------------------------------------------------------------------------- - Generate the name of the file where the log will be written. It goes in the directory - defined by either the TEMP or TMP environment variable. - - TODO: remove -----------------------------------------------------------------------------------------------*/ -//bool GrTableManager::LogFileName(std::string & staFile) -//{ -// char * pchTmpEnv = getenv("TEMP"); -// if (pchTmpEnv == 0) -// pchTmpEnv = getenv("TMP"); -// if (pchTmpEnv == 0) -// return false; -// -// staFile.assign(pchTmpEnv); -// if (staFile[staFile.size() - 1] != '\\') -// staFile.append("\\"); -// staFile.append("gr_xductn.log"); -// -// return true; -//} - -/*---------------------------------------------------------------------------------------------- - Output a file showing a log of the transduction process and the resulting segment. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::WriteXductnLog(std::ostream & strmOut, - GrCharStream * pchstrm, Segment * psegRet, - int cbPrevSegDat, byte * pbPrevSegDat) -{ - if (cbPrevSegDat == 0) - LogUnderlying(strmOut, pchstrm, 0); - else - { - Assert(*(pbPrevSegDat + 4) == 0); // skip offset for first pass - LogUnderlying(strmOut, pchstrm, *(pbPrevSegDat + 3)); - } - - LogPass1Input(strmOut); - - for (int ipass = 1; ipass < m_cpass; ipass++) - { - if (cbPrevSegDat == 0) - LogPassOutput(strmOut, ipass, 0); - else - LogPassOutput(strmOut, ipass, *(pbPrevSegDat + 4 + ipass)); - } - - LogFinalPositions(strmOut); - - strmOut << "\n\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n"; -} - -/*---------------------------------------------------------------------------------------------- - Write out a log of the underlying input. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogUnderlying(std::ostream & strmOut, GrCharStream * pchstrm, - int cchwBackup) -{ - strmOut << "UNDERLYING INPUT\n\n"; - - int rgnChars[MAX_SLOTS]; - bool rgfNewRun[MAX_SLOTS]; - std::fill_n(rgfNewRun, MAX_SLOTS, false); - GrFeatureValues rgfval[MAX_SLOTS]; - int cchwMaxRawChars; - - int cnUtf32 = pchstrm->GetLogData(this, rgnChars, rgfNewRun, rgfval, - cchwBackup, &cchwMaxRawChars); - cnUtf32 = min(cnUtf32, MAX_SLOTS); - - int ichw; - - // For UTF-8 and surrogate representation: - utf16 rgchwChars2[MAX_SLOTS]; - utf16 rgchwChars3[MAX_SLOTS]; - utf16 rgchwChars4[MAX_SLOTS]; - utf16 rgchwChars5[MAX_SLOTS]; - utf16 rgchwChars6[MAX_SLOTS]; - int rgcchwRaw[MAX_SLOTS]; - - if (cchwMaxRawChars > 1) - { - cchwMaxRawChars = min(cchwMaxRawChars, 6); // max of 6 raw (UTF-8 or UTF-16) chars per slot - pchstrm->GetLogDataRaw(this, cnUtf32, cchwBackup, cchwMaxRawChars, - rgnChars, rgchwChars2, rgchwChars3, rgchwChars4, rgchwChars5, rgchwChars6, - rgcchwRaw); - } - else - { - for (ichw = 0; ichw < cnUtf32; ichw++) - { - rgcchwRaw[ichw] = 1; - rgchwChars2[ichw] = 0; - rgchwChars3[ichw] = 0; - rgchwChars4[ichw] = 0; - rgchwChars5[ichw] = 0; - rgchwChars6[ichw] = 0; - } - } - - LogUnderlyingHeader(strmOut, pchstrm->Min(), (pchstrm->Min() + cnUtf32 - cchwBackup), - cchwBackup, rgcchwRaw); - - // Text - strmOut << "Text: "; // 15 spaces - for (ichw = 0; ichw < cnUtf32; ichw++) - { - if (rgnChars[ichw] < 0x0100 && rgchwChars2[ichw] == 0) // ANSI - strmOut << (char)rgnChars[ichw] << " "; // 6 spaces - else if (rgnChars[ichw] == knLRM) - strmOut << "<LRM> "; - else if (rgnChars[ichw] == knRLM) - strmOut << "<RLM> "; - else if (rgnChars[ichw] == knLRO) - strmOut << "<LRO> "; - else if (rgnChars[ichw] == knRLO) - strmOut << "<RLO> "; - else if (rgnChars[ichw] == knLRE) - strmOut << "<LRE> "; - else if (rgnChars[ichw] == knRLE) - strmOut << "<RLE> "; - else if (rgnChars[ichw] == knPDF) - strmOut << "<PDF> "; - else - strmOut << " "; - } - strmOut << "\n"; - - // Unicode - strmOut << "Unicode: "; - for (ichw = 0; ichw < cnUtf32; ichw++) - LogHexInTable(strmOut, utf16(rgnChars[ichw])); - strmOut << "\n"; - for (int icchRaw = 2; icchRaw <= cchwMaxRawChars; icchRaw++) - { - strmOut << " "; - for (ichw = 0; ichw < cnUtf32; ichw++) - { - utf16 chw; - switch (icchRaw) - { - case 2: chw = rgchwChars2[ichw]; break; - case 3: chw = rgchwChars3[ichw]; break; - case 4: chw = rgchwChars4[ichw]; break; - case 5: chw = rgchwChars5[ichw]; break; - case 6: chw = rgchwChars6[ichw]; break; - default: chw = 0; - } - if (chw == 0) - strmOut << " "; - else - LogHexInTable(strmOut, chw); - } - strmOut << "\n"; - } - - // Runs - strmOut << "Runs: "; - int crun = 0; - for (ichw = 0; ichw < cnUtf32; ichw++) - { - if (rgfNewRun[ichw]) - { - crun++; - strmOut << "|" << crun << ((crun < 10) ? " " : " "); - } - else - strmOut << " "; - } - strmOut << "\n"; - - // Features - strmOut << "Features and character properties:\n"; - crun = 0; - for (ichw = 0; ichw < cnUtf32; ichw++) - { - if (rgfNewRun[ichw]) - { - crun++; - strmOut << " Run " << crun << ": "; - rgfval[ichw].WriteXductnLog(this, strmOut); - - } - } -} - - -void GrFeatureValues::WriteXductnLog(GrTableManager * ptman, std::ostream & strmOut) -{ - bool fFirst = true; - for (int i = 0; i < kMaxFeatures; i++) - { - if (m_rgnFValues[i] != 0) - { - GrFeature * pfeat = ptman->Feature(i); - if (!fFirst) - strmOut << ","; - strmOut << pfeat->ID() << "=" << m_rgnFValues[i]; - fFirst = false; - } - } - if (fFirst) - strmOut << "all features=0"; - - strmOut << "\n\n"; -} - -/*---------------------------------------------------------------------------------------------- - Loop through the input stream of underlying characters, storing information in the - arrays for the log. - ENHANCE SharonC: do we need to show the underline properties? -----------------------------------------------------------------------------------------------*/ -int GrCharStream::GetLogData(GrTableManager * ptman, int * rgchl, bool * rgfNewRun, - GrFeatureValues * rgfval, int cchrBackup, int * pcchrMax) -{ - Assert(cchrBackup <= m_cchrBackedUp); - - int ichrPosToStop = m_ichrPos; - int ichrStart = m_ichrMin - max(cchrBackup, m_cchrBackedUp); - - *pcchrMax = 0; - - // Restart the stream. - m_ichrPos = ichrStart; - m_ichrRunMin = 0; - m_ichrRunLim = 0; - m_ichrRunOffset = kPosInfinity; - m_vislotNextChunkMap.clear(); - - int cchrSkipBackup = m_cchrBackedUp - cchrBackup; - - int c = 0; - int cchr = 0; - - while (m_ichrPos < ichrPosToStop) - { - if ((c < MAX_SLOTS) && (m_ichrPos >= m_ichrRunLim)) - { - rgfNewRun[c] = true; - } - - GrFeatureValues fval; - int ichrOffset, cchrThis; - int chl = NextGet(ptman, &fval, &ichrOffset, &cchrThis); - cchr += cchrThis; - if (cchr <= cchrSkipBackup) - {} // ignore - this is before the pre-segment stuff that we want to skip - else if (c < MAX_SLOTS) - { - rgchl[c] = chl; - *pcchrMax = max(*pcchrMax, cchrThis); - if (rgfNewRun[c]) - { - rgfval[c] = fval; - } - c++; - } - } - - ////return (m_ichwPos - (m_ichwMin - cchwBackup)); - return c; -} - -/*---------------------------------------------------------------------------------------------- - If any of the characters are comprised of surrogates or UTF-8, fill in the arrays with - the raw (UTF-16 or UTF-8) chars for display. To do this we get the raw characters - directly from the text source. -----------------------------------------------------------------------------------------------*/ -void GrCharStream::GetLogDataRaw(GrTableManager * ptman, int cchl, int cchrBackup, - int cchrMaxRaw, int * prgchl, - utf16 * prgchw2, utf16 * prgchw3, utf16 * prgchw4, utf16 * prgchw5, utf16 * prgchw6, - int * prgcchr) -{ - for (int i = 0; i < cchl; i++) - { - prgchw2[i] = 0; - } - - int ichrLim = m_ichrPos; - int ichrMin = m_ichrMin - cchrBackup; - - int cchrRange = ichrLim - ichrMin; - int ichr; - utf16 * prgchwRunText = new utf16[cchrRange]; - utf8 * prgchsRunText8 = NULL; - - UtfType utf = m_pgts->utfEncodingForm(); - - switch (utf) - { - case kutf8: - prgchsRunText8 = new utf8[cchrRange]; - m_pgts->fetch(ichrMin, cchrRange, prgchsRunText8); - for (int ichr = 0; ichr < cchrRange; ichr++) - prgchwRunText[ichr] = (utf16)prgchsRunText8[ichr]; // zero-extend into UTF-16 buffer - break; - case kutf16: - m_pgts->fetch(ichrMin, cchrRange, prgchwRunText); - break; - default: - case kutf32: // this method should never have been called - Assert(false); - for (int ichrLp = 0; ichrLp < cchrRange; ichrLp++) - { - prgcchr[ichrLp] = 1; - prgchw2[ichrLp] = 0; - prgchw3[ichrLp] = 0; - prgchw4[ichrLp] = 0; - prgchw5[ichrLp] = 0; - prgchw6[ichrLp] = 0; - } - return; - } - - ichr = ichrMin; - int ichl = 0; - while (ichr < ichrLim) - { - int cchrThis = 1; - // Replace 32-bit char with (first) 16-bit or 8-bit char. - prgchl[ichl] = (int)prgchwRunText[ichr - ichrMin]; - prgcchr[ichr] = cchrThis; - ichr++; - - while (!AtUnicodeCharBoundary(prgchwRunText, cchrRange, ichr - ichrMin, utf)) - { - cchrThis++; - switch (cchrThis) - { - case 2: prgchw2[ichl] = prgchwRunText[ichr - ichrMin]; break; - case 3: prgchw3[ichl] = prgchwRunText[ichr - ichrMin]; break; - case 4: prgchw4[ichl] = prgchwRunText[ichr - ichrMin]; break; - case 5: prgchw5[ichl] = prgchwRunText[ichr - ichrMin]; break; - case 6: prgchw6[ichl] = prgchwRunText[ichr - ichrMin]; break; - default: - break; - } - prgcchr[ichr] = cchrThis; - ichr++; - } - switch (cchrThis) - { - case 1: - prgchw2[ichl] = 0; - // fall through - case 2: - prgchw3[ichl] = 0; - // fall through - case 3: - prgchw4[ichl] = 0; - // fall through - case 4: - prgchw5[ichl] = 0; - // fall through - case 5: - prgchw6[ichl] = 0; - } - ichl++; - } - - delete[] prgchwRunText; - delete[] prgchsRunText8; -} - -/*---------------------------------------------------------------------------------------------- - Output the glyph IDs generated by the glyph generation pass (pass 0). -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogPass1Input(std::ostream & strmOut) -{ - strmOut << "INPUT TO PASS 1\n\n"; - - GrSlotStream * psstrm = OutputStream(0); - - LogSlotHeader(strmOut, psstrm->WritePos(), SP_PER_SLOT, LEADING_SP); - - LogSlotGlyphs(strmOut, psstrm); - - strmOut << "\n"; -} - -/*---------------------------------------------------------------------------------------------- - Output the the results of pass. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogPassOutput(std::ostream & strmOut, int ipass, int cslotSkipped) -{ - strmOut << "\n"; - - GrPass * ppass = Pass(ipass); - GrSlotStream * psstrmIn = InputStream(ipass); - GrSlotStream * psstrmOut = OutputStream(ipass); - - int islot; - // Mark each slot with its index in the input and output streams. - for (islot = 0; islot < psstrmIn->ReadPos(); islot++) - psstrmIn->SlotAt(islot)->m_islotTmpIn = islot; - - for (islot = 0; islot < psstrmOut->WritePos(); islot++) - psstrmOut->SlotAt(islot)->m_islotTmpOut = islot; - - if (!dynamic_cast<GrBidiPass *>(ppass)) - ppass->LogRulesFiredAndFailed(strmOut, psstrmIn); - - strmOut << "\nOUTPUT OF PASS " << ipass; - if (dynamic_cast<GrBidiPass *>(ppass)) - strmOut << " (bidi)"; - else if (dynamic_cast<GrSubPass *>(ppass)) - { - if (ipass >= m_ipassJust1) - strmOut << " (justification)"; - else - strmOut << " (substitution)"; - } - else if (dynamic_cast<GrPosPass *>(ppass)) - strmOut << " (positioning)"; - else if (dynamic_cast<GrLineBreakPass *>(ppass)) - strmOut << " (linebreak)"; - strmOut << "\n"; - - ppass->LogInsertionsAndDeletions(strmOut, psstrmOut); - - LogSlotHeader(strmOut, psstrmOut->WritePos(), SP_PER_SLOT, LEADING_SP); - - LogSlotGlyphs(strmOut, psstrmOut); - - bool fAnyPseudos = false; - if (dynamic_cast<GrPosPass *>(ppass)) - { - for (islot = 0; islot < psstrmOut->WritePos(); islot++) - { - GrSlotState * pslotTmp = psstrmOut->SlotAt(islot); - if (pslotTmp->GlyphID() != pslotTmp->ActualGlyphForOutput(this)) - { - fAnyPseudos = true; - break; - } - } - } - if (fAnyPseudos) - { - strmOut << "Actual glyphs: "; - for (islot = 0; islot < psstrmOut->WritePos(); islot++) - { - GrSlotState * pslotTmp = psstrmOut->SlotAt(islot); - if (pslotTmp->GlyphID() != pslotTmp->ActualGlyphForOutput(this)) - LogHexInTable(strmOut, pslotTmp->ActualGlyphForOutput(this)); - else - strmOut << " "; - } - strmOut << "\n"; - } - - LogAttributes(strmOut, ipass); - - // Do this later, after we're sure the positions have been set: - //if (ipass == m_cpass - 1) - // LogFinalPositions(strmOut); - - if (cslotSkipped > 0) - { - strmOut << "\n "; - for (islot = 0; islot < cslotSkipped; islot++) - strmOut << "SKIP "; - strmOut << "\n"; - } - - // If this was the pass just before the justification routines get run, output a - // special line that just shows the results, ie, the values of justify.width. - // TODO: adjust this when measure mode get functioning. - if (ipass == m_ipassJust1 - 1 && ShouldLogJustification() - && m_engst.m_jmodi == kjmodiJustify) - { - strmOut << "\nJUSTIFICATION\n\n"; - LogSlotHeader(strmOut, psstrmOut->WritePos(), SP_PER_SLOT, LEADING_SP); - LogSlotGlyphs(strmOut, psstrmOut); - LogAttributes(strmOut, ipass, true); - } -} - -/*---------------------------------------------------------------------------------------------- - Write the list of rules fired and failed for a given pass. -----------------------------------------------------------------------------------------------*/ -void GrPass::LogRulesFiredAndFailed(std::ostream & strmOut, GrSlotStream * psstrmIn) -{ - m_pzpst->LogRulesFiredAndFailed(strmOut, psstrmIn); -} - -void PassState::LogRulesFiredAndFailed(std::ostream & strmOut, GrSlotStream * psstrmIn) -{ - - strmOut << "PASS " << m_ipass << "\n\n" << "Rules matched: "; - if (m_crulrec == 0) - strmOut << "none"; - strmOut << "\n"; - - for (int irulrec = 0; irulrec < m_crulrec; irulrec++) - { - if (m_rgrulrec[irulrec].m_fFired) - strmOut << " * "; - else - strmOut << " "; - - strmOut << m_rgrulrec[irulrec].m_islot << ". "; - - if (m_rgrulrec[irulrec].m_irul == PassState::kHitMaxRuleLoop) - strmOut << "hit MaxRuleLoop\n"; - else if (m_rgrulrec[irulrec].m_irul == PassState::kHitMaxBackup) - strmOut << "hit MaxBackup\n"; - else - { - strmOut << "rule " << m_ipass << "." << m_rgrulrec[irulrec].m_irul; - - if (m_rgrulrec[irulrec].m_fFired) - strmOut << " FIRED\n"; - else - strmOut << " failed\n"; - } - } -} - -/*---------------------------------------------------------------------------------------------- - Write out the marks on top of the slot table indicating insertions and deletions. -----------------------------------------------------------------------------------------------*/ -void GrPass::LogInsertionsAndDeletions(std::ostream & strmOut, GrSlotStream * psstrmOut) -{ - m_pzpst->LogInsertionsAndDeletions(strmOut, psstrmOut); -} - -void PassState::LogInsertionsAndDeletions(std::ostream & strmOut, GrSlotStream * psstrmOut) -{ - int cslotDel = m_rgcslotDeletions[0]; - bool fIns; - if (cslotDel > 1) - strmOut << "\n DEL-" << cslotDel; - else if (cslotDel == 1) - strmOut << "\n DEL "; - else - strmOut << "\n "; - - for (int islot = 0; islot < psstrmOut->WritePos(); islot++) - { - cslotDel = (islot + 1 >= MAX_SLOTS) ? 0 : m_rgcslotDeletions[islot + 1]; - fIns = (islot >= MAX_SLOTS) ? 0 : m_rgfInsertion[islot]; - - if (fIns) - { - strmOut << "INS"; - if (cslotDel > 0) - { - if (cslotDel > 1) - strmOut << "/D-" << cslotDel; - else - strmOut << "/DEL"; - } - else - strmOut << " "; - - } - else if (cslotDel > 0) - { - if (cslotDel >= 10) - strmOut << "DEL-" << cslotDel << " "; - else if (cslotDel > 1) - strmOut << " DEL-" << cslotDel << " "; - else - strmOut << " DEL "; - } - else - strmOut << " "; - } - - strmOut << "\n"; -} - -/*---------------------------------------------------------------------------------------------- - Write out a line for each slot attribute that changed during the pass. - - @param fJustWidths - a special pass that writes out just the effects of the justification - routines, ie, the values of justify.width -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogAttributes(std::ostream & strmOut, int ipass, - bool fJustWidths) -{ - // Figure out which slot attributes were modified for some slot during the pass. - bool * prgfMods = new bool[kslatMax + NumUserDefn() - 1]; - - bool fPreJust = (!fJustWidths && ipass == m_ipassJust1 - 1 && ShouldLogJustification()); - bool fPostJust = ((fJustWidths || ipass == m_ipassJust1) && ShouldLogJustification()); - - int ccomp; // max number of components per slot - int cassoc; // max number of associations per slot - SlotAttrsModified(ipass, prgfMods, fPreJust, &ccomp, &cassoc); - - if (fPreJust) - { - // prgfMods[kslatJStretch] = true; - // prgfMods[kslatJShrink] = true; - // prgfMods[kslatJStep] = true; - // prgfMods[kslatWeight] = true; - prgfMods[kslatJWidth] = false; // output j.width in its own line (we call this - // method with fJustWidths == true) - } - else if (fPostJust) - prgfMods[kslatJWidth] = true; - - GrPass * ppass = Pass(ipass); - GrPass * ppassNext = (ipass < m_cpass - 1) ? Pass(ipass + 1) : NULL; - GrSlotStream * psstrm = OutputStream(ipass); - - if (fJustWidths) - {} - else if (dynamic_cast<GrBidiPass *>(ppass)) - { - // Special stuff for Bidi pass: - // Log value of directionality attribute. - strmOut << "directionality "; - int islot; - for (islot = 0; islot < psstrm->WritePos(); islot++) - { - GrSlotState * pslot = psstrm->SlotAt(islot); - LogDirCodeInTable(strmOut, pslot->DirProcessed()); - } - strmOut << "\n"; - - // Log final direction level for bidi pass. - strmOut << "dir level "; - for (islot = 0; islot < psstrm->WritePos(); islot++) - { - GrSlotState * pslot = psstrm->SlotAt(islot); - LogInTable(strmOut, pslot->DirLevel()); - } - strmOut << "\n"; - } - else if (ppassNext && dynamic_cast<GrBidiPass *>(ppassNext)) - { - // Next pass is Bidi: log input values of directionality attribute that are input for it. - strmOut << "directionality "; - for (int islot = 0; islot < psstrm->WritePos(); islot++) - { - GrSlotState * pslot = psstrm->SlotAt(islot); - LogDirCodeInTable(strmOut, pslot->Directionality()); - } - strmOut << "\n"; - } - - for (int slat = 0; slat < kslatMax + NumUserDefn() - 1; slat++) - { - int cIndexLim = 1; - if (slat == kslatCompRef) - cIndexLim = ccomp; - else if (slat == kslatUserDefn) - cIndexLim = 1; // kMaxUserDefinedSlotAttributes; - - if (fJustWidths && slat != kslatJWidth) - continue; - - bool fValidAttr = true; - for (int iIndex = 0; iIndex < cIndexLim; iIndex++) - { - if (prgfMods[slat]) - { - switch(slat) - { - case kslatAdvX: strmOut << "advance.x "; break; - case kslatAdvY: strmOut << "advance.y "; break; - case kslatAttTo: strmOut << "att.to "; break; - case kslatAttAtX: strmOut << "att.at.x "; break; - case kslatAttAtY: strmOut << "att.at.y "; break; - case kslatAttAtGpt: strmOut << "att.at.gpt "; break; - case kslatAttAtXoff: strmOut << "att.at.xoff "; break; - case kslatAttAtYoff: strmOut << "att.at.yoff "; break; - case kslatAttWithX: strmOut << "att.with.x "; break; - case kslatAttWithY: strmOut << "att.with.y "; break; - case kslatAttWithGpt: strmOut << "att.with.gpt "; break; - case kslatAttWithXoff: strmOut << "att.with.xoff "; break; - case kslatAttWithYoff: strmOut << "att.with.yoff "; break; - case kslatAttLevel: strmOut << "att.level "; break; - case kslatBreak: strmOut << "breakweight "; break; - case kslatCompRef: strmOut << "component " << iIndex + 1 // 1-based - << " "; break; - case kslatDir: strmOut << "dir "; break; - case kslatInsert: strmOut << "insert "; break; - case kslatMeasureSol: strmOut << "measure.sol "; break; - case kslatMeasureEol: strmOut << "measure.eol "; break; - case kslatJStretch: strmOut << "j.stretch "; break; - case kslatJShrink: strmOut << "j.shrink "; break; - case kslatJStep: strmOut << "j.step "; break; - case kslatJWeight: strmOut << "j.weight "; break; - case kslatJWidth: strmOut << "j.width "; break; - case kslatPosX: - case kslatPosY: - Assert(false); - break; - case kslatShiftX: strmOut << "shift.x "; break; - case kslatShiftY: strmOut << "shift.y "; break; - default: - if (kslatUserDefn <= slat && - slat < kslatUserDefn + NumUserDefn()) - { - strmOut << "user" << (slat - kslatUserDefn + 1) // 1-based - << ((iIndex >= 9) ? " " : " "); - } - else - { - // Invalid attribute: - Warn("bad slot attribute"); - fValidAttr = false; - break; - } - } - - if (!fValidAttr) - break; // out of iIndex loop - - for (int islot = 0; islot < psstrm->WritePos(); islot++) - { - GrSlotState * pslot = psstrm->SlotAt(islot); - pslot->LogSlotAttributeValue(this, strmOut, ipass, slat, iIndex, - fPreJust, fPostJust); - } - - strmOut << "\n"; - } - } - } - - if (fJustWidths) - goto LDone; - - for (int iassoc = 0; iassoc < cassoc; iassoc++) - { - // Log associations. Put them on one line it that will work; otherwise use several. - bool fBoth = (cassoc <= 2); - bool fAfter = (iassoc == (cassoc - 1)); - if (fBoth) - strmOut << "assocs "; - else if (iassoc == 0) - strmOut << "assocs-before "; - else if (fAfter) - strmOut << " -after "; - else - strmOut << " -other "; - - for (int islot = 0; islot < psstrm->WritePos(); islot++) - { - GrSlotState * pslot = psstrm->SlotAt(islot); - pslot->LogAssociation(this, strmOut, ipass, iassoc, fBoth, fAfter); - } - - strmOut << "\n"; - - if (fBoth) - break; - } - - if (cassoc == 0 && dynamic_cast<GrBidiPass *>(ppass)) - { - strmOut << "assocs "; - - // Log associations for all slots moved during the Bidi pass. - for (int islot = 0; islot < psstrm->WritePos(); islot++) - { - GrSlotState * pslot = psstrm->SlotAt(islot); - if (pslot->m_islotTmpIn != pslot->m_islotTmpOut) - LogInTable(strmOut, pslot->m_islotTmpIn); - else - strmOut << " "; - } - - strmOut << "\n"; - } - -LDone: - - delete[] prgfMods; -} - -/*---------------------------------------------------------------------------------------------- - Write out the final positions. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogFinalPositions(std::ostream & strmOut) -{ - GrSlotStream * psstrm = OutputStream(m_cpass - 1); - - strmOut << "x position "; - for (int islot = 0; islot < psstrm->WritePos(); islot++) - { - GrSlotState * pslot = psstrm->SlotAt(islot); - if (pslot->IsLineBreak(LBGlyphID())) - { - strmOut << " "; - continue; - } - LogInTable(strmOut, pslot->XPosition()); - } - strmOut << "\n"; - - strmOut << "y position "; - for (int islot = 0; islot < psstrm->WritePos(); islot++) - { - GrSlotState * pslot = psstrm->SlotAt(islot); - if (pslot->IsLineBreak(LBGlyphID())) - { - strmOut << " "; - continue; - } - LogInTable(strmOut, pslot->YPosition()); - } - strmOut << "\n"; -} -#endif // TRACING - -/*---------------------------------------------------------------------------------------------- - Write out the final underlying-to-surface associations. -----------------------------------------------------------------------------------------------*/ -void Segment::LogUnderlyingToSurface(GrTableManager * ptman, std::ostream & strmOut, - GrCharStream * pchstrm) -{ -#ifdef TRACING - strmOut << "\n\nUNDERLYING TO SURFACE MAPPINGS\n\n"; - - size_t cassocs = 0; - int fLigs = false; - int ichw; - for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - if (m_prgpvisloutAssocs[ichw]) - cassocs = max(cassocs, m_prgpvisloutAssocs[ichw]->size()); - if (m_prgisloutLigature[ichw] != kNegInfinity) - fLigs = true; - } - -// ptman->LogSlotHeader(strmOut, m_ichwAssocsLim, SP_PER_SLOT, LEADING_SP, m_ichwAssocsMin); - ptman->LogUnderlyingHeader(strmOut, pchstrm->Min(), (pchstrm->Min() + m_ichwAssocsLim), - -m_ichwAssocsMin, NULL); - - int rgnChars[MAX_SLOTS]; - bool rgfNewRun[MAX_SLOTS]; - std::fill_n(rgfNewRun, MAX_SLOTS, false); - GrFeatureValues rgfval[MAX_SLOTS]; - int cchwMaxRawChars; - - int cchw = pchstrm->GetLogData(ptman, rgnChars, rgfNewRun, rgfval, - -m_ichwAssocsMin, &cchwMaxRawChars); - cchw = min(cchw, MAX_SLOTS); - - utf16 rgchwChars2[MAX_SLOTS]; - utf16 rgchwChars3[MAX_SLOTS]; - utf16 rgchwChars4[MAX_SLOTS]; - utf16 rgchwChars5[MAX_SLOTS]; - utf16 rgchwChars6[MAX_SLOTS]; - int rgcchwRaw[MAX_SLOTS]; - if (cchwMaxRawChars > 1) - { - cchwMaxRawChars = min(cchwMaxRawChars, 6); - pchstrm->GetLogDataRaw(ptman, cchw, -m_ichwAssocsMin, cchwMaxRawChars, - rgnChars, rgchwChars2, rgchwChars3, rgchwChars4, rgchwChars5, rgchwChars6, - rgcchwRaw); - } - else - { - for (ichw = 0 ; ichw <(m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - rgcchwRaw[ichw] = 1; - rgchwChars2[ichw] = 0; - rgchwChars3[ichw] = 0; - rgchwChars4[ichw] = 0; - rgchwChars5[ichw] = 0; - rgchwChars6[ichw] = 0; - } - } - - // Text - strmOut << "Text: "; // 15 spaces - int inUtf32 = 0; - for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - utf16 chw, chwNext; - switch (rgcchwRaw[ichw]) - { - default: - case 1: chw = utf16(rgnChars[inUtf32]); chwNext = rgchwChars2[inUtf32]; break; - case 2: chw = rgchwChars2[inUtf32]; chwNext = rgchwChars3[inUtf32]; break; - case 3: chw = rgchwChars3[inUtf32]; chwNext = rgchwChars4[inUtf32]; break; - case 4: chw = rgchwChars4[inUtf32]; chwNext = rgchwChars5[inUtf32]; break; - case 5: chw = rgchwChars5[inUtf32]; chwNext = rgchwChars6[inUtf32]; break; - case 6: chw = rgchwChars6[inUtf32]; chwNext = 0; break; - } - if (rgcchwRaw[ichw] == 1 && chwNext == 0 && chw < 0x0100) // ANSI - strmOut << (char)chw << " "; // 6 spaces - else - strmOut << " "; // 7 spaces - if (chwNext == 0) - inUtf32++; - } - strmOut << "\n"; - - // Unicode - strmOut << "Unicode: "; - inUtf32 = 0; - for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - utf16 chw, chwNext; - switch (rgcchwRaw[ichw]) - { - default: - case 1: chw = utf16(rgnChars[inUtf32]); chwNext = rgchwChars2[inUtf32]; break; - case 2: chw = rgchwChars2[inUtf32]; chwNext = rgchwChars3[inUtf32]; break; - case 3: chw = rgchwChars3[inUtf32]; chwNext = rgchwChars4[inUtf32]; break; - case 4: chw = rgchwChars4[inUtf32]; chwNext = rgchwChars5[inUtf32]; break; - case 5: chw = rgchwChars5[inUtf32]; chwNext = rgchwChars6[inUtf32]; break; - case 6: chw = rgchwChars6[inUtf32]; chwNext = 0; break; - } - ptman->LogHexInTable(strmOut, chw, chwNext != 0); - if (chwNext == 0) - inUtf32++; - } - strmOut << "\n"; - - strmOut << "before "; - for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - if (rgcchwRaw[ichw] > 1) - // continuation of Unicode codepoint - strmOut << " "; - else if (m_prgisloutBefore[ichw] == kNegInfinity) - strmOut << "<-- "; - else if (m_prgisloutBefore[ichw] == kPosInfinity) - strmOut << "--> "; - else - ptman->LogInTable(strmOut, m_prgisloutBefore[ichw]); - } - strmOut <<"\n"; - - for (int ix = 1; ix < signed(cassocs) - 1; ix++) //(cassocs > 2) - { - if (ix == 1) - strmOut << "other "; - else - strmOut << " "; - for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - std::vector<int> * pvislout = m_prgpvisloutAssocs[ichw]; - if (pvislout == NULL) - strmOut << " "; - else if (signed(pvislout->size()) <= ix) - strmOut << " "; - else if ((*pvislout)[ix] != m_prgisloutAfter[ichw]) - ptman->LogInTable(strmOut, (*pvislout)[ix]); - else - strmOut << " "; - } - strmOut << "\n"; - } - - strmOut << "after "; - for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - if (rgcchwRaw[ichw] > 1) - // continuation of Unicode codepoint - strmOut << " "; - else if (m_prgisloutAfter[ichw] == kNegInfinity) - strmOut << "<-- "; - else if (m_prgisloutAfter[ichw] == kPosInfinity) - strmOut << "--> "; - else - ptman->LogInTable(strmOut, m_prgisloutAfter[ichw]); - } - strmOut <<"\n"; - - if (fLigs) - { - strmOut << "ligature "; - for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - if (rgcchwRaw[ichw] > 1) - // continuation of Unicode codepoint - strmOut << " "; - else if (m_prgisloutLigature[ichw] != kNegInfinity) - ptman->LogInTable(strmOut, m_prgisloutLigature[ichw]); - else - strmOut << " "; - } - strmOut << "\n"; - - strmOut << "component "; - for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - if (rgcchwRaw[ichw] > 1) - // continuation of Unicode codepoint - strmOut << " "; - else if (m_prgisloutLigature[ichw] != kNegInfinity) - ptman->LogInTable(strmOut, m_prgiComponent[ichw] + 1); // 1-based - else - strmOut << " "; - } - strmOut << "\n"; - } - - strmOut << "\n"; -#endif -} - -/*---------------------------------------------------------------------------------------------- - Write out the final surface-to-underlying associations. -----------------------------------------------------------------------------------------------*/ -void Segment::LogSurfaceToUnderlying(GrTableManager * ptman, std::ostream & strmOut) -{ -#ifdef TRACING - strmOut << "\nSURFACE TO UNDERLYING MAPPINGS\n\n"; - - ptman->LogSlotHeader(strmOut, m_cslout, SP_PER_SLOT, LEADING_SP); - - int ccomp = 0; - - strmOut << "Glyph IDs: "; - int islout; - for (islout = 0; islout < m_cslout; islout++) - { - GrSlotOutput * psloutTmp = m_prgslout + islout; - if (psloutTmp->SpecialSlotFlag() == kspslLbInitial || - psloutTmp->SpecialSlotFlag() == kspslLbFinal) - { - strmOut << "# "; - } - else - { - ptman->LogHexInTable(strmOut, psloutTmp->GlyphID()); - ccomp = max(ccomp, psloutTmp->NumberOfComponents()); - } - } - strmOut << "\n"; - - bool fAnyPseudos = false; - for (islout = 0; islout < m_cslout; islout++) - { - GrSlotOutput * psloutTmp = m_prgslout + islout; - if (psloutTmp->GlyphID() != psloutTmp->ActualGlyphForOutput(ptman)) - { - fAnyPseudos = true; - break; - } - } - if (fAnyPseudos) - { - strmOut << "Actual glyphs: "; - for (int islout = 0; islout < m_cslout; islout++) - { - GrSlotOutput * psloutTmp = m_prgslout + islout; - if (psloutTmp->GlyphID() != psloutTmp->ActualGlyphForOutput(ptman)) - ptman->LogHexInTable(strmOut, psloutTmp->ActualGlyphForOutput(ptman)); - else - strmOut << " "; - } - strmOut << "\n"; - } - - strmOut << "before "; - for (islout = 0; islout < m_cslout; islout++) - { - GrSlotOutput * psloutTmp = m_prgslout + islout; - if (psloutTmp->SpecialSlotFlag() == kspslLbInitial || - psloutTmp->SpecialSlotFlag() == kspslLbFinal) - { - strmOut << " "; - } - else - ptman->LogInTable(strmOut, psloutTmp->BeforeAssoc()); - } - strmOut << "\n"; - - strmOut << "after "; - for (islout = 0; islout < m_cslout; islout++) - { - GrSlotOutput * psloutTmp = m_prgslout + islout; - if (psloutTmp->SpecialSlotFlag() == kspslLbInitial || - psloutTmp->SpecialSlotFlag() == kspslLbFinal) - { - strmOut << " "; - } - else - ptman->LogInTable(strmOut, psloutTmp->AfterAssoc()); - } - strmOut << "\n"; - - for (int icomp = 0; icomp < ccomp; icomp++) - { - strmOut << "component " << icomp + 1 // 1=based - << " "; - for (islout = 0; islout < m_cslout; islout++) - { - GrSlotOutput * psloutTmp = m_prgslout + islout; - if (psloutTmp->SpecialSlotFlag() == kspslLbInitial || - psloutTmp->SpecialSlotFlag() == kspslLbFinal) - { - strmOut << " "; - } - else if (icomp < psloutTmp->NumberOfComponents()) - ptman->LogInTable(strmOut, psloutTmp->UnderlyingComponent(icomp)); - else - strmOut << " "; - } - strmOut << "\n"; - } -#endif -} - -#ifdef TRACING -/*---------------------------------------------------------------------------------------------- - Write out the header lines for the underlying data. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogUnderlyingHeader(std::ostream & strmOut, int iMin, - int iLim, int cBackup, int * prgichr) -{ - strmOut << "string "; - int i, iLabel; - int * pichr = prgichr; - for (i = iMin - cBackup, iLabel = i; i < iLim; i++, iLabel++, pichr++) - { - while (prgichr && *pichr > 1) - { - // continuation of upper-plane char - iLabel++; - pichr++; - } - LogInTable(strmOut, iLabel); - } - strmOut << "\n"; - - strmOut << "segment "; - pichr = prgichr; - for (i = 0 - cBackup, iLabel = i; i < (iLim - iMin); i++, iLabel++, pichr++) - { - while (prgichr && *pichr > 1) - { - // continuation of upper-plane char - iLabel++; - pichr++; - } - LogInTable(strmOut, iLabel); - } - strmOut << "\n\n"; -} - -/*---------------------------------------------------------------------------------------------- - Write out the header lines for the slot contents. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogSlotHeader(std::ostream & strmOut, int islotLim, - int cspPerSlot, int cspLeading, int islotMin) -{ - islotLim = min(islotLim, MAX_SLOTS); - - int isp, islot; - - for (isp = 0; isp < cspLeading; isp++) - strmOut << " "; - - for (islot = islotMin; islot < islotLim; islot++) - LogInTable(strmOut, islot); - strmOut << "\n\n"; - -/**** - if (cslot >= 100) - { - for (isp = 0; isp < cspLeading; isp++) - strmOut << " "; - - for (islot = 0; islot < 100; islot++) - { - for (isp = 0; isp < cspPerSlot; isp++) - strmOut << " "; - } - - for (islot = 100; islot < cslot; islot++) - { - strmOut << "1"; - for (isp = 1; isp < cspPerSlot; isp++) - strmOut << " "; - } - } - - if (cslot > 10) - { - for (isp = 0; isp < cspLeading; isp++) - strmOut << " "; - - for (islot = 0; islot < 10; islot++) - { - for (isp = 0; isp < cspPerSlot; isp++) - strmOut << " "; - } - - for (islot = 10; islot < cslot; islot++) - { - if (true) // (islot % 10 == 0) - { - if (islot >= 100) - strmOut << ((islot - 100) / 10); - else - strmOut << (islot / 10); - } - else - strmOut << " "; - - for (isp = 1; isp < cspPerSlot; isp++) - strmOut << " "; - } - strmOut << "\n"; - } - - for (isp = 0; isp < cspLeading; isp++) - strmOut << " "; - - for (islot = 0; islot < cslot; islot++) - { - strmOut << (islot % 10); - for (isp = 1; isp < cspPerSlot; isp++) - strmOut << " "; - - } - strmOut << "\n"; -****/ -} - -/*---------------------------------------------------------------------------------------------- - Write out the glyph numbers for the given stream. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogSlotGlyphs(std::ostream & strmOut, GrSlotStream * psstrm) -{ - strmOut << "Glyph IDs: "; - int islot; - for (islot = 0; islot < psstrm->WritePos(); islot++) - { - GrSlotState * pslotTmp = psstrm->SlotAt(islot); - if (pslotTmp->IsLineBreak(LBGlyphID())) - strmOut << "# "; - else - LogHexInTable(strmOut, pslotTmp->GlyphID()); - } - strmOut << "\n"; -} - -/*---------------------------------------------------------------------------------------------- - Return flags indicating which attributes were modified for some slot during the pass - and therefore need a line in the log file. - - The 'pfMods' array has one flag per slot attribute; the final group are the user- - definable attributes. 'pccomp' returns the maximum number of ligature components - in this pass. Associations are assumed to have changed if anything else for the slot did. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::SlotAttrsModified(int ipass, bool * rgfMods, bool fPreJust, - int * pccomp, int * pcassoc) -{ - // Zero the flags - std::fill_n(rgfMods, kslatMax + NumUserDefn() - 1, false); - *pccomp = 0; - *pcassoc = 0; - - //GrSlotStream * psstrmIn = InputStream(ipass); - GrSlotStream * psstrmOut = OutputStream(ipass); - - for (int islot = 0; islot < psstrmOut->WritePos(); islot++) - { - GrSlotState * pslot = psstrmOut->SlotAt(islot); - Assert(pslot->PassModified() <= ipass); - if (pslot->PassModified() < ipass && !fPreJust) - continue; // not modified during this pass - - pslot->SlotAttrsModified(rgfMods, fPreJust, pccomp, pcassoc); - } -} - -void GrSlotState::SlotAttrsModified(bool * rgfMods, bool fPreJust, int * pccomp, int * pcassoc) -{ - // To handle reprocessing, in which case there may be a chain of slots modified - // in the same pass: - GrSlotState * pslotPrev = m_pslotPrevState; - while (pslotPrev && pslotPrev->PassModified() == PassModified()) - pslotPrev = pslotPrev->m_pslotPrevState; - - if (!pslotPrev) - { - // Inserted slot? - if (m_fAdvXSet) - rgfMods[kslatAdvX] = true; - if (m_fAdvYSet) - rgfMods[kslatAdvY] = true; - - if (m_srAttachTo != 0) - rgfMods[kslatAttTo] = true; - - if (m_mAttachAtX != kNotYetSet || m_mAttachAtY != 0) - { // always do these in pairs - rgfMods[kslatAttAtX] = true; - rgfMods[kslatAttAtY] = true; - } - if (m_nAttachAtGpoint != kNotYetSet) - rgfMods[kslatAttAtGpt] = true; - if (m_mAttachAtXOffset != 0 || m_mAttachAtYOffset != 0) - { // always do these in pairs - rgfMods[kslatAttAtXoff] = true; - rgfMods[kslatAttAtYoff] = true; - } - - if (m_mAttachWithX != kNotYetSet || m_mAttachWithY != 0) - { // always do these in pairs - rgfMods[kslatAttWithX] = true; - rgfMods[kslatAttWithY] = true; - } - if (m_nAttachWithGpoint != kNotYetSet) - rgfMods[kslatAttWithGpt] = true; - if (m_mAttachWithXOffset != 0 || m_mAttachWithYOffset != 0) - { // always do these in pairs - rgfMods[kslatAttWithXoff] = true; - rgfMods[kslatAttWithYoff] = true; - } - - if (m_nAttachLevel != 0) - rgfMods[kslatAttLevel] = true; - - if (m_lb != kNotYetSet8) - rgfMods[kslatBreak] = true; - if (m_dirc != kNotYetSet8) - rgfMods[kslatDir] = true; - if (m_fInsertBefore != true) - rgfMods[kslatInsert] = true; - - if (m_mMeasureSol != kNotYetSet && m_mMeasureSol != 0) - rgfMods[kslatMeasureSol] = true; - if (m_mMeasureEol != kNotYetSet && m_mMeasureEol != 0) - rgfMods[kslatMeasureEol] = true; - - if (m_mJStretch0 != kNotYetSet && m_mJStretch0 != 0) - rgfMods[kslatJStretch] = true; - if (m_mJShrink0 != kNotYetSet && m_mJShrink0 != 0) - rgfMods[kslatJShrink] = true; - if (m_mJStep0 != kNotYetSet && m_mJStep0 != 0) - rgfMods[kslatJStep] = true; - if (m_nJWeight0 != byte(kNotYetSet) && - m_nJWeight0 != 0 && m_nJWeight0 != 1) - rgfMods[kslatJWeight] = true; - if (m_mJWidth0 != kNotYetSet && m_mJWidth0 != 0) - rgfMods[kslatJWidth] = true; - - if (m_mShiftX != 0) - rgfMods[kslatShiftX] = true; - if (m_mShiftY != 0) - rgfMods[kslatShiftY] = true; - - int i; - for (i = 0; i < m_cnCompPerLig; i++) - { - if (CompRef(i) != NULL) - rgfMods[kslatCompRef] = true; - if (CompRef(i)) - *pccomp = max(*pccomp, i + 1); // max number of ligatures in this pass - } - - for (i = 0; i < m_cnUserDefn; i++) - { - if (UserDefn(i) != 0) - rgfMods[kslatUserDefn + i] = true; - } - } - else - { - if (m_fAdvXSet && m_mAdvanceX != pslotPrev->m_mAdvanceX) - rgfMods[kslatAdvX] = true; - if (m_fAdvYSet && m_mAdvanceY != pslotPrev->m_mAdvanceY) - rgfMods[kslatAdvY] = true; - - if (m_srAttachTo != pslotPrev->m_srAttachTo) - rgfMods[kslatAttTo] = true; - - if (m_mAttachAtX != pslotPrev->m_mAttachAtX || m_mAttachAtY != pslotPrev->m_mAttachAtY) - { - rgfMods[kslatAttAtX] = true; - rgfMods[kslatAttAtY] = true; - } - if (m_nAttachAtGpoint != pslotPrev->m_nAttachAtGpoint) - rgfMods[kslatAttAtGpt] = true; - if (m_mAttachAtXOffset != pslotPrev->m_mAttachAtXOffset || - m_mAttachAtYOffset != pslotPrev->m_mAttachAtYOffset) - { - rgfMods[kslatAttAtXoff] = true; - rgfMods[kslatAttAtYoff] = true; - } - - if (m_mAttachWithX != pslotPrev->m_mAttachWithX || - m_mAttachWithY != pslotPrev->m_mAttachWithY) - { - rgfMods[kslatAttWithX] = true; - rgfMods[kslatAttWithY] = true; - } - if (m_nAttachWithGpoint != pslotPrev->m_nAttachWithGpoint) - rgfMods[kslatAttWithGpt] = true; - if (m_mAttachWithXOffset != pslotPrev->m_mAttachWithXOffset || - m_mAttachWithYOffset != pslotPrev->m_mAttachWithYOffset) - { - rgfMods[kslatAttWithXoff] = true; - rgfMods[kslatAttWithYoff] = true; - } - - if (m_nAttachLevel != pslotPrev->m_nAttachLevel) - rgfMods[kslatAttLevel] = true; - - if (m_lb != pslotPrev->m_lb) - rgfMods[kslatBreak] = true; - if (m_dirc != pslotPrev->m_dirc) - rgfMods[kslatDir] = true; - if (m_fInsertBefore != pslotPrev->m_fInsertBefore) - rgfMods[kslatInsert] = true; - - if (m_mMeasureSol != pslotPrev->m_mMeasureSol) - rgfMods[kslatMeasureSol] = true; - if (m_mMeasureEol != pslotPrev->m_mMeasureEol) - rgfMods[kslatMeasureEol] = true; - - if (m_mJStretch0 != pslotPrev->m_mJStretch0 || (fPreJust && m_mJStretch0 != 0)) - rgfMods[kslatJStretch] = true; - if (m_mJShrink0 != pslotPrev->m_mJShrink0 || (fPreJust && m_mJShrink0 != 0)) - rgfMods[kslatJShrink] = true; - if (m_mJStep0 != pslotPrev->m_mJStep0 || (fPreJust && m_mJStep0 != 0)) - rgfMods[kslatJStep] = true; - if (m_nJWeight0 != pslotPrev->m_nJWeight0 || (fPreJust && m_nJWeight0 != 0)) - rgfMods[kslatJWeight] = true; - if (m_mJWidth0 != pslotPrev->m_mJWidth0) - rgfMods[kslatJWidth] = true; - - if (m_mShiftX != pslotPrev->m_mShiftX) - rgfMods[kslatShiftX] = true; - if (m_mShiftY != pslotPrev->m_mShiftY) - rgfMods[kslatShiftY] = true; - - int i; - for (i = 0; i < m_cnCompPerLig; i++) - { - if (CompRef(i) != pslotPrev->CompRef(i)) - rgfMods[kslatCompRef] = true; - if (CompRef(i)) - *pccomp = max(*pccomp, i + 1); // max number of ligatures in this pass - } - - for (i = 0; i < m_cnUserDefn; i++) - { - if (UserDefn(i) != pslotPrev->UserDefn(i)) - rgfMods[kslatUserDefn + i] = true; - } - } - - *pcassoc = max(*pcassoc, AssocsSize()); -} - -/*---------------------------------------------------------------------------------------------- - Log the value of the slot attribute for the given slot, if it changed. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::LogSlotAttributeValue(GrTableManager * ptman, - std::ostream & strmOut, int ipass, int slat, int iIndex, - bool fPreJust, bool fPostJust) -{ - if (m_ipassModified != ipass && !fPreJust && !fPostJust) - { - strmOut << " "; - return; - } - - // To handle reprocessing, in which case there may be a chain of slots modified - // in the same pass: - GrSlotState * pslotPrev = m_pslotPrevState; - while (pslotPrev && pslotPrev->PassModified() == PassModified()) - pslotPrev = pslotPrev->m_pslotPrevState; - - // General-purpose variables for em-unit attributes: - int mThis = 0; - int mPrev = 0; - switch (slat) - { - case kslatShiftX: - mThis = m_mShiftX; - mPrev = (pslotPrev) ? pslotPrev->m_mShiftX : 0; - break; - case kslatShiftY: - mThis = m_mShiftY; - mPrev = (pslotPrev) ? pslotPrev->m_mShiftY : 0; - break; - case kslatMeasureSol: - mThis = m_mMeasureSol; - mPrev = (pslotPrev) ? pslotPrev->m_mMeasureSol : 0; - break; - case kslatMeasureEol: - mThis = m_mMeasureEol; - mPrev = (pslotPrev) ? pslotPrev->m_mMeasureEol : 0; - break; - case kslatJStretch: - mThis = m_mJStretch0; - mPrev = (pslotPrev) ? pslotPrev->m_mJStretch0 : 0; - mPrev = (fPreJust && mThis > 0) ? -1 : mPrev; // log it even if it didn't change - break; - case kslatJShrink: - mThis = m_mJShrink0; - mPrev = (pslotPrev) ? pslotPrev->m_mJShrink0 : 0; - mPrev = (fPreJust && mThis > 0) ? -1 : mPrev; // log it even if it didn't change - break; - case kslatJStep: - mThis = m_mJStep0; - mPrev = (pslotPrev) ? pslotPrev->m_mJStep0 : 0; - mPrev = (fPreJust && mThis > 1) ? -1 : mPrev; // log it even if it didn't change - break; - case kslatJWeight: - mThis = m_nJWeight0; - mPrev = (pslotPrev) ? pslotPrev->m_nJWeight0 : 0; - mPrev = (fPreJust && mThis > 1) ? -1 : mPrev; // log it even if it didn't change - break; - case kslatJWidth: - mThis = m_mJWidth0; - mPrev = (pslotPrev) ? pslotPrev->m_mJWidth0 : 0; - mPrev = (fPostJust && mThis > 0) ? -1 : mPrev; // log it even if it didn't change - break; - default: - // don't use these variables - break; - } - - switch (slat) - { - case kslatAdvX: - if (m_fAdvXSet && (!pslotPrev || m_mAdvanceX != pslotPrev->m_mAdvanceX)) - { - ptman->LogInTable(strmOut, m_mAdvanceX); - return; - } - break; - case kslatAdvY: - if (m_fAdvYSet && (!pslotPrev || m_mAdvanceY != pslotPrev->m_mAdvanceY)) - { - ptman->LogInTable(strmOut, m_mAdvanceY); - return; - } - break; - - case kslatAttTo: - if (m_srAttachTo != (pslotPrev ? pslotPrev->m_srAttachTo : 0)) - { - ptman->LogInTable(strmOut, m_srAttachTo); - return; - } - break; - - case kslatAttAtX: // always do these in pairs - case kslatAttAtY: - if (m_mAttachAtX != (pslotPrev ? pslotPrev->m_mAttachAtX : kNotYetSet) || - m_mAttachAtY != (pslotPrev ? pslotPrev->m_mAttachAtY : 0)) - { - ptman->LogInTable(strmOut, - ((slat == kslatAttAtX) ? m_mAttachAtX : m_mAttachAtY)); - return; - } - break; - case kslatAttAtGpt: - if (m_nAttachAtGpoint != (pslotPrev ? pslotPrev->m_nAttachAtGpoint : kNotYetSet)) - { - ptman->LogInTable(strmOut, - ((m_nAttachAtGpoint == kGpointZero) ? 0 : m_nAttachAtGpoint)); - return; - } - break; - case kslatAttAtXoff: // always do these in pairs - case kslatAttAtYoff: - if (m_mAttachAtXOffset != (pslotPrev ? pslotPrev->m_mAttachAtXOffset : 0) || - m_mAttachAtYOffset != (pslotPrev ? pslotPrev->m_mAttachAtYOffset : 0)) - { - ptman->LogInTable(strmOut, - ((slat == kslatAttAtXoff) ? m_mAttachAtXOffset : m_mAttachAtYOffset)); - return; - } - break; - - case kslatAttWithX: // always do these in pairs - case kslatAttWithY: - if (m_mAttachWithX != (pslotPrev ? pslotPrev->m_mAttachWithX : kNotYetSet) || - m_mAttachWithY != (pslotPrev ? pslotPrev->m_mAttachWithY : 0)) - { - ptman->LogInTable(strmOut, - ((slat == kslatAttWithX) ? m_mAttachWithX : m_mAttachWithY)); - return; - } - break; - case kslatAttWithGpt: - if (m_nAttachWithGpoint != (pslotPrev ? pslotPrev->m_nAttachWithGpoint : kNotYetSet)) - { - ptman->LogInTable(strmOut, - ((m_nAttachWithGpoint == kGpointZero) ? 0 : m_nAttachWithGpoint)); - return; - } - break; - case kslatAttWithXoff: // always do these in pairs - case kslatAttWithYoff: - if (m_mAttachWithXOffset != (pslotPrev ? pslotPrev->m_mAttachWithXOffset : 0) || - m_mAttachWithYOffset != (pslotPrev ? pslotPrev->m_mAttachWithYOffset : 0)) - { - ptman->LogInTable(strmOut, - ((slat == kslatAttWithXoff) ? m_mAttachWithXOffset : m_mAttachWithYOffset)); - return; - } - break; - - case kslatAttLevel: - if (m_nAttachLevel != (pslotPrev ? pslotPrev->m_nAttachLevel : 0)) - { - ptman->LogInTable(strmOut, m_nAttachLevel); - return; - } - break; - - case kslatBreak: - if (m_lb != (pslotPrev ? pslotPrev->m_lb : kNotYetSet8)) - { - ptman->LogBreakWeightInTable(strmOut, m_lb); - return; - } - break; - case kslatDir: - if (m_dirc != (pslotPrev ? pslotPrev->m_dirc : kNotYetSet8)) - { - ptman->LogDirCodeInTable(strmOut, m_dirc); - return; - } - break; - case kslatInsert: - if (m_fInsertBefore != (pslotPrev ? pslotPrev->m_fInsertBefore : true)) - { - if (m_fInsertBefore) - strmOut << "true "; - else - strmOut << "false "; - return; - } - break; - - case kslatJWeight: - if (m_mJStretch0 == 0 && m_mJShrink0 == 0) - mPrev = mThis; // don't log; weight is irrelevant - // fall through - case kslatShiftX: - case kslatShiftY: - case kslatMeasureSol: - case kslatMeasureEol: - case kslatJStretch: - case kslatJShrink: - case kslatJStep: - case kslatJWidth: - if (mThis != mPrev) - { - ptman->LogInTable(strmOut, mThis); - return; - } - break; - - case kslatCompRef: - if (CompRef(iIndex) != (pslotPrev ? pslotPrev->CompRef(iIndex) : 0)) - { - GrSlotState * pslotComp = reinterpret_cast<GrSlotState *>(CompRef(iIndex)); - ptman->LogInTable(strmOut, pslotComp->m_islotTmpIn); - return; - } - break; - - default: - if (kslatUserDefn <= slat && slat <= kslatUserDefn + m_cnUserDefn) - { - int iTmp = slat - kslatUserDefn; - if (UserDefn(iTmp) != (pslotPrev ? pslotPrev->UserDefn(iTmp) : 0)) - { - ptman->LogInTable(strmOut, UserDefn(iTmp)); - return; - } - } - else - gAssert(false); - } - - strmOut << " "; -} - -/*---------------------------------------------------------------------------------------------- - Log the value of the association, if the slot changed. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::LogAssociation(GrTableManager * ptman, - std::ostream & strmOut, int ipass, int iassoc, bool fBoth, bool fAfter) -{ - if (m_ipassModified != ipass) - { - strmOut << " "; - return; - } - - if (fBoth) - { - GrSlotState * pslotBefore = AssocSlot(0); - GrSlotState * pslotAfter = AssocSlot(m_vpslotAssoc.size() - 1); - - int nBefore, nAfter; - - int csp = 4; - if (pslotBefore) - { - nBefore = pslotBefore->m_islotTmpIn; - strmOut << nBefore; - if (nBefore > 99) csp--; - if (nBefore > 9) csp--; - } - else - { - strmOut << "??"; - csp--; - } - if (pslotAfter) - { - nAfter = pslotAfter->m_islotTmpIn; - strmOut << "/" << nAfter; - if (nAfter > 99) csp--; - if (nAfter > 9) csp--; - } - else - { - if (pslotBefore) - { - strmOut << "/" << "??"; - csp--; - } - else - csp = 5; - } - - for (int isp = 0; isp < csp; isp++) - strmOut << " "; - } - - else if (fAfter) - { - Assert(m_vpslotAssoc.size()); - GrSlotState * pslotAfter = AssocSlot(m_vpslotAssoc.size() - 1); - - if (pslotAfter) - { - int nAfter = pslotAfter->m_islotTmpIn; - ptman->LogInTable(strmOut, nAfter); - } - else - strmOut << "?? "; - } - else if (iassoc < signed(m_vpslotAssoc.size() - 1)) - { - GrSlotState * pslot = AssocSlot(iassoc); - - if (pslot) - { - int n = pslot->m_islotTmpIn; - ptman->LogInTable(strmOut, n); - } - else - strmOut << "?? "; - } - else - strmOut << " "; -} - -/*---------------------------------------------------------------------------------------------- - Write a hex value (a glyphID or Unicode codepoint) into the table. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogInTable(std::ostream & strmOut, int n) -{ - if (n == kNegInfinity) - { - strmOut << "-inf "; - return; - } - if (n == kPosInfinity) - { - strmOut << "+inf "; - return; - } - if (n > 999999) - { - strmOut << "****** "; - return; - } - if (n < -99999) - { - strmOut << "-***** "; - return; - } - - strmOut << n; - int csp = SP_PER_SLOT - 1; - - if (abs(n) > 99999) csp--; - if (abs(n) > 9999) csp--; - if (abs(n) > 999) csp--; - if (abs(n) > 99) csp--; - if (abs(n) > 9) csp--; - - if (n < 0) csp--; - - for (int isp = 0; isp < csp; isp++) - strmOut << " "; -} - -void GrTableManager::LogInTable(std::ostream & strmOut, float n) -{ - if (n == kNegInfFloat) - { - strmOut << "-inf "; - return; - } - if (n == kPosInfFloat) - { - strmOut << "+inf "; - return; - } - if (n > 9999) - { - strmOut << "****.* "; - return; - } - if (n < -999) - { - strmOut << "-***.* "; - return; - } - - int csp = SP_PER_SLOT - 4; - - int nInt = (int)(fabsf(n)); - int nTenths = (int)fabsf((fabsf(n) - float(nInt) + 0.05f) * 10); - if (nTenths >= 10) - { - nTenths = 0; - nInt++; - } - - if (nInt >= 1000) csp--; - if (nInt >= 100) csp--; - if (nInt >= 10) csp--; - - if (n < 0) csp--; - - for (int isp = 0; isp < csp; isp++) - strmOut << " "; - if (n < 0) - strmOut << "-"; - strmOut << nInt << "." << nTenths << " "; -} - -/*---------------------------------------------------------------------------------------------- - Write a hex value (a glyphID or Unicode codepoint) into the table. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogHexInTable(std::ostream & strmOut, utf16 chw, bool fPlus) -{ - //char rgch[20]; - if (chw <= 0x0fff) strmOut << "0"; - if (chw <= 0x00ff) strmOut << "0"; - if (chw <= 0x000f) strmOut << "0"; - - strmOut << std::hex << chw << std::dec; - - for (int i = 4; i < SP_PER_SLOT - 2; i++) - strmOut << " "; - - if (fPlus) - strmOut << "+ "; - else - strmOut << " "; -} - -/*---------------------------------------------------------------------------------------------- - Write a directionality code to the table. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogDirCodeInTable(std::ostream & strmOut, int dirc) -{ - switch (dirc) - { - case kdircUnknown: strmOut << "??? "; break; - case kdircNeutral: strmOut << "ON "; break; - case kdircL: strmOut << "L "; break; - case kdircR: strmOut << "R "; break; - case kdircRArab: strmOut << "AR "; break; - case kdircEuroNum: strmOut << "EN "; break; - case kdircEuroSep: strmOut << "ES "; break; - case kdircEuroTerm: strmOut << "ET "; break; - case kdircArabNum: strmOut << "AN "; break; - case kdircComSep: strmOut << "CS "; break; - case kdircWhiteSpace: strmOut << "WS "; break; - case kdircBndNeutral: strmOut << "BN "; break; - case kdircNSM: strmOut << "NSM "; break; - case kdircLRO: strmOut << "LRO "; break; - case kdircRLO: strmOut << "RLO "; break; - case kdircLRE: strmOut << "LRE "; break; - case kdircRLE: strmOut << "RLE "; break; - case kdircPDF: strmOut << "PDF "; break; - case kdircPdfL: strmOut << "PDF-L "; break; - case kdircPdfR: strmOut << "PDF-R "; break; - case kdircLlb: strmOut << "L "; break; - case kdircRlb: strmOut << "R "; break; - default: LogInTable(strmOut, dirc); break; - } -} - -/*---------------------------------------------------------------------------------------------- - Write a breakweight code to the table. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogBreakWeightInTable(std::ostream & strmOut, int lb) -{ - if (lb < 0) - { - lb = lb * -1; - switch (lb) - { - case klbWsBreak: strmOut << "-ws "; break; - case klbWordBreak: strmOut << "-word "; break; - case klbHyphenBreak: strmOut << "-intra "; break; - case klbLetterBreak: strmOut << "-lettr "; break; - case klbClipBreak: strmOut << "-clip "; break; - default: LogInTable(strmOut, lb*-1); break; - } - } - else - { - switch (lb) - { - case klbNoBreak: strmOut << "none "; break; - case klbWsBreak: strmOut << "ws "; break; - case klbWordBreak: strmOut << "word "; break; - case klbHyphenBreak: strmOut << "intra "; break; - case klbLetterBreak: strmOut << "letter "; break; - case klbClipBreak: strmOut << "clip "; break; - default: LogInTable(strmOut, lb); break; - } - } -} - -#endif // TRACING - -} // namespace gr diff --git a/Build/source/libs/graphite-engine/src/segment/XmlTransductionLog.cpp b/Build/source/libs/graphite-engine/src/segment/XmlTransductionLog.cpp deleted file mode 100644 index d0dfcaafbe8..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/XmlTransductionLog.cpp +++ /dev/null @@ -1,1583 +0,0 @@ -/*--------------------------------------------------------------------*//*:Ignore this sentence. -Copyright (C) 2008 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: TransductionLog.cpp -Responsibility: Sharon Correll -Last reviewed: Not yet. - -Description: - Contains the functions for writing a log of the transduction process using an XML format. -----------------------------------------------------------------------------------------------*/ - -//:>******************************************************************************************** -//:> Include files -//:>******************************************************************************************** -#include "Main.h" - -#ifdef _MSC_VER -#pragma hdrstop -#endif - -#include <math.h> - -#undef THIS_FILE -DEFINE_THIS_FILE - -//:End Ignore - -//:>******************************************************************************************** -//:> Forward declarations -//:>******************************************************************************************** - -//:>******************************************************************************************** -//:> Local Constants and static variables -//:>******************************************************************************************** - -namespace gr -{ - -//:>******************************************************************************************** -//:> Methods -//:>******************************************************************************************** - -#define SP_PER_SLOT 7 -#define LEADING_SP 15 -#define MAX_SLOTS 128 - -/*---------------------------------------------------------------------------------------------- - Output a file showing a log of the transduction process and the resulting segment. -----------------------------------------------------------------------------------------------*/ -bool GrTableManager::WriteXmlLog(std::ostream * pstrmLog, - GrCharStream * pchstrm, Segment * psegRet, int cbPrevSegDat, byte * pbPrevSegDat) -{ -#ifdef TRACING - if (!pstrmLog) - return false; - std::ostream & strmOut = *pstrmLog; - WriteXmlLogAux(strmOut, pchstrm, psegRet, cbPrevSegDat, pbPrevSegDat); - return true; -#else - return false; -#endif // TRACING -} - - -bool GrTableManager::WriteXmlAssocLog(std::ostream * pstrmLog, - GrCharStream * pchstrm, Segment * psegRet) -{ -#ifdef TRACING - if (!pstrmLog) - return false; - - std::ostream & strmOut = *pstrmLog; - LogFinalPositions(strmOut); - - LogXmlTagOpen(strmOut, "Mappings", 1, true); - LogXmlTagPostAttrs(strmOut, true); - - //psegRet->LogXmlUnderlyingToSurface(strmOut, this, pchstrm, 2); - //psegRet->LogXmlSurfaceToUnderlying(strmOut, this, 2); - - LogXmlTagClose(strmOut, "Mappings", 1, true); - - strmOut << "\n"; - LogXmlTagClose(strmOut, "GraphiteTraceLog", 0, true); - - return true; -#else - return false; -#endif // TRACING -} - -#ifdef TRACING - -/*---------------------------------------------------------------------------------------------- - Output a file showing a log of the transduction process and the resulting segment. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::WriteXmlLogAux(std::ostream & strmOut, - GrCharStream * pchstrm, Segment * psegRet, - int cbPrevSegDat, byte * pbPrevSegDat) -{ - strmOut - << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - << "<!DOCTYPE GraphiteTraceLog SYSTEM \"GraphiteTraceLog.dtd\">\n" - << "\n"; - - LogXmlTagOpen(strmOut, "GraphiteTraceLog", 0, true); - LogXmlTagPostAttrs(strmOut, true); - strmOut << "\n"; - - LogXmlTagOpen(strmOut, "SegmentRun", 1, true); - LogXmlTagAttr(strmOut, "stringOffset", pchstrm->Min(), 0); - LogXmlTagPostAttrs(strmOut, true); - - if (cbPrevSegDat == 0) - LogXmlUnderlying(strmOut, pchstrm, 0, 2); - else - { - Assert(*(pbPrevSegDat + 4) == 0); // skip offset for first pass - LogXmlUnderlying(strmOut, pchstrm, *(pbPrevSegDat + 3), 2); - } - - //LogXmlPass1Input(strmOut); - - for (int ipass = 0; ipass < m_cpass; ipass++) - { - if (cbPrevSegDat == 0) - LogXmlPass(strmOut, ipass, 0, 2); - else - LogXmlPass(strmOut, ipass, *(pbPrevSegDat + 4 + ipass), 2); - } - - LogXmlTagClose(strmOut, "SegmentRun", 1, true); - strmOut << "\n"; - - // Don't do this until after we've logged the associations. - //LogXmlTagClose(strmOut, "GraphiteTraceLog", 0, true); -} - -/*---------------------------------------------------------------------------------------------- - Write out a log of the underlying input. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogXmlUnderlying(std::ostream & strmOut, GrCharStream * pchstrm, - int cchwBackup, size_t nIndent) -{ - LogXmlTagOpen(strmOut, "Input", nIndent, true); - LogXmlTagPostAttrs(strmOut, true); - - LogXmlUnderlyingAux(strmOut, pchstrm, cchwBackup, -1, nIndent, - true, // text - true, // features - true, // color - false, // string offset - false, // ligature components - false); // glyph associations - - LogXmlTagClose(strmOut, "Input", nIndent, true); -} - -void GrTableManager::LogXmlUnderlyingAux(std::ostream & strmOut, GrCharStream * pchstrm, - int cch32Backup, int cch32Lim, size_t nIndent, - bool fLogText, bool fLogFeatures, bool fLogColor, bool fLogStrOff, bool fLogLig, bool fLogGlyphs) -{ - int rgnChars[MAX_SLOTS]; - bool rgfNewRun[MAX_SLOTS]; - std::fill_n(rgfNewRun, MAX_SLOTS, false); - GrFeatureValues rgfval[MAX_SLOTS]; - int cchwMaxRawChars; - - int cch32 = pchstrm->GetLogData(this, rgnChars, rgfNewRun, rgfval, - cch32Backup, &cchwMaxRawChars); - cch32 = min(cch32, MAX_SLOTS); - if (cch32Lim > -1) - cch32 = min(cch32Lim, cch32); - - int ichw; - - // For UTF-8 and surrogate representation: - int rgchwChars1[MAX_SLOTS]; - utf16 rgchwChars2[MAX_SLOTS]; - utf16 rgchwChars3[MAX_SLOTS]; - utf16 rgchwChars4[MAX_SLOTS]; - utf16 rgchwChars5[MAX_SLOTS]; - utf16 rgchwChars6[MAX_SLOTS]; - utf16 rgiRawString[MAX_SLOTS]; // indices from underlying slots to text-source chars (0-based) - - int rgichwRaw[MAX_SLOTS]; // index of input char with in the given UTF32, 1-based - - if (cchwMaxRawChars > 1) - { - cchwMaxRawChars = min(cchwMaxRawChars, 6); // max of 6 raw (UTF-8 or UTF-16) chars per slot - pchstrm->GetLogDataRaw(this, cch32, cch32Backup, cchwMaxRawChars, - rgchwChars1, rgchwChars2, rgchwChars3, rgchwChars4, rgchwChars5, rgchwChars6, - rgichwRaw); - } - else - { - for (ichw = 0; ichw < cch32; ichw++) - { - rgichwRaw[ichw] = 1; - rgchwChars1[ichw] = rgnChars[ichw]; - rgchwChars2[ichw] = 0; - rgchwChars3[ichw] = 0; - rgchwChars4[ichw] = 0; - rgchwChars5[ichw] = 0; - rgchwChars6[ichw] = 0; - } - } - - int ichUtf32 = 0; - ichw = 0; - while (ichUtf32 < cch32) - { - if (rgichwRaw[ichw] == 1) - { - rgiRawString[ichUtf32++] = (utf16)ichw; - } - ichw++; - } - - int ichwFeat = 0; - for (ichw = 0; ichw < cch32; ichw++) - { - if (rgfNewRun[ichw]) - ichwFeat = ichw; // because rgfval only saves features for first of run - - // See if there are any features. - bool fFeatures = false; - size_t ifeat; - for (ifeat = 0; fLogFeatures && ifeat < kMaxFeatures; ifeat++) - { - if (rgfval[ichwFeat].FeatureValue(ifeat) != 0) - { - fFeatures = true; - break; - } - } - - bool fContent = fFeatures; - - LogXmlTagOpen(strmOut, "Char", nIndent+1, fContent); - - LogXmlTagAttr(strmOut, "index", rgiRawString[ichw] - cch32Backup, 0); - LogXmlTagAttrHex(strmOut, "usv", rgnChars[ichw], 0); - - if (fLogText) - { - char rgch[20]; - rgch[0] = (char)rgnChars[ichw]; - rgch[1] = 0; - if (rgnChars[ichw] < 0x0100 && rgchwChars2[ichw] == 0) // ANSI - LogXmlTagAttr(strmOut, "text", rgch); - else if (rgnChars[ichw] == knLRM) - LogXmlTagAttr(strmOut, "text", "<LRM>"); - else if (rgnChars[ichw] == knRLM) - LogXmlTagAttr(strmOut, "text", "<RLM>"); - else if (rgnChars[ichw] == knLRO) - LogXmlTagAttr(strmOut, "text", "<LRO>"); - else if (rgnChars[ichw] == knRLO) - LogXmlTagAttr(strmOut, "text", "<RLO>"); - else if (rgnChars[ichw] == knLRE) - LogXmlTagAttr(strmOut, "text", "<LRE>"); - else if (rgnChars[ichw] == knRLE) - LogXmlTagAttr(strmOut, "text", "<RLE>"); - else if (rgnChars[ichw] == knPDF) - LogXmlTagAttr(strmOut, "text", "<PDF>"); - } - - if (fLogStrOff) - LogXmlTagAttr(strmOut, "stringOffset", pchstrm->Min() + rgiRawString[ichw] - cch32Backup, 0); - - if (rgchwChars2[ichw] != 0) - { - std::string strHex = HexString(rgchwChars1[ichw], rgchwChars2[ichw], rgchwChars3[ichw], - rgchwChars4[ichw], rgchwChars5[ichw], rgchwChars6[ichw]); - if (pchstrm->TextSrc()->utfEncodingForm() == kutf8) - LogXmlTagAttr(strmOut, "textSourceUtf8", strHex.c_str()); - else - LogXmlTagAttr(strmOut, "textSourceUtf16", strHex.c_str()); - } - - if (fLogColor) - { - IColorTextSource * tscolor = dynamic_cast<IColorTextSource *>(pchstrm->TextSrc()); - if (tscolor) - { - int clrFore, clrBack; - tscolor->getColors(ichw, &clrFore, &clrBack); - LogXmlTagColor(strmOut, "color", clrFore, false); - LogXmlTagColor(strmOut, "background", clrBack, true); - } - } - - if (fLogLig) - { - - } - -//if (fLogLig || fLogGlyphs) -//{ -// size_t cassocs = 0; -// int fLigs = false; -// int ichw; -// for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) -// { -// if (m_prgpvisloutAssocs[ichw]) -// cassocs = max(cassocs, m_prgpvisloutAssocs[ichw]->size()); -// if (m_prgisloutLigature[ichw] != kNegInfinity) -// fLigs = true; -// } -//} - - LogXmlTagPostAttrs(strmOut, fContent); - - if (fLogFeatures) - { - for (ifeat = 0; ifeat < kMaxFeatures; ifeat++) - { - if (rgfval[ichwFeat].FeatureValue(ifeat) != 0) - { - GrFeature * pfeat = Feature(ifeat); - - LogXmlTagOpen(strmOut, "Feature", nIndent+2, false); - LogXmlTagAttr(strmOut, "id", pfeat->ID()); - LogXmlTagAttr(strmOut, "value", rgfval[ichwFeat].FeatureValue(ifeat)); - //LogXmlTagPostAttrs(strmOut, false); - LogXmlTagClose(strmOut, "Feature", nIndent+1, false); - } - } - } - - if (fLogGlyphs) - { - } - - LogXmlTagClose(strmOut, "Char", nIndent+1, fContent); - } -} - -/*---------------------------------------------------------------------------------------------- - Output the the results of pass. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogXmlPass(std::ostream & strmOut, int ipass, int cslotSkipped, int nIndent) -{ - strmOut << "\n"; - - GrPass * ppass = Pass(ipass); - GrSlotStream * psstrmIn = (ipass == 0) ? NULL : InputStream(ipass); - GrSlotStream * psstrmOut = OutputStream(ipass); - - int islot; - // Mark each slot with its index in the input and output streams. - for (islot = 0; ipass > 0 && islot < psstrmIn->ReadPos(); islot++) - psstrmIn->SlotAt(islot)->m_islotTmpIn = islot; - - for (islot = 0; islot < psstrmOut->WritePos(); islot++) - psstrmOut->SlotAt(islot)->m_islotTmpOut = islot; - - LogXmlTagOpen(strmOut, "Pass", nIndent, true); - LogXmlTagAttr(strmOut, "number", ipass); - - std::string strType; - if (dynamic_cast<GrGlyphGenPass *>(ppass)) - strType = "glyphGeneration"; - else if (dynamic_cast<GrBidiPass *>(ppass)) - strType = "bidi"; - else if (dynamic_cast<GrSubPass *>(ppass)) - { - if (ipass >= m_ipassJust1) - strType = "justification"; - else - strType = "substitution"; - } - else if (dynamic_cast<GrPosPass *>(ppass)) - strType = "positioning"; - else if (dynamic_cast<GrLineBreakPass *>(ppass)) - strType = "linebreak"; - LogXmlTagAttr(strmOut, "type", strType.c_str()); - - LogXmlTagPostAttrs(strmOut, true); - - if (!dynamic_cast<GrBidiPass *>(ppass) && !dynamic_cast<GrGlyphGenPass *>(ppass)) - { - LogXmlTagOpen(strmOut, "RulesMatched", nIndent+1, true); - LogXmlTagPostAttrs(strmOut, true); - ppass->LogXmlRules(strmOut, this, psstrmIn, nIndent+2); - LogXmlTagClose(strmOut, "RulesMatched", nIndent+1, true); - } - - bool fJustWidths = false; - if (ipass == m_ipassJust1 - 1 && ShouldLogJustification() - && m_engst.m_jmodi == kjmodiJustify) - { - fJustWidths = true; - } - - LogXmlTagOpen(strmOut, "Output", nIndent+1, true); - LogXmlTagPostAttrs(strmOut, true); - bool fPreJust = (!fJustWidths && ipass == m_ipassJust1 - 1 && ShouldLogJustification()); - bool fPostJust = (fJustWidths || ipass == m_ipassJust1 && ShouldLogJustification()); - ppass->LogXmlGlyphs(strmOut, this, psstrmOut, m_ipassJust1, fPreJust, fPostJust, cslotSkipped, nIndent+2); - LogXmlTagClose(strmOut, "Output", nIndent+1, true); - - LogXmlTagClose(strmOut, "Pass", nIndent, true); - -#ifdef XMLOMIT - - // If this was the pass just before the justification routines get run, output a - // special line that just shows the results, ie, the values of justify.width. - // TODO: adjust this when measure mode get functioning. - if (ipass == m_ipassJust1 - 1 && ShouldLogJustification() - && m_engst.m_jmodi == kjmodiJustify) - { - strmOut << "\nJUSTIFICATION\n\n"; - LogSlotHeader(strmOut, psstrmOut->WritePos(), SP_PER_SLOT, LEADING_SP); - LogSlotGlyphs(strmOut, psstrmOut); - LogAttributes(strmOut, ipass, true); - } - -#endif // XMLOMIT - -} - -/*---------------------------------------------------------------------------------------------- - Write the list of rules fired and failed for a given pass. -----------------------------------------------------------------------------------------------*/ -void GrPass::LogXmlRules(std::ostream & strmOut, GrTableManager * ptman, - GrSlotStream * psstrmIn, int nIndent) -{ - m_pzpst->LogXmlRules(strmOut, ptman, psstrmIn, nIndent); -} - -void PassState::LogXmlRules(std::ostream & strmOut, GrTableManager * ptman, - GrSlotStream * psstrmIn, int nIndent) -{ - if (m_crulrec == 0) - { - ptman->LogXmlComment(strmOut, "none", nIndent); - return; - } - - for (int irulrec = 0; irulrec < m_crulrec; irulrec++) - { - bool fSourceAvailable = false; - - ptman->LogXmlTagOpen(strmOut, "Rule", nIndent, fSourceAvailable); - - ptman->LogXmlTagAttr(strmOut, "slot", m_rgrulrec[irulrec].m_islot); - - if (m_rgrulrec[irulrec].m_irul == PassState::kHitMaxRuleLoop) - ptman->LogXmlTagAttr(strmOut, "hitMaxRuleLoop", "true"); - else if (m_rgrulrec[irulrec].m_irul == PassState::kHitMaxBackup) - ptman->LogXmlTagAttr(strmOut, "hitMaxBackup", "true"); - else - { - ptman->LogXmlTagAttr(strmOut, "debugNumber", m_rgrulrec[irulrec].m_irul); - ptman->LogXmlTagAttr(strmOut, "fired", (m_rgrulrec[irulrec].m_fFired) ? "true" : "false"); - } - - ptman->LogXmlTagPostAttrs(strmOut, fSourceAvailable); - - // TODO: output Source - - ptman->LogXmlTagClose(strmOut, "Rule", nIndent, fSourceAvailable); - } -} - -void GrPass::LogXmlGlyphs(std::ostream & strmOut, GrTableManager * ptman, GrSlotStream * psstrmOut, - int ipassJust1, bool fPreJust, bool fPostJust, int cslotSkipped, int nIndent) -{ - GrBidiPass * ppassBidi = dynamic_cast<GrBidiPass *>(this); - GrBidiPass * ppassBidiNext = (m_ipass + 1 >= ptman->NumberOfPasses()) ? - NULL : - dynamic_cast<GrBidiPass *>(ptman->Pass(m_ipass + 1)); - m_pzpst->LogXmlGlyphs(strmOut, ptman, psstrmOut, ipassJust1, fPreJust, fPostJust, - (ppassBidi != NULL), (ppassBidiNext != NULL), cslotSkipped, nIndent); -} - -void PassState::LogXmlGlyphs(std::ostream & strmOut, GrTableManager * ptman, GrSlotStream * psstrmOut, - int ipassJust1, bool fPreJust, bool fPostJust, bool fBidi, bool fBidiNext, int cslotSkipped, - int nIndent) -{ - ptman->LogXmlTagOpen(strmOut, "Output", nIndent, true); - ptman->LogXmlTagPostAttrs(strmOut, true); - - for (int islot = 0; islot < psstrmOut->WritePos() + 1; islot++) // +1 allows us to handle final deletion - { - if (islot > MAX_SLOTS) - break; - - for (int islotDel = 0; islotDel < m_rgcslotDeletions[islot]; islotDel++) - { - ptman->LogXmlTagOpen(strmOut, "Glyph", nIndent+1, false); - ptman->LogXmlTagAttr(strmOut, "slot", "deleted"); - ptman->LogXmlTagPostAttrs(strmOut, false); - ptman->LogXmlTagClose(strmOut, "Glyph", nIndent+1, false); - } - if (islot >= psstrmOut->WritePos()) - break; - - GrSlotState * pslot = psstrmOut->SlotAt(islot); - - bool fMod = (pslot->PassModified() >= m_ipass && m_ipass > 0); - if (fBidi || fBidiNext) - fMod = true; - - ptman->LogXmlTagOpen(strmOut, "Glyph", nIndent+1, fMod); - - ptman->LogXmlTagAttr(strmOut, "slot", islot); - if (pslot->GlyphID() == ptman->LBGlyphID()) - ptman->LogXmlTagAttr(strmOut, "gid", "linebreak"); - else - ptman->LogXmlTagAttr(strmOut, "gid", pslot->GlyphID()); - if (pslot->GlyphID() != pslot->ActualGlyphForOutput(ptman)) - ptman->LogXmlTagAttr(strmOut, "actual", pslot->ActualGlyphForOutput(ptman)); - if (m_rgfInsertion[islot]) - ptman->LogXmlTagAttr(strmOut, "inserted", "true"); - if (islot < cslotSkipped) - ptman->LogXmlTagAttr(strmOut, "nextPassSkips", "true"); - - ptman->LogXmlTagPostAttrs(strmOut, fMod); - - if (fMod) - { - pslot->LogXmlAttributes(strmOut, ptman, psstrmOut, m_ipass, islot, - fPreJust, fPostJust, fBidi, fBidiNext, nIndent+2); - } - - ptman->LogXmlTagClose(strmOut, "Glyph", nIndent+1, fMod); - } - - ptman->LogXmlTagClose(strmOut, "Output", nIndent, true); -} - -/*---------------------------------------------------------------------------------------------- - Write out the attributes that have changes. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::LogXmlAttributes(std::ostream & strmOut, GrTableManager * ptman, - GrSlotStream * psstrmOut, int ipass, - int islot, bool fPreJust, bool fPostJust, bool fBidi, bool fBidiNext, int nIndent) -{ - // To handle reprocessing, in which case there may be a chain of slots modified - // in the same pass: - GrSlotState * pslotPrev = PrevState(); - while (pslotPrev && pslotPrev->PassModified() == PassModified()) - pslotPrev = pslotPrev->m_pslotPrevState; - - bool * prgfMods = new bool[kslatMax + ptman->NumUserDefn() - 1]; - memset(prgfMods, 0, (kslatMax + ptman->NumUserDefn() - 1) * sizeof(bool)); - int ccomp; - int cassoc; - SlotAttrsModified(prgfMods, fPreJust, &ccomp, &cassoc); // just for this one slot - - if (fPreJust) - prgfMods[kslatJWidth] = false; - else if (fPostJust) - prgfMods[kslatJWidth] = true; - - //if (fJustWidths) - //{} - - bool fLogAssocs = false; - - for (int slat = 0; slat < kslatMax + ptman->NumUserDefn() - 1; slat++) - { - if (!prgfMods[slat] && (slat != kslatDir || (!fBidi && !fBidiNext))) - continue; - - if (slat == kslatPosX) - continue; - if (slat == kslatPosY) - continue; - - std::string strAttrName; - switch (slat) - { - case kslatAdvX: strAttrName = "advance.x"; break; - case kslatAdvY: strAttrName = "advance.y"; break; - case kslatAttTo: strAttrName = "att.to"; break; - case kslatAttAtX: strAttrName = "att.at.x"; break; - case kslatAttAtY: strAttrName = "att.at.y"; break; - case kslatAttAtGpt: strAttrName = "att.at.gpt"; break; - case kslatAttAtXoff: strAttrName = "att.at.xoff"; break; - case kslatAttAtYoff: strAttrName = "att.at.yoff"; break; - case kslatAttWithX: strAttrName = "att.with.x"; break; - case kslatAttWithY: strAttrName = "att.with.y"; break; - case kslatAttWithGpt: strAttrName = "att.with.gpt"; break; - case kslatAttWithXoff: strAttrName = "att.with.xoff"; break; - case kslatAttWithYoff: strAttrName = "att.with.yoff"; break; - case kslatAttLevel: strAttrName = "att.level"; break; - case kslatBreak: strAttrName = "breakweight"; break; - case kslatCompRef: strAttrName = "component"; break; // << iIndex + 1 - 1-based - case kslatDir: strAttrName = "dir"; break; - case kslatInsert: strAttrName = "insert"; break; - case kslatMeasureSol: strAttrName = "measure.sol"; break; - case kslatMeasureEol: strAttrName = "measure.eol"; break; - case kslatJStretch: strAttrName = "just.stretch"; break; - case kslatJShrink: strAttrName = "just.shrink"; break; - case kslatJStep: strAttrName = "just.step"; break; - case kslatJWeight: strAttrName = "just.weight"; break; - case kslatJWidth: strAttrName = "just.width"; break; - case kslatPosX: - case kslatPosY: - Assert(false); - break; - case kslatShiftX: strAttrName = "shift.x"; break; - case kslatShiftY: strAttrName = "shift.y"; break; - default: - if (kslatUserDefn <= slat && - slat < kslatUserDefn + ptman->NumUserDefn()) - { - strAttrName.assign("user"); - char rgch[20]; - itoa(slat - kslatUserDefn + 1, rgch, 10); // 1-based - strAttrName.append(rgch); - } - else - { - // Invalid attribute: - Warn("bad slot attribute"); - break; - } - } - - fLogAssocs = (fLogAssocs || prgfMods[slat]); - - if (slat == kslatCompRef) - { - for (int icomp = 0; icomp < ccomp; icomp++) - { - ptman->LogXmlTagOpen(strmOut, "Attribute", nIndent, false); - ptman->LogXmlTagAttr(strmOut, "name", strAttrName.c_str()); - ptman->LogXmlTagAttr(strmOut, "index", icomp+1); - int nValue = GetSlotAttrValue(strmOut, ptman, ipass, slat, icomp, fPreJust, fPostJust); - ptman->LogXmlTagAttr(strmOut, "newValue", nValue); - ptman->LogXmlTagPostAttrs(strmOut, false); - ptman->LogXmlTagClose(strmOut, "Attribute", nIndent, false); - } - } - else - { - std::string strValue = "newValue"; - if ((!prgfMods[slat] && fBidiNext) || fBidi) - strValue = "value"; - - ptman->LogXmlTagOpen(strmOut, "Attribute", nIndent, false); - ptman->LogXmlTagAttr(strmOut, "name", strAttrName.c_str()); - int nValue = GetSlotAttrValue(strmOut, ptman, ipass, slat, 0, fPreJust, fPostJust); - switch (slat) - { - case kslatDir: ptman->LogXmlDirCode(strmOut, strValue.c_str(), nValue);break; - case kslatBreak: ptman->LogXmlBreakWeight(strmOut, "newValue", nValue); break; - default: ptman->LogXmlTagAttr(strmOut, "newValue", nValue); break; - } - ptman->LogXmlTagPostAttrs(strmOut, false); - ptman->LogXmlTagClose(strmOut, "Attribute", nIndent, false); - } - } - - if (fBidi) - { - // Output final directionality level - ptman->LogXmlTagOpen(strmOut, "Attribute", nIndent, false); - ptman->LogXmlTagAttr(strmOut, "name", "directionLevel"); - ptman->LogXmlTagAttr(strmOut, "value", DirLevel()); - ptman->LogXmlTagPostAttrs(strmOut, false); - ptman->LogXmlTagClose(strmOut, "Attribute", nIndent, false); - } - - if (m_vpslotAssoc.size() > 1) - fLogAssocs = true; // multiple associations - else if (m_vpslotAssoc.size() == 1) - { - // association change from previous stream - GrSlotState * pslotAssoc = AssocSlot(0); - if (pslotAssoc == NULL || pslotAssoc->m_islotTmpIn != islot) - fLogAssocs = true; - } - if (fLogAssocs) - { - std::string strAssocs; - char rgch[20]; - for (size_t iassoc = 0; iassoc < m_vpslotAssoc.size(); iassoc++) - { - GrSlotState * pslotAssoc = AssocSlot(iassoc); - if (pslotAssoc) - { - int n = pslotAssoc->m_islotTmpIn; - memset(rgch,0,20); - itoa(n,rgch,10); - if (iassoc > 0) - strAssocs.append(" "); - strAssocs.append(rgch); - } - } - if (strAssocs.length() == 0) - strAssocs.assign("??"); - ptman->LogXmlTagOpen(strmOut, "Associations", nIndent, false); - ptman->LogXmlTagAttr(strmOut, "slots", strAssocs.c_str()); - //ptman->LogXmlTagPostAttrs(strmOut, false); - ptman->LogXmlTagClose(strmOut, "Associations", nIndent, false); - } - - delete prgfMods; -} - -#if XMLOMIT -/*---------------------------------------------------------------------------------------------- - Write out the final positions. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogFinalPositions(std::ostream & strmOut) -{ - GrSlotStream * psstrm = OutputStream(m_cpass - 1); - - strmOut << "x position "; - for (int islot = 0; islot < psstrm->WritePos(); islot++) - { - GrSlotState * pslot = psstrm->SlotAt(islot); - if (pslot->IsLineBreak(LBGlyphID())) - { - strmOut << " "; - continue; - } - LogInTable(strmOut, pslot->XPosition()); - } - strmOut << "\n"; - - strmOut << "y position "; - for (int islot = 0; islot < psstrm->WritePos(); islot++) - { - GrSlotState * pslot = psstrm->SlotAt(islot); - if (pslot->IsLineBreak(LBGlyphID())) - { - strmOut << " "; - continue; - } - LogInTable(strmOut, pslot->YPosition()); - } - strmOut << "\n"; -} - -#endif // XMLOMIT - -/*---------------------------------------------------------------------------------------------- - Log the value of the slot attribute for the given slot. Assume it has changed. -----------------------------------------------------------------------------------------------*/ -int GrSlotState::GetSlotAttrValue(std::ostream & strmOut, GrTableManager * ptman, - int ipass, int slat, int iIndex, bool fPreJust, bool fPostJust) -{ - switch (slat) - { - case kslatAdvX: - return int(m_mAdvanceX); - case kslatAdvY: - return int(m_mAdvanceY); - - case kslatAttTo: - return m_srAttachTo; - - case kslatAttAtX: // always do these in pairs - return m_mAttachAtX; - case kslatAttAtY: - return m_mAttachAtY; - case kslatAttAtGpt: - return m_nAttachAtGpoint; - - case kslatAttAtXoff: // always do these in pairs - return m_mAttachAtXOffset; - case kslatAttAtYoff: - return m_mAttachAtYOffset; - - case kslatAttWithX: // always do these in pairs - return m_mAttachWithX; - case kslatAttWithY: - return m_mAttachWithY; - - case kslatAttWithGpt: - return m_nAttachWithGpoint; - - case kslatAttWithXoff: // always do these in pairs - return m_mAttachWithXOffset; - case kslatAttWithYoff: - return m_mAttachWithYOffset; - - case kslatAttLevel: - return m_nAttachLevel; - - case kslatBreak: - return m_lb; - - case kslatDir: - return m_dirc; - - case kslatInsert: - return m_fInsertBefore; - - case kslatShiftX: - return m_mShiftX; - case kslatShiftY: - return m_mShiftY; - case kslatMeasureSol: - return m_mMeasureSol; - case kslatMeasureEol: - return m_mMeasureEol; - case kslatJStretch: - return m_mJStretch0; - case kslatJShrink: - return m_mJShrink0; - case kslatJStep: - return m_mJStep0; - case kslatJWeight: - return m_nJWeight0; - case kslatJWidth: - return m_mJWidth0; - - case kslatCompRef: - { - GrSlotState * pslotComp = reinterpret_cast<GrSlotState *>(CompRef(iIndex)); - return pslotComp->m_islotTmpIn; - } - - default: - if (kslatUserDefn <= slat && slat <= kslatUserDefn + m_cnUserDefn) - { - int iTmp = slat - kslatUserDefn; - return UserDefn(iTmp); - } - else - gAssert(false); - } - - return 0; -} - -#endif // TRACING - - -/*---------------------------------------------------------------------------------------------- - Write out the final underlying-to-surface associations. -----------------------------------------------------------------------------------------------*/ -void Segment::LogXmlUnderlyingToSurface(std::ostream & strmOut, GrTableManager * ptman, - GrCharStream * pchstrm, int nIndent) -{ -#ifdef TRACING - - ptman->LogXmlTagOpen(strmOut, "UnderlyingToSurface", nIndent, true); - ptman->LogXmlTagPostAttrs(strmOut, true); - - ptman->LogXmlUnderlyingAux(strmOut, pchstrm, -m_ichwAssocsMin, (m_ichwAssocsLim - m_ichwAssocsMin), - nIndent+1, - true, // text - false, // features - false, // color - true, // string offset - true, // ligature components - true // glyph associations - ); - - ptman->LogXmlTagClose(strmOut, "UnderlyingToSurface", nIndent, true); - - -#ifdef XMLOMIT - ptman->LogXmlTagOpen(strmOut, "UnderlyingToSurface", nIndent, true); - - size_t cassocs = 0; - int fLigs = false; - int ichw; - for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - if (m_prgpvisloutAssocs[ichw]) - cassocs = max(cassocs, m_prgpvisloutAssocs[ichw]->size()); - if (m_prgisloutLigature[ichw] != kNegInfinity) - fLigs = true; - } - - ptman->LogUnderlyingHeader(strmOut, pchstrm->Min(), (pchstrm->Min() + m_ichwAssocsLim), - -m_ichwAssocsMin, NULL); - - int rgnChars[MAX_SLOTS]; - bool rgfNewRun[MAX_SLOTS]; - std::fill_n(rgfNewRun, MAX_SLOTS, false); - GrFeatureValues rgfval[MAX_SLOTS]; - int cchwMaxRawChars; - - int cchw = pchstrm->GetLogData(ptman, rgnChars, rgfNewRun, rgfval, - -m_ichwAssocsMin, &cchwMaxRawChars); - cchw = min(cchw, MAX_SLOTS); - - utf16 rgchwChars2[MAX_SLOTS]; - utf16 rgchwChars3[MAX_SLOTS]; - utf16 rgchwChars4[MAX_SLOTS]; - utf16 rgchwChars5[MAX_SLOTS]; - utf16 rgchwChars6[MAX_SLOTS]; - int rgcchwRaw[MAX_SLOTS]; - if (cchwMaxRawChars > 1) - { - cchwMaxRawChars = min(cchwMaxRawChars, 6); - pchstrm->GetLogDataRaw(ptman, cchw, -m_ichwAssocsMin, cchwMaxRawChars, - rgnChars, rgchwChars2, rgchwChars3, rgchwChars4, rgchwChars5, rgchwChars6, - rgcchwRaw); - } - else - { - for (ichw = 0 ; ichw <(m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - rgcchwRaw[ichw] = 1; - rgchwChars2[ichw] = 0; - rgchwChars3[ichw] = 0; - rgchwChars4[ichw] = 0; - rgchwChars5[ichw] = 0; - rgchwChars6[ichw] = 0; - } - } - - // Text - strmOut << "Text: "; // 15 spaces - int inUtf32 = 0; - for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - utf16 chw, chwNext; - switch (rgcchwRaw[ichw]) - { - default: - case 1: chw = utf16(rgnChars[inUtf32]); chwNext = rgchwChars2[inUtf32]; break; - case 2: chw = rgchwChars2[inUtf32]; chwNext = rgchwChars3[inUtf32]; break; - case 3: chw = rgchwChars3[inUtf32]; chwNext = rgchwChars4[inUtf32]; break; - case 4: chw = rgchwChars4[inUtf32]; chwNext = rgchwChars5[inUtf32]; break; - case 5: chw = rgchwChars5[inUtf32]; chwNext = rgchwChars6[inUtf32]; break; - case 6: chw = rgchwChars6[inUtf32]; chwNext = 0; break; - } - if (rgcchwRaw[ichw] == 1 && chwNext == 0 && chw < 0x0100) // ANSI - strmOut << (char)chw << " "; // 6 spaces - else - strmOut << " "; // 7 spaces - if (chwNext == 0) - inUtf32++; - } - strmOut << "\n"; - - // Unicode - strmOut << "Unicode: "; - inUtf32 = 0; - for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - utf16 chw, chwNext; - switch (rgcchwRaw[ichw]) - { - default: - case 1: chw = utf16(rgnChars[inUtf32]); chwNext = rgchwChars2[inUtf32]; break; - case 2: chw = rgchwChars2[inUtf32]; chwNext = rgchwChars3[inUtf32]; break; - case 3: chw = rgchwChars3[inUtf32]; chwNext = rgchwChars4[inUtf32]; break; - case 4: chw = rgchwChars4[inUtf32]; chwNext = rgchwChars5[inUtf32]; break; - case 5: chw = rgchwChars5[inUtf32]; chwNext = rgchwChars6[inUtf32]; break; - case 6: chw = rgchwChars6[inUtf32]; chwNext = 0; break; - } - ptman->LogHexInTable(strmOut, chw, chwNext != 0); - if (chwNext == 0) - inUtf32++; - } - strmOut << "\n"; - - strmOut << "before "; - for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - if (rgcchwRaw[ichw] > 1) - // continuation of Unicode codepoint - strmOut << " "; - else if (m_prgisloutBefore[ichw] == kNegInfinity) - strmOut << "<-- "; - else if (m_prgisloutBefore[ichw] == kPosInfinity) - strmOut << "--> "; - else - ptman->LogInTable(strmOut, m_prgisloutBefore[ichw]); - } - strmOut <<"\n"; - - for (int ix = 1; ix < signed(cassocs) - 1; ix++) //(cassocs > 2) - { - if (ix == 1) - strmOut << "other "; - else - strmOut << " "; - for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - std::vector<int> * pvislout = m_prgpvisloutAssocs[ichw]; - if (pvislout == NULL) - strmOut << " "; - else if (signed(pvislout->size()) <= ix) - strmOut << " "; - else if ((*pvislout)[ix] != m_prgisloutAfter[ichw]) - ptman->LogInTable(strmOut, (*pvislout)[ix]); - else - strmOut << " "; - } - strmOut << "\n"; - } - - strmOut << "after "; - for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - if (rgcchwRaw[ichw] > 1) - // continuation of Unicode codepoint - strmOut << " "; - else if (m_prgisloutAfter[ichw] == kNegInfinity) - strmOut << "<-- "; - else if (m_prgisloutAfter[ichw] == kPosInfinity) - strmOut << "--> "; - else - ptman->LogInTable(strmOut, m_prgisloutAfter[ichw]); - } - strmOut <<"\n"; - - if (fLigs) - { - strmOut << "ligature "; - for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - if (rgcchwRaw[ichw] > 1) - // continuation of Unicode codepoint - strmOut << " "; - else if (m_prgisloutLigature[ichw] != kNegInfinity) - ptman->LogInTable(strmOut, m_prgisloutLigature[ichw]); - else - strmOut << " "; - } - strmOut << "\n"; - - strmOut << "component "; - for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) - { - if (rgcchwRaw[ichw] > 1) - // continuation of Unicode codepoint - strmOut << " "; - else if (m_prgisloutLigature[ichw] != kNegInfinity) - ptman->LogInTable(strmOut, m_prgiComponent[ichw] + 1); // 1-based - else - strmOut << " "; - } - strmOut << "\n"; - } - - strmOut << "\n"; -#endif // XMLOMIT -#endif // TRACING - -} - -#ifdef XMLOMIT - -/*---------------------------------------------------------------------------------------------- - Write out the final surface-to-underlying associations. -----------------------------------------------------------------------------------------------*/ -void Segment::LogSurfaceToUnderlying(GrTableManager * ptman, std::ostream & strmOut) -{ -#ifdef TRACING - strmOut << "\nSURFACE TO UNDERLYING MAPPINGS\n\n"; - - ptman->LogSlotHeader(strmOut, m_cslout, SP_PER_SLOT, LEADING_SP); - - int ccomp = 0; - - strmOut << "Glyph IDs: "; - int islout; - for (islout = 0; islout < m_cslout; islout++) - { - GrSlotOutput * psloutTmp = m_prgslout + islout; - if (psloutTmp->SpecialSlotFlag() == kspslLbInitial || - psloutTmp->SpecialSlotFlag() == kspslLbFinal) - { - strmOut << "# "; - } - else - { - ptman->LogHexInTable(strmOut, psloutTmp->GlyphID()); - ccomp = max(ccomp, psloutTmp->NumberOfComponents()); - } - } - strmOut << "\n"; - - bool fAnyPseudos = false; - for (islout = 0; islout < m_cslout; islout++) - { - GrSlotOutput * psloutTmp = m_prgslout + islout; - if (psloutTmp->GlyphID() != psloutTmp->ActualGlyphForOutput(ptman)) - { - fAnyPseudos = true; - break; - } - } - if (fAnyPseudos) - { - strmOut << "Actual glyphs: "; - for (int islout = 0; islout < m_cslout; islout++) - { - GrSlotOutput * psloutTmp = m_prgslout + islout; - if (psloutTmp->GlyphID() != psloutTmp->ActualGlyphForOutput(ptman)) - ptman->LogHexInTable(strmOut, psloutTmp->ActualGlyphForOutput(ptman)); - else - strmOut << " "; - } - strmOut << "\n"; - } - - strmOut << "before "; - for (islout = 0; islout < m_cslout; islout++) - { - GrSlotOutput * psloutTmp = m_prgslout + islout; - if (psloutTmp->SpecialSlotFlag() == kspslLbInitial || - psloutTmp->SpecialSlotFlag() == kspslLbFinal) - { - strmOut << " "; - } - else - ptman->LogInTable(strmOut, psloutTmp->BeforeAssoc()); - } - strmOut << "\n"; - - strmOut << "after "; - for (islout = 0; islout < m_cslout; islout++) - { - GrSlotOutput * psloutTmp = m_prgslout + islout; - if (psloutTmp->SpecialSlotFlag() == kspslLbInitial || - psloutTmp->SpecialSlotFlag() == kspslLbFinal) - { - strmOut << " "; - } - else - ptman->LogInTable(strmOut, psloutTmp->AfterAssoc()); - } - strmOut << "\n"; - - for (int icomp = 0; icomp < ccomp; icomp++) - { - strmOut << "component " << icomp + 1 // 1=based - << " "; - for (islout = 0; islout < m_cslout; islout++) - { - GrSlotOutput * psloutTmp = m_prgslout + islout; - if (psloutTmp->SpecialSlotFlag() == kspslLbInitial || - psloutTmp->SpecialSlotFlag() == kspslLbFinal) - { - strmOut << " "; - } - else if (icomp < psloutTmp->NumberOfComponents()) - ptman->LogInTable(strmOut, psloutTmp->UnderlyingComponent(icomp)); - else - strmOut << " "; - } - strmOut << "\n"; - } -#endif // TRACING -} - -#ifdef TRACING -/*---------------------------------------------------------------------------------------------- - Log the value of the association, if the slot changed. -----------------------------------------------------------------------------------------------*/ -void GrSlotState::LogAssociation(GrTableManager * ptman, - std::ostream & strmOut, int ipass, int iassoc, bool fBoth, bool fAfter) -{ - if (m_ipassModified != ipass) - { - strmOut << " "; - return; - } - - if (fBoth) - { - GrSlotState * pslotBefore = (m_vpslotAssoc.size()) ? m_vpslotAssoc[0] : NULL; - GrSlotState * pslotAfter = (m_vpslotAssoc.size()) ? m_vpslotAssoc.back() : NULL; - // handle possible reprocessing - while (pslotBefore && pslotBefore->PassModified() == m_ipassModified) - pslotBefore = pslotBefore->m_pslotPrevState; - while (pslotAfter && pslotAfter->PassModified() == m_ipassModified) - pslotAfter = pslotAfter->m_pslotPrevState; - - int nBefore, nAfter; - - - int csp = 4; - if (pslotBefore) - { - nBefore = pslotBefore->m_islotTmpIn; - strmOut << nBefore; - if (nBefore > 99) csp--; - if (nBefore > 9) csp--; - } - else - { - strmOut << "??"; - csp--; - } - if (pslotAfter) - { - nAfter = pslotAfter->m_islotTmpIn; - strmOut << "/" << nAfter; - if (nAfter > 99) csp--; - if (nAfter > 9) csp--; - } - else - { - if (pslotBefore) - { - strmOut << "/" << "??"; - csp--; - } - else - csp = 5; - } - - for (int isp = 0; isp < csp; isp++) - strmOut << " "; - } - - else if (fAfter) - { - Assert(m_vpslotAssoc.size()); - GrSlotState * pslotAfter = m_vpslotAssoc.back(); - // handle possible reprocessing - while (pslotAfter && pslotAfter->PassModified() == m_ipassModified) - pslotAfter = pslotAfter->m_pslotPrevState; - - if (pslotAfter) - { - int nAfter = pslotAfter->m_islotTmpIn; - ptman->LogInTable(strmOut, nAfter); - } - else - strmOut << "?? "; - } - else if (iassoc < signed(m_vpslotAssoc.size())) - { - GrSlotState * pslot = m_vpslotAssoc[iassoc]; - // handle possible reprocessing - while (pslot && pslot->PassModified() == m_ipassModified) - pslot = pslot->m_pslotPrevState; - - if (pslot) - { - int n = pslot->m_islotTmpIn; - ptman->LogInTable(strmOut, n); - } - else - strmOut << "?? "; - } - else - strmOut << " "; -} - - -/*---------------------------------------------------------------------------------------------- - Write a directionality code to the table. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogDirCodeInTable(std::ostream & strmOut, int dirc) -{ - switch (dirc) - { - case kdircUnknown: strmOut << "??? "; break; - case kdircNeutral: strmOut << "ON "; break; - case kdircL: strmOut << "L "; break; - case kdircR: strmOut << "R "; break; - case kdircRArab: strmOut << "AR "; break; - case kdircEuroNum: strmOut << "EN "; break; - case kdircEuroSep: strmOut << "ES "; break; - case kdircEuroTerm: strmOut << "ET "; break; - case kdircArabNum: strmOut << "AN "; break; - case kdircComSep: strmOut << "CS "; break; - case kdircWhiteSpace: strmOut << "WS "; break; - case kdircBndNeutral: strmOut << "BN "; break; - case kdircNSM: strmOut << "NSM "; break; - case kdircLRO: strmOut << "LRO "; break; - case kdircRLO: strmOut << "RLO "; break; - case kdircLRE: strmOut << "LRE "; break; - case kdircRLE: strmOut << "RLE "; break; - case kdircPDF: strmOut << "PDF "; break; - case kdircPdfL: strmOut << "PDF-L "; break; - case kdircPdfR: strmOut << "PDF-R "; break; - case kdircLlb: strmOut << "L "; break; - case kdircRlb: strmOut << "R "; break; - default: LogInTable(strmOut, dirc); break; - } -} - -/*---------------------------------------------------------------------------------------------- - Write a breakweight code to the table. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogBreakWeightInTable(std::ostream & strmOut, int lb) -{ - if (lb < 0) - { - lb = lb * -1; - switch (lb) - { - case klbWsBreak: strmOut << "-ws "; break; - case klbWordBreak: strmOut << "-word "; break; - case klbHyphenBreak: strmOut << "-intra "; break; - case klbLetterBreak: strmOut << "-lettr "; break; - case klbClipBreak: strmOut << "-clip "; break; - default: LogInTable(strmOut, lb); break; - } - } - else - { - switch (lb) - { - case klbNoBreak: strmOut << "none "; break; - case klbWsBreak: strmOut << "ws "; break; - case klbWordBreak: strmOut << "word "; break; - case klbHyphenBreak: strmOut << "intra "; break; - case klbLetterBreak: strmOut << "letter "; break; - case klbClipBreak: strmOut << "clip "; break; - default: LogInTable(strmOut, lb); break; - } - } -} - -#endif // TRACING - -#endif // XMLOMIT - -#ifdef TRACING -/*---------------------------------------------------------------------------------------------- - Write an XML tag, leaving it open to possibly add attributes. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogXmlTagOpen(std::ostream & strmOut, std::string strTag, size_t nIndent, - bool fContent) -{ - for (size_t i = 0; i < nIndent; i++) - strmOut << " "; - - strmOut << "<" << strTag; -} - -/*---------------------------------------------------------------------------------------------- - Write the termination of the opening XML tag. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogXmlTagPostAttrs(std::ostream & strmOut, - bool fContent) -{ - if (fContent) - strmOut << ">\n"; -} - -/*---------------------------------------------------------------------------------------------- - Write the closing form of the XML tag. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogXmlTagClose(std::ostream & strmOut, std::string strTag, size_t nIndent, - bool fContent) -{ - if (fContent) - { - for (size_t i = 0; i < nIndent; i++) - strmOut << " "; - strmOut << "</" << strTag << ">\n"; - } - else - { - strmOut << " />\n"; - } -} - -/*---------------------------------------------------------------------------------------------- - Write an attribute/value pair inside of a tag. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogXmlTagAttr(std::ostream & strmOut, std::string strAttr, int nValue, - size_t nIndent) -{ - char chBuf[20]; - itoa(nValue, chBuf, 10); - LogXmlTagAttr(strmOut, strAttr, chBuf, nIndent); -} - -void GrTableManager::LogXmlTagAttr(std::ostream & strmOut, std::string strAttr, const char * szValue, - size_t nIndent) -{ - if (nIndent > 0) - { - strmOut << "\n"; - for (size_t i = 0; i < nIndent + 2; i++) - strmOut << " "; - } - else - strmOut << " "; - - strmOut << strAttr << "=\"" << szValue << "\""; -} - -void GrTableManager::LogXmlTagAttrHex(std::ostream & strmOut, std::string strAttr, int nValue, - size_t nIndent) -{ - char chBuf[20]; - chBuf[0] = chBuf[1] = chBuf[2] = '0'; - if (nValue < 0x10) - itoa(nValue, chBuf+3, 16); // prepend 3 zeros - else if (nValue < 0x100) - itoa(nValue, chBuf+2, 16); // prepend 2 zeros - else if (nValue < 0x1000) - itoa(nValue, chBuf+1, 16); // prepend 1 zero - else - itoa(nValue, chBuf, 16); - LogXmlTagAttr(strmOut, strAttr, chBuf, nIndent); -} - -/*---------------------------------------------------------------------------------------------- - Concatenate the hex form of the given numbers into a string. -----------------------------------------------------------------------------------------------*/ -std::string GrTableManager::HexString(std::vector<int> vn) -{ - std::string strRet; - for (size_t in = 0; in < vn.size(); in++) - { - char rgch[20]; - itoa(vn[in],rgch,16); - strRet.append(rgch); - if (in < vn.size() - 1) - strRet.append(" "); - } - return strRet; -} - -std::string GrTableManager::HexString(int n1, int n2, int n3, int n4, int n5, int n6) -{ - std::vector<int> vn; - if (n1 > 0) - { - vn.push_back(n1); - if (n2 > 0) - { - vn.push_back(n2); - if (n3 > 0) - { - vn.push_back(n3); - if (n4 > 0) - { - vn.push_back(n4); - if (n5 > 0) - { - vn.push_back(n5); - if (n6 > 0) - vn.push_back(n6); - } - } - } - } - } - return HexString(vn); -} - -/*---------------------------------------------------------------------------------------------- - Write an attribute/value pair inside of a tag. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogXmlTagColor(std::ostream & strmOut, std::string strAttr, int clrValue, - bool fBack, size_t nIndent) -{ - // Ignore black foreground and white background. - if (!fBack && clrValue == kclrBlack) - return; - if (fBack && (clrValue == kclrWhite || clrValue == kclrTransparent)) - return; - - std::string strValue; - char rgch[20]; - switch (clrValue) - { - case kclrBlack: strValue = "black"; break; - case kclrWhite: strValue = "white"; break; - case kclrRed: strValue = "red"; break; - case kclrGreen: strValue = "green"; break; - case kclrBlue: strValue = "blue"; break; - case 0x00ffff: strValue = "yellow"; break; - case 0xff00ff: strValue = "magenta"; break; - case 0xffff00: strValue = "cyan"; break; - default: - rgch[0] = '#'; - itoa(clrValue, rgch+1, 16); - strValue.assign(rgch); - break; - } - - LogXmlTagAttr(strmOut, strAttr, strValue.c_str(), nIndent); -} - -/*---------------------------------------------------------------------------------------------- - Write a directionality code to the table. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogXmlDirCode(std::ostream & strmOut, std::string strAttr, int dircValue, - size_t nIndent) -{ - std::string strValue; - char rgch[20]; - switch (dircValue) - { - case kdircUnknown: strValue = "unknown"; break; - case kdircNeutral: strValue = "ON"; break; - case kdircL: strValue = "L"; break; - case kdircR: strValue = "R"; break; - case kdircRArab: strValue = "AR"; break; - case kdircEuroNum: strValue = "EN"; break; - case kdircEuroSep: strValue = "ES"; break; - case kdircEuroTerm: strValue = "ET"; break; - case kdircArabNum: strValue = "AN"; break; - case kdircComSep: strValue = "CS"; break; - case kdircWhiteSpace: strValue = "WS"; break; - case kdircBndNeutral: strValue = "BN"; break; - case kdircNSM: strValue = "NSM"; break; - case kdircLRO: strValue = "LRO"; break; - case kdircRLO: strValue = "RLO"; break; - case kdircLRE: strValue = "LRE"; break; - case kdircRLE: strValue = "RLE"; break; - case kdircPDF: strValue = "PDF"; break; - case kdircPdfL: strValue = "PDF-L"; break; - case kdircPdfR: strValue = "PDF-R"; break; - case kdircLlb: strValue = "L"; break; - case kdircRlb: strValue = "R"; break; - default: - itoa(dircValue, rgch, 10); - strValue.assign(rgch); - break; - } - LogXmlTagAttr(strmOut, strAttr, strValue.c_str(), nIndent); -} - -/*---------------------------------------------------------------------------------------------- - Write a breakweight code to the table. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogXmlBreakWeight(std::ostream & strmOut, std::string strAttr, int lbValue, - size_t nIndent) -{ - std::string strValue; - char rgch[20]; - if (lbValue < 0) - { - lbValue = lbValue * -1; - switch (lbValue) - { - case klbWsBreak: strValue = "-ws"; break; - case klbWordBreak: strValue = "-word"; break; - case klbHyphenBreak: strValue = "-intra"; break; - case klbLetterBreak: strValue = "-letter"; break; - case klbClipBreak: strValue = "-clip"; break; - default: - itoa(lbValue * -1, rgch, 10); - strValue.assign(rgch); - break; - } - } - else - { - switch (lbValue) - { - case klbNoBreak: strValue = "none"; break; - case klbWsBreak: strValue = "ws"; break; - case klbWordBreak: strValue = "word"; break; - case klbHyphenBreak: strValue = "intra"; break; - case klbLetterBreak: strValue = "letter"; break; - case klbClipBreak: strValue = "clip"; break; - default: - itoa(lbValue, rgch, 10); - strValue.assign(rgch); - break; - } - } - LogXmlTagAttr(strmOut, strAttr, strValue.c_str(), nIndent); -} - -/*---------------------------------------------------------------------------------------------- - Add a comment to the log file. -----------------------------------------------------------------------------------------------*/ -void GrTableManager::LogXmlComment(std::ostream & strmOut, std::string strComment, - size_t nIndent) -{ - for (size_t i = 0; i < nIndent; i++) - strmOut << " "; - - strmOut << "<!-- " << strComment << " -->\n"; -} - - -#endif // TRACING - -} // namespace gr diff --git a/Build/source/libs/graphite-engine/src/segment/resource.h b/Build/source/libs/graphite-engine/src/segment/resource.h deleted file mode 100644 index 775418f76bf..00000000000 --- a/Build/source/libs/graphite-engine/src/segment/resource.h +++ /dev/null @@ -1,15 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by Graphite.rc -// - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif |