Bug 1216851 - Allow flattening of opacity when it contains text. r=roc

This commit is contained in:
Matt Woodrow 2015-10-23 11:22:45 +13:00
parent dadbb2efae
commit cb3432f21b
4 changed files with 102 additions and 47 deletions

View File

@ -4578,28 +4578,11 @@ nsTextFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo)
return NS_OK;
}
class nsDisplayTextGeometry : public nsCharClipGeometry
{
public:
nsDisplayTextGeometry(nsCharClipDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
: nsCharClipGeometry(aItem, aBuilder)
{
nsTextFrame* f = static_cast<nsTextFrame*>(aItem->Frame());
f->GetTextDecorations(f->PresContext(), nsTextFrame::eResolvedColors, mDecorations);
}
/**
* We store the computed text decorations here since they are
* computed using style data from parent frames. Any changes to these
* styles will only invalidate the parent frame and not this frame.
*/
nsTextFrame::TextDecorations mDecorations;
};
class nsDisplayText : public nsCharClipDisplayItem {
public:
nsDisplayText(nsDisplayListBuilder* aBuilder, nsTextFrame* aFrame) :
nsCharClipDisplayItem(aBuilder, aFrame),
mOpacity(1.0f),
mDisableSubpixelAA(false) {
MOZ_COUNT_CTOR(nsDisplayText);
}
@ -4634,40 +4617,102 @@ public:
return GetBounds(aBuilder, &snap);
}
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
{
return new nsDisplayTextGeometry(this, aBuilder);
}
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override;
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion) override
{
const nsDisplayTextGeometry* geometry = static_cast<const nsDisplayTextGeometry*>(aGeometry);
nsTextFrame* f = static_cast<nsTextFrame*>(mFrame);
nsTextFrame::TextDecorations decorations;
f->GetTextDecorations(f->PresContext(), nsTextFrame::eResolvedColors, decorations);
bool snap;
nsRect newRect = geometry->mBounds;
nsRect oldRect = GetBounds(aBuilder, &snap);
if (decorations != geometry->mDecorations ||
mVisIStartEdge != geometry->mVisIStartEdge ||
mVisIEndEdge != geometry->mVisIEndEdge ||
!oldRect.IsEqualInterior(newRect) ||
!geometry->mBorderRect.IsEqualInterior(GetBorderRect())) {
aInvalidRegion->Or(oldRect, newRect);
}
}
nsRegion *aInvalidRegion) override;
virtual void DisableComponentAlpha() override {
mDisableSubpixelAA = true;
}
bool CanApplyOpacity() const override
{
nsTextFrame* f = static_cast<nsTextFrame*>(mFrame);
if (f->IsSelected()) {
return false;
}
const nsStyleText* textStyle = f->StyleText();
if (textStyle->mTextShadow) {
return false;
}
nsTextFrame::TextDecorations decorations;
f->GetTextDecorations(f->PresContext(), nsTextFrame::eResolvedColors, decorations);
if (decorations.HasDecorationLines()) {
return false;
}
return true;
}
void ApplyOpacity(nsDisplayListBuilder* aBuilder,
float aOpacity,
const DisplayItemClip* aClip) override
{
NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity should be allowed");
mOpacity = aOpacity;
if (aClip) {
IntersectClip(aBuilder, *aClip);
}
}
float mOpacity;
bool mDisableSubpixelAA;
};
class nsDisplayTextGeometry : public nsCharClipGeometry
{
public:
nsDisplayTextGeometry(nsDisplayText* aItem, nsDisplayListBuilder* aBuilder)
: nsCharClipGeometry(aItem, aBuilder)
, mOpacity(aItem->mOpacity)
{
nsTextFrame* f = static_cast<nsTextFrame*>(aItem->Frame());
f->GetTextDecorations(f->PresContext(), nsTextFrame::eResolvedColors, mDecorations);
}
/**
* We store the computed text decorations here since they are
* computed using style data from parent frames. Any changes to these
* styles will only invalidate the parent frame and not this frame.
*/
nsTextFrame::TextDecorations mDecorations;
float mOpacity;
};
nsDisplayItemGeometry*
nsDisplayText::AllocateGeometry(nsDisplayListBuilder* aBuilder)
{
return new nsDisplayTextGeometry(this, aBuilder);
}
void
nsDisplayText::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion)
{
const nsDisplayTextGeometry* geometry = static_cast<const nsDisplayTextGeometry*>(aGeometry);
nsTextFrame* f = static_cast<nsTextFrame*>(mFrame);
nsTextFrame::TextDecorations decorations;
f->GetTextDecorations(f->PresContext(), nsTextFrame::eResolvedColors, decorations);
bool snap;
nsRect newRect = geometry->mBounds;
nsRect oldRect = GetBounds(aBuilder, &snap);
if (decorations != geometry->mDecorations ||
mVisIStartEdge != geometry->mVisIStartEdge ||
mVisIEndEdge != geometry->mVisIEndEdge ||
!oldRect.IsEqualInterior(newRect) ||
!geometry->mBorderRect.IsEqualInterior(GetBorderRect()) ||
mOpacity != geometry->mOpacity) {
aInvalidRegion->Or(oldRect, newRect);
}
}
void
nsDisplayText::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) {
@ -4698,7 +4743,8 @@ nsDisplayText::Paint(nsDisplayListBuilder* aBuilder,
NS_ASSERTION(mVisIStartEdge >= 0, "illegal start edge");
NS_ASSERTION(mVisIEndEdge >= 0, "illegal end edge");
f->PaintText(aCtx, ToReferenceFrame(), extraVisible, *this);
f->PaintText(aCtx, ToReferenceFrame(), extraVisible, *this,
nullptr, nullptr, mOpacity);
}
void
@ -6234,7 +6280,8 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
const nsRect& aDirtyRect,
const nsCharClipDisplayItem& aItem,
gfxTextContextPaint* aContextPaint,
nsTextFrame::DrawPathCallbacks* aCallbacks)
nsTextFrame::DrawPathCallbacks* aCallbacks,
float aOpacity /* = 1.0f */)
{
// Don't pass in aRenderingContext here, because we need a *reference*
// context and aRenderingContext might have some transform in it
@ -6291,6 +6338,7 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
aDirtyRect.width, aDirtyRect.height);
// Fork off to the (slower) paint-with-selection path if necessary.
if (IsSelected()) {
MOZ_ASSERT(aOpacity == 1.0f, "We don't support opacity with selections!");
gfxSkipCharsIterator tmp(provider.GetStart());
int32_t contentOffset = tmp.ConvertSkippedToOriginal(startOffset);
int32_t contentLength =
@ -6304,6 +6352,12 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
}
nscolor foregroundColor = textPaintStyle.GetTextColor();
if (aOpacity != 1.0f) {
gfx::Color gfxColor = gfx::Color::FromABGR(foregroundColor);
gfxColor.a *= aOpacity;
foregroundColor = gfxColor.ToABGR();
}
if (!aCallbacks) {
const nsStyleText* textStyle = StyleText();
PaintShadows(textStyle->mTextShadow, startOffset, maxLength,

View File

@ -393,7 +393,8 @@ public:
void PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
const nsRect& aDirtyRect, const nsCharClipDisplayItem& aItem,
gfxTextContextPaint* aContextPaint = nullptr,
DrawPathCallbacks* aCallbacks = nullptr);
DrawPathCallbacks* aCallbacks = nullptr,
float aOpacity = 1.0f);
// helper: paint text frame when we're impacted by at least one selection.
// Return false if the text was not painted and we should continue with
// the fast path.

