diff --git a/gfx/thebes/gfxTextRun.cpp b/gfx/thebes/gfxTextRun.cpp index c715e69f80..79f4cfacc8 100644 --- a/gfx/thebes/gfxTextRun.cpp +++ b/gfx/thebes/gfxTextRun.cpp @@ -147,7 +147,6 @@ gfxTextRun::gfxTextRun(const gfxTextRunFactory::Parameters *aParams, : gfxShapedText(aLength, aFlags, aParams->mAppUnitsPerDevUnit) , mUserData(aParams->mUserData) , mFontGroup(aFontGroup) - , mReleasedFontGroup(false) , mShapingState(eShapingState_Normal) { NS_ASSERTION(mAppUnitsPerDevUnit > 0, "Invalid app unit scale"); @@ -184,30 +183,18 @@ gfxTextRun::~gfxTextRun() mFlags = 0xFFFFFFFF; #endif - // The cached ellipsis textrun (if any) in a fontgroup will have already - // been told to release its reference to the group, so we mustn't do that - // again here. - if (!mReleasedFontGroup) { #ifdef DEBUG - gfxTextPerfMetrics *tp = mFontGroup->GetTextPerfMetrics(); - if (tp) { - tp->current.textrunDestr++; - } -#endif - NS_RELEASE(mFontGroup); + gfxTextPerfMetrics* tp = mFontGroup->GetTextPerfMetrics(); + if (tp) { + tp->current.textrunDestr++; } +#endif + + NS_RELEASE(mFontGroup); MOZ_COUNT_DTOR(gfxTextRun); } -void -gfxTextRun::ReleaseFontGroup() -{ - NS_ASSERTION(!mReleasedFontGroup, "doubly released!"); - NS_RELEASE(mFontGroup); - mReleasedFontGroup = true; -} - bool gfxTextRun::SetPotentialLineBreaks(Range aRange, const uint8_t* aBreakBefore) { @@ -2541,17 +2528,11 @@ gfxFontGroup::InitScriptRun(DrawTarget* aDrawTarget, } } -gfxTextRun * -gfxFontGroup::GetEllipsisTextRun(int32_t aAppUnitsPerDevPixel, uint32_t aFlags, - LazyReferenceDrawTargetGetter& aRefDrawTargetGetter) -{ +already_AddRefed +gfxFontGroup::MakeEllipsisTextRun(int32_t aAppUnitsPerDevPixel, uint32_t aFlags, + DrawTarget* aRefDrawTarget) { MOZ_ASSERT(!(aFlags & ~TEXT_ORIENT_MASK), "flags here should only be used to specify orientation"); - if (mCachedEllipsisTextRun && - (mCachedEllipsisTextRun->GetFlags() & TEXT_ORIENT_MASK) == aFlags && - mCachedEllipsisTextRun->GetAppUnitsPerDevUnit() == aAppUnitsPerDevPixel) { - return mCachedEllipsisTextRun.get(); - } // Use a Unicode ellipsis if the font supports it, // otherwise use three ASCII periods as fallback. @@ -2562,20 +2543,11 @@ gfxFontGroup::GetEllipsisTextRun(int32_t aAppUnitsPerDevPixel, uint32_t aFlags, : nsDependentString(kASCIIPeriodsChar, ArrayLength(kASCIIPeriodsChar) - 1); - RefPtr refDT = aRefDrawTargetGetter.GetRefDrawTarget(); Parameters params = { - refDT, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevPixel + aRefDrawTarget, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevPixel }; - mCachedEllipsisTextRun = - MakeTextRun(ellipsis.get(), ellipsis.Length(), ¶ms, - aFlags | TEXT_IS_PERSISTENT, nullptr); - if (!mCachedEllipsisTextRun) { - return nullptr; - } - // don't let the presence of a cached ellipsis textrun prolong the - // fontgroup's life - mCachedEllipsisTextRun->ReleaseFontGroup(); - return mCachedEllipsisTextRun.get(); + return MakeTextRun(ellipsis.get(), ellipsis.Length(), ¶ms, + aFlags | TEXT_IS_PERSISTENT, nullptr); } already_AddRefed diff --git a/gfx/thebes/gfxTextRun.h b/gfx/thebes/gfxTextRun.h index 8189861756..c63365cb0f 100644 --- a/gfx/thebes/gfxTextRun.h +++ b/gfx/thebes/gfxTextRun.h @@ -755,8 +755,6 @@ private: bool mSkipDrawing; // true if the font group we used had a user font // download that's in progress, so we should hide text // until the download completes (or timeout fires) - bool mReleasedFontGroup; // we already called NS_RELEASE on - // mFontGroup, so don't do it again // shaping state for handling variant fallback features // such as subscript/superscript variant glyphs @@ -897,7 +895,6 @@ public: mUnderlineOffset = UNDERLINE_OFFSET_NOT_SET; mSkipDrawing = false; mHyphenWidth = -1; - mCachedEllipsisTextRun = nullptr; } // If there is a user font set, check to see whether the font list or any @@ -911,17 +908,11 @@ public: return mSkipDrawing; } - class LazyReferenceDrawTargetGetter { - public: - virtual already_AddRefed GetRefDrawTarget() = 0; - }; - // The gfxFontGroup keeps ownership of this textrun. - // It is only guaranteed to exist until the next call to GetEllipsisTextRun - // (which might use a different appUnitsPerDev value or flags) for the font - // group, or until UpdateUserFonts is called, or the fontgroup is destroyed. - // Get it/use it/forget it :) - don't keep a reference that might go stale. - gfxTextRun* GetEllipsisTextRun(int32_t aAppUnitsPerDevPixel, uint32_t aFlags, - LazyReferenceDrawTargetGetter& aRefDrawTargetGetter); + // Make a textrun for the ellipsis character (with fallback to "..." if + // ellipsis is not supported by the font). + already_AddRefed MakeEllipsisTextRun(int32_t aAppUnitsPerDevPixel, + uint32_t aFlags, + DrawTarget* aRefDrawTarget); protected: // search through pref fonts for a character, return nullptr if no matching pref font @@ -1093,10 +1084,6 @@ protected: gfxTextPerfMetrics *mTextPerf; - // Cache a textrun representing an ellipsis (useful for CSS text-overflow) - // at a specific appUnitsPerDevPixel size and orientation - RefPtr mCachedEllipsisTextRun; - // cache the most recent pref font to avoid general pref font lookup RefPtr mLastPrefFamily; RefPtr mLastPrefFont; diff --git a/layout/generic/TextOverflow.cpp b/layout/generic/TextOverflow.cpp index 3d78eaf911..6827b4f29a 100644 --- a/layout/generic/TextOverflow.cpp +++ b/layout/generic/TextOverflow.cpp @@ -27,34 +27,15 @@ namespace mozilla { namespace css { -class LazyReferenceRenderingDrawTargetGetterFromFrame final : - public gfxFontGroup::LazyReferenceDrawTargetGetter { -public: - typedef mozilla::gfx::DrawTarget DrawTarget; - - explicit LazyReferenceRenderingDrawTargetGetterFromFrame(nsIFrame* aFrame) - : mFrame(aFrame) {} - virtual already_AddRefed GetRefDrawTarget() override - { - RefPtr ctx = - mFrame->PresContext()->PresShell()->CreateReferenceRenderingContext(); - RefPtr dt = ctx->GetDrawTarget(); - return dt.forget(); - } -private: - nsIFrame* mFrame; -}; - -static gfxTextRun* -GetEllipsisTextRun(nsIFrame* aFrame) +static already_AddRefed +MakeEllipsisTextRun(nsIFrame* aFrame) { - RefPtr fm = - nsLayoutUtils::GetInflatedFontMetricsForFrame(aFrame); - LazyReferenceRenderingDrawTargetGetterFromFrame lazyRefDrawTargetGetter(aFrame); - return fm->GetThebesFontGroup()->GetEllipsisTextRun( + RefPtr fm = nsLayoutUtils::GetInflatedFontMetricsForFrame(aFrame); + RefPtr ctx = aFrame->PresContext()->PresShell()->CreateReferenceRenderingContext(); + return fm->GetThebesFontGroup()->MakeEllipsisTextRun( aFrame->PresContext()->AppUnitsPerDevPixel(), nsLayoutUtils::GetTextRunOrientFlagsForStyle(aFrame->StyleContext()), - lazyRefDrawTargetGetter); + ctx->GetDrawTarget()); } static nsIFrame* @@ -166,16 +147,22 @@ public: nsDisplayTextOverflowMarker(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, const nsRect& aRect, nscoord aAscent, const nsStyleTextOverflowSide* aStyle, - uint32_t aIndex) - : nsDisplayItem(aBuilder, aFrame), mRect(aRect), - mStyle(aStyle), mAscent(aAscent), mIndex(aIndex) { + uint32_t aIndex, gfxTextRun* aTextRun) + : nsDisplayItem(aBuilder, aFrame) + , mRect(aRect) + , mStyle(aStyle) + , mAscent(aAscent) + , mIndex(aIndex) + , mTextRun(aTextRun) { MOZ_COUNT_CTOR(nsDisplayTextOverflowMarker); } + #ifdef NS_BUILD_REFCNT_LOGGING virtual ~nsDisplayTextOverflowMarker() { MOZ_COUNT_DTOR(nsDisplayTextOverflowMarker); } #endif + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override { *aSnap = false; @@ -208,10 +195,11 @@ public: nsPoint aOffsetFromRect); NS_DISPLAY_DECL_NAME("TextOverflow", TYPE_TEXT_OVERFLOW) private: - nsRect mRect; // in reference frame coordinates + nsRect mRect; // in reference frame coordinates const nsStyleTextOverflowSide* mStyle; nscoord mAscent; // baseline for the marker text in mRect uint32_t mIndex; + RefPtr mTextRun; // pre-cached textrun, if available }; static void @@ -259,21 +247,18 @@ nsDisplayTextOverflowMarker::PaintTextToContext(nsRenderingContext* aCtx, } pt += aOffsetFromRect; - if (mStyle->mType == NS_STYLE_TEXT_OVERFLOW_ELLIPSIS) { - gfxTextRun* textRun = GetEllipsisTextRun(mFrame); - if (textRun) { - NS_ASSERTION(!textRun->IsRightToLeft(), - "Ellipsis textruns should always be LTR!"); - gfxPoint gfxPt(pt.x, pt.y); - textRun->Draw(gfxTextRun::Range(textRun), gfxPt, - gfxTextRun::DrawParams(aCtx->ThebesContext())); - } - } else { - RefPtr fm = - nsLayoutUtils::GetInflatedFontMetricsForFrame(mFrame); - nsLayoutUtils::DrawString(mFrame, *fm, aCtx, mStyle->mString.get(), - mStyle->mString.Length(), pt); + if (mTextRun) { + gfxPoint gfxPt(pt.x, pt.y); + mTextRun->Draw(gfxTextRun::Range(mTextRun), gfxPt, + gfxTextRun::DrawParams(aCtx->ThebesContext())); + return; } + + MOZ_ASSERT(mStyle->mType != NS_STYLE_TEXT_OVERFLOW_ELLIPSIS); + RefPtr fm = + nsLayoutUtils::GetInflatedFontMetricsForFrame(mFrame); + nsLayoutUtils::DrawString(mFrame, *fm, aCtx, mStyle->mString.get(), + mStyle->mString.Length(), pt); } TextOverflow::TextOverflow(nsDisplayListBuilder* aBuilder, @@ -784,7 +769,10 @@ TextOverflow::CreateMarkers(const nsLineBox* aLine, markerRect, clipState); nsDisplayItem* marker = new (mBuilder) nsDisplayTextOverflowMarker(mBuilder, mBlock, markerRect, - aLine->GetLogicalAscent(), mIStart.mStyle, 0); + aLine->GetLogicalAscent(), mIStart.mStyle, 0, + mIStart.mStyle->mType == NS_STYLE_TEXT_OVERFLOW_ELLIPSIS ? + GetEllipsisTextRun() : + nullptr); mMarkerList.AppendNewToTop(marker); } @@ -801,11 +789,21 @@ TextOverflow::CreateMarkers(const nsLineBox* aLine, markerRect, clipState); nsDisplayItem* marker = new (mBuilder) nsDisplayTextOverflowMarker(mBuilder, mBlock, markerRect, - aLine->GetLogicalAscent(), mIEnd.mStyle, 1); + aLine->GetLogicalAscent(), mIEnd.mStyle, 1, + mIEnd.mStyle->mType == NS_STYLE_TEXT_OVERFLOW_ELLIPSIS ? + GetEllipsisTextRun() : + nullptr); mMarkerList.AppendNewToTop(marker); } } +gfxTextRun* TextOverflow::GetEllipsisTextRun() { + if (!mEllipsisTextRun) { + mEllipsisTextRun = MakeEllipsisTextRun(mBlock); + } + return mEllipsisTextRun; +} + void TextOverflow::Marker::SetupString(nsIFrame* aFrame) { @@ -814,7 +812,7 @@ TextOverflow::Marker::SetupString(nsIFrame* aFrame) } if (mStyle->mType == NS_STYLE_TEXT_OVERFLOW_ELLIPSIS) { - gfxTextRun* textRun = GetEllipsisTextRun(aFrame); + RefPtr textRun = MakeEllipsisTextRun(aFrame); if (textRun) { mISize = textRun->GetAdvanceWidth(); } else { diff --git a/layout/generic/TextOverflow.h b/layout/generic/TextOverflow.h index 5c20ba68c2..9700f83a16 100644 --- a/layout/generic/TextOverflow.h +++ b/layout/generic/TextOverflow.h @@ -203,6 +203,8 @@ class TextOverflow { bool aCreateIStart, bool aCreateIEnd, const LogicalRect& aInsideMarkersArea); + gfxTextRun* GetEllipsisTextRun(); + LogicalRect mContentArea; nsDisplayListBuilder* mBuilder; nsIFrame* mBlock; @@ -250,6 +252,8 @@ class TextOverflow { Marker mIStart; // the inline start marker Marker mIEnd; // the inline end marker + + RefPtr mEllipsisTextRun; // Cached ellipsis textrun, if available }; } // namespace css