/*--------------------------------------------------------------------*//*: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 &); 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 & vichw); int BeforeAssoc(); int AfterAssoc(); void CleanUpAssocs(); void SetComponentRefsFor(GrSlotOutput *, int iComp = -1); void AllComponentRefs(std::vector & 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 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 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 & 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