View File

@ -688,7 +688,7 @@ skip-if(B2G||Mulet) == 378937-1.html 378937-1-ref.html # Initial mulet triage: p
== 379178-html.html 379178-html-ref.html
== 379178-svg.svg 379178-svg-ref.svg
== 379316-1.html 379316-1-ref.html
skip-if(B2G||Mulet) fails-if(Android) random-if(cocoaWidget) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.2/.test(http.oscpu),1,170) fuzzy-if(gtkWidget,1,191) == 379316-2.html 379316-2-ref.html # bug 379786 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fails-if(Android) random-if(cocoaWidget) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fuzzy-if(winWidget,1,180) fuzzy-if(gtkWidget,1,191) == 379316-2.html 379316-2-ref.html # bug 379786 # Initial mulet triage: parity with B2G/B2G Desktop
== 379328-1.html 379328-1-ref.html
== 379349-1a.xhtml 379349-1-ref.xhtml
# fuzzy because of different border rendering approach in bug 1185636
@ -1743,7 +1743,7 @@ random-if(Android&&AndroidVersion<15) == 776265-1a.html 776265-1-ref.html
== 786254-1.html 786254-1-ref.html
== 787947-1.html 787947-1-ref.html
== 796847-1.svg 796847-1-ref.svg
fuzzy(40,850) fuzzy-if(azureQuartz,73,542) == 797797-1.html 797797-1-ref.html # 'opacity:N' and rgba(,,,N) text don't match precisely
fuzzy(40,875) fuzzy-if(azureQuartz,73,542) == 797797-1.html 797797-1-ref.html # 'opacity:N' and rgba(,,,N) text don't match precisely
fuzzy(40,850) fuzzy-if(azureQuartz,68,586) == 797797-2.html 797797-2-ref.html # 'opacity:N' and rgba(,,,N) text don't match precisely
== 801994-1.html 801994-1-ref.html
== 804323-1.html 804323-1-ref.html

View File

@ -5,7 +5,7 @@ skip-if(B2G||Mulet) HTTP(..) == marker-string.html marker-string-ref.html # Init
skip-if(Android||B2G) HTTP(..) == bidi-simple.html bidi-simple-ref.html # Fails on Android due to anti-aliasing
skip-if(!gtkWidget) fuzzy-if(gtkWidget,2,289) HTTP(..) == bidi-simple-scrolled.html bidi-simple-scrolled-ref.html # Fails on Windows and OSX due to anti-aliasing
skip-if(B2G||Mulet) fuzzy-if(Android&&AndroidVersion<15,206,41) fuzzy-if(Android&&AndroidVersion>=15,24,4000) fuzzy-if(cocoaWidget,1,40) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,1770) HTTP(..) == scroll-rounding.html scroll-rounding-ref.html # bug 760264 # Initial mulet triage: parity with B2G/B2G Desktop
fuzzy-if(OSX==1008,1,1) HTTP(..) == anonymous-block.html anonymous-block-ref.html
fuzzy(2,453) HTTP(..) == anonymous-block.html anonymous-block-ref.html
skip-if(B2G||Mulet) HTTP(..) == false-marker-overlap.html false-marker-overlap-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
HTTP(..) == visibility-hidden.html visibility-hidden-ref.html
skip-if(B2G||Mulet) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,1724) HTTP(..) == block-padding.html block-padding-ref.html # Initial mulet triage: parity with B2G/B2G Desktop