From c5e1a54d597852fe84b95b69b08fa58d0ad8ae55 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Tue, 30 Sep 2014 07:38:26 +0100 Subject: [PATCH] Bug 1065002 pt 1.3 - Add an Orientation parameter to gfxFont::GetMetrics and dispatch to horizontal or vertical as needed. r=jdaggett --- dom/canvas/CanvasRenderingContext2D.cpp | 2 +- gfx/src/nsFontMetrics.cpp | 2 +- gfx/thebes/gfxFont.cpp | 21 +++++++++++++-------- gfx/thebes/gfxFont.h | 18 +++++++++++++++--- gfx/thebes/gfxGlyphExtents.cpp | 4 +++- gfx/thebes/gfxGlyphExtents.h | 7 ++++--- gfx/thebes/gfxPangoFonts.cpp | 3 ++- gfx/thebes/gfxTextRun.cpp | 23 +++++++++++++++++------ layout/generic/nsTextFrame.cpp | 8 +++++--- layout/style/nsRuleNode.cpp | 5 +++-- 10 files changed, 64 insertions(+), 29 deletions(-) diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index 0c1a96d8324b..d2ff09b235f6 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -3443,7 +3443,7 @@ CanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText, // offset pt.y based on text baseline processor.mFontgrp->UpdateUserFonts(); // ensure user font generation is current const gfxFont::Metrics& fontMetrics = - processor.mFontgrp->GetFirstValidFont()->GetMetrics(); + processor.mFontgrp->GetFirstValidFont()->GetMetrics(gfxFont::eHorizontal); // XXX vertical? gfxFloat anchorY; diff --git a/gfx/src/nsFontMetrics.cpp b/gfx/src/nsFontMetrics.cpp index 1e1a902b4acf..61873a5267f2 100644 --- a/gfx/src/nsFontMetrics.cpp +++ b/gfx/src/nsFontMetrics.cpp @@ -147,7 +147,7 @@ nsFontMetrics::Destroy() const gfxFont::Metrics& nsFontMetrics::GetMetrics() const { - return mFontGroup->GetFirstValidFont()->GetMetrics(); + return mFontGroup->GetFirstValidFont()->GetMetrics(gfxFont::eHorizontal); // XXX vertical? } nscoord diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index 9f3cc504992c..dbd0fedb3f19 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -658,7 +658,7 @@ gfxShapedText::SetMissingGlyph(uint32_t aIndex, uint32_t aChar, gfxFont *aFont) details->mAdvance = 0; } else { gfxFloat width = - std::max(aFont->GetMetrics().aveCharWidth, + std::max(aFont->GetMetrics(gfxFont::eHorizontal).aveCharWidth, gfxFontMissingGlyphs::GetDesiredMinWidth(aChar, mAppUnitsPerDevUnit)); details->mAdvance = uint32_t(width * mAppUnitsPerDevUnit); @@ -788,7 +788,7 @@ gfxFont::GetGlyphHAdvance(gfxContext *aCtx, uint16_t aGID) return GetGlyphWidth(aCtx, aGID) / 65536.0; } if (mFUnitsConvFactor == 0.0f) { - GetMetrics(); + GetMetrics(eHorizontal); } NS_ASSERTION(mFUnitsConvFactor > 0.0f, "missing font unit conversion factor"); @@ -1780,7 +1780,7 @@ gfxFont::DrawGlyphs(gfxShapedText *aShapedText, ToDeviceUnits(aPt->y, aRunParams.devPerApp)); gfxFloat advanceDevUnits = ToDeviceUnits(advance, aRunParams.devPerApp); - gfxFloat height = GetMetrics().maxAscent; + gfxFloat height = GetMetrics(eHorizontal).maxAscent; gfxRect glyphRect(pt.x, pt.y - height, advanceDevUnits, height); @@ -2059,7 +2059,9 @@ gfxFont::Measure(gfxTextRun *aTextRun, const int32_t appUnitsPerDevUnit = aTextRun->GetAppUnitsPerDevUnit(); // Current position in appunits - const gfxFont::Metrics& fontMetrics = GetMetrics(); + gfxFont::Orientation orientation = + aTextRun->IsVertical() ? gfxFont::eVertical : gfxFont::eHorizontal; + const gfxFont::Metrics& fontMetrics = GetMetrics(orientation); RunMetrics metrics; metrics.mAscent = fontMetrics.maxAscent*appUnitsPerDevUnit; @@ -2103,6 +2105,7 @@ 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()); @@ -2130,6 +2133,7 @@ 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 @@ -2937,7 +2941,8 @@ gfxFont::GetOrCreateGlyphExtents(int32_t aAppUnitsPerDevUnit) { } void -gfxFont::SetupGlyphExtents(gfxContext *aContext, uint32_t aGlyphID, bool aNeedTight, +gfxFont::SetupGlyphExtents(gfxContext *aContext, Orientation aOrientation, + uint32_t aGlyphID, bool aNeedTight, gfxGlyphExtents *aExtents) { gfxContextMatrixAutoSaveRestore matrixRestore(aContext); @@ -2962,7 +2967,7 @@ gfxFont::SetupGlyphExtents(gfxContext *aContext, uint32_t aGlyphID, bool aNeedTi cairo_text_extents_t extents; cairo_glyph_extents(aContext->GetCairo(), &glyph, 1, &extents); - const Metrics& fontMetrics = GetMetrics(); + const Metrics& fontMetrics = GetMetrics(aOrientation); int32_t appUnitsPerDevUnit = aExtents->GetAppUnitsPerDevUnit(); if (!aNeedTight && extents.x_bearing >= 0 && extents.y_bearing >= -fontMetrics.maxAscent && @@ -3368,8 +3373,8 @@ gfxFont::SynthesizeSpaceWidth(uint32_t aCh) case 0x2004: return GetAdjustedSize() / 3; // three-per-em space case 0x2005: return GetAdjustedSize() / 4; // four-per-em space case 0x2006: return GetAdjustedSize() / 6; // six-per-em space - case 0x2007: return GetMetrics().zeroOrAveCharWidth; // figure space - case 0x2008: return GetMetrics().spaceWidth; // punctuation space + case 0x2007: return GetMetrics(eHorizontal).zeroOrAveCharWidth; // figure space + case 0x2008: return GetMetrics(eHorizontal).spaceWidth; // punctuation space case 0x2009: return GetAdjustedSize() / 5; // thin space case 0x200a: return GetAdjustedSize() / 10; // hair space case 0x202f: return GetAdjustedSize() / 5; // narrow no-break space diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index 55f193bbe833..f92e4f48ecf2 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -1442,9 +1442,20 @@ public: // equal to .aveCharWidth }; - const Metrics& GetMetrics() + enum Orientation { + eHorizontal, + eVertical + }; + + const Metrics& GetMetrics(Orientation aOrientation) { - return GetHorizontalMetrics(); + if (aOrientation == eHorizontal) { + return GetHorizontalMetrics(); + } + if (!mVerticalMetrics) { + mVerticalMetrics = CreateVerticalMetrics(); + } + return *mVerticalMetrics; } /** @@ -1562,7 +1573,8 @@ public: gfxGlyphExtents *GetOrCreateGlyphExtents(int32_t aAppUnitsPerDevUnit); // You need to call SetupCairoFont on the aCR just before calling this - virtual void SetupGlyphExtents(gfxContext *aContext, uint32_t aGlyphID, + virtual void SetupGlyphExtents(gfxContext *aContext, + Orientation aOrientation, uint32_t aGlyphID, bool aNeedTight, gfxGlyphExtents *aExtents); // This is called by the default Draw() implementation above. diff --git a/gfx/thebes/gfxGlyphExtents.cpp b/gfx/thebes/gfxGlyphExtents.cpp index 0f5bd16e7d0d..2a946456ce03 100644 --- a/gfx/thebes/gfxGlyphExtents.cpp +++ b/gfx/thebes/gfxGlyphExtents.cpp @@ -36,6 +36,7 @@ gfxGlyphExtents::~gfxGlyphExtents() bool gfxGlyphExtents::GetTightGlyphExtentsAppUnits(gfxFont *aFont, + gfxFont::Orientation aOrientation, gfxContext *aContext, uint32_t aGlyphID, gfxRect *aExtents) { HashEntry *entry = mTightGlyphExtents.GetEntry(aGlyphID); @@ -49,7 +50,8 @@ gfxGlyphExtents::GetTightGlyphExtentsAppUnits(gfxFont *aFont, #ifdef DEBUG_TEXT_RUN_STORAGE_METRICS ++gGlyphExtentsSetupLazyTight; #endif - aFont->SetupGlyphExtents(aContext, aGlyphID, true, this); + aFont->SetupGlyphExtents(aContext, aOrientation, aGlyphID, true, + this); entry = mTightGlyphExtents.GetEntry(aGlyphID); } if (!entry) { diff --git a/gfx/thebes/gfxGlyphExtents.h b/gfx/thebes/gfxGlyphExtents.h index 59ec4225d55f..28952a8c7955 100644 --- a/gfx/thebes/gfxGlyphExtents.h +++ b/gfx/thebes/gfxGlyphExtents.h @@ -6,13 +6,13 @@ #ifndef GFX_GLYPHEXTENTS_H #define GFX_GLYPHEXTENTS_H +#include "gfxFont.h" #include "nsTHashtable.h" #include "nsHashKeys.h" #include "nsTArray.h" #include "mozilla/MemoryReporting.h" class gfxContext; -class gfxFont; struct gfxRect; /** @@ -62,8 +62,9 @@ public: // Get glyph extents; a rectangle relative to the left baseline origin // Returns true on success. Can fail on OOM or when aContext is null // and extents were not (successfully) prefetched. - bool GetTightGlyphExtentsAppUnits(gfxFont *aFont, gfxContext *aContext, - uint32_t aGlyphID, gfxRect *aExtents); + bool GetTightGlyphExtentsAppUnits(gfxFont *aFont, + gfxFont::Orientation aOrientation, + gfxContext *aContext, uint32_t aGlyphID, gfxRect *aExtents); void SetContainedGlyphWidthAppUnits(uint32_t aGlyphID, uint16_t aWidth) { mContainedGlyphWidths.Set(aGlyphID, aWidth); diff --git a/gfx/thebes/gfxPangoFonts.cpp b/gfx/thebes/gfxPangoFonts.cpp index 46d5180f0c92..84bdab8fd085 100644 --- a/gfx/thebes/gfxPangoFonts.cpp +++ b/gfx/thebes/gfxPangoFonts.cpp @@ -1861,7 +1861,8 @@ gfxPangoFontGroup::GetBaseFontSet() if (size != 0.0 && mStyle.sizeAdjust != 0.0) { gfxFcFont *font = fontSet->GetFontAt(0, GetStyle()); if (font) { - const gfxFont::Metrics& metrics = font->GetMetrics(); + const gfxFont::Metrics& metrics = + font->GetMetrics(gfxFont::eHorizontal); // XXX vertical? // The factor of 0.1 ensures that xHeight is sane so fonts don't // become huge. Strictly ">" ensures that xHeight and emHeight are diff --git a/gfx/thebes/gfxTextRun.cpp b/gfx/thebes/gfxTextRun.cpp index db04ba516970..bbe232f99cc7 100644 --- a/gfx/thebes/gfxTextRun.cpp +++ b/gfx/thebes/gfxTextRun.cpp @@ -1264,8 +1264,12 @@ gfxTextRun::SetSpaceGlyphIfSimple(gfxFont *aFont, gfxContext *aContext, return false; } + gfxFont::Orientation fontOrientation = + (aOrientation & gfxTextRunFactory::TEXT_ORIENT_VERTICAL_UPRIGHT) ? + gfxFont::eVertical : gfxFont::eHorizontal; uint32_t spaceWidthAppUnits = - NS_lroundf(aFont->GetMetrics().spaceWidth * mAppUnitsPerDevUnit); + NS_lroundf(aFont->GetMetrics(fontOrientation).spaceWidth * + mAppUnitsPerDevUnit); if (!CompressedGlyph::IsSimpleAdvance(spaceWidthAppUnits)) { return false; } @@ -1306,6 +1310,8 @@ 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 @@ -1322,7 +1328,8 @@ gfxTextRun::FetchGlyphExtents(gfxContext *aRefContext) #ifdef DEBUG_TEXT_RUN_STORAGE_METRICS ++gGlyphExtentsSetupEagerSimple; #endif - font->SetupGlyphExtents(aRefContext, glyphIndex, false, extents); + font->SetupGlyphExtents(aRefContext, orientation, + glyphIndex, false, extents); } } } else if (!glyphData->IsMissing()) { @@ -1347,7 +1354,8 @@ gfxTextRun::FetchGlyphExtents(gfxContext *aRefContext) #ifdef DEBUG_TEXT_RUN_STORAGE_METRICS ++gGlyphExtentsSetupEagerTight; #endif - font->SetupGlyphExtents(aRefContext, glyphIndex, true, extents); + font->SetupGlyphExtents(aRefContext, orientation, + glyphIndex, true, extents); } } } @@ -2474,16 +2482,19 @@ gfxFontGroup::GetUnderlineOffset() if (!font) { continue; } - gfxFloat bad = font->GetMetrics().underlineOffset; + gfxFloat bad = font->GetMetrics(gfxFont::eHorizontal). + underlineOffset; gfxFloat first = - GetFirstValidFont()->GetMetrics().underlineOffset; + GetFirstValidFont()->GetMetrics(gfxFont::eHorizontal). + underlineOffset; mUnderlineOffset = std::min(first, bad); return mUnderlineOffset; } } // no bad underline fonts, use the first valid font's metric - mUnderlineOffset = GetFirstValidFont()->GetMetrics().underlineOffset; + mUnderlineOffset = GetFirstValidFont()-> + GetMetrics(gfxFont::eHorizontal).underlineOffset; } return mUnderlineOffset; diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index a2da9611212d..bb1bd5683aee 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -1798,7 +1798,7 @@ GetFirstFontMetrics(gfxFontGroup* aFontGroup) gfxFont* font = aFontGroup->GetFirstValidFont(); if (!font) return gfxFont::Metrics(); - return font->GetMetrics(); + return font->GetMetrics(gfxFont::eHorizontal); // XXX vertical } PR_STATIC_ASSERT(NS_STYLE_WHITESPACE_NORMAL == 0); @@ -5672,7 +5672,8 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx, gfxFont* firstFont = aProvider.GetFontGroup()->GetFirstValidFont(); if (!firstFont) return; // OOM - gfxFont::Metrics decorationMetrics(firstFont->GetMetrics()); + gfxFont::Metrics + decorationMetrics(firstFont->GetMetrics(gfxFont::eHorizontal)); // XXX vertical? decorationMetrics.underlineOffset = aProvider.GetFontGroup()->GetUnderlineOffset(); @@ -6353,7 +6354,8 @@ nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext, gfxFont* firstFont = fontGroup->GetFirstValidFont(); if (!firstFont) return false; // OOM - const gfxFont::Metrics& metrics = firstFont->GetMetrics(); + const gfxFont::Metrics& metrics = + firstFont->GetMetrics(gfxFont::eHorizontal); // XXX vertical? gfxFloat underlineOffset = fontGroup->GetUnderlineOffset(); gfxFloat ascent = aPresContext->AppUnitsToGfxUnits(mAscent); gfxFloat descentLimit = diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 675bb19b1ccb..22f6ff87c2a2 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -500,8 +500,9 @@ static nscoord CalcLengthWith(const nsCSSValue& aValue, nsRefPtr fm = GetMetricsFor(aPresContext, aStyleContext, styleFont, aFontSize, aUseUserFontSet); - gfxFloat zeroWidth = (fm->GetThebesFontGroup()->GetFirstValidFont() - ->GetMetrics().zeroOrAveCharWidth); + gfxFloat zeroWidth = + fm->GetThebesFontGroup()->GetFirstValidFont()-> + GetMetrics(gfxFont::eHorizontal).zeroOrAveCharWidth; // XXX vertical? return ScaleCoordRound(aValue, ceil(aPresContext->AppUnitsPerDevPixel() * zeroWidth));