зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1319626 - Part 3: Refactor nsCSSRendering border painting so callers can access the border renderer. r=mstange
--HG-- extra : rebase_source : 8ce157b743e13578a6ae06fc58f40e4b58c75241
This commit is contained in:
Родитель
1985af695f
Коммит
8203047d48
|
@ -673,14 +673,142 @@ nsCSSRendering::PaintBorder(nsPresContext* aPresContext,
|
|||
nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_color)[side]);
|
||||
newStyleBorder.mBorderColor[side] = StyleComplexColor::FromColor(color);
|
||||
}
|
||||
DrawResult result =
|
||||
PaintBorderWithStyleBorder(aPresContext, aRenderingContext, aForFrame,
|
||||
aDirtyRect, aBorderArea, newStyleBorder,
|
||||
aStyleContext, aFlags, aSkipSides);
|
||||
|
||||
return result;
|
||||
return PaintBorderWithStyleBorder(aPresContext, aRenderingContext, aForFrame,
|
||||
aDirtyRect, aBorderArea, newStyleBorder,
|
||||
aStyleContext, aFlags, aSkipSides);
|
||||
}
|
||||
|
||||
Maybe<nsCSSBorderRenderer>
|
||||
nsCSSRendering::CreateBorderRenderer(nsPresContext* aPresContext,
|
||||
DrawTarget* aDrawTarget,
|
||||
nsIFrame* aForFrame,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsRect& aBorderArea,
|
||||
nsStyleContext* aStyleContext,
|
||||
Sides aSkipSides)
|
||||
{
|
||||
nsStyleContext *styleIfVisited = aStyleContext->GetStyleIfVisited();
|
||||
const nsStyleBorder *styleBorder = aStyleContext->StyleBorder();
|
||||
// Don't check RelevantLinkVisited here, since we want to take the
|
||||
// same amount of time whether or not it's true.
|
||||
if (!styleIfVisited) {
|
||||
return CreateBorderRendererWithStyleBorder(aPresContext, aDrawTarget,
|
||||
aForFrame, aDirtyRect,
|
||||
aBorderArea, *styleBorder,
|
||||
aStyleContext, aSkipSides);
|
||||
}
|
||||
|
||||
nsStyleBorder newStyleBorder(*styleBorder);
|
||||
|
||||
NS_FOR_CSS_SIDES(side) {
|
||||
nscolor color = aStyleContext->GetVisitedDependentColor(
|
||||
nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_color)[side]);
|
||||
newStyleBorder.mBorderColor[side] = StyleComplexColor::FromColor(color);
|
||||
}
|
||||
return CreateBorderRendererWithStyleBorder(aPresContext, aDrawTarget,
|
||||
aForFrame, aDirtyRect, aBorderArea,
|
||||
newStyleBorder, aStyleContext,
|
||||
aSkipSides);
|
||||
}
|
||||
|
||||
nsCSSBorderRenderer
|
||||
ConstructBorderRenderer(nsPresContext* aPresContext,
|
||||
nsStyleContext* aStyleContext,
|
||||
DrawTarget* aDrawTarget,
|
||||
nsIFrame* aForFrame,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsRect& aBorderArea,
|
||||
const nsStyleBorder& aStyleBorder,
|
||||
Sides aSkipSides,
|
||||
bool* aNeedsClip)
|
||||
{
|
||||
nsMargin border = aStyleBorder.GetComputedBorder();
|
||||
|
||||
// Get our style context's color struct.
|
||||
const nsStyleColor* ourColor = aStyleContext->StyleColor();
|
||||
|
||||
// In NavQuirks mode we want to use the parent's context as a starting point
|
||||
// for determining the background color.
|
||||
bool quirks = aPresContext->CompatibilityMode() == eCompatibility_NavQuirks;
|
||||
nsIFrame* bgFrame = nsCSSRendering::FindNonTransparentBackgroundFrame(aForFrame, quirks);
|
||||
nsStyleContext* bgContext = bgFrame->StyleContext();
|
||||
nscolor bgColor =
|
||||
bgContext->GetVisitedDependentColor(eCSSProperty_background_color);
|
||||
|
||||
// Compute the outermost boundary of the area that might be painted.
|
||||
// Same coordinate space as aBorderArea & aBGClipRect.
|
||||
nsRect joinedBorderArea =
|
||||
::BoxDecorationRectForBorder(aForFrame, aBorderArea, aSkipSides, &aStyleBorder);
|
||||
RectCornerRadii bgRadii;
|
||||
::GetRadii(aForFrame, aStyleBorder, aBorderArea, joinedBorderArea, &bgRadii);
|
||||
|
||||
PrintAsFormatString(" joinedBorderArea: %d %d %d %d\n", joinedBorderArea.x, joinedBorderArea.y,
|
||||
joinedBorderArea.width, joinedBorderArea.height);
|
||||
|
||||
// start drawing
|
||||
if (::IsBoxDecorationSlice(aStyleBorder)) {
|
||||
if (joinedBorderArea.IsEqualEdges(aBorderArea)) {
|
||||
// No need for a clip, just skip the sides we don't want.
|
||||
border.ApplySkipSides(aSkipSides);
|
||||
} else {
|
||||
// We're drawing borders around the joined continuation boxes so we need
|
||||
// to clip that to the slice that we want for this frame.
|
||||
*aNeedsClip = true;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(joinedBorderArea.IsEqualEdges(aBorderArea),
|
||||
"Should use aBorderArea for box-decoration-break:clone");
|
||||
MOZ_ASSERT(aForFrame->GetSkipSides().IsEmpty() ||
|
||||
IS_TRUE_OVERFLOW_CONTAINER(aForFrame),
|
||||
"Should not skip sides for box-decoration-break:clone except "
|
||||
"::first-letter/line continuations or other frame types that "
|
||||
"don't have borders but those shouldn't reach this point. "
|
||||
"Overflow containers do reach this point though.");
|
||||
border.ApplySkipSides(aSkipSides);
|
||||
}
|
||||
|
||||
// Convert to dev pixels.
|
||||
nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
|
||||
Rect joinedBorderAreaPx = NSRectToRect(joinedBorderArea, twipsPerPixel);
|
||||
Float borderWidths[4] = { Float(border.top / twipsPerPixel),
|
||||
Float(border.right / twipsPerPixel),
|
||||
Float(border.bottom / twipsPerPixel),
|
||||
Float(border.left / twipsPerPixel) };
|
||||
Rect dirtyRect = NSRectToRect(aDirtyRect, twipsPerPixel);
|
||||
|
||||
uint8_t borderStyles[4];
|
||||
nscolor borderColors[4];
|
||||
nsBorderColors* compositeColors[4];
|
||||
|
||||
// pull out styles, colors, composite colors
|
||||
NS_FOR_CSS_SIDES (i) {
|
||||
borderStyles[i] = aStyleBorder.GetBorderStyle(i);
|
||||
borderColors[i] = ourColor->CalcComplexColor(aStyleBorder.mBorderColor[i]);
|
||||
aStyleBorder.GetCompositeColors(i, &compositeColors[i]);
|
||||
}
|
||||
|
||||
PrintAsFormatString(" borderStyles: %d %d %d %d\n", borderStyles[0], borderStyles[1], borderStyles[2], borderStyles[3]);
|
||||
|
||||
nsIDocument* document = nullptr;
|
||||
nsIContent* content = aForFrame->GetContent();
|
||||
if (content) {
|
||||
document = content->OwnerDoc();
|
||||
}
|
||||
|
||||
return nsCSSBorderRenderer(aPresContext,
|
||||
document,
|
||||
aDrawTarget,
|
||||
dirtyRect,
|
||||
joinedBorderAreaPx,
|
||||
borderStyles,
|
||||
borderWidths,
|
||||
bgRadii,
|
||||
borderColors,
|
||||
compositeColors,
|
||||
bgColor);
|
||||
}
|
||||
|
||||
|
||||
DrawResult
|
||||
nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
|
@ -724,17 +852,6 @@ nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
|||
result = DrawResult::NOT_READY;
|
||||
}
|
||||
|
||||
// Get our style context's color struct.
|
||||
const nsStyleColor* ourColor = aStyleContext->StyleColor();
|
||||
|
||||
// In NavQuirks mode we want to use the parent's context as a starting point
|
||||
// for determining the background color.
|
||||
bool quirks = aPresContext->CompatibilityMode() == eCompatibility_NavQuirks;
|
||||
nsIFrame* bgFrame = FindNonTransparentBackgroundFrame(aForFrame, quirks);
|
||||
nsStyleContext* bgContext = bgFrame->StyleContext();
|
||||
nscolor bgColor =
|
||||
bgContext->GetVisitedDependentColor(eCSSProperty_background_color);
|
||||
|
||||
nsMargin border = aStyleBorder.GetComputedBorder();
|
||||
if (0 == border.left && 0 == border.right &&
|
||||
0 == border.top && 0 == border.bottom) {
|
||||
|
@ -742,93 +859,27 @@ nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
|||
return result;
|
||||
}
|
||||
|
||||
// Compute the outermost boundary of the area that might be painted.
|
||||
// Same coordinate space as aBorderArea & aBGClipRect.
|
||||
nsRect joinedBorderArea =
|
||||
::BoxDecorationRectForBorder(aForFrame, aBorderArea, aSkipSides, &aStyleBorder);
|
||||
RectCornerRadii bgRadii;
|
||||
::GetRadii(aForFrame, aStyleBorder, aBorderArea, joinedBorderArea, &bgRadii);
|
||||
bool needsClip = false;
|
||||
nsCSSBorderRenderer br = ConstructBorderRenderer(aPresContext,
|
||||
aStyleContext,
|
||||
&aDrawTarget,
|
||||
aForFrame,
|
||||
aDirtyRect,
|
||||
aBorderArea,
|
||||
aStyleBorder,
|
||||
aSkipSides,
|
||||
&needsClip);
|
||||
|
||||
PrintAsFormatString(" joinedBorderArea: %d %d %d %d\n", joinedBorderArea.x, joinedBorderArea.y,
|
||||
joinedBorderArea.width, joinedBorderArea.height);
|
||||
|
||||
// start drawing
|
||||
bool needToPopClip = false;
|
||||
|
||||
if (::IsBoxDecorationSlice(aStyleBorder)) {
|
||||
if (joinedBorderArea.IsEqualEdges(aBorderArea)) {
|
||||
// No need for a clip, just skip the sides we don't want.
|
||||
border.ApplySkipSides(aSkipSides);
|
||||
} else {
|
||||
// We're drawing borders around the joined continuation boxes so we need
|
||||
// to clip that to the slice that we want for this frame.
|
||||
aDrawTarget.PushClipRect(
|
||||
if (needsClip) {
|
||||
aDrawTarget.PushClipRect(
|
||||
NSRectToSnappedRect(aBorderArea,
|
||||
aForFrame->PresContext()->AppUnitsPerDevPixel(),
|
||||
aDrawTarget));
|
||||
needToPopClip = true;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(joinedBorderArea.IsEqualEdges(aBorderArea),
|
||||
"Should use aBorderArea for box-decoration-break:clone");
|
||||
MOZ_ASSERT(aForFrame->GetSkipSides().IsEmpty() ||
|
||||
IS_TRUE_OVERFLOW_CONTAINER(aForFrame),
|
||||
"Should not skip sides for box-decoration-break:clone except "
|
||||
"::first-letter/line continuations or other frame types that "
|
||||
"don't have borders but those shouldn't reach this point. "
|
||||
"Overflow containers do reach this point though.");
|
||||
border.ApplySkipSides(aSkipSides);
|
||||
}
|
||||
|
||||
// Convert to dev pixels.
|
||||
nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
|
||||
Rect joinedBorderAreaPx = NSRectToRect(joinedBorderArea, twipsPerPixel);
|
||||
Float borderWidths[4] = { Float(border.top / twipsPerPixel),
|
||||
Float(border.right / twipsPerPixel),
|
||||
Float(border.bottom / twipsPerPixel),
|
||||
Float(border.left / twipsPerPixel) };
|
||||
Rect dirtyRect = NSRectToRect(aDirtyRect, twipsPerPixel);
|
||||
|
||||
uint8_t borderStyles[4];
|
||||
nscolor borderColors[4];
|
||||
nsBorderColors *compositeColors[4];
|
||||
|
||||
// pull out styles, colors, composite colors
|
||||
NS_FOR_CSS_SIDES (i) {
|
||||
borderStyles[i] = aStyleBorder.GetBorderStyle(i);
|
||||
borderColors[i] = ourColor->CalcComplexColor(aStyleBorder.mBorderColor[i]);
|
||||
aStyleBorder.GetCompositeColors(i, &compositeColors[i]);
|
||||
}
|
||||
|
||||
PrintAsFormatString(" borderStyles: %d %d %d %d\n", borderStyles[0], borderStyles[1], borderStyles[2], borderStyles[3]);
|
||||
//PrintAsFormatString ("bgRadii: %f %f %f %f\n", bgRadii[0], bgRadii[1], bgRadii[2], bgRadii[3]);
|
||||
|
||||
#if 0
|
||||
// this will draw a transparent red backround underneath the border area
|
||||
ColorPattern color(ToDeviceColor(Color(1.f, 0.f, 0.f, 0.5f)));
|
||||
aDrawTarget.FillRect(joinedBorderAreaPx, color);
|
||||
#endif
|
||||
|
||||
nsIDocument* document = nullptr;
|
||||
nsIContent* content = aForFrame->GetContent();
|
||||
if (content) {
|
||||
document = content->OwnerDoc();
|
||||
}
|
||||
|
||||
nsCSSBorderRenderer br(aPresContext,
|
||||
document,
|
||||
&aDrawTarget,
|
||||
dirtyRect,
|
||||
joinedBorderAreaPx,
|
||||
borderStyles,
|
||||
borderWidths,
|
||||
bgRadii,
|
||||
borderColors,
|
||||
compositeColors,
|
||||
bgColor);
|
||||
br.DrawBorders();
|
||||
|
||||
if (needToPopClip) {
|
||||
if (needsClip) {
|
||||
aDrawTarget.PopClip();
|
||||
}
|
||||
|
||||
|
@ -837,6 +888,53 @@ nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
|||
return result;
|
||||
}
|
||||
|
||||
Maybe<nsCSSBorderRenderer>
|
||||
nsCSSRendering::CreateBorderRendererWithStyleBorder(nsPresContext* aPresContext,
|
||||
DrawTarget* aDrawTarget,
|
||||
nsIFrame* aForFrame,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsRect& aBorderArea,
|
||||
const nsStyleBorder& aStyleBorder,
|
||||
nsStyleContext* aStyleContext,
|
||||
Sides aSkipSides)
|
||||
{
|
||||
const nsStyleDisplay* displayData = aStyleContext->StyleDisplay();
|
||||
if (displayData->mAppearance) {
|
||||
nsITheme *theme = aPresContext->GetTheme();
|
||||
if (theme &&
|
||||
theme->ThemeSupportsWidget(aPresContext, aForFrame,
|
||||
displayData->mAppearance)) {
|
||||
return Nothing();
|
||||
}
|
||||
}
|
||||
|
||||
if (aStyleBorder.mBorderImageSource.GetType() != eStyleImageType_Null) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
nsMargin border = aStyleBorder.GetComputedBorder();
|
||||
if (0 == border.left && 0 == border.right &&
|
||||
0 == border.top && 0 == border.bottom) {
|
||||
// Empty border area
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
bool needsClip = false;
|
||||
nsCSSBorderRenderer br = ConstructBorderRenderer(aPresContext,
|
||||
aStyleContext,
|
||||
aDrawTarget,
|
||||
aForFrame,
|
||||
aDirtyRect,
|
||||
aBorderArea,
|
||||
aStyleBorder,
|
||||
aSkipSides,
|
||||
&needsClip);
|
||||
if (needsClip) {
|
||||
return Nothing();
|
||||
}
|
||||
return Some(br);
|
||||
}
|
||||
|
||||
static nsRect
|
||||
GetOutlineInnerRect(nsIFrame* aFrame)
|
||||
{
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "nsLayoutUtils.h"
|
||||
#include "nsStyleStruct.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsCSSRenderingBorders.h"
|
||||
|
||||
class gfxDrawable;
|
||||
class nsStyleContext;
|
||||
|
@ -416,6 +417,25 @@ struct nsCSSRendering {
|
|||
mozilla::PaintBorderFlags aFlags,
|
||||
Sides aSkipSides = Sides());
|
||||
|
||||
static mozilla::Maybe<nsCSSBorderRenderer>
|
||||
CreateBorderRenderer(nsPresContext* aPresContext,
|
||||
DrawTarget* aDrawTarget,
|
||||
nsIFrame* aForFrame,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsRect& aBorderArea,
|
||||
nsStyleContext* aStyleContext,
|
||||
Sides aSkipSides = Sides());
|
||||
|
||||
static mozilla::Maybe<nsCSSBorderRenderer>
|
||||
CreateBorderRendererWithStyleBorder(nsPresContext* aPresContext,
|
||||
DrawTarget* aDrawTarget,
|
||||
nsIFrame* aForFrame,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsRect& aBorderArea,
|
||||
const nsStyleBorder& aBorderStyle,
|
||||
nsStyleContext* aStyleContext,
|
||||
Sides aSkipSides = Sides());
|
||||
|
||||
|
||||
/**
|
||||
* Render the outline for an element using css rendering rules
|
||||
|
|
|
@ -106,8 +106,8 @@ IsZeroSize(const Size& sz) {
|
|||
return sz.width == 0.0 || sz.height == 0.0;
|
||||
}
|
||||
|
||||
static bool
|
||||
AllCornersZeroSize(const RectCornerRadii& corners) {
|
||||
/* static */ bool
|
||||
nsCSSBorderRenderer::AllCornersZeroSize(const RectCornerRadii& corners) {
|
||||
return IsZeroSize(corners[NS_CORNER_TOP_LEFT]) &&
|
||||
IsZeroSize(corners[NS_CORNER_TOP_RIGHT]) &&
|
||||
IsZeroSize(corners[NS_CORNER_BOTTOM_RIGHT]) &&
|
||||
|
@ -182,16 +182,17 @@ nsCSSBorderRenderer::nsCSSBorderRenderer(nsPresContext* aPresContext,
|
|||
mDrawTarget(aDrawTarget),
|
||||
mDirtyRect(aDirtyRect),
|
||||
mOuterRect(aOuterRect),
|
||||
mBorderStyles(aBorderStyles),
|
||||
mBorderWidths(aBorderWidths),
|
||||
mBorderRadii(aBorderRadii),
|
||||
mBorderColors(aBorderColors),
|
||||
mCompositeColors(aCompositeColors),
|
||||
mBackgroundColor(aBackgroundColor)
|
||||
{
|
||||
if (!mCompositeColors) {
|
||||
PodCopy(mBorderStyles, aBorderStyles, 4);
|
||||
PodCopy(mBorderWidths, aBorderWidths, 4);
|
||||
PodCopy(mBorderColors, aBorderColors, 4);
|
||||
if (aCompositeColors) {
|
||||
PodCopy(mCompositeColors, aCompositeColors, 4);
|
||||
} else {
|
||||
static nsBorderColors * const noColors[4] = { nullptr };
|
||||
mCompositeColors = &noColors[0];
|
||||
PodCopy(mCompositeColors, noColors, 4);
|
||||
}
|
||||
|
||||
mInnerRect = mOuterRect;
|
||||
|
@ -271,7 +272,7 @@ ComputeBorderCornerDimensions(const Float* aBorderWidths,
|
|||
Float rightWidth = aBorderWidths[eSideRight];
|
||||
Float bottomWidth = aBorderWidths[eSideBottom];
|
||||
|
||||
if (AllCornersZeroSize(aRadii)) {
|
||||
if (nsCSSBorderRenderer::AllCornersZeroSize(aRadii)) {
|
||||
// These will always be in pixel units from CSS
|
||||
(*aDimsRet)[C_TL] = Size(leftWidth, topWidth);
|
||||
(*aDimsRet)[C_TR] = Size(rightWidth, topWidth);
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
#include "nsColor.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsStyleStruct.h"
|
||||
#include "nsPresContext.h"
|
||||
|
||||
struct nsBorderColors;
|
||||
class nsDisplayBorder;
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
@ -75,6 +77,8 @@ class nsCSSBorderRenderer final
|
|||
typedef mozilla::gfx::RectCornerRadii RectCornerRadii;
|
||||
typedef mozilla::gfx::StrokeOptions StrokeOptions;
|
||||
|
||||
friend class nsDisplayBorder;
|
||||
|
||||
public:
|
||||
|
||||
nsCSSBorderRenderer(nsPresContext* aPresContext,
|
||||
|
@ -105,6 +109,8 @@ public:
|
|||
const Float* aBorderSizes,
|
||||
RectCornerRadii* aOuterRadiiRet);
|
||||
|
||||
static bool AllCornersZeroSize(const RectCornerRadii& corners);
|
||||
|
||||
private:
|
||||
|
||||
RectCornerRadii mBorderCornerDimensions;
|
||||
|
@ -115,20 +121,20 @@ private:
|
|||
|
||||
// destination DrawTarget and dirty rect
|
||||
DrawTarget* mDrawTarget;
|
||||
const Rect& mDirtyRect;
|
||||
const Rect mDirtyRect;
|
||||
|
||||
// the rectangle of the outside and the inside of the border
|
||||
Rect mOuterRect;
|
||||
Rect mInnerRect;
|
||||
|
||||
// the style and size of the border
|
||||
const uint8_t* mBorderStyles;
|
||||
const Float* mBorderWidths;
|
||||
uint8_t mBorderStyles[4];
|
||||
Float mBorderWidths[4];
|
||||
RectCornerRadii mBorderRadii;
|
||||
|
||||
// colors
|
||||
const nscolor* mBorderColors;
|
||||
nsBorderColors* const* mCompositeColors;
|
||||
nscolor mBorderColors[4];
|
||||
nsBorderColors* mCompositeColors[4];
|
||||
|
||||
// the background color
|
||||
nscolor mBackgroundColor;
|
||||
|
|
Загрузка…
Ссылка в новой задаче