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

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

@ -77,7 +77,9 @@ typedef enum {
struct nsCSSBorderRenderer {
typedef mozilla::gfx::ColorPattern ColorPattern;
typedef mozilla::gfx::DrawTarget DrawTarget;
typedef mozilla::gfx::Float Float;
typedef mozilla::gfx::Path Path;
typedef mozilla::gfx::Rect Rect;
typedef mozilla::gfx::RectCornerRadii RectCornerRadii;
@ -93,6 +95,7 @@ struct nsCSSBorderRenderer {
RectCornerRadii mBorderCornerDimensions;
// destination context
DrawTarget* mDrawTarget;
gfxContext* mContext;
// the rectangle of the outside and the inside of the border
@ -130,10 +133,10 @@ struct nsCSSBorderRenderer {
// Path generation functions
//
// add the path for drawing the given corner to the context
void DoCornerSubPath(mozilla::css::Corner aCorner);
// Get the Rect for drawing the given corner
Rect GetCornerRect(mozilla::css::Corner aCorner);
// 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
// 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
// don't ever (mathematically) overlap; the pixel overlap
// 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.
//