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