Bug 1155261 - Fix computation of glyph extents and text-frame visual overflow for vertical text frames. r=smontagu

This commit is contained in:
Jonathan Kew 2015-04-27 09:45:55 +01:00
parent 4582eeaaf4
commit c050cf8885
6 changed files with 46 additions and 45 deletions

View File

@ -2124,8 +2124,8 @@ gfxFont::IsSpaceGlyphInvisible(gfxContext *aRefContext, gfxTextRun *aTextRun)
GetOrCreateGlyphExtents(aTextRun->GetAppUnitsPerDevUnit());
gfxRect glyphExtents;
mFontEntry->mSpaceGlyphIsInvisible =
extents->GetTightGlyphExtentsAppUnits(this, eHorizontal,
aRefContext, GetSpaceGlyph(), &glyphExtents) &&
extents->GetTightGlyphExtentsAppUnits(this, aRefContext,
GetSpaceGlyph(), &glyphExtents) &&
glyphExtents.IsEmpty();
mFontEntry->mSpaceGlyphIsInvisibleInitialized = true;
}
@ -2232,11 +2232,14 @@ gfxFont::Measure(gfxTextRun *aTextRun,
} else {
gfxRect glyphRect;
if (!extents->GetTightGlyphExtentsAppUnits(this,
orientation,
aRefContext, glyphIndex, &glyphRect)) {
glyphRect = gfxRect(0, metrics.mBoundingBox.Y(),
advance, metrics.mBoundingBox.Height());
}
if (orientation == eVertical) {
Swap(glyphRect.x, glyphRect.y);
Swap(glyphRect.width, glyphRect.height);
}
if (isRTL) {
glyphRect -= gfxPoint(advance, 0);
}
@ -2261,13 +2264,16 @@ gfxFont::Measure(gfxTextRun *aTextRun,
gfxRect glyphRect;
if (glyphData->IsMissing() || !extents ||
!extents->GetTightGlyphExtentsAppUnits(this,
orientation,
aRefContext, glyphIndex, &glyphRect)) {
// We might have failed to get glyph extents due to
// OOM or something
glyphRect = gfxRect(0, -metrics.mAscent,
advance, metrics.mAscent + metrics.mDescent);
}
if (orientation == eVertical) {
Swap(glyphRect.x, glyphRect.y);
Swap(glyphRect.width, glyphRect.height);
}
if (isRTL) {
glyphRect -= gfxPoint(advance, 0);
}
@ -3128,7 +3134,7 @@ gfxFont::GetOrCreateGlyphExtents(int32_t aAppUnitsPerDevUnit) {
}
void
gfxFont::SetupGlyphExtents(gfxContext *aContext, Orientation aOrientation,
gfxFont::SetupGlyphExtents(gfxContext *aContext,
uint32_t aGlyphID, bool aNeedTight,
gfxGlyphExtents *aExtents)
{
@ -3154,7 +3160,7 @@ gfxFont::SetupGlyphExtents(gfxContext *aContext, Orientation aOrientation,
cairo_text_extents_t extents;
cairo_glyph_extents(aContext->GetCairo(), &glyph, 1, &extents);
const Metrics& fontMetrics = GetMetrics(aOrientation);
const Metrics& fontMetrics = GetMetrics(eHorizontal);
int32_t appUnitsPerDevUnit = aExtents->GetAppUnitsPerDevUnit();
if (!aNeedTight && extents.x_bearing >= 0 &&
extents.y_bearing >= -fontMetrics.maxAscent &&

View File

@ -1619,8 +1619,7 @@ public:
gfxGlyphExtents *GetOrCreateGlyphExtents(int32_t aAppUnitsPerDevUnit);
// You need to call SetupCairoFont on the aCR just before calling this
virtual void SetupGlyphExtents(gfxContext *aContext,
Orientation aOrientation, uint32_t aGlyphID,
virtual void SetupGlyphExtents(gfxContext *aContext, uint32_t aGlyphID,
bool aNeedTight, gfxGlyphExtents *aExtents);
// This is called by the default Draw() implementation above.

View File

@ -36,7 +36,6 @@ gfxGlyphExtents::~gfxGlyphExtents()
bool
gfxGlyphExtents::GetTightGlyphExtentsAppUnits(gfxFont *aFont,
gfxFont::Orientation aOrientation,
gfxContext *aContext, uint32_t aGlyphID, gfxRect *aExtents)
{
HashEntry *entry = mTightGlyphExtents.GetEntry(aGlyphID);
@ -50,8 +49,7 @@ gfxGlyphExtents::GetTightGlyphExtentsAppUnits(gfxFont *aFont,
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
++gGlyphExtentsSetupLazyTight;
#endif
aFont->SetupGlyphExtents(aContext, aOrientation, aGlyphID, true,
this);
aFont->SetupGlyphExtents(aContext, aGlyphID, true, this);
entry = mTightGlyphExtents.GetEntry(aGlyphID);
}
if (!entry) {

View File

@ -63,7 +63,6 @@ public:
// Returns true on success. Can fail on OOM or when aContext is null
// and extents were not (successfully) prefetched.
bool GetTightGlyphExtentsAppUnits(gfxFont *aFont,
gfxFont::Orientation aOrientation,
gfxContext *aContext, uint32_t aGlyphID, gfxRect *aExtents);
void SetContainedGlyphWidthAppUnits(uint32_t aGlyphID, uint16_t aWidth) {

View File

@ -1373,8 +1373,6 @@ gfxTextRun::FetchGlyphExtents(gfxContext *aRefContext)
for (j = start; j < end; ++j) {
const gfxTextRun::CompressedGlyph *glyphData = &charGlyphs[j];
gfxFont::Orientation orientation =
IsVertical() ? gfxFont::eVertical : gfxFont::eHorizontal;
if (glyphData->IsSimpleGlyph()) {
// If we're in speed mode, don't set up glyph extents here; we'll
// just return "optimistic" glyph bounds later
@ -1391,7 +1389,7 @@ gfxTextRun::FetchGlyphExtents(gfxContext *aRefContext)
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
++gGlyphExtentsSetupEagerSimple;
#endif
font->SetupGlyphExtents(aRefContext, orientation,
font->SetupGlyphExtents(aRefContext,
glyphIndex, false, extents);
}
}
@ -1417,7 +1415,7 @@ gfxTextRun::FetchGlyphExtents(gfxContext *aRefContext)
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
++gGlyphExtentsSetupEagerTight;
#endif
font->SetupGlyphExtents(aRefContext, orientation,
font->SetupGlyphExtents(aRefContext,
glyphIndex, true, extents);
}
}

View File

@ -5537,6 +5537,9 @@ AddHyphenToMetrics(nsTextFrame* aTextFrame, gfxTextRun* aBaseTextRun,
gfxTextRun::Metrics hyphenMetrics =
hyphenTextRun->MeasureText(0, hyphenTextRun->GetLength(),
aBoundingBoxType, aContext, nullptr);
if (aTextFrame->GetWritingMode().IsLineInverted()) {
hyphenMetrics.mBoundingBox.y = -hyphenMetrics.mBoundingBox.YMost();
}
aMetrics->CombineWith(hyphenMetrics, aBaseTextRun->IsRightToLeft());
}
@ -7765,12 +7768,12 @@ nsTextFrame::ComputeTightBounds(gfxContext* aContext) const
ComputeTransformedLength(provider),
gfxFont::TIGHT_HINTED_OUTLINE_EXTENTS,
aContext, &provider);
if (GetWritingMode().IsLineInverted()) {
metrics.mBoundingBox.y = -metrics.mBoundingBox.YMost();
}
// mAscent should be the same as metrics.mAscent, but it's what we use to
// paint so that's the one we'll use.
nsRect boundingBox = RoundOut(metrics.mBoundingBox);
if (GetWritingMode().IsLineInverted()) {
boundingBox.y = -boundingBox.YMost();
}
boundingBox += nsPoint(0, mAscent);
if (mTextRun->IsVertical()) {
// Swap line-relative textMetrics dimensions to physical coordinates.
@ -8360,6 +8363,10 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
textMetrics.mDescent = gfxFloat(fm->MaxDescent());
}
}
if (GetWritingMode().IsLineInverted()) {
Swap(textMetrics.mAscent, textMetrics.mDescent);
textMetrics.mBoundingBox.y = -textMetrics.mBoundingBox.YMost();
}
// The "end" iterator points to the first character after the string mapped
// by this frame. Basically, its original-string offset is offset+charsFit
// after we've computed charsFit.
@ -8465,31 +8472,21 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
finalSize.BSize(wm) = 0;
} else if (boundingBoxType != gfxFont::LOOSE_INK_EXTENTS) {
// Use actual text metrics for floating first letter frame.
if (wm.IsLineInverted()) {
aMetrics.SetBlockStartAscent(NSToCoordCeil(textMetrics.mDescent));
finalSize.BSize(wm) = aMetrics.BlockStartAscent() +
NSToCoordCeil(textMetrics.mAscent);
} else {
aMetrics.SetBlockStartAscent(NSToCoordCeil(textMetrics.mAscent));
finalSize.BSize(wm) = aMetrics.BlockStartAscent() +
NSToCoordCeil(textMetrics.mDescent);
}
aMetrics.SetBlockStartAscent(NSToCoordCeil(textMetrics.mAscent));
finalSize.BSize(wm) = aMetrics.BlockStartAscent() +
NSToCoordCeil(textMetrics.mDescent);
} else {
// Otherwise, ascent should contain the overline drawable area.
// And also descent should contain the underline drawable area.
// nsFontMetrics::GetMaxAscent/GetMaxDescent contains them.
nsFontMetrics* fm = provider.GetFontMetrics();
nscoord fontAscent = fm->MaxAscent();
nscoord fontDescent = fm->MaxDescent();
if (wm.IsLineInverted()) {
aMetrics.SetBlockStartAscent(std::max(NSToCoordCeil(textMetrics.mDescent), fontDescent));
nscoord descent = std::max(NSToCoordCeil(textMetrics.mAscent), fontAscent);
finalSize.BSize(wm) = aMetrics.BlockStartAscent() + descent;
} else {
aMetrics.SetBlockStartAscent(std::max(NSToCoordCeil(textMetrics.mAscent), fontAscent));
nscoord descent = std::max(NSToCoordCeil(textMetrics.mDescent), fontDescent);
finalSize.BSize(wm) = aMetrics.BlockStartAscent() + descent;
}
nscoord fontAscent =
wm.IsLineInverted() ? fm->MaxDescent() : fm->MaxAscent();
nscoord fontDescent =
wm.IsLineInverted() ? fm->MaxAscent() : fm->MaxDescent();
aMetrics.SetBlockStartAscent(std::max(NSToCoordCeil(textMetrics.mAscent), fontAscent));
nscoord descent = std::max(NSToCoordCeil(textMetrics.mDescent), fontDescent);
finalSize.BSize(wm) = aMetrics.BlockStartAscent() + descent;
}
aMetrics.SetSize(wm, finalSize);
@ -8503,14 +8500,18 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
// Handle text that runs outside its normal bounds.
nsRect boundingBox = RoundOut(textMetrics.mBoundingBox);
if (wm.IsLineInverted()) {
boundingBox.y = -boundingBox.YMost();
}
boundingBox += nsPoint(0, mAscent);
if (mTextRun->IsVertical()) {
// Swap line-relative textMetrics dimensions to physical coordinates.
Swap(boundingBox.x, boundingBox.y);
Swap(boundingBox.width, boundingBox.height);
if (GetWritingMode().IsVerticalRL()) {
boundingBox.x = -boundingBox.XMost();
boundingBox.x += aMetrics.Width() - mAscent;
} else {
boundingBox.x += mAscent;
}
} else {
boundingBox.y += mAscent;
}
aMetrics.SetOverflowAreasToDesiredBounds();
aMetrics.VisualOverflow().UnionRect(aMetrics.VisualOverflow(), boundingBox);
@ -8732,10 +8733,10 @@ nsTextFrame::RecomputeOverflow(nsIFrame* aBlockFrame)
ComputeTransformedLength(provider),
gfxFont::LOOSE_INK_EXTENTS, nullptr,
&provider);
nsRect boundingBox = RoundOut(textMetrics.mBoundingBox);
if (GetWritingMode().IsLineInverted()) {
boundingBox.y = -boundingBox.YMost();
textMetrics.mBoundingBox.y = -textMetrics.mBoundingBox.YMost();
}
nsRect boundingBox = RoundOut(textMetrics.mBoundingBox);
boundingBox += nsPoint(0, mAscent);
if (mTextRun->IsVertical()) {
// Swap line-relative textMetrics dimensions to physical coordinates.