mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1155261 - Fix computation of glyph extents and text-frame visual overflow for vertical text frames. r=smontagu
This commit is contained in:
parent
4582eeaaf4
commit
c050cf8885
@ -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 &&
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user