summaryrefslogtreecommitdiff
path: root/Build/source/libs/graphite-engine/src/segment/Segment.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/graphite-engine/src/segment/Segment.cpp')
-rw-r--r--Build/source/libs/graphite-engine/src/segment/Segment.cpp425
1 files changed, 281 insertions, 144 deletions
diff --git a/Build/source/libs/graphite-engine/src/segment/Segment.cpp b/Build/source/libs/graphite-engine/src/segment/Segment.cpp
index 319baef85b5..69e5349bca3 100644
--- a/Build/source/libs/graphite-engine/src/segment/Segment.cpp
+++ b/Build/source/libs/graphite-engine/src/segment/Segment.cpp
@@ -75,20 +75,20 @@ Segment::Segment() :
m_cbNextSegDat(0),
m_prgInitDat(NULL),
m_cbInitDat(0),
- m_fUseSepBase(0),
+// m_fUseSepBase(0),
//m_psegAltEndLine(NULL),
m_prgisloutBefore(NULL),
m_prgisloutAfter(NULL),
- m_prgvisloutAssocs(NULL),
+ m_prgpvisloutAssocs(NULL),
m_prgisloutLigature(NULL),
m_prgiComponent(NULL),
- m_psstrm(NULL),
+// m_psstrm(NULL),
m_cslout(0),
m_prgslout(NULL),
m_prgnSlotVarLenBuf(NULL),
- m_cnUserDefn(0),
+// m_cnUserDefn(0),
m_cnCompPerLig(0),
- m_cnFeat(0),
+// m_cnFeat(0),
m_cginf(0),
m_prgginf(NULL)
{
@@ -96,8 +96,8 @@ Segment::Segment() :
g_csegTotal++;
- m_stuFaceName.erase();
- m_stuBaseFaceName.erase();
+// m_stuFaceName.erase();
+// m_stuBaseFaceName.erase();
m_vnSkipOffsets.clear();
}
@@ -247,12 +247,12 @@ void Segment::Initialize(ITextSource * pgts, int ichwMin, int ichwLim,
m_dxsVisibleWidth = -1;
m_dxsTotalWidth = -1;
- m_psstrm = NULL;
+// m_psstrm = NULL;
m_prgslout = NULL;
m_prgnSlotVarLenBuf = NULL;
m_prgisloutBefore = NULL;
m_prgisloutAfter = NULL;
- m_prgvisloutAssocs = NULL;
+ m_prgpvisloutAssocs = NULL;
m_prgisloutLigature = NULL;
m_prgiComponent = NULL;
@@ -261,12 +261,12 @@ void Segment::Initialize(ITextSource * pgts, int ichwMin, int ichwLim,
//m_psegAltEndLine = NULL;
- m_stuFaceName.erase();
- m_stuBaseFaceName.erase();
- m_fUseSepBase = false;
+// m_stuFaceName.erase();
+// m_stuBaseFaceName.erase();
+// m_fUseSepBase = false;
- m_psegPrev = NULL; // obsolete
- m_psegNext = NULL;
+// m_psegPrev = NULL; // obsolete
+// m_psegNext = NULL;
//InitializePlatform();
}
@@ -311,7 +311,12 @@ void Segment::DestroyContents()
delete[] m_prgnSlotVarLenBuf;
delete[] m_prgisloutBefore;
delete[] m_prgisloutAfter;
- delete[] m_prgvisloutAssocs;
+ for (int ichw = 0; ichw < m_ichwAssocsLim - m_ichwAssocsMin; ichw++)
+ {
+ if (m_prgpvisloutAssocs && m_prgpvisloutAssocs[ichw])
+ delete m_prgpvisloutAssocs[ichw];
+ }
+ delete[] m_prgpvisloutAssocs;
delete[] m_prgisloutLigature;
delete[] m_prgiComponent;
delete[] m_prgbNextSegDat;
@@ -446,14 +451,14 @@ Segment::Segment(Segment & seg)
m_cbNextSegDat = seg.m_cbNextSegDat;
m_prgbNextSegDat = new byte[m_cbNextSegDat];
std::copy(seg.m_prgbNextSegDat, seg.m_prgbNextSegDat + m_cbNextSegDat, m_prgbNextSegDat);
- m_psegPrev = seg.m_psegPrev;
- m_psegNext = seg.m_psegNext;
- m_stuFaceName = seg.m_stuFaceName;
- m_stuBaseFaceName = seg.m_stuBaseFaceName;
- m_fUseSepBase = seg.m_fUseSepBase;
- m_pixHeight = seg.m_pixHeight;
- m_fBold = seg.m_fBold;
- m_fItalic = seg.m_fItalic;
+// m_psegPrev = seg.m_psegPrev;
+// m_psegNext = seg.m_psegNext;
+// m_stuFaceName = seg.m_stuFaceName;
+// m_stuBaseFaceName = seg.m_stuBaseFaceName;
+// m_fUseSepBase = seg.m_fUseSepBase;
+// m_pixHeight = seg.m_pixHeight;
+// m_fBold = seg.m_fBold;
+// m_fItalic = seg.m_fItalic;
m_lbStart = seg.m_lbStart;
m_lbEnd = seg.m_lbEnd;
m_fStartLine = seg.m_fStartLine;
@@ -463,8 +468,8 @@ Segment::Segment(Segment & seg)
m_dysFontAscent = seg.m_dysFontAscent;
m_dysFontDescent = seg.m_dysFontDescent;
m_xysEmSquare = seg.m_xysEmSquare;
- m_xsDPI = seg.m_xsDPI;
- m_ysDPI = seg.m_ysDPI;
+// m_xsDPI = seg.m_xsDPI;
+// m_ysDPI = seg.m_ysDPI;
m_dxsStretch = seg.m_dxsStretch;
m_dxsWidth = seg.m_dxsWidth;
m_dysHeight = seg.m_dysHeight;
@@ -488,16 +493,22 @@ Segment::Segment(Segment & seg)
std::copy(seg.m_prgisloutBefore, seg.m_prgisloutBefore + dichw, m_prgisloutBefore);
m_prgisloutAfter = new int[dichw];
std::copy(seg.m_prgisloutAfter, seg.m_prgisloutAfter + dichw, m_prgisloutAfter);
- m_prgvisloutAssocs = new std::vector<int>[dichw];
- std::copy(seg.m_prgvisloutAssocs, seg.m_prgvisloutAssocs + dichw,
- m_prgvisloutAssocs);
+ m_prgpvisloutAssocs = new std::vector<int> * [dichw];
+ for (int ivislout = 0; ivislout < dichw; ivislout++)
+ {
+ std::vector<int> * pvislout = seg.m_prgpvisloutAssocs[ivislout];
+ if (pvislout)
+ {
+ std::vector<int> * pvisloutNew = new std::vector<int>;
+ m_prgpvisloutAssocs[ivislout] = pvisloutNew;
+ *pvisloutNew = *pvislout; // copy the vector
+ }
+ }
m_prgisloutLigature = new int[dichw];
std::copy(seg.m_prgisloutLigature, seg.m_prgisloutLigature + dichw, m_prgisloutLigature);
- m_prgiComponent = new int[dichw];
+ m_prgiComponent = new sdata8[dichw];
std::copy(seg.m_prgiComponent, seg.m_prgiComponent + dichw, m_prgiComponent);
- // m_psstrm
-
m_cslout = seg.m_cslout;
int cnExtraPerSlot = (m_cslout > 0) ? seg.m_prgslout[0].CExtraSpaceSlout() : 0;
m_prgnSlotVarLenBuf = new u_intslot[m_cslout * cnExtraPerSlot];
@@ -511,9 +522,9 @@ Segment::Segment(Segment & seg)
cnExtraPerSlot);
}
- m_cnUserDefn = seg.m_cnUserDefn;
+// m_cnUserDefn = seg.m_cnUserDefn;
m_cnCompPerLig = seg.m_cnCompPerLig;
- m_cnFeat = seg.m_cnFeat;
+// m_cnFeat = seg.m_cnFeat;
m_cslotRestartBackup = seg.m_cslotRestartBackup;
std::copy(seg.m_prgnSlotVarLenBuf, seg.m_prgnSlotVarLenBuf +
(m_cslout * cnExtraPerSlot), m_prgnSlotVarLenBuf);
@@ -921,14 +932,19 @@ std::pair<GlyphIterator, GlyphIterator> Segment::glyphs()
----------------------------------------------------------------------------------------------*/
std::pair<GlyphSetIterator, GlyphSetIterator> Segment::charToGlyphs(toffset ich)
{
- std::vector<int> * pvislout = UnderlyingToLogicalAssocs(ich);
+ std::vector<int> vislout = UnderlyingToLogicalAssocs(ich);
- // UnderlyingToLogicalAssocs can return NULL for edge cases
- if (pvislout == NULL)
+ if (vislout.size() == 0)
return std::make_pair(GlyphSetIterator(), GlyphSetIterator());
else
- return std::make_pair(GlyphSetIterator(*this, 0, *pvislout),
- GlyphSetIterator(*this, pvislout->size(), *pvislout));
+ {
+ // Note that BOTH instances of GlyphSetIterator must use the same underlying vector,
+ // so that comparisons make sense.
+ RcVector * qvislout = new RcVector(vislout);
+ return std::make_pair(
+ GlyphSetIterator(*this, 0, qvislout),
+ GlyphSetIterator(*this, vislout.size(), qvislout));
+ }
}
/*----------------------------------------------------------------------------------------------
@@ -1107,7 +1123,7 @@ LineBrk Segment::getBreakWeight(int ich, bool fBreakBefore)
return klbClipBreak;
GrSlotOutput * psloutFirst = m_prgslout + isloutFirst;
bool fNotFirst = false;
- if (psloutFirst->HasComponents()
+ if ((psloutFirst->NumberOfComponents() > 0)
&& psloutFirst->UnderlyingComponent(0) != ich)
{
// Not the first component of a ligature.
@@ -1124,7 +1140,7 @@ LineBrk Segment::getBreakWeight(int ich, bool fBreakBefore)
return klbClipBreak;
GrSlotOutput * psloutLast = m_prgslout + isloutLast;
bool fNotLast = false;
- if (psloutLast->HasComponents()
+ if ((psloutLast->NumberOfComponents() > 0)
&& psloutLast->UnderlyingComponent(psloutLast->NumberOfComponents() - 1) != ich)
{
// Not the last component of a ligature.
@@ -1285,7 +1301,7 @@ int Segment::findNextBreakPoint(int ichStart,
else
iginfMin = iginfMid;
}
- Assert(iginfLim < m_cginf);
+ Assert(iginfLim <= m_cginf);
if (iginfLim >= m_cginf) iginfLim = m_cginf - 1;
ichFit = PhysicalSurfaceToUnderlying(iginfLim, false);
}
@@ -1534,11 +1550,11 @@ void Segment::SetUpOutputArrays(Font * pfont, GrTableManager * ptman,
m_mFontEmUnits = EngineImpl()->GetFontEmUnits();
pfont->getFontMetrics(&m_dysFontAscent, &m_dysFontDescent, &m_xysEmSquare);
- m_xsDPI = (float)pfont->getDPIx();
- m_ysDPI = (float)pfont->getDPIy();
+// m_xsDPI = (float)pfont->getDPIx();
+// m_ysDPI = (float)pfont->getDPIy();
// Note that storing both of these values is redundant; they should be the same.
- Assert(m_xysEmSquare == m_pixHeight);
+// Assert(m_xysEmSquare == m_pixHeight);
m_twsh = twsh;
m_fParaRtl = fParaRtl;
@@ -1560,24 +1576,24 @@ void Segment::SetUpOutputArrays(Font * pfont, GrTableManager * ptman,
m_prgisloutAfter = new int[cchwInThisSeg];
- m_prgvisloutAssocs = new std::vector<int>[cchwInThisSeg];
+ m_prgpvisloutAssocs = new std::vector<int> * [cchwInThisSeg];
m_prgisloutLigature = new int[cchwInThisSeg];
- m_prgiComponent = new int[cchwInThisSeg];
+ m_prgiComponent = new sdata8[cchwInThisSeg];
int cslot = 0;
- m_psstrm = psstrmFinal; // TODO: make a local variable
- if (m_psstrm)
- cslot = m_psstrm->FinalSegLim();
+ //m_psstrm = psstrmFinal; // TODO: make a local variable
+ if (psstrmFinal)
+ cslot = psstrmFinal->FinalSegLim();
else
Assert(fEmpty);
float xsMin = 0;
int islot;
- int islotMin = (m_psstrm) ? m_psstrm->IndexOffset() : 0;
+ int islotMin = (psstrmFinal) ? psstrmFinal->IndexOffset() : 0;
for (islot = islotMin; islot < cslot; islot++)
- xsMin = min(xsMin, m_psstrm->SlotAt(islot)->XPosition());
+ xsMin = min(xsMin, psstrmFinal->SlotAt(islot)->XPosition());
// For right-to-left segments, the draw origin is at the left side of the visible
// portion of the text. So if necessary, scoot everything left so that the invisible
@@ -1587,7 +1603,7 @@ void Segment::SetUpOutputArrays(Font * pfont, GrTableManager * ptman,
float dxsInvisible = (m_fEndLine) ? m_dxsTotalWidth - m_dxsVisibleWidth : 0;
for (islot = islotMin; ((m_nDirDepth % 2) && (islot < cslot)); islot++)
{
- GrSlotState * pslot = m_psstrm->SlotAt(islot);
+ GrSlotState * pslot = psstrmFinal->SlotAt(islot);
// int islout = islot - islotMin;
if (pslot->GlyphID() == chwLB)
continue; // skip over linebreak markers
@@ -1606,38 +1622,50 @@ void Segment::SetUpOutputArrays(Font * pfont, GrTableManager * ptman,
{
m_prgisloutBefore[ichw] = kPosInfinity;
m_prgisloutAfter[ichw] = kNegInfinity;
- m_prgvisloutAssocs[ichw].clear();
+ m_prgpvisloutAssocs[ichw] = new std::vector<int>;
m_prgisloutLigature[ichw] = kNegInfinity;
m_prgiComponent[ichw] = 0;
}
m_cslout = csloutSurface;
- m_cnUserDefn = ptman->NumUserDefn();
+ if (ptman->NumUserDefn() > 0 && ptman->NumCompPerLig() > 0)
+ {
+ int x; x = 3;
+ }
+
+// m_cnUserDefn = ptman->NumUserDefn();
m_cnCompPerLig = ptman->NumCompPerLig();
- m_cnFeat = ptman->NumFeat();
+// m_cnFeat = ptman->NumFeat();
// Normal buffers, plus underlying indices of ligature components, plus
// map from used components to defined components.
- int cnExtraPerSlot = m_cnUserDefn + (m_cnCompPerLig * 2) + m_cnFeat + (m_cnCompPerLig * 2);
+// int cnExtraPerSlot = m_cnUserDefn + (m_cnCompPerLig * 2) + m_cnFeat + (m_cnCompPerLig * 2);
+
+ // We don't need to store the user-defined slot attributes or the features in the segment itself.
+ // What we need is: (1) component.ref attr settings, (2) slot-attribute indices,
+ // (3) underlying indicates of ligature components, and (4) map from used components
+ // to defined components
+ int cnExtraPerSlot = m_cnCompPerLig * 4;
m_prgslout = new GrSlotOutput[m_cslout];
m_prgnSlotVarLenBuf = new u_intslot[m_cslout * cnExtraPerSlot];
m_isloutVisLim = 0;
- if (m_psstrm)
+ if (psstrmFinal)
{
for (islot = islotMin; islot < psstrmFinal->FinalSegLim(); ++islot)
{
- int isloutAdj = islot - islotMin;
+ int isloutRel = islot - islotMin;
GrSlotState * pslot = psstrmFinal->SlotAt(islot);
- pslot->SetPosPassIndex(isloutAdj, false);
+ pslot->SetPosPassIndex(isloutRel, false);
pslot->EnsureCacheForOutput(ptman);
- GrSlotOutput * pslout = OutputSlot(isloutAdj);
- pslout->SetBufferPtr(m_prgnSlotVarLenBuf + (isloutAdj * cnExtraPerSlot));
- pslout->CopyFrom(pslot);
+ GrSlotOutput * pslout = OutputSlot(isloutRel);
+ pslout->SetBufferPtr(m_prgnSlotVarLenBuf + (isloutRel * cnExtraPerSlot));
+ pslout->InitializeOutputFrom(pslot);
pslout->SetBeforeAssoc(pslot->BeforeAssoc());
pslout->SetAfterAssoc(pslot->AfterAssoc());
if (pslot->HasComponents())
- pslot->SetComponentRefsFor(pslout); // also sets it for pslout, since they share the buffer
+ pslot->SetComponentRefsFor(pslout);
+ Assert(pslot->HasComponents() == (pslout->NumberOfComponents() > 0));
//if (pslot->HasClusterMembers())
//{
//Assert(pslot->HasClusterMembers() || pslot->ClusterRootOffset() == 0);
@@ -1659,7 +1687,7 @@ void Segment::SetUpOutputArrays(Font * pfont, GrTableManager * ptman,
int isloutBaseIndex = pslot->Base(psstrmFinal)->PosPassIndex();
if (!pslot->IsBase())
{
- OutputSlot(isloutBaseIndex)->AddClusterMember(pslot->PosPassIndex());
+ OutputSlot(isloutBaseIndex)->AddClusterMember(isloutBaseIndex, pslot->PosPassIndex());
OutputSlot(isloutAdj)->SetClusterBase(isloutBaseIndex);
}
else if (pslot->HasClusterMembers() && pslot->IsBase())
@@ -1680,7 +1708,7 @@ void Segment::SetUpOutputArrays(Font * pfont, GrTableManager * ptman,
// Final output for draw routines.
- SetUpGlyphInfo(ptman, chwLB, nDirDepth, islotMin, cslot);
+ SetUpGlyphInfo(ptman, psstrmFinal, chwLB, nDirDepth, islotMin, cslot);
//SetUpOutputArraysPlatform(ptman, chwLB, nDirDepth, islotMin, cslot);
@@ -1689,8 +1717,8 @@ void Segment::SetUpOutputArrays(Font * pfont, GrTableManager * ptman,
/*----------------------------------------------------------------------------------------------
Set up the data structures that represent the actual rendered glyphs for the new segment.
----------------------------------------------------------------------------------------------*/
-void Segment::SetUpGlyphInfo(GrTableManager * ptman, gid16 chwLB, int nDirDepth,
- int islotMin, int cslot)
+void Segment::SetUpGlyphInfo(GrTableManager * ptman, GrSlotStream * psstrmFinal,
+ gid16 chwLB, int nDirDepth, int islotMin, int cslot)
{
//int paraDirLevel = (ptman->State()->ParaRightToLeft()) ? 1 : 0;
@@ -1699,7 +1727,7 @@ void Segment::SetUpGlyphInfo(GrTableManager * ptman, gid16 chwLB, int nDirDepth,
int islot;
for (islot = islotMin; islot < cslot; islot++)
{
- if (m_psstrm->SlotAt(islot)->GlyphID() != chwLB)
+ if (psstrmFinal->SlotAt(islot)->GlyphID() != chwLB)
{
m_cginf++;
}
@@ -1718,7 +1746,7 @@ void Segment::SetUpGlyphInfo(GrTableManager * ptman, gid16 chwLB, int nDirDepth,
int iginf = 0;
for (int islot = islotMin; islot < cslot; islot++)
{
- GrSlotState * pslot = m_psstrm->SlotAt(islot);
+ GrSlotState * pslot = psstrmFinal->SlotAt(islot);
if (pslot->GlyphID() == chwLB)
{
@@ -1737,32 +1765,37 @@ void Segment::SetUpGlyphInfo(GrTableManager * ptman, gid16 chwLB, int nDirDepth,
// Fill in stuff in the output slot that is needed by the GlyphInfo object.
pslout->m_xsAdvanceX = pslot->GlyphMetricLogUnits(ptman, kgmetAdvWidth);
- pslout->m_ysAdvanceY = pslot->GlyphMetricLogUnits(ptman, kgmetAdvHeight);
- pslout->m_rectBB.top
- = pslot->YPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbTop);
- pslout->m_rectBB.bottom
- = pslot->YPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbBottom);
- pslout->m_rectBB.left
- = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbLeft);
- if (pslot->IsSpace(ptman))
- pslout->m_rectBB.right
- = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetAdvWidth);
- else
- pslout->m_rectBB.right
- = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbRight);
+ //pslout->m_ysAdvanceY = pslot->GlyphMetricLogUnits(ptman, kgmetAdvHeight);
+ //pslout->m_rectBB.top
+ // = pslot->YPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbTop);
+ //pslout->m_rectBB.bottom
+ // = pslot->YPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbBottom);
+ //pslout->m_rectBB.left
+ // = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbLeft);
+ //if (pslot->IsSpace(ptman))
+ // pslout->m_rectBB.right
+ // = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetAdvWidth);
+ //else
+ // pslout->m_rectBB.right
+ // = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbRight);
iginf++;
}
if (cslot - islotMin == 0)
m_isloutGinf0 = 0;
+ if (m_isloutGinf0 == -1)
+ {
+ Assert(m_cginf == 0);
+ m_isloutGinf0 = ((OutputSlot(0)->IsInitialLineBreak()) ? 1 : 0);
+ }
Assert(m_isloutGinf0 == 0 || m_isloutGinf0 == 1);
}
/*
// OLD VERSION
-void Segment::SetUpGlyphInfo(GrTableManager * ptman, gid16 chwLB, int nDirDepth,
+void Segment::SetUpGlyphInfo(GrTableManager * ptman, GrSlotStream * psstrmFinal, gid16 chwLB, int nDirDepth,
int islotMin, int cslot)
{
int paraDirLevel = (ptman->State()->ParaRightToLeft()) ? 1 : 0;
@@ -1771,7 +1804,7 @@ void Segment::SetUpGlyphInfo(GrTableManager * ptman, gid16 chwLB, int nDirDepth,
int islot;
for (islot = islotMin; islot < cslot; islot++)
{
- if (m_psstrm->SlotAt(islot)->GlyphID() != chwLB)
+ if (psstrmFinal->SlotAt(islot)->GlyphID() != chwLB)
m_cginf++;
}
@@ -1788,7 +1821,7 @@ void Segment::SetUpGlyphInfo(GrTableManager * ptman, gid16 chwLB, int nDirDepth,
m_isloutGinf0 = -1;
for (islot = islotMin; islot < cslot; islot++)
{
- GrSlotState * pslot = m_psstrm->SlotAt(islot);
+ GrSlotState * pslot = psstrmFinal->SlotAt(islot);
int islout = islot - islotMin;
if (pslot->GlyphID() == chwLB)
@@ -2030,6 +2063,30 @@ void Segment::AdjustAfterArrayFromNextSeg()
#endif // -------------------------- END OF OBSOLETE CODE ----------------------------------
+
+/*----------------------------------------------------------------------------------------------
+ Generate a list of all the glyphs that are attached to the base with the given index.
+ Note that we want to generate glyph indices, not slot indices.
+
+ @param disloutCluster - indicates how far on either side of the base to look.
+----------------------------------------------------------------------------------------------*/
+void Segment::ClusterMembersForGlyph(int isloutBase, int disloutCluster,
+ std::vector<int> & visloutRet)
+{
+ for (int islout = max(0, isloutBase - disloutCluster);
+ islout < min(m_cslout, isloutBase + disloutCluster + 1);
+ islout++)
+ {
+ if (islout == isloutBase)
+ continue; // don't include the base itself
+ GrSlotOutput * pslout = m_prgslout + islout;
+ if (pslout->ClusterBase() == isloutBase)
+ {
+ visloutRet.push_back(islout);
+ }
+ }
+}
+
/*----------------------------------------------------------------------------------------------
Record an underlying-to-surface association mapping, based on the fact that there is
a corresponding surface-to-underlying association in the streams.
@@ -2062,7 +2119,7 @@ void Segment::RecordSurfaceAssoc(int ichwUnder, int islotSurface, int nDir)
min(m_prgisloutAfter[ ichwUnder - m_ichwAssocsMin], islotSurface);
}
- m_prgvisloutAssocs[ichwUnder - m_ichwAssocsMin].push_back(islotSurface);
+ m_prgpvisloutAssocs[ichwUnder - m_ichwAssocsMin]->push_back(islotSurface);
}
/*----------------------------------------------------------------------------------------------
@@ -2083,7 +2140,8 @@ void Segment::RecordLigature(int ichwUnder, int islotSurface, int iComponent)
Assert(m_prgisloutLigature[ichwUnder - m_ichwAssocsMin] == kNegInfinity);
m_prgisloutLigature[ichwUnder - m_ichwAssocsMin] = islotSurface;
- m_prgiComponent[ ichwUnder - m_ichwAssocsMin] = iComponent;
+ Assert(iComponent < kMaxComponentsPerGlyph);
+ m_prgiComponent[ ichwUnder - m_ichwAssocsMin] = sdata8(iComponent);
}
/*----------------------------------------------------------------------------------------------
@@ -2141,12 +2199,12 @@ void Segment::EnsureSpaceAtLineBoundaries(int ichwUnder)
m_prgisloutAfter + cchwPreAdd);
delete[] prgisloutTmp;
- std::vector<int> * pvisloutTmp = m_prgvisloutAssocs;
- m_prgvisloutAssocs = new std::vector<int>[cchwNewLim - cchwNewMin];
- std::swap_ranges(m_prgvisloutAssocs + cchwPreAdd,
- m_prgvisloutAssocs + cchwPreAdd +
- (m_ichwAssocsLim - m_ichwAssocsMin), pvisloutTmp);
- delete[] pvisloutTmp;
+ std::vector<int> ** ppvisloutTmp = m_prgpvisloutAssocs;
+ m_prgpvisloutAssocs = new std::vector<int> * [cchwNewLim - cchwNewMin];
+ std::swap_ranges(m_prgpvisloutAssocs + cchwPreAdd,
+ m_prgpvisloutAssocs + cchwPreAdd +
+ (m_ichwAssocsLim - m_ichwAssocsMin), ppvisloutTmp);
+ delete[] ppvisloutTmp;
prgisloutTmp = m_prgisloutLigature;
m_prgisloutLigature = new int[cchwNewLim - cchwNewMin];
@@ -2154,11 +2212,11 @@ void Segment::EnsureSpaceAtLineBoundaries(int ichwUnder)
m_prgisloutLigature + cchwPreAdd);
delete[] prgisloutTmp;
- prgisloutTmp = m_prgiComponent;
- m_prgiComponent = new int[cchwNewLim - cchwNewMin];
- std::copy(prgisloutTmp, prgisloutTmp + (m_ichwAssocsLim - m_ichwAssocsMin),
+ sdata8 * prgiCompTmp = m_prgiComponent;
+ m_prgiComponent = new sdata8[cchwNewLim - cchwNewMin];
+ std::copy(prgiCompTmp, prgiCompTmp + (m_ichwAssocsLim - m_ichwAssocsMin),
m_prgiComponent + cchwPreAdd);
- delete[] prgisloutTmp;
+ delete[] prgiCompTmp;
// Initialize new slots.
int i;
@@ -2166,7 +2224,7 @@ void Segment::EnsureSpaceAtLineBoundaries(int ichwUnder)
{
m_prgisloutBefore[i] = kPosInfinity;
m_prgisloutAfter[i] = kNegInfinity;
- m_prgvisloutAssocs[i].clear();
+ m_prgpvisloutAssocs[i] = new std::vector<int>;
m_prgisloutLigature[i] = kNegInfinity;
m_prgiComponent[i] = 0;
}
@@ -2176,7 +2234,7 @@ void Segment::EnsureSpaceAtLineBoundaries(int ichwUnder)
{
m_prgisloutBefore[i] = kPosInfinity;
m_prgisloutAfter[i] = kNegInfinity;
- m_prgvisloutAssocs[i].clear();
+ m_prgpvisloutAssocs[i] = new std::vector<int>;
m_prgisloutLigature[i] = kNegInfinity;
m_prgiComponent[i] = 0;
}
@@ -2212,11 +2270,11 @@ void Segment::SetFont(Font * pfont)
{
m_pfont = pfont->copyThis();
- m_fBold = pfont->bold();
- m_fItalic = pfont->italic();
+// m_fBold = pfont->bold();
+// m_fItalic = pfont->italic();
// Note that we store the character height (which does not include the internal leading),
// not the actual font height, ie, ascent + descent. This is what is used in the LOGFONT.
- pfont->getFontMetrics(NULL, NULL, &m_pixHeight);
+ pfont->getFontMetrics(NULL, NULL, &m_xysEmSquare); // m_xysEmSquare = m_pixHeight
}
/*----------------------------------------------------------------------------------------------
@@ -2308,7 +2366,7 @@ int Segment::LogicalSurfaceToUnderlying(int islout, float xsOffset, float ysClic
// If the slot has components, see if the offset falls within one of them.
- if (pslout->HasComponents())
+ if (pslout->NumberOfComponents() > 0)
{
GrEngine * pgreng = EngineImpl();
if (!pgreng)
@@ -2388,6 +2446,9 @@ LNotLigature:
// diCharAdj--;
}
+ if (dichw == kNegInfinity || dichw == kPosInfinity)
+ return dichw;
+
// This should be true because of the way the associations are set up:
Assert(GrCharStream::AtUnicodeCharBoundary(m_pgts, m_ichwMin + dichw)); // + diCharAdj));
@@ -2516,6 +2577,7 @@ int Segment::LogicalToPhysicalSurface(int islout)
return the physical surface locations of all the associated surface glyphs.
OBSOLETE
----------------------------------------------------------------------------------------------*/
+#if 0
void Segment::UnderlyingToPhysicalAssocs(int ichw, std::vector<int> & viginf)
{
int ichwSegOffset = ichw - m_ichwMin;
@@ -2539,29 +2601,48 @@ void Segment::UnderlyingToPhysicalAssocs(int ichw, std::vector<int> & viginf)
}
}
}
+#endif
/*----------------------------------------------------------------------------------------------
Given an underlying character position (relative to the beginning of the string),
return a pointer to the vector containing the logical surface locations of
all the associated surface glyphs.
- WARNING: this method returns a pointer to the actual data, not a copy of it.
- Do not modify the returned vector!
+ Returns an empty vector (not something containing infinities) if the character is
+ "invisible."
----------------------------------------------------------------------------------------------*/
-std::vector<int> * Segment::UnderlyingToLogicalAssocs(int ichw)
+std::vector<int> Segment::UnderlyingToLogicalAssocs(int ichw)
{
+ std::vector<int> vnEmpty;
+ vnEmpty.clear();
+ Assert(vnEmpty.size() == 0);
+
int ichwSegOffset = ichw - m_ichwMin;
if (ichwSegOffset < m_ichwAssocsMin)
- return NULL; // probably rendered in previous segment
+ return vnEmpty; // probably rendered in previous segment
else if (ichwSegOffset >= m_ichwAssocsLim)
- return NULL; // probably rendered in following segment
+ return vnEmpty; // probably rendered in following segment
+ else if (m_prgpvisloutAssocs[ichwSegOffset - m_ichwAssocsMin] == NULL)
+ {
+ // Create a vector using the before and after values.
+ std::vector<int> visloutRet;
+ int isloutBefore = m_prgisloutBefore[ichwSegOffset - m_ichwAssocsMin];
+ int isloutAfter = m_prgisloutAfter[ichwSegOffset - m_ichwAssocsMin];
+ if (isloutBefore != kPosInfinity && isloutBefore != kNegInfinity)
+ visloutRet.push_back(isloutBefore);
+ if (isloutAfter != kPosInfinity && isloutAfter != kNegInfinity && isloutBefore != isloutAfter)
+ {
+ visloutRet.push_back(isloutAfter);
+ }
+ return visloutRet;
+ }
else
{
- std::vector<int> * pvisloutRet = &(m_prgvisloutAssocs[ichwSegOffset - m_ichwAssocsMin]);
- return pvisloutRet;
+ std::vector<int> * pvisloutRet = m_prgpvisloutAssocs[ichwSegOffset - m_ichwAssocsMin];
+ return *pvisloutRet;
}
}
@@ -2573,15 +2654,12 @@ std::vector<int> * Segment::UnderlyingToLogicalAssocs(int ichw)
int Segment::UnderlyingToLogicalInThisSeg(int ichw)
{
int isloutTest = kNegInfinity;
- std::vector<int> * pvislout = UnderlyingToLogicalAssocs(ichw);
- if (pvislout)
+ std::vector<int> vislout = UnderlyingToLogicalAssocs(ichw);
+ for (size_t iislout = 0; iislout < vislout.size(); iislout++)
{
- for (size_t iislout = 0; iislout < pvislout->size(); iislout++)
- {
- isloutTest = (*pvislout)[iislout];
- if (isloutTest != kNegInfinity && isloutTest != kPosInfinity)
- return isloutTest;
- }
+ isloutTest = vislout[iislout];
+ if (isloutTest != kNegInfinity && isloutTest != kPosInfinity)
+ return isloutTest;
}
return isloutTest;
}
@@ -2591,20 +2669,26 @@ int Segment::UnderlyingToLogicalInThisSeg(int ichw)
----------------------------------------------------------------------------------------------*/
bool Segment::SameSurfaceGlyphs(int ichw1, int ichw2)
{
- std::vector<int> * pvislout1 = UnderlyingToLogicalAssocs(ichw1);
- std::vector<int> * pvislout2 = UnderlyingToLogicalAssocs(ichw2);
-
- if (pvislout1 == NULL || pvislout1 == NULL)
- return false;
+ std::vector<int> vislout1 = UnderlyingToLogicalAssocs(ichw1);
+ std::vector<int> vislout2 = UnderlyingToLogicalAssocs(ichw2);
- if (pvislout1->size() != pvislout2->size())
- return false;
- for (size_t islout = 0; islout < pvislout1->size(); islout++)
+ bool fRet = true;
+ if (vislout1.size() == 0 || vislout2.size() == 0)
+ fRet = false;
+ else if (vislout1.size() != vislout2.size())
+ fRet = false;
+ else
{
- if ((*pvislout1)[islout] != (*pvislout2)[islout])
- return false;
+ for (size_t islout = 0; islout < vislout1.size(); islout++)
+ {
+ if (vislout1[islout] != vislout2[islout])
+ {
+ fRet = false;
+ break;
+ }
+ }
}
- return true;
+ return fRet;
}
/*----------------------------------------------------------------------------------------------
@@ -2767,9 +2851,9 @@ GrResult Segment::getUniscribeClusters(
// insertion is not allowed.
for (ich = 0; ich < m_dichwLim; ich++)
{
- std::vector<int> * pvislout = UnderlyingToLogicalAssocs(ich + m_ichwMin);
+ std::vector<int> vislout = UnderlyingToLogicalAssocs(ich + m_ichwMin);
- if (!pvislout || pvislout->size() == 0)
+ if (vislout.size() == 0)
{
// No glyphs represent this character. Merge it with the previous
// character.
@@ -2779,9 +2863,9 @@ GrResult Segment::getUniscribeClusters(
}
size_t iislout;
- for (iislout = 0; iislout < pvislout->size(); iislout++)
+ for (iislout = 0; iislout < vislout.size(); iislout++)
{
- int islout = (*pvislout)[iislout];
+ int islout = vislout[iislout];
if (!m_prgslout[islout].InsertBefore())
{
// This glyph does not allow insertion before it; make its character part
@@ -2823,6 +2907,10 @@ GrResult Segment::getUniscribeClusters(
for (ich = 0; ich < m_dichwLim - 1; ich++)
{
Assert(visloutBefore[ich] <= visloutAfter[ich]);
+ Assert(visloutBefore[ich] != kPosInfinity);
+ Assert(visloutBefore[ich] != kNegInfinity);
+ Assert(visloutAfter[ich] != kPosInfinity);
+ Assert(visloutAfter[ich] != kNegInfinity);
const int b1 = visloutBefore[ich];
const int a1 = visloutAfter[ich];
const int b2 = visloutBefore[ich + 1];
@@ -3174,10 +3262,11 @@ int Segment::GlyphHit(float xsClick, float ysClick)
return 0;
}
- // Find all BB that OVERLAP the click point (BbLeft < XClick < BbRight).
+ // Find all BB that OVERLAP the click point (bb.left < XClick < bb.right).
for (iginf = iginfHit; iginf >= 0; iginf--)
{
- if (m_prgginf[iginf].bb().left <= xsClick && xsClick <= m_prgginf[iginf].bb().right)
+ Rect rectBB = m_prgginf[iginf].bb();
+ if (rectBB.left <= xsClick && xsClick <= rectBB.right)
{
viginfNear.push_back(iginf);
}
@@ -3194,11 +3283,36 @@ int Segment::GlyphHit(float xsClick, float ysClick)
}
}
- // Find all BB for which the click is within their advance width.
+ if (viginfNear.size() > 2 && viginfHit.size() == 0)
+ {
+ // No hit along y-axis; find the closest thing.
+ float dy = float(10000000.0);
+ for (int iiginf2 = 0; iiginf2 < (int)viginfNear.size(); iiginf2++)
+ {
+ Rect rectBB = m_prgginf[viginfNear[iiginf2]].bb();
+ if (fabsf(rectBB.top - ysClick) < dy)
+ {
+ dy = fabsf(rectBB.top - ysClick);
+ viginfHit.clear();
+ viginfHit.push_back(viginfNear[iiginf2]);
+ }
+ if (fabsf(rectBB.bottom - ysClick) < dy)
+ {
+ dy = fabsf(rectBB.bottom - ysClick);
+ viginfHit.clear();
+ viginfHit.push_back(viginfNear[iiginf2]);
+ }
+ }
+ }
+
+ // Find all BB for which the click is within their advance width, if any.
for (iiginf = 0; iiginf < (int)viginfHit.size(); iiginf++)
{
- Rect rectBB = m_prgginf[viginfHit[iiginf]].bb();
- if (rectBB.left <= xsClick && xsClick <= rectBB.right)
+ //Rect rectBB = m_prgginf[viginfHit[iiginf]].bb(); -- ?? this tests the bounding box again :-/
+ //if (rectBB.left <= xsClick && xsClick <= rectBB.right)
+ gr::GlyphInfo * pginf = m_prgginf + viginfHit[iiginf];
+ if (pginf->advanceWidth() == 0 // advance width is irrelevant
+ || (pginf->origin() < xsClick && xsClick <= pginf->origin() + pginf->advanceWidth()))
{
viginfInside.push_back(viginfHit[iiginf]);
}
@@ -3253,7 +3367,8 @@ int Segment::GlyphHit(float xsClick, float ysClick)
/*----------------------------------------------------------------------------------------------
Select the bounding box we will use for a mouse hit.
- Select the BB with the left-most (LTR) or right-most (RTL) edge.
+ First select any glyph with a significantly smaller bounding box.
+ Then, select the BB with the left-most (LTR) or right-most (RTL) edge.
If more than one BB has same edge of interest, select the one that is closest to the
the baseline.
If that is a tie, select the one with the lowest islout.
@@ -3272,6 +3387,27 @@ int Segment::SelectBb(std::vector<int> & viginf, bool fRTL)
if (viginf.size() == 1)
return viginf[0];
+ // Find a glyph that has a signficantly smaller bounding box.
+ // The idea is that it is going to be harder to hit than the bigger glyph.
+ float smallestArea = float(1000000000.0);
+ float largestArea = 0.0;
+ size_t iiginfSmallest;
+ size_t iiginf;
+ for (iiginf = 0; iiginf < viginf.size(); iiginf++)
+ {
+ gr::GlyphInfo * pginf = m_prgginf + viginf[iiginf];
+ Rect rectBB = pginf->bb();
+ float thisArea = (rectBB.right - rectBB.left) * (rectBB.top - rectBB.bottom);
+ if (smallestArea > thisArea)
+ {
+ smallestArea = thisArea;
+ iiginfSmallest = iiginf;
+ }
+ largestArea = max(largestArea, thisArea);
+ }
+ if (smallestArea * 2.0 < largestArea)
+ return viginf[iiginfSmallest];
+
// Find appropriate x coor of leading edge.
float xsLeading;
if (!fRTL)
@@ -3279,27 +3415,28 @@ int Segment::SelectBb(std::vector<int> & viginf, bool fRTL)
else
xsLeading = m_prgginf[viginf[0]].bb().right;
- size_t iiginf;
for (iiginf = 1; iiginf < viginf.size(); iiginf++)
{
+ Rect rectBB = m_prgginf[viginf[iiginf]].bb();
if (!fRTL)
- xsLeading = min(xsLeading, m_prgginf[viginf[iiginf]].bb().left);
+ xsLeading = min(xsLeading, rectBB.left);
else
- xsLeading = max(xsLeading, m_prgginf[viginf[iiginf]].bb().right);
+ xsLeading = max(xsLeading, rectBB.right);
}
// Find BBs with the leading edge.
std::vector<int> viginfSameEdge;
for (iiginf = 0; iiginf < viginf.size(); iiginf++)
{
+ Rect rectBB = m_prgginf[viginf[iiginf]].bb();
if (!fRTL)
{
- if (m_prgginf[viginf[iiginf]].bb().left == xsLeading)
+ if (rectBB.left == xsLeading)
viginfSameEdge.push_back(viginf[iiginf]);
}
else
{
- if (m_prgginf[viginf[iiginf]].bb().right == xsLeading)
+ if (rectBB.right == xsLeading)
viginfSameEdge.push_back(viginf[iiginf]);
}
}