summaryrefslogtreecommitdiff
path: root/Build/source/libs/graphite-engine/src/painter/SegmentPainter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/graphite-engine/src/painter/SegmentPainter.cpp')
-rw-r--r--Build/source/libs/graphite-engine/src/painter/SegmentPainter.cpp223
1 files changed, 145 insertions, 78 deletions
diff --git a/Build/source/libs/graphite-engine/src/painter/SegmentPainter.cpp b/Build/source/libs/graphite-engine/src/painter/SegmentPainter.cpp
index 4e6a730cf21..559f72fb887 100644
--- a/Build/source/libs/graphite-engine/src/painter/SegmentPainter.cpp
+++ b/Build/source/libs/graphite-engine/src/painter/SegmentPainter.cpp
@@ -520,7 +520,7 @@ void SegmentPainter::pointToChar(Point zptdClickPosition, int * pichw, bool * pf
if (m_pseg->m_dysAscent < 0 || m_pseg->m_dxsWidth < 0)
m_pseg->ComputeDimensions();
- if (m_pseg->m_dichwLim == 0)
+ if (m_pseg->m_dichwLim == 0 || m_pseg->m_cginf == 0)
{
*pichw = m_pseg->m_ichwMin;
*pfAssocPrev = false;
@@ -1435,6 +1435,8 @@ void SegmentPainter::InvertSplitIP(float xs, float ysTop, float ysBottom,
void SegmentPainter::CalcIP(int ichwSel, bool fBefore,
float * pxs, float * pysTop, float * pysBottom, bool * pfRtl)
{
+ Font & font = this->m_pseg->getFont();
+
int ichw = (fBefore) ? ichwSel : ichwSel - 1;
int iginfOutput;
@@ -1508,77 +1510,89 @@ void SegmentPainter::CalcIP(int ichwSel, bool fBefore,
if (kPosInfinity == iginfOutput || kNegInfinity == iginfOutput)
*pxs = kPosInfFloat;
- else if (psloutTmp->IsPartOfCluster())
+ else
{
- // Cluster member.
-
- if (AtEdgeOfCluster(psloutTmp, islout, fBefore) &&
- !CanInsertIntoCluster(psloutTmp, islout))
+ bool fCluster = (psloutTmp->IsPartOfCluster());
+ bool fHighlightBB = fCluster;
+ // Test below should match the one in CalcHighlightRect:
+ if ((psloutTmp->ClusterAdvance() == 0
+ || psloutTmp->GlyphMetricLogUnits(&font, kgmetAdvWidth) == 0)
+ && !psloutTmp->IsSpace())
{
- // Place the IP at the edge of the whole cluster.
-
- int isloutBase = psloutTmp->ClusterBase();
- GrSlotOutput * psloutBase = m_pseg->OutputSlot(isloutBase);
- //int igbbBase = psloutBase->GlyphBbIndex();
- int iginfBase = m_pseg->LogicalToPhysicalSurface(isloutBase);
-
- float xsBase = m_pseg->GlyphLeftEdge(iginfBase);
-
- float xsLeft = xsBase + psloutBase->ClusterXOffset();
- float xsRight = xsBase + psloutBase->ClusterAdvance();
-
- if (fBefore == *pfRtl)
- // Position of interest is to the right
- *pxs = xsRight;
- else
- // Position of interest is to the left.
- *pxs = xsLeft;
+ fHighlightBB = true; // use bounding box for zero-advance glyph
}
- else
+ if (fHighlightBB)
{
- // Place the IP on the perimeter of the bounding box of the cluster member.
+ // Cluster member or zero-width glyph.
- float xsGlyphStart = m_pseg->GlyphLeftEdge(iginfOutput);
+ if (fCluster && AtEdgeOfCluster(psloutTmp, islout, fBefore) &&
+ !CanInsertIntoCluster(psloutTmp, islout))
+ {
+ // Place the IP at the edge of the whole cluster.
+
+ int isloutBase = psloutTmp->ClusterBase();
+ GrSlotOutput * psloutBase = m_pseg->OutputSlot(isloutBase);
+ //int igbbBase = psloutBase->GlyphBbIndex();
+ int iginfBase = m_pseg->LogicalToPhysicalSurface(isloutBase);
+
+ float xsBase = m_pseg->GlyphLeftEdge(iginfBase);
+
+ float xsLeft = xsBase + psloutBase->ClusterXOffset();
+ float xsRight = xsBase + psloutBase->ClusterAdvance();
+
+ if (fBefore == *pfRtl)
+ // Position of interest is to the right
+ *pxs = xsRight;
+ else
+ // Position of interest is to the left.
+ *pxs = xsLeft;
+ }
+ else
+ {
+ // Place the IP on the perimeter of the bounding box of the cluster member.
-// float dysFontAscent;
-// res = GetFontAscentSourceUnits(pgg, &dysFontAscent);
-// if (ResultFailed(res)) THROW(WARN(res));
-// dysFontAscent += m_dysXAscent;
+ float xsGlyphStart = m_pseg->GlyphLeftEdge(iginfOutput);
- float ysBbTop = psloutTmp->GlyphMetricLogUnits(kgmetBbTop);
- float ysBbBottom = psloutTmp->GlyphMetricLogUnits(kgmetBbBottom);
- float xsBbLeft = psloutTmp->GlyphMetricLogUnits(kgmetBbLeft);
- float xsBbRight = psloutTmp->GlyphMetricLogUnits(kgmetBbRight);
+// float dysFontAscent;
+// res = GetFontAscentSourceUnits(pgg, &dysFontAscent);
+// if (ResultFailed(res)) THROW(WARN(res));
+// dysFontAscent += m_dysXAscent;
- int twoPixels = 2; // assume dest coords are in pixels
+ float ysBbTop = psloutTmp->GlyphMetricLogUnits(&font, kgmetBbTop);
+ float ysBbBottom = psloutTmp->GlyphMetricLogUnits(&font, kgmetBbBottom);
+ float xsBbLeft = psloutTmp->GlyphMetricLogUnits(&font, kgmetBbLeft);
+ float xsBbRight = psloutTmp->GlyphMetricLogUnits(&font, kgmetBbRight);
- if (fBefore == *pfRtl)
- // Position of interest is to the right
- *pxs = xsGlyphStart + xsBbRight + twoPixels;
- else
- // Position of interest is to the left.
- *pxs = xsGlyphStart + xsBbLeft - twoPixels;
+ int twoPixels = 2; // assume dest coords are in pixels
- GlyphInfo * pginf = m_pseg->m_prgginf + iginfOutput;
- float ysGlyph = pginf->yOffset();
- float ysGlyphBaseline = m_pseg->m_dysAscent - ysGlyph; // relative to top
+ if (fBefore == *pfRtl)
+ // Position of interest is to the right
+ *pxs = xsGlyphStart + xsBbRight + twoPixels;
+ else
+ // Position of interest is to the left.
+ *pxs = xsGlyphStart + xsBbLeft - twoPixels;
- *pysTop = ysGlyphBaseline - ysBbTop - twoPixels;
- *pysBottom = ysGlyphBaseline - ysBbBottom + twoPixels;
- }
- }
- else
- {
- // Insertion point goes at origin or advance width of glyph.
+ GlyphInfo * pginf = m_pseg->m_prgginf + iginfOutput;
+ float ysGlyph = pginf->yOffset();
+ float ysGlyphBaseline = m_pseg->m_dysAscent - ysGlyph; // relative to top
- *pxs = m_pseg->GlyphLeftEdge(iginfOutput);
- if (fBefore == *pfRtl)
+ *pysTop = ysGlyphBaseline - ysBbTop - twoPixels;
+ *pysBottom = ysGlyphBaseline - ysBbBottom + twoPixels;
+ }
+ }
+ else
{
- // Position of interest is to the right
- //*pxs += psloutTmp->GlyphMetricLogUnits(kgmetAdvWidth);
- *pxs += psloutTmp->ClusterAdvance();
+ // Insertion point goes at origin or advance width of glyph.
+
+ *pxs = m_pseg->GlyphLeftEdge(iginfOutput);
+ if (fBefore == *pfRtl)
+ {
+ // Position of interest is to the right
+ //*pxs += psloutTmp->GlyphMetricLogUnits(&font, kgmetAdvWidth);
+ *pxs += psloutTmp->ClusterAdvance();
+ }
+ // else position of interest is to the left
}
- // else position of interest is to the left
}
}
}
@@ -1635,11 +1649,40 @@ bool SegmentPainter::AtEdgeOfCluster(GrSlotOutput * pslout, int islout, bool fBe
// If the adjacent slot in whatever direction we're interested in has the same
// cluster base, this slot is not on the edge of the cluster.
- int isloutAdjacentBase = (fBefore) ?
- m_pseg->OutputSlot(islout - 1)->ClusterBase() :
- m_pseg->OutputSlot(islout + 1)->ClusterBase();
+ // -- NO, because you could have an intervening glyph that is not part of the
+ // cluster.
+ //int isloutAdjacentBase = (fBefore) ?
+ // m_pseg->OutputSlot(islout - 1)->ClusterBase() :
+ // m_pseg->OutputSlot(islout + 1)->ClusterBase();
+ //return (isloutAdjacentBase != m_pseg->OutputSlot(islout)->ClusterBase());
+
+ // Ask the cluster base.
+ return AtEdgeOfCluster(m_pseg->OutputSlot(pslout->ClusterBase()), pslout->ClusterBase(),
+ pslout, islout, fBefore);
+}
+
+bool SegmentPainter::AtEdgeOfCluster(GrSlotOutput * psloutBase, int isloutBase,
+ GrSlotOutput * pslout, int islout, bool fBefore)
+{
+ // Compare pslout to all the members of the cluster. If it is the minimum or maximum, it
+ // is at an edge.
+ if (fBefore && isloutBase < islout)
+ return false;
+ if (!fBefore && isloutBase > islout)
+ return false;
- return (isloutAdjacentBase != m_pseg->OutputSlot(islout)->ClusterBase());
+ std::vector<int> visloutCluster;
+ m_pseg->ClusterMembersForGlyph(isloutBase, psloutBase->ClusterRange(), visloutCluster);
+
+ for (size_t iislout = 0; iislout < visloutCluster.size(); iislout++)
+ {
+ int isloutMember = visloutCluster[iislout];
+ if (fBefore && isloutMember < islout)
+ return false;
+ if (!fBefore && isloutMember > islout)
+ return false;
+ }
+ return true;
}
/*----------------------------------------------------------------------------------------------
@@ -1655,16 +1698,19 @@ bool SegmentPainter::CanInsertIntoCluster(GrSlotOutput * pslout, int islout)
if (islout != isloutBase)
{
// Ask the cluster base.
- Assert(pslout->NumClusterMembers() == 0);
+ Assert(pslout->ClusterRange() == 0);
return CanInsertIntoCluster(m_pseg->OutputSlot(isloutBase), isloutBase);
}
if (!AtEdgeOfCluster(pslout, islout, true) && pslout->InsertBefore())
return true;
- for (int iislout = 0; iislout < pslout->NumClusterMembers(); iislout++)
+ std::vector<int> visloutCluster;
+ m_pseg->ClusterMembersForGlyph(isloutBase, pslout->ClusterRange(), visloutCluster);
+
+ for (size_t iislout = 0; iislout < visloutCluster.size(); iislout++)
{
- int isloutMember = pslout->ClusterMember(iislout);
+ int isloutMember = visloutCluster[iislout];
if (AtEdgeOfCluster(m_pseg->OutputSlot(isloutMember), isloutMember, true))
// Inserting before the first member of the cluster doesn't count.
continue;
@@ -1752,6 +1798,8 @@ void SegmentPainter::CalcHighlightRect(int ichw,
GrGlyphTable * pgtbl = (pgreng) ? pgreng->GlyphTable() : NULL;
//bool fRtl = m_pseg->rightToLeft();
+ Font & font = m_pseg->getFont();
+
if (!GrCharStream::AtUnicodeCharBoundary(m_pseg->GetString(), ichw))
// Second half of a surrogate pair, or UTF-8: ignore.
return;
@@ -1802,26 +1850,40 @@ void SegmentPainter::CalcHighlightRect(int ichw,
}
else
{
- std::vector<int> * pvislout = m_pseg->UnderlyingToLogicalAssocs(ichw);
- if (!pvislout)
+ std::vector<int> vislout = m_pseg->UnderlyingToLogicalAssocs(ichw);
+ if (vislout.size() == 0)
return;
float xsGlyphLeft, xsGlyphRight;
res = kresOk;
- for (size_t iislout = 0; iislout < pvislout->size(); iislout++)
+ for (size_t iislout = 0; iislout < vislout.size(); iislout++)
{
- int islout = (*pvislout)[iislout];
+ int islout = vislout[iislout];
+ if (islout == kNegInfinity || islout == kPosInfinity)
+ continue;
int iginfTmp = m_pseg->LogicalToPhysicalSurface(islout);
+ Assert(iginfTmp != kNegInfinity);
+ Assert(iginfTmp != kPosInfinity);
if (fSkipTrSpace && islout >= m_pseg->m_isloutVisLim)
continue;
Rect rsNew;
GrSlotOutput * psloutTmp = m_pseg->OutputSlot(islout);
+ bool fHighlightBB = psloutTmp->IsPartOfCluster();
+ // Test below should match the one in CalcIP--
+ // If the glyph has no advance width but does have a real bounding box,
+ // highlight the bounding box. Review: do we want this???
+ if ((psloutTmp->ClusterAdvance() == 0
+ || psloutTmp->GlyphMetricLogUnits(&font, kgmetAdvWidth) == 0)
+ && !psloutTmp->IsSpace())
+ {
+ fHighlightBB = true;
+ }
xsGlyphLeft = m_pseg->GlyphLeftEdge(iginfTmp);
- if (psloutTmp->IsPartOfCluster())
+ if (fHighlightBB)
{
// For now, highlight just the bounding box of this glyph. After we finish
// highlighting all glyphs individually, we'll go back and highlight
@@ -1836,10 +1898,10 @@ void SegmentPainter::CalcHighlightRect(int ichw,
float ysForGlyph = pginf->yOffset();
float ysGlyphBaseline = m_pseg->m_dysAscent - ysForGlyph; // relative to top
- float ysBbTop = psloutTmp->GlyphMetricLogUnits(kgmetBbTop);
- float ysBbBottom = psloutTmp->GlyphMetricLogUnits(kgmetBbBottom);
- float xsBbLeft = psloutTmp->GlyphMetricLogUnits(kgmetBbLeft);
- float xsBbRight = psloutTmp->GlyphMetricLogUnits(kgmetBbRight);
+ float ysBbTop = psloutTmp->GlyphMetricLogUnits(&font, kgmetBbTop);
+ float ysBbBottom = psloutTmp->GlyphMetricLogUnits(&font, kgmetBbBottom);
+ float xsBbLeft = psloutTmp->GlyphMetricLogUnits(&font, kgmetBbLeft);
+ float xsBbRight = psloutTmp->GlyphMetricLogUnits(&font, kgmetBbRight);
rsNew.top = ysGlyphBaseline - ysBbTop - 2;
rsNew.bottom = ysGlyphBaseline - ysBbBottom + 2;
@@ -1853,9 +1915,12 @@ void SegmentPainter::CalcHighlightRect(int ichw,
// Highlight entire width of the glyph from the top of the line to the bottom.
// Horizontally, highlight from the origin of the glyph to the advance width.
- //xsGlyphRight = xsGlyphLeft + psloutTmp->GlyphMetricLogUnits(kgmetAdvWidth);
+ //xsGlyphRight = xsGlyphLeft + psloutTmp->GlyphMetricLogUnits(&font kgmetAdvWidth);
xsGlyphRight = xsGlyphLeft + psloutTmp->ClusterAdvance();
+ if (xsGlyphLeft > xsGlyphRight)
+ std::swap(xsGlyphLeft, xsGlyphRight);
+
rsNew.top = 0;
rsNew.bottom = m_pseg->m_dysHeight;
rsNew.left = xsGlyphLeft;
@@ -1889,7 +1954,7 @@ void SegmentPainter::CalcCompleteCluster(int islout,
//GrEngine * pgreng = m_pseg->EngineImpl();
GrSlotOutput * pslout = m_pseg->OutputSlot(islout);
- if (pslout->NumClusterMembers() == 0)
+ if (pslout->ClusterRange() == 0)
return;
int iginfDraw = m_pseg->LogicalToPhysicalSurface(islout);
@@ -1898,9 +1963,11 @@ void SegmentPainter::CalcCompleteCluster(int islout,
bool fAllHighlighted = true;
- for (int i = 0; i < pslout->NumClusterMembers(); i++)
+ std::vector<int> visloutCluster;
+ m_pseg->ClusterMembersForGlyph(islout, pslout->ClusterRange(), visloutCluster);
+ for (size_t i = 0; i < visloutCluster.size(); i++)
{
- int iginfMemberDraw = m_pseg->LogicalToPhysicalSurface(pslout->ClusterMember(i));
+ int iginfMemberDraw = m_pseg->LogicalToPhysicalSurface(visloutCluster[i]);
if (!prgfHighlighted[iginfMemberDraw])
{
fAllHighlighted = false;