Bug 1388614 - Make sure MathML display items are unique. r=karlt

FrameLayerBuilder requires the the (frame,per-frame-key) for each display item is unique. It only enforces this in certain situations though, so there's cases where we've gotten away without this.

Retained display lists introduces more situations where we rely on this, so I've found a few.

MathML nsDisplayNotation and nsDisplayMathMLBar are the two fixed by this patch.
This commit is contained in:
Matt Woodrow 2017-08-10 23:26:42 +12:00
parent 95f2e31f88
commit f47c170811
5 changed files with 70 additions and 53 deletions

View File

@ -328,8 +328,8 @@ nsMathMLFrame::DisplayBoundingMetrics(nsDisplayListBuilder* aBuilder,
class nsDisplayMathMLBar : public nsDisplayItem {
public:
nsDisplayMathMLBar(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, const nsRect& aRect)
: nsDisplayItem(aBuilder, aFrame), mRect(aRect) {
nsIFrame* aFrame, const nsRect& aRect, uint32_t aIndex)
: nsDisplayItem(aBuilder, aFrame), mRect(aRect), mIndex(aIndex) {
MOZ_COUNT_CTOR(nsDisplayMathMLBar);
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -338,11 +338,16 @@ public:
}
#endif
virtual uint32_t GetPerFrameKey() override {
return (mIndex << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
}
virtual void Paint(nsDisplayListBuilder* aBuilder,
gfxContext* aCtx) override;
NS_DISPLAY_DECL_NAME("MathMLBar", TYPE_MATHML_BAR)
private:
nsRect mRect;
uint32_t mIndex;
};
void nsDisplayMathMLBar::Paint(nsDisplayListBuilder* aBuilder,
@ -362,12 +367,13 @@ void nsDisplayMathMLBar::Paint(nsDisplayListBuilder* aBuilder,
void
nsMathMLFrame::DisplayBar(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, const nsRect& aRect,
const nsDisplayListSet& aLists) {
const nsDisplayListSet& aLists,
uint32_t aIndex) {
if (!aFrame->StyleVisibility()->IsVisible() || aRect.IsEmpty())
return;
aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayMathMLBar(aBuilder, aFrame, aRect));
nsDisplayMathMLBar(aBuilder, aFrame, aRect, aIndex));
}
void

View File

@ -363,7 +363,8 @@ protected:
*/
void DisplayBar(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, const nsRect& aRect,
const nsDisplayListSet& aLists);
const nsDisplayListSet& aLists,
uint32_t aIndex = 0);
// information about the presentation policy of the frame
nsPresentationData mPresentationData;

View File

@ -47,7 +47,7 @@ NS_NewMathMLmencloseFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmencloseFrame)
nsMathMLmencloseFrame::nsMathMLmencloseFrame(nsStyleContext* aContext, ClassID aID) :
nsMathMLContainerFrame(aContext, aID), mNotationsToDraw(0),
nsMathMLContainerFrame(aContext, aID),
mRuleThickness(0), mRadicalRuleThickness(0),
mLongDivCharIndex(-1), mRadicalCharIndex(-1), mContentWidth(0)
{
@ -99,42 +99,47 @@ nsresult nsMathMLmencloseFrame::AddNotation(const nsAString& aNotation)
if (aNotation.EqualsLiteral("longdiv")) {
rv = AllocateMathMLChar(NOTATION_LONGDIV);
NS_ENSURE_SUCCESS(rv, rv);
mNotationsToDraw |= NOTATION_LONGDIV;
mNotationsToDraw += NOTATION_LONGDIV;
} else if (aNotation.EqualsLiteral("actuarial")) {
mNotationsToDraw |= (NOTATION_RIGHT | NOTATION_TOP);
mNotationsToDraw += NOTATION_RIGHT;
mNotationsToDraw += NOTATION_TOP;
} else if (aNotation.EqualsLiteral("radical")) {
rv = AllocateMathMLChar(NOTATION_RADICAL);
NS_ENSURE_SUCCESS(rv, rv);
mNotationsToDraw |= NOTATION_RADICAL;
mNotationsToDraw += NOTATION_RADICAL;
} else if (aNotation.EqualsLiteral("box")) {
mNotationsToDraw |= (NOTATION_LEFT | NOTATION_RIGHT |
NOTATION_TOP | NOTATION_BOTTOM);
mNotationsToDraw += NOTATION_LEFT;
mNotationsToDraw += NOTATION_RIGHT;
mNotationsToDraw += NOTATION_TOP;
mNotationsToDraw += NOTATION_BOTTOM;
} else if (aNotation.EqualsLiteral("roundedbox")) {
mNotationsToDraw |= NOTATION_ROUNDEDBOX;
mNotationsToDraw += NOTATION_ROUNDEDBOX;
} else if (aNotation.EqualsLiteral("circle")) {
mNotationsToDraw |= NOTATION_CIRCLE;
mNotationsToDraw += NOTATION_CIRCLE;
} else if (aNotation.EqualsLiteral("left")) {
mNotationsToDraw |= NOTATION_LEFT;
mNotationsToDraw += NOTATION_LEFT;
} else if (aNotation.EqualsLiteral("right")) {
mNotationsToDraw |= NOTATION_RIGHT;
mNotationsToDraw += NOTATION_RIGHT;
} else if (aNotation.EqualsLiteral("top")) {
mNotationsToDraw |= NOTATION_TOP;
mNotationsToDraw += NOTATION_TOP;
} else if (aNotation.EqualsLiteral("bottom")) {
mNotationsToDraw |= NOTATION_BOTTOM;
mNotationsToDraw += NOTATION_BOTTOM;
} else if (aNotation.EqualsLiteral("updiagonalstrike")) {
mNotationsToDraw |= NOTATION_UPDIAGONALSTRIKE;
mNotationsToDraw += NOTATION_UPDIAGONALSTRIKE;
} else if (aNotation.EqualsLiteral("updiagonalarrow")) {
mNotationsToDraw |= NOTATION_UPDIAGONALARROW;
mNotationsToDraw += NOTATION_UPDIAGONALARROW;
} else if (aNotation.EqualsLiteral("downdiagonalstrike")) {
mNotationsToDraw |= NOTATION_DOWNDIAGONALSTRIKE;
mNotationsToDraw += NOTATION_DOWNDIAGONALSTRIKE;
} else if (aNotation.EqualsLiteral("verticalstrike")) {
mNotationsToDraw |= NOTATION_VERTICALSTRIKE;
mNotationsToDraw += NOTATION_VERTICALSTRIKE;
} else if (aNotation.EqualsLiteral("horizontalstrike")) {
mNotationsToDraw |= NOTATION_HORIZONTALSTRIKE;
mNotationsToDraw += NOTATION_HORIZONTALSTRIKE;
} else if (aNotation.EqualsLiteral("madruwb")) {
mNotationsToDraw |= (NOTATION_RIGHT | NOTATION_BOTTOM);
mNotationsToDraw += NOTATION_RIGHT;
mNotationsToDraw += NOTATION_BOTTOM;
} else if (aNotation.EqualsLiteral("phasorangle")) {
mNotationsToDraw |= (NOTATION_BOTTOM | NOTATION_PHASORANGLE);
mNotationsToDraw += NOTATION_BOTTOM;
mNotationsToDraw += NOTATION_PHASORANGLE;
}
return NS_OK;
@ -145,7 +150,7 @@ nsresult nsMathMLmencloseFrame::AddNotation(const nsAString& aNotation)
*/
void nsMathMLmencloseFrame::InitNotations()
{
mNotationsToDraw = 0;
mNotationsToDraw.clear();
mLongDivCharIndex = mRadicalCharIndex = -1;
mMathMLChar.Clear();
@ -163,13 +168,13 @@ void nsMathMLmencloseFrame::InitNotations()
// the two notations are drawn then the strike line may cause the point of
// the arrow to be too wide. Hence we will only draw the updiagonalarrow
// and the arrow shaft may be thought to be the updiagonalstrike.
mNotationsToDraw &= ~NOTATION_UPDIAGONALSTRIKE;
mNotationsToDraw -= NOTATION_UPDIAGONALSTRIKE;
}
} else {
// default: longdiv
if (NS_FAILED(AllocateMathMLChar(NOTATION_LONGDIV)))
return;
mNotationsToDraw = NOTATION_LONGDIV;
mNotationsToDraw += NOTATION_LONGDIV;
}
}
@ -220,7 +225,7 @@ nsMathMLmencloseFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
mMathMLChar[mRadicalCharIndex].GetRect(rect);
rect.MoveBy(StyleVisibility()->mDirection ? -mContentWidth : rect.width, 0);
rect.SizeTo(mContentWidth, mRadicalRuleThickness);
DisplayBar(aBuilder, this, rect, aLists);
DisplayBar(aBuilder, this, rect, aLists, NOTATION_RADICAL);
}
if (IsToDraw(NOTATION_PHASORANGLE)) {
@ -234,29 +239,29 @@ nsMathMLmencloseFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsRect rect;
mMathMLChar[mLongDivCharIndex].GetRect(rect);
rect.SizeTo(rect.width + mContentWidth, mRuleThickness);
DisplayBar(aBuilder, this, rect, aLists);
DisplayBar(aBuilder, this, rect, aLists, NOTATION_LONGDIV);
}
if (IsToDraw(NOTATION_TOP)) {
nsRect rect(0, 0, mencloseRect.width, mRuleThickness);
DisplayBar(aBuilder, this, rect, aLists);
DisplayBar(aBuilder, this, rect, aLists, NOTATION_TOP);
}
if (IsToDraw(NOTATION_BOTTOM)) {
nsRect rect(0, mencloseRect.height - mRuleThickness,
mencloseRect.width, mRuleThickness);
DisplayBar(aBuilder, this, rect, aLists);
DisplayBar(aBuilder, this, rect, aLists, NOTATION_BOTTOM);
}
if (IsToDraw(NOTATION_LEFT)) {
nsRect rect(0, 0, mRuleThickness, mencloseRect.height);
DisplayBar(aBuilder, this, rect, aLists);
DisplayBar(aBuilder, this, rect, aLists, NOTATION_LEFT);
}
if (IsToDraw(NOTATION_RIGHT)) {
nsRect rect(mencloseRect.width - mRuleThickness, 0,
mRuleThickness, mencloseRect.height);
DisplayBar(aBuilder, this, rect, aLists);
DisplayBar(aBuilder, this, rect, aLists, NOTATION_RIGHT);
}
if (IsToDraw(NOTATION_ROUNDEDBOX)) {
@ -287,13 +292,13 @@ nsMathMLmencloseFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
if (IsToDraw(NOTATION_HORIZONTALSTRIKE)) {
nsRect rect(0, mencloseRect.height / 2 - mRuleThickness / 2,
mencloseRect.width, mRuleThickness);
DisplayBar(aBuilder, this, rect, aLists);
DisplayBar(aBuilder, this, rect, aLists, NOTATION_HORIZONTALSTRIKE);
}
if (IsToDraw(NOTATION_VERTICALSTRIKE)) {
nsRect rect(mencloseRect.width / 2 - mRuleThickness / 2, 0,
mRuleThickness, mencloseRect.height);
DisplayBar(aBuilder, this, rect, aLists);
DisplayBar(aBuilder, this, rect, aLists, NOTATION_VERTICALSTRIKE);
}
}
@ -756,6 +761,10 @@ public:
}
#endif
virtual uint32_t GetPerFrameKey() override {
return (mType << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
}
virtual void Paint(nsDisplayListBuilder* aBuilder,
gfxContext* aCtx) override;
NS_DISPLAY_DECL_NAME("MathMLMencloseNotation", TYPE_MATHML_MENCLOSE_NOTATION)

View File

@ -8,6 +8,7 @@
#define nsMathMLmencloseFrame_h___
#include "mozilla/Attributes.h"
#include "mozilla/EnumSet.h"
#include "nsMathMLContainerFrame.h"
//
@ -26,20 +27,20 @@
enum nsMencloseNotation
{
NOTATION_LONGDIV = 0x1,
NOTATION_RADICAL = 0x2,
NOTATION_ROUNDEDBOX = 0x4,
NOTATION_CIRCLE = 0x8,
NOTATION_LEFT = 0x10,
NOTATION_RIGHT = 0x20,
NOTATION_TOP = 0x40,
NOTATION_BOTTOM = 0x80,
NOTATION_UPDIAGONALSTRIKE = 0x100,
NOTATION_DOWNDIAGONALSTRIKE = 0x200,
NOTATION_VERTICALSTRIKE = 0x400,
NOTATION_HORIZONTALSTRIKE = 0x800,
NOTATION_UPDIAGONALARROW = 0x1000,
NOTATION_PHASORANGLE = 0x2000
NOTATION_LONGDIV,
NOTATION_RADICAL,
NOTATION_ROUNDEDBOX,
NOTATION_CIRCLE,
NOTATION_LEFT,
NOTATION_RIGHT,
NOTATION_TOP,
NOTATION_BOTTOM,
NOTATION_UPDIAGONALSTRIKE,
NOTATION_DOWNDIAGONALSTRIKE,
NOTATION_VERTICALSTRIKE,
NOTATION_HORIZONTALSTRIKE,
NOTATION_UPDIAGONALARROW,
NOTATION_PHASORANGLE
};
class nsMathMLmencloseFrame : public nsMathMLContainerFrame {
@ -101,10 +102,10 @@ protected:
void InitNotations();
// Description of the notations to draw
uint32_t mNotationsToDraw;
bool IsToDraw(nsMencloseNotation mask)
mozilla::EnumSet<nsMencloseNotation> mNotationsToDraw;
bool IsToDraw(nsMencloseNotation notation)
{
return mask & mNotationsToDraw;
return mNotationsToDraw.contains(notation);
}
nscoord mRuleThickness;

View File

@ -34,7 +34,7 @@ nsMathMLmsqrtFrame::Init(nsIContent* aContent,
{
nsMathMLContainerFrame::Init(aContent, aParent, aPrevInFlow);
AllocateMathMLChar(NOTATION_RADICAL);
mNotationsToDraw |= NOTATION_RADICAL;
mNotationsToDraw += NOTATION_RADICAL;
}
NS_IMETHODIMP