summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-12 01:50:29 +0000
committerbrettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-12 01:50:29 +0000
commit4fbca13f3478efb8652b4438951de4865e53c705 (patch)
tree51bfb51593a7de74d599c5ebb5995d5cfc1de8e5
parentb18cac7c944156edce33426ea5199466936c8e51 (diff)
downloadchromium_src-4fbca13f3478efb8652b4438951de4865e53c705.zip
chromium_src-4fbca13f3478efb8652b4438951de4865e53c705.tar.gz
chromium_src-4fbca13f3478efb8652b4438951de4865e53c705.tar.bz2
Cleanup style and alphabetize the functions in GraphicsContextSkia. It should
be much closer to WebKit style, and you can actually find the functions now. Review URL: http://codereview.chromium.org/10407 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5249 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--webkit/port/platform/graphics/GraphicsContextSkia.cpp970
1 files changed, 497 insertions, 473 deletions
diff --git a/webkit/port/platform/graphics/GraphicsContextSkia.cpp b/webkit/port/platform/graphics/GraphicsContextSkia.cpp
index 4c3f045..78ed6ce 100644
--- a/webkit/port/platform/graphics/GraphicsContextSkia.cpp
+++ b/webkit/port/platform/graphics/GraphicsContextSkia.cpp
@@ -1,16 +1,16 @@
/*
** Copyright 2006, Google Inc.
**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
**
-** http://www.apache.org/licenses/LICENSE-2.0
+** http://www.apache.org/licenses/LICENSE-2.0
**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
** limitations under the License.
*/
@@ -20,7 +20,6 @@
#include "GraphicsContext.h"
#include "GraphicsContextPlatformPrivate.h"
#include "GraphicsContextPrivate.h"
-#include "wtf/MathExtras.h"
#include "Assertions.h"
#include "AffineTransform.h"
@@ -30,11 +29,11 @@
#include "IntRect.h"
#include "NativeImageSkia.h"
#include "NotImplemented.h"
+#include "SkBitmap.h"
#include "SkBlurDrawLooper.h"
#include "SkCornerPathEffect.h"
#include "SkiaUtils.h"
-
-#include "SkBitmap.h"
+#include "wtf/MathExtras.h"
#include "base/gfx/platform_canvas.h"
@@ -115,23 +114,23 @@ bool IsPathReasonable(const SkMatrix& transform, const SkPath& path)
verb = iter.next(current_points)) {
switch (verb) {
case SkPath::kMove_Verb:
- // This move will be duplicated in the next verb, so we can ignore it.
+ // This move will be duplicated in the next verb, so we can ignore.
break;
case SkPath::kLine_Verb:
- // iter.next returns 2 points
+ // iter.next returns 2 points.
if (!IsPointReasonable(transform, current_points[0]) ||
!IsPointReasonable(transform, current_points[1]))
return false;
break;
case SkPath::kQuad_Verb:
- // iter.next returns 3 points
+ // iter.next returns 3 points.
if (!IsPointReasonable(transform, current_points[0]) ||
!IsPointReasonable(transform, current_points[1]) ||
!IsPointReasonable(transform, current_points[2]))
return false;
break;
case SkPath::kCubic_Verb:
- // iter.next returns 4 points
+ // iter.next returns 4 points.
if (!IsPointReasonable(transform, current_points[0]) ||
!IsPointReasonable(transform, current_points[1]) ||
!IsPointReasonable(transform, current_points[2]) ||
@@ -152,19 +151,31 @@ bool IsPathReasonable(const SkMatrix& transform, const SkPath& path)
// Local helper functions ------------------------------------------------------
-void add_corner_arc(SkPath* path, const SkRect& rect, const IntSize& size, int startAngle)
+void addCornerArc(SkPath* path,
+ const SkRect& rect,
+ const IntSize& size,
+ int startAngle)
{
- SkIRect ir;
- int rx = SkMin32(SkScalarRound(rect.width()), size.width());
- int ry = SkMin32(SkScalarRound(rect.height()), size.height());
-
+ SkIRect ir;
+ int rx = SkMin32(SkScalarRound(rect.width()), size.width());
+ int ry = SkMin32(SkScalarRound(rect.height()), size.height());
+
ir.set(-rx, -ry, rx, ry);
switch (startAngle) {
- case 0: ir.offset(rect.fRight - ir.fRight, rect.fBottom - ir.fBottom); break;
- case 90: ir.offset(rect.fLeft - ir.fLeft, rect.fBottom - ir.fBottom); break;
- case 180: ir.offset(rect.fLeft - ir.fLeft, rect.fTop - ir.fTop); break;
- case 270: ir.offset(rect.fRight - ir.fRight, rect.fTop - ir.fTop); break;
- default: SkASSERT(!"unexpected startAngle in add_corner_arc");
+ case 0:
+ ir.offset(rect.fRight - ir.fRight, rect.fBottom - ir.fBottom);
+ break;
+ case 90:
+ ir.offset(rect.fLeft - ir.fLeft, rect.fBottom - ir.fBottom);
+ break;
+ case 180:
+ ir.offset(rect.fLeft - ir.fLeft, rect.fTop - ir.fTop);
+ break;
+ case 270:
+ ir.offset(rect.fRight - ir.fRight, rect.fTop - ir.fTop);
+ break;
+ default:
+ ASSERT(0);
}
SkRect r;
@@ -172,9 +183,24 @@ void add_corner_arc(SkPath* path, const SkRect& rect, const IntSize& size, int s
path->arcTo(r, SkIntToScalar(startAngle), SkIntToScalar(90), false);
}
+inline int fastMod(int value, int max)
+{
+ int sign = SkExtractSign(value);
+
+ value = SkApplySign(value, sign);
+ if (value >= max)
+ value %= max;
+ return SkApplySign(value, sign);
+}
+
+inline float square(float n)
+{
+ return n * n;
}
-////////////////////////////////////////////////////////////////////////////////////////////////
+} // namespace
+
+// -----------------------------------------------------------------------------
// This may be called with a NULL pointer to create a graphics context that has
// no painting.
@@ -191,6 +217,14 @@ GraphicsContext::~GraphicsContext()
this->destroyGraphicsContextPrivate(m_common);
}
+PlatformGraphicsContext* GraphicsContext::platformContext() const
+{
+ ASSERT(!paintingDisabled());
+ return m_data->context();
+}
+
+// State saving ----------------------------------------------------------------
+
void GraphicsContext::savePlatformState()
{
if (paintingDisabled())
@@ -209,21 +243,257 @@ void GraphicsContext::restorePlatformState()
platformContext()->restore();
}
-// Draws a filled rectangle with a stroked border.
-void GraphicsContext::drawRect(const IntRect& rect)
+void GraphicsContext::beginTransparencyLayer(float opacity)
+{
+ if (paintingDisabled())
+ return;
+
+ // We need the "alpha" layer flag here because the base layer is opaque
+ // (the surface of the page) but layers on top may have transparent parts.
+ // Without explicitly setting the alpha flag, the layer will inherit the
+ // opaque setting of the base and some things won't work properly.
+ platformContext()->canvas()->saveLayerAlpha(
+ 0,
+ static_cast<unsigned char>(opacity * 255),
+ static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag |
+ SkCanvas::kFullColorLayer_SaveFlag));
+}
+
+void GraphicsContext::endTransparencyLayer()
+{
+ if (paintingDisabled())
+ return;
+
+#if PLATFORM(WIN_OS)
+ platformContext()->canvas()->getTopPlatformDevice().
+ fixupAlphaBeforeCompositing();
+#endif
+ platformContext()->canvas()->restore();
+}
+
+// Graphics primitives ---------------------------------------------------------
+
+void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
+{
+ if (paintingDisabled())
+ return;
+
+ SkRect r(rect);
+ if (!IsRectReasonable(getCTM(), r))
+ return;
+
+ SkPath path;
+ path.addOval(r, SkPath::kCW_Direction);
+ // only perform the inset if we won't invert r
+ if (2 * thickness < rect.width() && 2 * thickness < rect.height()) {
+ r.inset(SkIntToScalar(thickness) ,SkIntToScalar(thickness));
+ path.addOval(r, SkPath::kCCW_Direction);
+ }
+ platformContext()->canvas()->clipPath(path);
+}
+
+void GraphicsContext::addPath(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+ platformContext()->addPath(*path.platformPath());
+}
+
+void GraphicsContext::beginPath()
+{
+ if (paintingDisabled())
+ return;
+ platformContext()->beginPath();
+}
+
+void GraphicsContext::clearPlatformShadow()
+{
+ if (paintingDisabled())
+ return;
+ platformContext()->setDrawLooper(0);
+}
+
+void GraphicsContext::clearRect(const FloatRect& rect)
{
if (paintingDisabled())
return;
SkRect r = rect;
- if (!IsRectReasonable(getCTM(), r)) {
- // See the fillRect below.
+ if (!IsRectReasonable(getCTM(), r))
ClipRectToCanvas(*platformContext()->canvas(), r, &r);
+
+ SkPaint paint;
+ platformContext()->setupPaintForFilling(&paint);
+ paint.setPorterDuffXfermode(SkPorterDuff::kClear_Mode);
+ platformContext()->canvas()->drawRect(r, paint);
+}
+
+void GraphicsContext::clip(const FloatRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ SkRect r(rect);
+ if (!IsRectReasonable(getCTM(), r))
+ return;
+
+ platformContext()->canvas()->clipRect(r);
+}
+
+void GraphicsContext::clip(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+
+ const SkPath& p = *path.platformPath();
+ if (!IsPathReasonable(getCTM(), p))
+ return;
+
+ platformContext()->canvas()->clipPath(p);
+}
+
+void GraphicsContext::clipOut(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ SkRect r(rect);
+ if (!IsRectReasonable(getCTM(), r))
+ return;
+
+ platformContext()->canvas()->clipRect(r, SkRegion::kDifference_Op);
+}
+
+void GraphicsContext::clipOut(const Path& p)
+{
+ if (paintingDisabled())
+ return;
+
+ const SkPath& path = *p.platformPath();
+ if (!IsPathReasonable(getCTM(), path))
+ return;
+
+ platformContext()->canvas()->clipPath(path, SkRegion::kDifference_Op);
+}
+
+void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ SkRect oval(rect);
+ if (!IsRectReasonable(getCTM(), oval))
+ return;
+
+ SkPath path;
+ path.addOval(oval, SkPath::kCCW_Direction);
+ platformContext()->canvas()->clipPath(path, SkRegion::kDifference_Op);
+}
+
+void GraphicsContext::clipToImageBuffer(const FloatRect& rect,
+ const ImageBuffer* imageBuffer)
+{
+ if (paintingDisabled())
+ return;
+
+ // TODO(eseidel): This is needed for image masking and complex text fills.
+ notImplemented();
+}
+
+void GraphicsContext::concatCTM(const AffineTransform& xform)
+{
+ if (paintingDisabled())
+ return;
+ platformContext()->canvas()->concat(xform);
+}
+
+void GraphicsContext::drawConvexPolygon(size_t numPoints,
+ const FloatPoint* points,
+ bool shouldAntialias)
+{
+ if (paintingDisabled())
+ return;
+
+ if (numPoints <= 1)
+ return;
+
+ SkPath path;
+
+ path.incReserve(numPoints);
+ path.moveTo(WebCoreFloatToSkScalar(points[0].x()),
+ WebCoreFloatToSkScalar(points[0].y()));
+ for (size_t i = 1; i < numPoints; i++) {
+ path.lineTo(WebCoreFloatToSkScalar(points[i].x()),
+ WebCoreFloatToSkScalar(points[i].y()));
}
- platformContext()->drawRect(r);
+ if (!IsPathReasonable(getCTM(), path))
+ return;
+
+ SkPaint paint;
+ if (fillColor().rgb() & 0xFF000000) {
+ platformContext()->setupPaintForFilling(&paint);
+ platformContext()->canvas()->drawPath(path, paint);
+ }
+
+ if (strokeStyle() != NoStroke) {
+ paint.reset();
+ platformContext()->setupPaintForStroking(&paint, 0, 0);
+ platformContext()->canvas()->drawPath(path, paint);
+ }
+}
+
+// This method is only used to draw the little circles used in lists.
+void GraphicsContext::drawEllipse(const IntRect& elipseRect)
+{
+ if (paintingDisabled())
+ return;
+
+ SkRect rect = elipseRect;
+ if (!IsRectReasonable(getCTM(), rect))
+ return;
+
+ SkPaint paint;
+ if (fillColor().rgb() & 0xFF000000) {
+ platformContext()->setupPaintForFilling(&paint);
+ platformContext()->canvas()->drawOval(rect, paint);
+ }
+ if (strokeStyle() != NoStroke) {
+ paint.reset();
+ platformContext()->setupPaintForStroking(&paint, &rect, 0);
+ platformContext()->canvas()->drawOval(rect, paint);
+ }
+}
+
+void GraphicsContext::drawFocusRing(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+ const Vector<IntRect>& rects = focusRingRects();
+ unsigned rectCount = rects.size();
+ if (0 == rectCount)
+ return;
+
+ SkRegion exterior_region;
+ const SkScalar exterior_offset = WebCoreFloatToSkScalar(0.5);
+ for (unsigned i = 0; i < rectCount; i++) {
+ SkIRect r = rects[i];
+ r.inset(-exterior_offset, -exterior_offset);
+ exterior_region.op(r, SkRegion::kUnion_Op);
+ }
+
+ SkPath path;
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+
+ paint.setColor(focusRingColor().rgb());
+ paint.setStrokeWidth(exterior_offset * 2);
+ paint.setPathEffect(new SkCornerPathEffect(exterior_offset * 2))->unref();
+ exterior_region.getBoundaryPath(&path);
+ platformContext()->canvas()->drawPath(path, paint);
}
-
+
// This is only used to draw borders.
void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
{
@@ -240,57 +510,33 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
!IsPointReasonable(getCTM(), pts[1]))
return;
- //we know these are vertical or horizontal lines, so the length will just be the sum of the
- //displacement component vectors give or take 1 - probably worth the speed up of no square
- //root, which also won't be exact
+ // We know these are vertical or horizontal lines, so the length will just
+ // be the sum of the displacement component vectors give or take 1 -
+ // probably worth the speed up of no square root, which also won't be exact.
SkPoint disp = pts[1] - pts[0];
int length = SkScalarRound(disp.fX + disp.fY);
int width = roundf(
platformContext()->setupPaintForStroking(&paint, 0, length));
-
- // "borrowed" this comment and idea from GraphicsContextCG.cpp
- // For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic
- // works out. For example, with a border width of 3, KHTML will pass us (y1+y2)/2, e.g.,
- // (50+53)/2 = 103/2 = 51 when we want 51.5. It is always true that an even width gave
- // us a perfect position, but an odd width gave us a position that is off by exactly 0.5.
-
+
+ // "Borrowed" this comment and idea from GraphicsContextCG.cpp
+ // For odd widths, we add in 0.5 to the appropriate x/y so that the float
+ // arithmetic works out. For example, with a border width of 3, KHTML will
+ // pass us (y1+y2)/2, e.g., (50+53)/2 = 103/2 = 51 when we want 51.5. It is
+ // always true that an even width gave us a perfect position, but an odd
+ // width gave us a position that is off by exactly 0.5.
bool isVerticalLine = pts[0].fX == pts[1].fX;
-
- if (width & 1) //odd
- {
+
+ if (width & 1) { // Odd.
if (isVerticalLine) {
pts[0].fX = pts[0].fX + SK_ScalarHalf;
pts[1].fX = pts[0].fX;
- } else //Horizontal line
- {
+ } else { // Horizontal line
pts[0].fY = pts[0].fY + SK_ScalarHalf;
pts[1].fY = pts[0].fY;
}
}
- platformContext()->canvas()->drawPoints(SkCanvas::kLines_PointMode, 2, pts, paint);
-}
-
-static void setrect_for_underline(SkRect* r, GraphicsContext* context, const IntPoint& point, int width)
-{
- int lineThickness = SkMax32(static_cast<int>(context->strokeThickness()), 1);
-
- r->fLeft = SkIntToScalar(point.x());
- r->fTop = SkIntToScalar(point.y());
- r->fRight = r->fLeft + SkIntToScalar(width);
- r->fBottom = r->fTop + SkIntToScalar(lineThickness);
-}
-
-void GraphicsContext::drawLineForText(const IntPoint& pt, int width, bool printing)
-{
- if (paintingDisabled())
- return;
-
- SkRect r;
- SkPaint paint;
-
- setrect_for_underline(&r, this, pt, width);
- paint.setColor(this->strokeColor().rgb());
- platformContext()->canvas()->drawRect(r, paint);
+ platformContext()->canvas()->drawPoints(
+ SkCanvas::kLines_PointMode, 2, pts, paint);
}
void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& pt,
@@ -370,94 +616,38 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& pt,
platformContext()->canvas()->drawRect(rect, paint);
}
-// This method is only used to draw the little circles used in lists.
-void GraphicsContext::drawEllipse(const IntRect& elipseRect)
+void GraphicsContext::drawLineForText(const IntPoint& pt,
+ int width,
+ bool printing)
{
if (paintingDisabled())
return;
- SkRect rect = elipseRect;
- if (!IsRectReasonable(getCTM(), rect))
- return;
-
- SkPaint paint;
- if (fillColor().rgb() & 0xFF000000) {
- platformContext()->setupPaintForFilling(&paint);
- platformContext()->canvas()->drawOval(rect, paint);
- }
- if (strokeStyle() != NoStroke) {
- paint.reset();
- platformContext()->setupPaintForStroking(&paint, &rect, 0);
- platformContext()->canvas()->drawOval(rect, paint);
- }
-}
-
-static inline int fast_mod(int value, int max)
-{
- int sign = SkExtractSign(value);
-
- value = SkApplySign(value, sign);
- if (value >= max) {
- value %= max;
- }
- return SkApplySign(value, sign);
-}
-
-void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan)
-{
- if (paintingDisabled())
- return;
+ int thickness = SkMax32(static_cast<int>(strokeThickness()), 1);
+ SkRect r;
+ r.fLeft = SkIntToScalar(pt.x());
+ r.fTop = SkIntToScalar(pt.y());
+ r.fRight = r.fLeft + SkIntToScalar(width);
+ r.fBottom = r.fTop + SkIntToScalar(thickness);
SkPaint paint;
- SkRect oval = r;
-
- if (strokeStyle() == NoStroke) {
- platformContext()->setupPaintForFilling(&paint); // We want the fill color.
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(WebCoreFloatToSkScalar(strokeThickness()));
- } else
- platformContext()->setupPaintForStroking(&paint, 0, 0);
-
- // we do this before converting to scalar, so we don't overflow SkFixed
- startAngle = fast_mod(startAngle, 360);
- angleSpan = fast_mod(angleSpan, 360);
-
- SkPath path;
- path.addArc(oval, SkIntToScalar(-startAngle), SkIntToScalar(-angleSpan));
- if (!IsPathReasonable(getCTM(), path))
- return;
- platformContext()->canvas()->drawPath(path, paint);
+ paint.setColor(this->strokeColor().rgb());
+ platformContext()->canvas()->drawRect(r, paint);
}
-void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias)
+// Draws a filled rectangle with a stroked border.
+void GraphicsContext::drawRect(const IntRect& rect)
{
if (paintingDisabled())
return;
- if (numPoints <= 1)
- return;
-
- SkPath path;
-
- path.incReserve(numPoints);
- path.moveTo(WebCoreFloatToSkScalar(points[0].x()), WebCoreFloatToSkScalar(points[0].y()));
- for (size_t i = 1; i < numPoints; i++)
- path.lineTo(WebCoreFloatToSkScalar(points[i].x()), WebCoreFloatToSkScalar(points[i].y()));
-
- if (!IsPathReasonable(getCTM(), path))
- return;
-
- SkPaint paint;
- if (fillColor().rgb() & 0xFF000000) {
- platformContext()->setupPaintForFilling(&paint);
- platformContext()->canvas()->drawPath(path, paint);
+ SkRect r = rect;
+ if (!IsRectReasonable(getCTM(), r)) {
+ // See the fillRect below.
+ ClipRectToCanvas(*platformContext()->canvas(), r, &r);
}
- if (strokeStyle() != NoStroke) {
- paint.reset();
- platformContext()->setupPaintForStroking(&paint, 0, 0);
- platformContext()->canvas()->drawPath(path, paint);
- }
+ platformContext()->drawRect(r);
}
void GraphicsContext::fillPath()
@@ -475,7 +665,7 @@ void GraphicsContext::fillPath()
return;
platformContext()->setFillRule(state.fillRule == RULE_EVENODD ?
- SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
+ SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
SkPaint paint;
platformContext()->setupPaintForFilling(&paint);
@@ -490,33 +680,6 @@ void GraphicsContext::fillPath()
platformContext()->canvas()->drawPath(path, paint);
}
-void GraphicsContext::strokePath()
-{
- if (paintingDisabled())
- return;
- const SkPath& path = *platformContext()->currentPath();
- if (!IsPathReasonable(getCTM(), path))
- return;
-
- const GraphicsContextState& state = m_common->state;
- ColorSpace colorSpace = state.strokeColorSpace;
-
- if (colorSpace == SolidColorSpace && !strokeColor().alpha())
- return;
-
- SkPaint paint;
- platformContext()->setupPaintForStroking(&paint, 0, 0);
-
- if (colorSpace == PatternColorSpace) {
- SkShader* pat = state.strokePattern->createPlatformPattern(getCTM());
- paint.setShader(pat);
- pat->unref();
- } else if (colorSpace == GradientColorSpace)
- paint.setShader(state.strokeGradient->platformGradient());
-
- platformContext()->canvas()->drawPath(path, paint);
-}
-
void GraphicsContext::fillRect(const FloatRect& rect)
{
if (paintingDisabled())
@@ -547,40 +710,13 @@ void GraphicsContext::fillRect(const FloatRect& rect)
platformContext()->canvas()->drawRect(r, paint);
}
-void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
-{
- if (paintingDisabled())
- return;
- if (!IsRectReasonable(getCTM(), rect))
- return;
-
- const GraphicsContextState& state = m_common->state;
- ColorSpace colorSpace = state.strokeColorSpace;
-
- if (colorSpace == SolidColorSpace && !strokeColor().alpha())
- return;
-
- SkPaint paint;
- platformContext()->setupPaintForStroking(&paint, 0, 0);
- paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth));
-
- if (colorSpace == PatternColorSpace) {
- SkShader* pat = state.strokePattern->createPlatformPattern(getCTM());
- paint.setShader(pat);
- pat->unref();
- } else if (colorSpace == GradientColorSpace)
- paint.setShader(state.strokeGradient->platformGradient());
-
- platformContext()->canvas()->drawRect(rect, paint);
-}
-
void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
{
if (paintingDisabled())
return;
if (color.rgb() & 0xFF000000) {
- SkRect r = rect;
+ SkRect r = rect;
if (!IsRectReasonable(getCTM(), r)) {
// Special case when the rectangle overflows fixed point. This is a
// workaround to fix bug 1212844. When the input rectangle is very
@@ -602,8 +738,12 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
}
}
-void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
- const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
+void GraphicsContext::fillRoundedRect(const IntRect& rect,
+ const IntSize& topLeft,
+ const IntSize& topRight,
+ const IntSize& bottomLeft,
+ const IntSize& bottomRight,
+ const Color& color)
{
if (paintingDisabled())
return;
@@ -614,11 +754,11 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
ClipRectToCanvas(*platformContext()->canvas(), r, &r);
}
- SkPath path;
- add_corner_arc(&path, r, topRight, 270);
- add_corner_arc(&path, r, bottomRight, 0);
- add_corner_arc(&path, r, bottomLeft, 90);
- add_corner_arc(&path, r, topLeft, 180);
+ SkPath path;
+ addCornerArc(&path, r, topRight, 270);
+ addCornerArc(&path, r, bottomRight, 0);
+ addCornerArc(&path, r, bottomLeft, 90);
+ addCornerArc(&path, r, topLeft, 180);
SkPaint paint;
platformContext()->setupPaintForFilling(&paint);
@@ -626,192 +766,59 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
return fillRect(rect, color);
}
-void GraphicsContext::clip(const FloatRect& rect)
-{
- if (paintingDisabled())
- return;
-
- SkRect r(rect);
- if (!IsRectReasonable(getCTM(), r))
- return;
-
- platformContext()->canvas()->clipRect(r);
-}
-
-void GraphicsContext::clip(const Path& path)
-{
- if (paintingDisabled())
- return;
-
- const SkPath& p = *path.platformPath();
- if (!IsPathReasonable(getCTM(), p))
- return;
-
- platformContext()->canvas()->clipPath(p);
-}
-
-void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
-{
- if (paintingDisabled())
- return;
-
- SkRect r(rect);
- if (!IsRectReasonable(getCTM(), r))
- return;
-
- SkPath path;
- path.addOval(r, SkPath::kCW_Direction);
- // only perform the inset if we won't invert r
- if (2*thickness < rect.width() && 2*thickness < rect.height()) {
- r.inset(SkIntToScalar(thickness) ,SkIntToScalar(thickness));
- path.addOval(r, SkPath::kCCW_Direction);
- }
- platformContext()->canvas()->clipPath(path);
-}
-
-
-void GraphicsContext::clipOut(const IntRect& rect)
-{
- if (paintingDisabled())
- return;
-
- SkRect r(rect);
- if (!IsRectReasonable(getCTM(), r))
- return;
-
- platformContext()->canvas()->clipRect(r, SkRegion::kDifference_Op);
-}
-
-void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
-{
- if (paintingDisabled())
- return;
-
- SkRect oval(rect);
- if (!IsRectReasonable(getCTM(), oval))
- return;
-
- SkPath path;
- path.addOval(oval, SkPath::kCCW_Direction);
- platformContext()->canvas()->clipPath(path, SkRegion::kDifference_Op);
-}
-
-void GraphicsContext::clipOut(const Path& p)
-{
- if (paintingDisabled())
- return;
-
- const SkPath& path = *p.platformPath();
- if (!IsPathReasonable(getCTM(), path))
- return;
-
- platformContext()->canvas()->clipPath(path, SkRegion::kDifference_Op);
-}
-
-void GraphicsContext::beginTransparencyLayer(float opacity)
-{
- if (paintingDisabled())
- return;
-
- // We need the "alpha" layer flag here because the base layer is opaque
- // (the surface of the page) but layers on top may have transparent parts.
- // Without explicitly setting the alpha flag, the layer will inherit the
- // opaque setting of the base and some things won't work properly.
- platformContext()->canvas()->saveLayerAlpha(
- 0,
- static_cast<unsigned char>(opacity * 255),
- static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag |
- SkCanvas::kFullColorLayer_SaveFlag));
-}
-
-void GraphicsContext::endTransparencyLayer()
-{
- if (paintingDisabled())
- return;
-
-#if PLATFORM(WIN_OS)
- platformContext()->canvas()->getTopPlatformDevice().fixupAlphaBeforeCompositing();
-#endif
- platformContext()->canvas()->restore();
-}
-
-void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& stroke)
+AffineTransform GraphicsContext::getCTM() const
{
- if (paintingDisabled())
- return;
- platformContext()->setStrokeStyle(stroke);
+ return platformContext()->canvas()->getTotalMatrix();
}
-void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color)
+FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
{
- if (paintingDisabled())
- return;
+ // This logic is copied from GraphicsContextCG, eseidel 5/05/08
- if (blur > 0) {
- SkColor c;
-
- if (color.isValid())
- c = color.rgb();
- else
- c = SkColorSetARGB(0xFF/3, 0, 0, 0); // "std" apple shadow color
-
- SkDrawLooper* dl = new SkBlurDrawLooper(SkIntToScalar(blur),
- SkIntToScalar(size.width()),
- SkIntToScalar(size.height()),
- c);
- platformContext()->setDrawLooper(dl);
- dl->unref();
- } else
- platformContext()->setDrawLooper(0);
-}
+ // It is not enough just to round to pixels in device space. The rotation
+ // part of the affine transform matrix to device space can mess with this
+ // conversion if we have a rotating image like the hands of the world clock
+ // widget. We just need the scale, so we get the affine transform matrix and
+ // extract the scale.
-void GraphicsContext::clearPlatformShadow()
-{
- if (paintingDisabled())
- return;
- platformContext()->setDrawLooper(0);
-}
+ const SkMatrix& deviceMatrix =
+ platformContext()->canvas()->getTotalMatrix();
+ if (deviceMatrix.isIdentity())
+ return rect;
-void GraphicsContext::drawFocusRing(const Color& color)
-{
- if (paintingDisabled())
- return;
- const Vector<IntRect>& rects = focusRingRects();
- unsigned rectCount = rects.size();
- if (0 == rectCount)
- return;
+ float deviceScaleX = sqrtf(square(deviceMatrix.getScaleX())
+ + square(deviceMatrix.getSkewY()));
+ float deviceScaleY = sqrtf(square(deviceMatrix.getSkewX())
+ + square(deviceMatrix.getScaleY()));
- SkRegion exterior_region;
- const SkScalar exterior_offset = WebCoreFloatToSkScalar(0.5);
- for (unsigned i = 0; i < rectCount; i++) {
- SkIRect r = rects[i];
- r.inset(-exterior_offset, -exterior_offset);
- exterior_region.op(r, SkRegion::kUnion_Op);
- }
+ FloatPoint deviceOrigin(rect.x() * deviceScaleX, rect.y() * deviceScaleY);
+ FloatPoint deviceLowerRight((rect.x() + rect.width()) * deviceScaleX,
+ (rect.y() + rect.height()) * deviceScaleY);
- SkPath path;
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
+ deviceOrigin.setX(roundf(deviceOrigin.x()));
+ deviceOrigin.setY(roundf(deviceOrigin.y()));
+ deviceLowerRight.setX(roundf(deviceLowerRight.x()));
+ deviceLowerRight.setY(roundf(deviceLowerRight.y()));
- paint.setColor(focusRingColor().rgb());
- paint.setStrokeWidth(exterior_offset * 2);
- paint.setPathEffect(new SkCornerPathEffect(exterior_offset * 2))->unref();
- exterior_region.getBoundaryPath(&path);
- platformContext()->canvas()->drawPath(path, paint);
-}
+ // Don't let the height or width round to 0 unless either was originally 0
+ if (deviceOrigin.y() == deviceLowerRight.y() && rect.height() != 0)
+ deviceLowerRight.move(0, 1);
+ if (deviceOrigin.x() == deviceLowerRight.x() && rect.width() != 0)
+ deviceLowerRight.move(1, 0);
-PlatformGraphicsContext* GraphicsContext::platformContext() const
-{
- ASSERT(!paintingDisabled());
- return m_data->context();
+ FloatPoint roundedOrigin(deviceOrigin.x() / deviceScaleX,
+ deviceOrigin.y() / deviceScaleY);
+ FloatPoint roundedLowerRight(deviceLowerRight.x() / deviceScaleX,
+ deviceLowerRight.y() / deviceScaleY);
+ return FloatRect(roundedOrigin, roundedLowerRight - roundedOrigin);
}
-void GraphicsContext::setMiterLimit(float limit)
+void GraphicsContext::scale(const FloatSize& size)
{
if (paintingDisabled())
return;
- platformContext()->setMiterLimit(limit);
+ platformContext()->canvas()->scale(WebCoreFloatToSkScalar(size.width()),
+ WebCoreFloatToSkScalar(size.height()));
}
void GraphicsContext::setAlpha(float alpha)
@@ -828,19 +835,9 @@ void GraphicsContext::setCompositeOperation(CompositeOperator op)
platformContext()->setPorterDuffMode(WebCoreCompositeToSkiaComposite(op));
}
-void GraphicsContext::clearRect(const FloatRect& rect)
+void GraphicsContext::setImageInterpolationQuality(InterpolationQuality)
{
- if (paintingDisabled())
- return;
-
- SkRect r = rect;
- if (!IsRectReasonable(getCTM(), r))
- ClipRectToCanvas(*platformContext()->canvas(), r, &r);
-
- SkPaint paint;
- platformContext()->setupPaintForFilling(&paint);
- paint.setPorterDuffXfermode(SkPorterDuff::kClear_Mode);
- platformContext()->canvas()->drawRect(r, paint);
+ notImplemented();
}
void GraphicsContext::setLineCap(LineCap cap)
@@ -858,7 +855,7 @@ void GraphicsContext::setLineCap(LineCap cap)
platformContext()->setLineCap(SkPaint::kSquare_Cap);
break;
default:
- SkDEBUGF(("GraphicsContext::setLineCap: unknown LineCap %d\n", cap));
+ ASSERT(0);
break;
}
}
@@ -877,7 +874,7 @@ void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
size_t count = (dashLength % 2) == 0 ? dashLength : dashLength * 2;
SkScalar* intervals = new SkScalar[count];
- for(unsigned int i = 0; i < count; i++)
+ for (unsigned int i = 0; i < count; i++)
intervals[i] = dashes[i % dashLength];
platformContext()->setDashPathEffect(new SkDashPathEffect(intervals,
@@ -901,155 +898,182 @@ void GraphicsContext::setLineJoin(LineJoin join)
platformContext()->setLineJoin(SkPaint::kBevel_Join);
break;
default:
- SkDEBUGF(("GraphicsContext::setLineJoin: unknown LineJoin %d\n", join));
+ ASSERT(0);
break;
}
}
-void GraphicsContext::scale(const FloatSize& size)
+void GraphicsContext::setMiterLimit(float limit)
{
if (paintingDisabled())
return;
- platformContext()->canvas()->scale(WebCoreFloatToSkScalar(size.width()), WebCoreFloatToSkScalar(size.height()));
+ platformContext()->setMiterLimit(limit);
}
-void GraphicsContext::rotate(float angleInRadians)
+void GraphicsContext::setPlatformFillColor(const Color& color)
{
if (paintingDisabled())
return;
- platformContext()->canvas()->rotate(WebCoreFloatToSkScalar(angleInRadians * (180.0f / 3.14159265f)));
+ platformContext()->setFillColor(color.rgb());
}
-void GraphicsContext::translate(float w, float h)
+void GraphicsContext::setPlatformShadow(const IntSize& size,
+ int blur,
+ const Color& color)
{
if (paintingDisabled())
return;
- platformContext()->canvas()->translate(WebCoreFloatToSkScalar(w), WebCoreFloatToSkScalar(h));
+
+ if (blur > 0) {
+ SkColor c;
+ if (color.isValid())
+ c = color.rgb();
+ else
+ c = SkColorSetARGB(0xFF/3, 0, 0, 0); // "std" apple shadow color.
+ SkDrawLooper* dl = new SkBlurDrawLooper(SkIntToScalar(blur),
+ SkIntToScalar(size.width()),
+ SkIntToScalar(size.height()),
+ c);
+ platformContext()->setDrawLooper(dl);
+ dl->unref();
+ } else
+ platformContext()->setDrawLooper(0);
}
-void GraphicsContext::concatCTM(const AffineTransform& xform)
+void GraphicsContext::setPlatformStrokeColor(const Color& strokecolor)
{
if (paintingDisabled())
return;
- platformContext()->canvas()->concat(xform);
+ platformContext()->setStrokeColor(strokecolor.rgb());
}
-AffineTransform GraphicsContext::getCTM() const
+void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& stroke)
{
- return platformContext()->canvas()->getTotalMatrix();
+ if (paintingDisabled())
+ return;
+ platformContext()->setStrokeStyle(stroke);
}
-static inline float square(float n)
+void GraphicsContext::setPlatformStrokeThickness(float thickness)
{
- return n * n;
+ if (paintingDisabled())
+ return;
+ platformContext()->setStrokeThickness(thickness);
}
-FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
+void GraphicsContext::setPlatformTextDrawingMode(int mode)
{
- // This logic is copied from GraphicsContextCG, eseidel 5/05/08
-
- // It is not enough just to round to pixels in device space. The rotation
- // part of the affine transform matrix to device space can mess with this
- // conversion if we have a rotating image like the hands of the world clock
- // widget. We just need the scale, so we get the affine transform matrix and
- // extract the scale.
-
- const SkMatrix& deviceMatrix = platformContext()->canvas()->getTotalMatrix();
- if (deviceMatrix.isIdentity())
- return rect;
-
- float deviceScaleX = sqrtf(square(deviceMatrix.getScaleX())
- + square(deviceMatrix.getSkewY()));
- float deviceScaleY = sqrtf(square(deviceMatrix.getSkewX())
- + square(deviceMatrix.getScaleY()));
-
- FloatPoint deviceOrigin(rect.x() * deviceScaleX, rect.y() * deviceScaleY);
- FloatPoint deviceLowerRight((rect.x() + rect.width()) * deviceScaleX,
- (rect.y() + rect.height()) * deviceScaleY);
-
- deviceOrigin.setX(roundf(deviceOrigin.x()));
- deviceOrigin.setY(roundf(deviceOrigin.y()));
- deviceLowerRight.setX(roundf(deviceLowerRight.x()));
- deviceLowerRight.setY(roundf(deviceLowerRight.y()));
-
- // Don't let the height or width round to 0 unless either was originally 0
- if (deviceOrigin.y() == deviceLowerRight.y() && rect.height() != 0)
- deviceLowerRight.move(0, 1);
- if (deviceOrigin.x() == deviceLowerRight.x() && rect.width() != 0)
- deviceLowerRight.move(1, 0);
-
- FloatPoint roundedOrigin(deviceOrigin.x() / deviceScaleX,
- deviceOrigin.y() / deviceScaleY);
- FloatPoint roundedLowerRight(deviceLowerRight.x() / deviceScaleX,
- deviceLowerRight.y() / deviceScaleY);
- return FloatRect(roundedOrigin, roundedLowerRight - roundedOrigin);
+ if (paintingDisabled())
+ return;
+ platformContext()->setTextDrawingMode(mode);
}
void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
{
}
-void GraphicsContext::setPlatformFillColor(const Color& color)
+void GraphicsContext::setUseAntialiasing(bool enable)
{
if (paintingDisabled())
return;
- platformContext()->setFillColor(color.rgb());
+ platformContext()->setUseAntialiasing(enable);
}
-void GraphicsContext::setPlatformStrokeColor(const Color& strokecolor)
+void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan)
{
if (paintingDisabled())
return;
- platformContext()->setStrokeColor(strokecolor.rgb());
-}
-void GraphicsContext::setPlatformStrokeThickness(float thickness)
-{
- if (paintingDisabled())
+ SkPaint paint;
+ SkRect oval = r;
+ if (strokeStyle() == NoStroke) {
+ // Stroke using the fill color.
+ // TODO(brettw) is this really correct? It seems unreasonable.
+ platformContext()->setupPaintForFilling(&paint);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(WebCoreFloatToSkScalar(strokeThickness()));
+ } else
+ platformContext()->setupPaintForStroking(&paint, 0, 0);
+
+ // We do this before converting to scalar, so we don't overflow SkFixed.
+ startAngle = fastMod(startAngle, 360);
+ angleSpan = fastMod(angleSpan, 360);
+
+ SkPath path;
+ path.addArc(oval, SkIntToScalar(-startAngle), SkIntToScalar(-angleSpan));
+ if (!IsPathReasonable(getCTM(), path))
return;
- platformContext()->setStrokeThickness(thickness);
+ platformContext()->canvas()->drawPath(path, paint);
}
-void GraphicsContext::setPlatformTextDrawingMode(int mode)
+void GraphicsContext::strokePath()
{
if (paintingDisabled())
return;
- platformContext()->setTextDrawingMode(mode);
-}
+ const SkPath& path = *platformContext()->currentPath();
+ if (!IsPathReasonable(getCTM(), path))
+ return;
-void GraphicsContext::addPath(const Path& path)
-{
- if (paintingDisabled())
+ const GraphicsContextState& state = m_common->state;
+ ColorSpace colorSpace = state.strokeColorSpace;
+
+ if (colorSpace == SolidColorSpace && !strokeColor().alpha())
return;
- platformContext()->addPath(*path.platformPath());
+
+ SkPaint paint;
+ platformContext()->setupPaintForStroking(&paint, 0, 0);
+
+ if (colorSpace == PatternColorSpace) {
+ SkShader* pat = state.strokePattern->createPlatformPattern(getCTM());
+ paint.setShader(pat);
+ pat->unref();
+ } else if (colorSpace == GradientColorSpace)
+ paint.setShader(state.strokeGradient->platformGradient());
+
+ platformContext()->canvas()->drawPath(path, paint);
}
-void GraphicsContext::beginPath()
+void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
{
if (paintingDisabled())
return;
- platformContext()->beginPath();
-}
+ if (!IsRectReasonable(getCTM(), rect))
+ return;
-void GraphicsContext::setUseAntialiasing(bool enable)
-{
- if (paintingDisabled())
+ const GraphicsContextState& state = m_common->state;
+ ColorSpace colorSpace = state.strokeColorSpace;
+
+ if (colorSpace == SolidColorSpace && !strokeColor().alpha())
return;
- platformContext()->setUseAntialiasing(enable);
+
+ SkPaint paint;
+ platformContext()->setupPaintForStroking(&paint, 0, 0);
+ paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth));
+
+ if (colorSpace == PatternColorSpace) {
+ SkShader* pat = state.strokePattern->createPlatformPattern(getCTM());
+ paint.setShader(pat);
+ pat->unref();
+ } else if (colorSpace == GradientColorSpace)
+ paint.setShader(state.strokeGradient->platformGradient());
+
+ platformContext()->canvas()->drawRect(rect, paint);
}
-// TODO(eseidel): This is needed for image masking and complex text fills
-void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer* imageBuffer)
+void GraphicsContext::rotate(float angleInRadians)
{
if (paintingDisabled())
return;
-
- notImplemented();
+ platformContext()->canvas()->rotate(WebCoreFloatToSkScalar(
+ angleInRadians * (180.0f / 3.14159265f)));
}
-void GraphicsContext::setImageInterpolationQuality(InterpolationQuality)
+void GraphicsContext::translate(float w, float h)
{
- notImplemented();
+ if (paintingDisabled())
+ return;
+ platformContext()->canvas()->translate(WebCoreFloatToSkScalar(w),
+ WebCoreFloatToSkScalar(h));
}
-}
+} // namespace WebCore