/*--------------------------------------------------------------------*//*: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 //: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 m_vslotblk; std::vector 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 & vnFeats, std::vector & 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); 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