diff options
Diffstat (limited to 'Build/source/libs/graphite/src/segment/GrTableManager.h')
-rw-r--r-- | Build/source/libs/graphite/src/segment/GrTableManager.h | 583 |
1 files changed, 583 insertions, 0 deletions
diff --git a/Build/source/libs/graphite/src/segment/GrTableManager.h b/Build/source/libs/graphite/src/segment/GrTableManager.h new file mode 100644 index 00000000000..e0306c832c7 --- /dev/null +++ b/Build/source/libs/graphite/src/segment/GrTableManager.h @@ -0,0 +1,583 @@ +/*--------------------------------------------------------------------*//*: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 |