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());
|
GetOrCreateGlyphExtents(aTextRun->GetAppUnitsPerDevUnit());
|
||||||
gfxRect glyphExtents;
|
gfxRect glyphExtents;
|
||||||
mFontEntry->mSpaceGlyphIsInvisible =
|
mFontEntry->mSpaceGlyphIsInvisible =
|
||||||
extents->GetTightGlyphExtentsAppUnits(this, eHorizontal,
|
extents->GetTightGlyphExtentsAppUnits(this, aRefContext,
|
||||||
aRefContext, GetSpaceGlyph(), &glyphExtents) &&
|
GetSpaceGlyph(), &glyphExtents) &&
|
||||||
glyphExtents.IsEmpty();
|
glyphExtents.IsEmpty();
|
||||||
mFontEntry->mSpaceGlyphIsInvisibleInitialized = true;
|
mFontEntry->mSpaceGlyphIsInvisibleInitialized = true;
|
||||||
}
|
}
|
||||||
@ -2232,11 +2232,14 @@ gfxFont::Measure(gfxTextRun *aTextRun,
|
|||||||
} else {
|
} else {
|
||||||
gfxRect glyphRect;
|
gfxRect glyphRect;
|
||||||
if (!extents->GetTightGlyphExtentsAppUnits(this,
|
if (!extents->GetTightGlyphExtentsAppUnits(this,
|
||||||
orientation,
|
|
||||||
aRefContext, glyphIndex, &glyphRect)) {
|
aRefContext, glyphIndex, &glyphRect)) {
|
||||||
glyphRect = gfxRect(0, metrics.mBoundingBox.Y(),
|
glyphRect = gfxRect(0, metrics.mBoundingBox.Y(),
|
||||||
advance, metrics.mBoundingBox.Height());
|
advance, metrics.mBoundingBox.Height());
|
||||||
}
|
}
|
||||||
|
if (orientation == eVertical) {
|
||||||
|
Swap(glyphRect.x, glyphRect.y);
|
||||||
|
Swap(glyphRect.width, glyphRect.height);
|
||||||
|
}
|
||||||
if (isRTL) {
|
if (isRTL) {
|
||||||
glyphRect -= gfxPoint(advance, 0);
|
glyphRect -= gfxPoint(advance, 0);
|
||||||
}
|
}
|
||||||
@ -2261,13 +2264,16 @@ gfxFont::Measure(gfxTextRun *aTextRun,
|
|||||||
gfxRect glyphRect;
|
gfxRect glyphRect;
|
||||||
if (glyphData->IsMissing() || !extents ||
|
if (glyphData->IsMissing() || !extents ||
|
||||||
!extents->GetTightGlyphExtentsAppUnits(this,
|
!extents->GetTightGlyphExtentsAppUnits(this,
|
||||||
orientation,
|
|
||||||
aRefContext, glyphIndex, &glyphRect)) {
|
aRefContext, glyphIndex, &glyphRect)) {
|
||||||
// We might have failed to get glyph extents due to
|
// We might have failed to get glyph extents due to
|
||||||
// OOM or something
|
// OOM or something
|
||||||
glyphRect = gfxRect(0, -metrics.mAscent,
|
glyphRect = gfxRect(0, -metrics.mAscent,
|
||||||
advance, metrics.mAscent + metrics.mDescent);
|
advance, metrics.mAscent + metrics.mDescent);
|
||||||
}
|
}
|
||||||
|
if (orientation == eVertical) {
|
||||||
|
Swap(glyphRect.x, glyphRect.y);
|
||||||
|
Swap(glyphRect.width, glyphRect.height);
|
||||||
|
}
|
||||||
if (isRTL) {
|
if (isRTL) {
|
||||||
glyphRect -= gfxPoint(advance, 0);
|
glyphRect -= gfxPoint(advance, 0);
|
||||||
}
|
}
|
||||||
@ -3128,7 +3134,7 @@ gfxFont::GetOrCreateGlyphExtents(int32_t aAppUnitsPerDevUnit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gfxFont::SetupGlyphExtents(gfxContext *aContext, Orientation aOrientation,
|
gfxFont::SetupGlyphExtents(gfxContext *aContext,
|
||||||
uint32_t aGlyphID, bool aNeedTight,
|
uint32_t aGlyphID, bool aNeedTight,
|
||||||
gfxGlyphExtents *aExtents)
|
gfxGlyphExtents *aExtents)
|
||||||
{
|
{
|
||||||
@ -3154,7 +3160,7 @@ gfxFont::SetupGlyphExtents(gfxContext *aContext, Orientation aOrientation,
|
|||||||
cairo_text_extents_t extents;
|
cairo_text_extents_t extents;
|
||||||
cairo_glyph_extents(aContext->GetCairo(), &glyph, 1, &extents);
|
cairo_glyph_extents(aContext->GetCairo(), &glyph, 1, &extents);
|
||||||
|
|
||||||
const Metrics& fontMetrics = GetMetrics(aOrientation);
|
const Metrics& fontMetrics = GetMetrics(eHorizontal);
|
||||||
int32_t appUnitsPerDevUnit = aExtents->GetAppUnitsPerDevUnit();
|
int32_t appUnitsPerDevUnit = aExtents->GetAppUnitsPerDevUnit();
|
||||||
if (!aNeedTight && extents.x_bearing >= 0 &&
|
if (!aNeedTight && extents.x_bearing >= 0 &&
|
||||||
extents.y_bearing >= -fontMetrics.maxAscent &&
|
extents.y_bearing >= -fontMetrics.maxAscent &&
|
||||||
|
@ -1619,8 +1619,7 @@ public:
|
|||||||
gfxGlyphExtents *GetOrCreateGlyphExtents(int32_t aAppUnitsPerDevUnit);
|
gfxGlyphExtents *GetOrCreateGlyphExtents(int32_t aAppUnitsPerDevUnit);
|
||||||
|
|
||||||
// You need to call SetupCairoFont on the aCR just before calling this
|
// You need to call SetupCairoFont on the aCR just before calling this
|
||||||
virtual void SetupGlyphExtents(gfxContext *aContext,
|
virtual void SetupGlyphExtents(gfxContext *aContext, uint32_t aGlyphID,
|
||||||
Orientation aOrientation, uint32_t aGlyphID,
|
|
||||||
bool aNeedTight, gfxGlyphExtents *aExtents);
|
bool aNeedTight, gfxGlyphExtents *aExtents);
|
||||||
|
|
||||||
// This is called by the default Draw() implementation above.
|
// This is called by the default Draw() implementation above.
|
||||||
|
@ -36,7 +36,6 @@ gfxGlyphExtents::~gfxGlyphExtents()
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
gfxGlyphExtents::GetTightGlyphExtentsAppUnits(gfxFont *aFont,
|
gfxGlyphExtents::GetTightGlyphExtentsAppUnits(gfxFont *aFont,
|
||||||
gfxFont::Orientation aOrientation,
|
|
||||||
gfxContext *aContext, uint32_t aGlyphID, gfxRect *aExtents)
|
gfxContext *aContext, uint32_t aGlyphID, gfxRect *aExtents)
|
||||||
{
|
{
|
||||||
HashEntry *entry = mTightGlyphExtents.GetEntry(aGlyphID);
|
HashEntry *entry = mTightGlyphExtents.GetEntry(aGlyphID);
|
||||||
@ -50,8 +49,7 @@ gfxGlyphExtents::GetTightGlyphExtentsAppUnits(gfxFont *aFont,
|
|||||||
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
|
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
|
||||||
++gGlyphExtentsSetupLazyTight;
|
++gGlyphExtentsSetupLazyTight;
|
||||||
#endif
|
#endif
|
||||||
aFont->SetupGlyphExtents(aContext, aOrientation, aGlyphID, true,
|
aFont->SetupGlyphExtents(aContext, aGlyphID, true, this);
|
||||||
this);
|
|
||||||
entry = mTightGlyphExtents.GetEntry(aGlyphID);
|
entry = mTightGlyphExtents.GetEntry(aGlyphID);
|
||||||
}
|
}
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
|
@ -63,7 +63,6 @@ public:
|
|||||||
// Returns true on success. Can fail on OOM or when aContext is null
|
// Returns true on success. Can fail on OOM or when aContext is null
|
||||||
// and extents were not (successfully) prefetched.
|
// and extents were not (successfully) prefetched.
|
||||||
bool GetTightGlyphExtentsAppUnits(gfxFont *aFont,
|
bool GetTightGlyphExtentsAppUnits(gfxFont *aFont,
|
||||||
gfxFont::Orientation aOrientation,
|
|
||||||
gfxContext *aContext, uint32_t aGlyphID, gfxRect *aExtents);
|
gfxContext *aContext, uint32_t aGlyphID, gfxRect *aExtents);
|
||||||
|
|
||||||
void SetContainedGlyphWidthAppUnits(uint32_t aGlyphID, uint16_t aWidth) {
|
void SetContainedGlyphWidthAppUnits(uint32_t aGlyphID, uint16_t aWidth) {
|
||||||
|
@ -1373,8 +1373,6 @@ gfxTextRun::FetchGlyphExtents(gfxContext *aRefContext)
|
|||||||
|
|
||||||
for (j = start; j < end; ++j) {
|
for (j = start; j < end; ++j) {
|
||||||
const gfxTextRun::CompressedGlyph *glyphData = &charGlyphs[j];
|
const gfxTextRun::CompressedGlyph *glyphData = &charGlyphs[j];
|
||||||
gfxFont::Orientation orientation =
|
|
||||||
IsVertical() ? gfxFont::eVertical : gfxFont::eHorizontal;
|
|
||||||
if (glyphData->IsSimpleGlyph()) {
|
if (glyphData->IsSimpleGlyph()) {
|
||||||
// If we're in speed mode, don't set up glyph extents here; we'll
|
// If we're in speed mode, don't set up glyph extents here; we'll
|
||||||
// just return "optimistic" glyph bounds later
|
// just return "optimistic" glyph bounds later
|
||||||
@ -1391,7 +1389,7 @@ gfxTextRun::FetchGlyphExtents(gfxContext *aRefContext)
|
|||||||
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
|
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
|
||||||
++gGlyphExtentsSetupEagerSimple;
|
++gGlyphExtentsSetupEagerSimple;
|
||||||
#endif
|
#endif
|
||||||
font->SetupGlyphExtents(aRefContext, orientation,
|
font->SetupGlyphExtents(aRefContext,
|
||||||
glyphIndex, false, extents);
|
glyphIndex, false, extents);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1417,7 +1415,7 @@ gfxTextRun::FetchGlyphExtents(gfxContext *aRefContext)
|
|||||||
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
|
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
|
||||||
++gGlyphExtentsSetupEagerTight;
|
++gGlyphExtentsSetupEagerTight;
|
||||||
#endif
|
#endif
|
||||||
font->SetupGlyphExtents(aRefContext, orientation,
|
font->SetupGlyphExtents(aRefContext,
|
||||||
glyphIndex, true, extents);
|
glyphIndex, true, extents);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5537,6 +5537,9 @@ AddHyphenToMetrics(nsTextFrame* aTextFrame, gfxTextRun* aBaseTextRun,
|
|||||||
gfxTextRun::Metrics hyphenMetrics =
|
gfxTextRun::Metrics hyphenMetrics =
|
||||||
hyphenTextRun->MeasureText(0, hyphenTextRun->GetLength(),
|
hyphenTextRun->MeasureText(0, hyphenTextRun->GetLength(),
|
||||||
aBoundingBoxType, aContext, nullptr);
|
aBoundingBoxType, aContext, nullptr);
|
||||||
|
if (aTextFrame->GetWritingMode().IsLineInverted()) {
|
||||||
|
hyphenMetrics.mBoundingBox.y = -hyphenMetrics.mBoundingBox.YMost();
|
||||||
|
}
|
||||||
aMetrics->CombineWith(hyphenMetrics, aBaseTextRun->IsRightToLeft());
|
aMetrics->CombineWith(hyphenMetrics, aBaseTextRun->IsRightToLeft());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7765,12 +7768,12 @@ nsTextFrame::ComputeTightBounds(gfxContext* aContext) const
|
|||||||
ComputeTransformedLength(provider),
|
ComputeTransformedLength(provider),
|
||||||
gfxFont::TIGHT_HINTED_OUTLINE_EXTENTS,
|
gfxFont::TIGHT_HINTED_OUTLINE_EXTENTS,
|
||||||
aContext, &provider);
|
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
|
// mAscent should be the same as metrics.mAscent, but it's what we use to
|
||||||
// paint so that's the one we'll use.
|
// paint so that's the one we'll use.
|
||||||
nsRect boundingBox = RoundOut(metrics.mBoundingBox);
|
nsRect boundingBox = RoundOut(metrics.mBoundingBox);
|
||||||
if (GetWritingMode().IsLineInverted()) {
|
|
||||||
boundingBox.y = -boundingBox.YMost();
|
|
||||||
}
|
|
||||||
boundingBox += nsPoint(0, mAscent);
|
boundingBox += nsPoint(0, mAscent);
|
||||||
if (mTextRun->IsVertical()) {
|
if (mTextRun->IsVertical()) {
|
||||||
// Swap line-relative textMetrics dimensions to physical coordinates.
|
// Swap line-relative textMetrics dimensions to physical coordinates.
|
||||||
@ -8360,6 +8363,10 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
|
|||||||
textMetrics.mDescent = gfxFloat(fm->MaxDescent());
|
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
|
// The "end" iterator points to the first character after the string mapped
|
||||||
// by this frame. Basically, its original-string offset is offset+charsFit
|
// by this frame. Basically, its original-string offset is offset+charsFit
|
||||||
// after we've computed charsFit.
|
// after we've computed charsFit.
|
||||||
@ -8465,31 +8472,21 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
|
|||||||
finalSize.BSize(wm) = 0;
|
finalSize.BSize(wm) = 0;
|
||||||
} else if (boundingBoxType != gfxFont::LOOSE_INK_EXTENTS) {
|
} else if (boundingBoxType != gfxFont::LOOSE_INK_EXTENTS) {
|
||||||
// Use actual text metrics for floating first letter frame.
|
// Use actual text metrics for floating first letter frame.
|
||||||
if (wm.IsLineInverted()) {
|
aMetrics.SetBlockStartAscent(NSToCoordCeil(textMetrics.mAscent));
|
||||||
aMetrics.SetBlockStartAscent(NSToCoordCeil(textMetrics.mDescent));
|
finalSize.BSize(wm) = aMetrics.BlockStartAscent() +
|
||||||
finalSize.BSize(wm) = aMetrics.BlockStartAscent() +
|
NSToCoordCeil(textMetrics.mDescent);
|
||||||
NSToCoordCeil(textMetrics.mAscent);
|
|
||||||
} else {
|
|
||||||
aMetrics.SetBlockStartAscent(NSToCoordCeil(textMetrics.mAscent));
|
|
||||||
finalSize.BSize(wm) = aMetrics.BlockStartAscent() +
|
|
||||||
NSToCoordCeil(textMetrics.mDescent);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, ascent should contain the overline drawable area.
|
// Otherwise, ascent should contain the overline drawable area.
|
||||||
// And also descent should contain the underline drawable area.
|
// And also descent should contain the underline drawable area.
|
||||||
// nsFontMetrics::GetMaxAscent/GetMaxDescent contains them.
|
// nsFontMetrics::GetMaxAscent/GetMaxDescent contains them.
|
||||||
nsFontMetrics* fm = provider.GetFontMetrics();
|
nsFontMetrics* fm = provider.GetFontMetrics();
|
||||||
nscoord fontAscent = fm->MaxAscent();
|
nscoord fontAscent =
|
||||||
nscoord fontDescent = fm->MaxDescent();
|
wm.IsLineInverted() ? fm->MaxDescent() : fm->MaxAscent();
|
||||||
if (wm.IsLineInverted()) {
|
nscoord fontDescent =
|
||||||
aMetrics.SetBlockStartAscent(std::max(NSToCoordCeil(textMetrics.mDescent), fontDescent));
|
wm.IsLineInverted() ? fm->MaxAscent() : fm->MaxDescent();
|
||||||
nscoord descent = std::max(NSToCoordCeil(textMetrics.mAscent), fontAscent);
|
aMetrics.SetBlockStartAscent(std::max(NSToCoordCeil(textMetrics.mAscent), fontAscent));
|
||||||
finalSize.BSize(wm) = aMetrics.BlockStartAscent() + descent;
|
nscoord descent = std::max(NSToCoordCeil(textMetrics.mDescent), fontDescent);
|
||||||
} else {
|
finalSize.BSize(wm) = aMetrics.BlockStartAscent() + descent;
|
||||||
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);
|
aMetrics.SetSize(wm, finalSize);
|
||||||
|
|
||||||
@ -8503,14 +8500,18 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
|
|||||||
|
|
||||||
// Handle text that runs outside its normal bounds.
|
// Handle text that runs outside its normal bounds.
|
||||||
nsRect boundingBox = RoundOut(textMetrics.mBoundingBox);
|
nsRect boundingBox = RoundOut(textMetrics.mBoundingBox);
|
||||||
if (wm.IsLineInverted()) {
|
|
||||||
boundingBox.y = -boundingBox.YMost();
|
|
||||||
}
|
|
||||||
boundingBox += nsPoint(0, mAscent);
|
|
||||||
if (mTextRun->IsVertical()) {
|
if (mTextRun->IsVertical()) {
|
||||||
// Swap line-relative textMetrics dimensions to physical coordinates.
|
// Swap line-relative textMetrics dimensions to physical coordinates.
|
||||||
Swap(boundingBox.x, boundingBox.y);
|
Swap(boundingBox.x, boundingBox.y);
|
||||||
Swap(boundingBox.width, boundingBox.height);
|
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.SetOverflowAreasToDesiredBounds();
|
||||||
aMetrics.VisualOverflow().UnionRect(aMetrics.VisualOverflow(), boundingBox);
|
aMetrics.VisualOverflow().UnionRect(aMetrics.VisualOverflow(), boundingBox);
|
||||||
@ -8732,10 +8733,10 @@ nsTextFrame::RecomputeOverflow(nsIFrame* aBlockFrame)
|
|||||||
ComputeTransformedLength(provider),
|
ComputeTransformedLength(provider),
|
||||||
gfxFont::LOOSE_INK_EXTENTS, nullptr,
|
gfxFont::LOOSE_INK_EXTENTS, nullptr,
|
||||||
&provider);
|
&provider);
|
||||||
nsRect boundingBox = RoundOut(textMetrics.mBoundingBox);
|
|
||||||
if (GetWritingMode().IsLineInverted()) {
|
if (GetWritingMode().IsLineInverted()) {
|
||||||
boundingBox.y = -boundingBox.YMost();
|
textMetrics.mBoundingBox.y = -textMetrics.mBoundingBox.YMost();
|
||||||
}
|
}
|
||||||
|
nsRect boundingBox = RoundOut(textMetrics.mBoundingBox);
|
||||||
boundingBox += nsPoint(0, mAscent);
|
boundingBox += nsPoint(0, mAscent);
|
||||||
if (mTextRun->IsVertical()) {
|
if (mTextRun->IsVertical()) {
|
||||||
// Swap line-relative textMetrics dimensions to physical coordinates.
|
// Swap line-relative textMetrics dimensions to physical coordinates.
|
||||||
|
Loading…
Reference in New Issue
Block a user