Bug 1092222, part 4 - Port nsCSSRenderingBorders fill painting to use Moz2D directly. r=roc

This commit is contained in:
Jonathan Watt 2014-11-03 10:03:11 +00:00
Родитель abddfde232
Коммит ae74d98a1e
2 изменённых файлов: 51 добавлений и 57 удалений

Просмотреть файл

@ -42,10 +42,10 @@ using namespace mozilla::gfx;
* |- for each corner * |- for each corner
* |- clip to DoCornerClipSubPath * |- clip to DoCornerClipSubPath
* |- for each side adjacent to corner * |- for each side adjacent to corner
* |- clip to DoSideClipSubPath * |- clip to GetSideClipSubPath
* |- DrawBorderSides with one side * |- DrawBorderSides with one side
* |- for each side * |- for each side
* |- DoSideClipWithoutCornersSubPath * |- GetSideClipWithoutCornersRect
* |- DrawDashedSide || DrawBorderSides with one side * |- DrawDashedSide || DrawBorderSides with one side
*/ */
@ -124,7 +124,8 @@ nsCSSBorderRenderer::nsCSSBorderRenderer(gfxContext* aDestContext,
const nscolor* aBorderColors, const nscolor* aBorderColors,
nsBorderColors* const* aCompositeColors, nsBorderColors* const* aCompositeColors,
nscolor aBackgroundColor) nscolor aBackgroundColor)
: mContext(aDestContext), : mDrawTarget(aDestContext->GetDrawTarget()),
mContext(aDestContext),
mOuterRect(aOuterRect), mOuterRect(aOuterRect),
mBorderStyles(aBorderStyles), mBorderStyles(aBorderStyles),
mBorderWidths(aBorderWidths), mBorderWidths(aBorderWidths),
@ -334,8 +335,8 @@ nsCSSBorderRenderer::BorderColorStyleForSolidCorner(uint8_t aStyle, mozilla::css
return BorderColorStyleNone; return BorderColorStyleNone;
} }
void Rect
nsCSSBorderRenderer::DoCornerSubPath(mozilla::css::Corner aCorner) nsCSSBorderRenderer::GetCornerRect(mozilla::css::Corner aCorner)
{ {
Point offset(0.f, 0.f); Point offset(0.f, 0.f);
@ -344,12 +345,12 @@ nsCSSBorderRenderer::DoCornerSubPath(mozilla::css::Corner aCorner)
if (aCorner == C_BR || aCorner == C_BL) if (aCorner == C_BR || aCorner == C_BL)
offset.y = mOuterRect.Height() - mBorderCornerDimensions[aCorner].height; offset.y = mOuterRect.Height() - mBorderCornerDimensions[aCorner].height;
mContext->Rectangle(ThebesRect(Rect(mOuterRect.TopLeft() + offset, return Rect(mOuterRect.TopLeft() + offset,
mBorderCornerDimensions[aCorner]))); mBorderCornerDimensions[aCorner]);
} }
void Rect
nsCSSBorderRenderer::DoSideClipWithoutCornersSubPath(mozilla::css::Side aSide) nsCSSBorderRenderer::GetSideClipWithoutCornersRect(mozilla::css::Side aSide)
{ {
Point offset(0.f, 0.f); Point offset(0.f, 0.f);
@ -384,7 +385,7 @@ nsCSSBorderRenderer::DoSideClipWithoutCornersSubPath(mozilla::css::Side aSide)
else else
rect.width = mBorderWidths[aSide]; rect.width = mBorderWidths[aSide];
mContext->Rectangle(ThebesRect(rect)); return rect;
} }
// The side border type and the adjacent border types are // The side border type and the adjacent border types are
@ -441,8 +442,8 @@ MaybeMoveToMidPoint(Point& aP0, Point& aP1, const Point& aMidPoint)
} }
} }
void TemporaryRef<Path>
nsCSSBorderRenderer::DoSideClipSubPath(mozilla::css::Side aSide) nsCSSBorderRenderer::GetSideClipSubPath(mozilla::css::Side aSide)
{ {
// the clip proceeds clockwise from the top left corner; // the clip proceeds clockwise from the top left corner;
// so "start" in each case is the start of the region from that side. // so "start" in each case is the start of the region from that side.
@ -502,11 +503,13 @@ nsCSSBorderRenderer::DoSideClipSubPath(mozilla::css::Side aSide)
end[0] = Point(mOuterRect.CWCorner(aSide).x, mInnerRect.CWCorner(aSide).y); end[0] = Point(mOuterRect.CWCorner(aSide).x, mInnerRect.CWCorner(aSide).y);
} }
mContext->MoveTo(ThebesPoint(start[0])); RefPtr<PathBuilder> builder = mDrawTarget->CreatePathBuilder();
mContext->LineTo(ThebesPoint(end[0])); builder->MoveTo(start[0]);
mContext->LineTo(ThebesPoint(end[1])); builder->LineTo(end[0]);
mContext->LineTo(ThebesPoint(start[1])); builder->LineTo(end[1]);
mContext->ClosePath(); builder->LineTo(start[1]);
builder->Close();
return builder->Finish();
} }
void void
@ -517,8 +520,6 @@ nsCSSBorderRenderer::FillSolidBorder(const Rect& aOuterRect,
int aSides, int aSides,
const ColorPattern& aColor) const ColorPattern& aColor)
{ {
DrawTarget* drawTarget = mContext->GetDrawTarget();
// Note that this function is allowed to draw more than just the // Note that this function is allowed to draw more than just the
// requested sides. // requested sides.
@ -526,7 +527,7 @@ nsCSSBorderRenderer::FillSolidBorder(const Rect& aOuterRect,
// and fill, regardless of what sides we're asked to draw. // and fill, regardless of what sides we're asked to draw.
if (!AllCornersZeroSize(aBorderRadii)) { if (!AllCornersZeroSize(aBorderRadii)) {
RefPtr<PathBuilder> builder = RefPtr<PathBuilder> builder =
drawTarget->CreatePathBuilder(FillRule::FILL_EVEN_ODD); mDrawTarget->CreatePathBuilder(FillRule::FILL_EVEN_ODD);
RectCornerRadii innerRadii; RectCornerRadii innerRadii;
ComputeInnerRadii(aBorderRadii, aBorderSizes, &innerRadii); ComputeInnerRadii(aBorderRadii, aBorderSizes, &innerRadii);
@ -539,7 +540,7 @@ nsCSSBorderRenderer::FillSolidBorder(const Rect& aOuterRect,
RefPtr<Path> path = builder->Finish(); RefPtr<Path> path = builder->Finish();
drawTarget->Fill(path, aColor); mDrawTarget->Fill(path, aColor);
return; return;
} }
@ -555,7 +556,7 @@ nsCSSBorderRenderer::FillSolidBorder(const Rect& aOuterRect,
Float strokeWidth = aBorderSizes[0]; Float strokeWidth = aBorderSizes[0];
Rect r(aOuterRect); Rect r(aOuterRect);
r.Deflate(strokeWidth / 2.f); r.Deflate(strokeWidth / 2.f);
drawTarget->StrokeRect(r, aColor, StrokeOptions(strokeWidth)); mDrawTarget->StrokeRect(r, aColor, StrokeOptions(strokeWidth));
return; return;
} }
@ -620,8 +621,8 @@ nsCSSBorderRenderer::FillSolidBorder(const Rect& aOuterRect,
// Filling these one by one is faster than filling them all at once. // Filling these one by one is faster than filling them all at once.
for (uint32_t i = 0; i < 4; i++) { for (uint32_t i = 0; i < 4; i++) {
if (aSides & (1 << i)) { if (aSides & (1 << i)) {
MaybeSnapToDevicePixels(r[i], *drawTarget, true); MaybeSnapToDevicePixels(r[i], *mDrawTarget, true);
drawTarget->FillRect(r[i], aColor); mDrawTarget->FillRect(r[i], aColor);
} }
} }
} }
@ -1139,8 +1140,6 @@ nsCSSBorderRenderer::DrawSingleWidthSolidBorder()
void void
nsCSSBorderRenderer::DrawNoCompositeColorSolidBorder() nsCSSBorderRenderer::DrawNoCompositeColorSolidBorder()
{ {
DrawTarget *dt = mContext->GetDrawTarget();
const Float alpha = 0.55191497064665766025f; const Float alpha = 0.55191497064665766025f;
const twoFloats cornerMults[4] = { { -1, 0 }, const twoFloats cornerMults[4] = { { -1, 0 },
@ -1192,7 +1191,7 @@ nsCSSBorderRenderer::DrawNoCompositeColorSolidBorder()
secondColor = mBorderColors[i1]; secondColor = mBorderColors[i1];
} }
RefPtr<PathBuilder> builder = dt->CreatePathBuilder(); RefPtr<PathBuilder> builder = mDrawTarget->CreatePathBuilder();
Point strokeStart, strokeEnd; Point strokeStart, strokeEnd;
@ -1212,21 +1211,24 @@ nsCSSBorderRenderer::DrawNoCompositeColorSolidBorder()
builder->MoveTo(strokeStart); builder->MoveTo(strokeStart);
builder->LineTo(strokeEnd); builder->LineTo(strokeEnd);
RefPtr<Path> path = builder->Finish(); RefPtr<Path> path = builder->Finish();
dt->Stroke(path, ColorPattern(ToDeviceColor(mBorderColors[i])), StrokeOptions(mBorderWidths[i])); mDrawTarget->Stroke(path, ColorPattern(ToDeviceColor(mBorderColors[i])),
StrokeOptions(mBorderWidths[i]));
builder = nullptr; builder = nullptr;
path = nullptr; path = nullptr;
Pattern *pattern; Pattern *pattern;
if (firstColor != secondColor) { if (firstColor != secondColor) {
gradPat.mStops = CreateCornerGradient(c, firstColor, secondColor, dt, gradPat.mBegin, gradPat.mEnd); gradPat.mStops = CreateCornerGradient(c, firstColor, secondColor,
mDrawTarget, gradPat.mBegin,
gradPat.mEnd);
pattern = &gradPat; pattern = &gradPat;
} else { } else {
colorPat.mColor = ToDeviceColor(firstColor); colorPat.mColor = ToDeviceColor(firstColor);
pattern = &colorPat; pattern = &colorPat;
} }
builder = dt->CreatePathBuilder(); builder = mDrawTarget->CreatePathBuilder();
if (mBorderRadii[c].width > 0 && mBorderRadii[c].height > 0) { if (mBorderRadii[c].width > 0 && mBorderRadii[c].height > 0) {
p0.x = pc.x + cornerMults[i].a * mBorderRadii[c].width; p0.x = pc.x + cornerMults[i].a * mBorderRadii[c].width;
@ -1271,7 +1273,7 @@ nsCSSBorderRenderer::DrawNoCompositeColorSolidBorder()
builder->BezierTo(p2, p1, p0); builder->BezierTo(p2, p1, p0);
builder->Close(); builder->Close();
path = builder->Finish(); path = builder->Finish();
dt->Fill(path, *pattern); mDrawTarget->Fill(path, *pattern);
} else { } else {
Point c1, c2, c3, c4; Point c1, c2, c3, c4;
@ -1289,7 +1291,7 @@ nsCSSBorderRenderer::DrawNoCompositeColorSolidBorder()
path = builder->Finish(); path = builder->Finish();
dt->Fill(path, *pattern); mDrawTarget->Fill(path, *pattern);
} }
} }
} }
@ -1329,11 +1331,9 @@ nsCSSBorderRenderer::DrawRectangularCompositeColors()
mContext->LineTo(ThebesPoint(secondCorner)); mContext->LineTo(ThebesPoint(secondCorner));
mContext->Stroke(); mContext->Stroke();
mContext->NewPath();
Point cornerTopLeft = rect.CWCorner(side); Point cornerTopLeft = rect.CWCorner(side);
cornerTopLeft.x -= 0.5; cornerTopLeft.x -= 0.5;
cornerTopLeft.y -= 0.5; cornerTopLeft.y -= 0.5;
mContext->Rectangle(ThebesRect(Rect(cornerTopLeft, Size(1, 1))));
Color nextColor = Color::FromABGR( Color nextColor = Color::FromABGR(
currentColors[sideNext] ? currentColors[sideNext]->mColor currentColors[sideNext] ? currentColors[sideNext]->mColor
: mBorderColors[sideNext]); : mBorderColors[sideNext]);
@ -1342,8 +1342,8 @@ nsCSSBorderRenderer::DrawRectangularCompositeColors()
(currentColor.g + nextColor.g) / 2.f, (currentColor.g + nextColor.g) / 2.f,
(currentColor.b + nextColor.b) / 2.f, (currentColor.b + nextColor.b) / 2.f,
(currentColor.a + nextColor.a) / 2.f); (currentColor.a + nextColor.a) / 2.f);
mContext->SetColor(ThebesColor(cornerColor)); mDrawTarget->FillRect(Rect(cornerTopLeft, Size(1, 1)),
mContext->Fill(); ColorPattern(ToDeviceColor(cornerColor)));
if (side != 0) { if (side != 0) {
// We'll have to keep side 0 for the color averaging on side 3. // We'll have to keep side 0 for the color averaging on side 3.
@ -1363,8 +1363,6 @@ nsCSSBorderRenderer::DrawRectangularCompositeColors()
void void
nsCSSBorderRenderer::DrawBorders() nsCSSBorderRenderer::DrawBorders()
{ {
DrawTarget* drawTarget = mContext->GetDrawTarget();
bool forceSeparateCorners = false; bool forceSeparateCorners = false;
// Examine the border style to figure out if we can draw it in one // Examine the border style to figure out if we can draw it in one
@ -1495,11 +1493,11 @@ nsCSSBorderRenderer::DrawBorders()
// the rounded parts are elipses we can offset exactly and can just compute // the rounded parts are elipses we can offset exactly and can just compute
// a new cubic approximation. // a new cubic approximation.
RefPtr<PathBuilder> builder = RefPtr<PathBuilder> builder =
drawTarget->CreatePathBuilder(FillRule::FILL_EVEN_ODD); mDrawTarget->CreatePathBuilder(FillRule::FILL_EVEN_ODD);
AppendRoundedRectToPath(builder, mOuterRect, mBorderRadii, true); AppendRoundedRectToPath(builder, mOuterRect, mBorderRadii, true);
AppendRoundedRectToPath(builder, ToRect(borderInnerRect.rect), borderInnerRect.corners, false); AppendRoundedRectToPath(builder, ToRect(borderInnerRect.rect), borderInnerRect.corners, false);
RefPtr<Path> path = builder->Finish(); RefPtr<Path> path = builder->Finish();
drawTarget->Fill(path, color); mDrawTarget->Fill(path, color);
} }
bool hasCompositeColors; bool hasCompositeColors;
@ -1628,22 +1626,18 @@ nsCSSBorderRenderer::DrawBorders()
IsZeroSize(mBorderRadii[corner]) && IsZeroSize(mBorderRadii[corner]) &&
IsSolidCornerStyle(mBorderStyles[sides[0]], corner)) IsSolidCornerStyle(mBorderStyles[sides[0]], corner))
{ {
mContext->NewPath();
DoCornerSubPath(corner);
Color color = MakeBorderColor(mBorderColors[sides[0]], Color color = MakeBorderColor(mBorderColors[sides[0]],
mBackgroundColor, mBackgroundColor,
BorderColorStyleForSolidCorner(mBorderStyles[sides[0]], corner)); BorderColorStyleForSolidCorner(mBorderStyles[sides[0]], corner));
mContext->SetColor(ThebesColor(color)); mDrawTarget->FillRect(GetCornerRect(corner),
mContext->Fill(); ColorPattern(ToDeviceColor(color)));
continue; continue;
} }
mContext->Save(); mContext->Save();
// clip to the corner // clip to the corner
mContext->NewPath(); mContext->Clip(GetCornerRect(corner));
DoCornerSubPath(corner);
mContext->Clip();
if (simpleCornerStyle) { if (simpleCornerStyle) {
// we don't need a group for this corner, the sides are the same, // we don't need a group for this corner, the sides are the same,
@ -1669,9 +1663,8 @@ nsCSSBorderRenderer::DrawBorders()
mContext->Save(); mContext->Save();
mContext->NewPath(); RefPtr<Path> path = GetSideClipSubPath(side);
DoSideClipSubPath(side); mContext->Clip(path);
mContext->Clip();
DrawBorderSides(1 << side); DrawBorderSides(1 << side);
@ -1738,9 +1731,7 @@ nsCSSBorderRenderer::DrawBorders()
// draws one side and not the corners, because then we can // draws one side and not the corners, because then we can
// avoid the potentially expensive clip. // avoid the potentially expensive clip.
mContext->Save(); mContext->Save();
mContext->NewPath(); mContext->Clip(GetSideClipWithoutCornersRect(side));
DoSideClipWithoutCornersSubPath(side);
mContext->Clip();
DrawBorderSides(1 << side); DrawBorderSides(1 << side);

Просмотреть файл

@ -77,7 +77,9 @@ typedef enum {
struct nsCSSBorderRenderer { struct nsCSSBorderRenderer {
typedef mozilla::gfx::ColorPattern ColorPattern; typedef mozilla::gfx::ColorPattern ColorPattern;
typedef mozilla::gfx::DrawTarget DrawTarget;
typedef mozilla::gfx::Float Float; typedef mozilla::gfx::Float Float;
typedef mozilla::gfx::Path Path;
typedef mozilla::gfx::Rect Rect; typedef mozilla::gfx::Rect Rect;
typedef mozilla::gfx::RectCornerRadii RectCornerRadii; typedef mozilla::gfx::RectCornerRadii RectCornerRadii;
@ -93,6 +95,7 @@ struct nsCSSBorderRenderer {
RectCornerRadii mBorderCornerDimensions; RectCornerRadii mBorderCornerDimensions;
// destination context // destination context
DrawTarget* mDrawTarget;
gfxContext* mContext; gfxContext* mContext;
// the rectangle of the outside and the inside of the border // the rectangle of the outside and the inside of the border
@ -130,10 +133,10 @@ struct nsCSSBorderRenderer {
// Path generation functions // Path generation functions
// //
// add the path for drawing the given corner to the context // Get the Rect for drawing the given corner
void DoCornerSubPath(mozilla::css::Corner aCorner); Rect GetCornerRect(mozilla::css::Corner aCorner);
// add the path for drawing the given side without any adjacent corners to the context // add the path for drawing the given side without any adjacent corners to the context
void DoSideClipWithoutCornersSubPath(mozilla::css::Side aSide); Rect GetSideClipWithoutCornersRect(mozilla::css::Side aSide);
// Create a clip path for the wedge that this side of // Create a clip path for the wedge that this side of
// the border should take up. This is only called // the border should take up. This is only called
@ -143,7 +146,7 @@ struct nsCSSBorderRenderer {
// This code needs to make sure that the individual pieces // This code needs to make sure that the individual pieces
// don't ever (mathematically) overlap; the pixel overlap // don't ever (mathematically) overlap; the pixel overlap
// is taken care of by the ADD compositing. // is taken care of by the ADD compositing.
void DoSideClipSubPath(mozilla::css::Side aSide); mozilla::TemporaryRef<Path> GetSideClipSubPath(mozilla::css::Side aSide);
// Given a set of sides to fill and a color, do so in the fastest way. // Given a set of sides to fill and a color, do so in the fastest way.
// //