Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
2009-10-08 Adam Langley <agl@google.com>
        Reviewed by Eric Seidel.

        Currently, Skia clip paths are 1-bit. This patch makes our path
        clipping anti-aliased for non-canvas drawing.

        http://code.google.com/p/chromium/issues/detail?id=5927
        https://bugs.webkit.org/show_bug.cgi?id=28820
        http://www.imperialviolet.org/2009/09/02/anti-aliased-clipping.html

        Already covered by layout tests. New baselines will be needed in the
        Chromium tree.

        (Reland. First landed in r49329, reverted in r49330 due to Windows
        build break)

        * html/canvas/CanvasRenderingContext2D.cpp:
        (WebCore::CanvasRenderingContext2D::clip):
        * platform/graphics/GraphicsContext.h:
        * platform/graphics/cairo/GraphicsContextCairo.cpp:
        (WebCore::GraphicsContext::canvasClip):
        * platform/graphics/cg/GraphicsContextCG.cpp:
        (WebCore::GraphicsContext::canvasClip):
        * platform/graphics/haiku/GraphicsContextHaiku.cpp:
        (WebCore::GraphicsContext::canvasClip):
        * platform/graphics/qt/GraphicsContextQt.cpp:
        (WebCore::GraphicsContext::canvasClip):
        * platform/graphics/skia/GraphicsContextSkia.cpp:
        (WebCore::GraphicsContext::addInnerRoundedRectClip):
        (WebCore::GraphicsContext::clip):
        (WebCore::GraphicsContext::canvasClip):
        (WebCore::GraphicsContext::clipPath):
        * platform/graphics/skia/PlatformContextSkia.cpp:
        (PlatformContextSkia::clipPathAntiAliased):
        (PlatformContextSkia::restore):
        (PlatformContextSkia::applyAntiAliasedClipPaths):
        * platform/graphics/skia/PlatformContextSkia.h:
        * platform/graphics/win/GraphicsContextWin.cpp:
        (WebCore::GraphicsContext::canvasClip):
        * platform/graphics/wince/GraphicsContextWince.cpp:
        (WebCore::GraphicsContext::canvasClip):
        * platform/graphics/wx/GraphicsContextWx.cpp:
        (WebCore::GraphicsContext::canvasClip):


Canonical link: https://commits.webkit.org/41105@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@49641 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Adam Langley committed Oct 15, 2009
1 parent c18d720 commit b920f7f
Show file tree
Hide file tree
Showing 12 changed files with 157 additions and 3 deletions.
45 changes: 45 additions & 0 deletions WebCore/ChangeLog
@@ -1,3 +1,48 @@
2009-10-08 Adam Langley <agl@google.com>

Reviewed by Eric Seidel.

Currently, Skia clip paths are 1-bit. This patch makes our path
clipping anti-aliased for non-canvas drawing.

http://code.google.com/p/chromium/issues/detail?id=5927
https://bugs.webkit.org/show_bug.cgi?id=28820
http://www.imperialviolet.org/2009/09/02/anti-aliased-clipping.html

Already covered by layout tests. New baselines will be needed in the
Chromium tree.

(Reland. First landed in r49329, reverted in r49330 due to Windows
build break)

* html/canvas/CanvasRenderingContext2D.cpp:
(WebCore::CanvasRenderingContext2D::clip):
* platform/graphics/GraphicsContext.h:
* platform/graphics/cairo/GraphicsContextCairo.cpp:
(WebCore::GraphicsContext::canvasClip):
* platform/graphics/cg/GraphicsContextCG.cpp:
(WebCore::GraphicsContext::canvasClip):
* platform/graphics/haiku/GraphicsContextHaiku.cpp:
(WebCore::GraphicsContext::canvasClip):
* platform/graphics/qt/GraphicsContextQt.cpp:
(WebCore::GraphicsContext::canvasClip):
* platform/graphics/skia/GraphicsContextSkia.cpp:
(WebCore::GraphicsContext::addInnerRoundedRectClip):
(WebCore::GraphicsContext::clip):
(WebCore::GraphicsContext::canvasClip):
(WebCore::GraphicsContext::clipPath):
* platform/graphics/skia/PlatformContextSkia.cpp:
(PlatformContextSkia::clipPathAntiAliased):
(PlatformContextSkia::restore):
(PlatformContextSkia::applyAntiAliasedClipPaths):
* platform/graphics/skia/PlatformContextSkia.h:
* platform/graphics/win/GraphicsContextWin.cpp:
(WebCore::GraphicsContext::canvasClip):
* platform/graphics/wince/GraphicsContextWince.cpp:
(WebCore::GraphicsContext::canvasClip):
* platform/graphics/wx/GraphicsContextWx.cpp:
(WebCore::GraphicsContext::canvasClip):

2009-10-15 Eric Carlson <eric.carlson@apple.com>

Reviewed by Simon Fraser.
Expand Down
2 changes: 1 addition & 1 deletion WebCore/html/canvas/CanvasRenderingContext2D.cpp
Expand Up @@ -687,7 +687,7 @@ void CanvasRenderingContext2D::clip()
return;
if (!state().m_invertibleCTM)
return;
c->clip(m_path);
c->canvasClip(m_path);
#if ENABLE(DASHBOARD_SUPPORT)
clearPathForDashboardBackwardCompatibilityMode();
#endif
Expand Down
5 changes: 5 additions & 0 deletions WebCore/platform/graphics/GraphicsContext.h
Expand Up @@ -297,6 +297,11 @@ namespace WebCore {
void addPath(const Path&);

void clip(const Path&);

// This clip function is used only by <canvas> code. It allows
// implementations to handle clipping on the canvas differently since
// the disipline is different.
void canvasClip(const Path&);
void clipOut(const Path&);

void scale(const FloatSize&);
Expand Down
5 changes: 5 additions & 0 deletions WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
Expand Up @@ -931,6 +931,11 @@ void GraphicsContext::clip(const Path& path)
m_data->clip(path);
}

void GraphicsContext::canvasClip(const Path& path)
{
clip(path);
}

void GraphicsContext::clipOut(const Path& path)
{
if (paintingDisabled())
Expand Down
5 changes: 5 additions & 0 deletions WebCore/platform/graphics/cg/GraphicsContextCG.cpp
Expand Up @@ -849,6 +849,11 @@ void GraphicsContext::clip(const Path& path)
m_data->clip(path);
}

void GraphicsContext::canvasClip(const Path& path)
{
clip(path);
}

void GraphicsContext::clipOut(const Path& path)
{
if (paintingDisabled())
Expand Down
5 changes: 5 additions & 0 deletions WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
Expand Up @@ -369,6 +369,11 @@ void GraphicsContext::clip(const Path& path)
m_data->m_view->ConstrainClippingRegion(path.platformPath());
}

void GraphicsContext::canvasClip(const Path& path)
{
clip(path);
}

void GraphicsContext::clipOut(const Path& path)
{
if (paintingDisabled())
Expand Down
5 changes: 5 additions & 0 deletions WebCore/platform/graphics/qt/GraphicsContextQt.cpp
Expand Up @@ -1053,6 +1053,11 @@ void GraphicsContext::clip(const Path& path)
m_data->p()->setClipPath(*path.platformPath(), Qt::IntersectClip);
}

void GraphicsContext::canvasClip(const Path& path)
{
clip(path);
}

void GraphicsContext::clipOut(const Path& path)
{
if (paintingDisabled())
Expand Down
16 changes: 14 additions & 2 deletions WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
Expand Up @@ -296,7 +296,7 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
r.inset(SkIntToScalar(thickness), SkIntToScalar(thickness));
path.addOval(r, SkPath::kCCW_Direction);
}
platformContext()->canvas()->clipPath(path);
platformContext()->clipPathAntiAliased(path);
}

void GraphicsContext::addPath(const Path& path)
Expand Down Expand Up @@ -348,6 +348,18 @@ void GraphicsContext::clip(const FloatRect& rect)
}

void GraphicsContext::clip(const Path& path)
{
if (paintingDisabled())
return;

const SkPath& p = *path.platformPath();
if (!isPathSkiaSafe(getCTM(), p))
return;

platformContext()->clipPathAntiAliased(p);
}

void GraphicsContext::canvasClip(const Path& path)
{
if (paintingDisabled())
return;
Expand Down Expand Up @@ -407,7 +419,7 @@ void GraphicsContext::clipPath(WindRule clipRule)
return;

path.setFillType(clipRule == RULE_EVENODD ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
platformContext()->canvas()->clipPath(path);
platformContext()->clipPathAntiAliased(path);
}

void GraphicsContext::clipToImageBuffer(const FloatRect& rect,
Expand Down
60 changes: 60 additions & 0 deletions WebCore/platform/graphics/skia/PlatformContextSkia.cpp
Expand Up @@ -45,6 +45,7 @@
#include "SkDashPathEffect.h"

#include <wtf/MathExtras.h>
#include <wtf/Vector.h>

namespace WebCore
{
Expand Down Expand Up @@ -95,6 +96,10 @@ struct PlatformContextSkia::State {
WebCore::FloatRect m_clip;
#endif

// This is a list of clipping paths which are currently active, in the
// order in which they were pushed.
WTF::Vector<SkPath> m_antiAliasClipPaths;

private:
// Not supported.
void operator=(const State&);
Expand Down Expand Up @@ -249,6 +254,21 @@ void PlatformContextSkia::beginLayerClippedToImage(const WebCore::FloatRect& rec
}
#endif

void PlatformContextSkia::clipPathAntiAliased(const SkPath& clipPath)
{
// If we are currently tracking any anti-alias clip paths, then we already
// have a layer in place and don't need to add another.
bool haveLayerOutstanding = m_state->m_antiAliasClipPaths.size();

// See comments in applyAntiAliasedClipPaths about how this works.
m_state->m_antiAliasClipPaths.append(clipPath);

if (!haveLayerOutstanding) {
SkRect bounds = clipPath.getBounds();
canvas()->saveLayerAlpha(&bounds, 255, static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag | SkCanvas::kClipToLayer_SaveFlag));
}
}

void PlatformContextSkia::restore()
{
#if defined(__linux__) || PLATFORM(WIN_OS)
Expand All @@ -258,6 +278,9 @@ void PlatformContextSkia::restore()
}
#endif

if (!m_state->m_antiAliasClipPaths.isEmpty())
applyAntiAliasedClipPaths(m_state->m_antiAliasClipPaths);

m_stateStack.removeLast();
m_state = &m_stateStack.last();

Expand Down Expand Up @@ -549,3 +572,40 @@ void PlatformContextSkia::applyClipFromImage(const WebCore::FloatRect& rect, con
m_canvas->drawBitmap(imageBuffer, SkFloatToScalar(rect.x()), SkFloatToScalar(rect.y()), &paint);
}
#endif

void PlatformContextSkia::applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths)
{
// Anti-aliased clipping:
//
// Skia's clipping is 1-bit only. Consider what would happen if it were 8-bit:
// We have a square canvas, filled with white and we declare a circular
// clipping path. Then we fill twice with a black rectangle. The fractional
// pixels would first get the correct color (white * alpha + black * (1 -
// alpha)), but the second fill would apply the alpha to the already
// modified color and the result would be too dark.
//
// This, anti-aliased clipping needs to be performed after the drawing has
// been done. In order to do this, we create a new layer of the canvas in
// clipPathAntiAliased and store the clipping path. All drawing is done to
// the layer's bitmap while it's in effect. When WebKit calls restore() to
// undo the clipping, this function is called.
//
// Here, we walk the list of clipping paths backwards and, for each, we
// clear outside of the clipping path. We only need a single extra layer
// for any number of clipping paths.
//
// When we call restore on the SkCanvas, the layer's bitmap is composed
// into the layer below and we end up with correct, anti-aliased clipping.

SkPaint paint;
paint.setXfermodeMode(SkXfermode::kClear_Mode);
paint.setAntiAlias(true);
paint.setStyle(SkPaint::kFill_Style);

for (size_t i = paths.size() - 1; i < paths.size(); --i) {
paths[i].setFillType(SkPath::kInverseWinding_FillType);
m_canvas->drawPath(paths[i], paint);
}

m_canvas->restore();
}
2 changes: 2 additions & 0 deletions WebCore/platform/graphics/skia/PlatformContextSkia.h
Expand Up @@ -92,6 +92,7 @@ class PlatformContextSkia : public Noncopyable {
void beginLayerClippedToImage(const WebCore::FloatRect&,
const WebCore::ImageBuffer*);
#endif
void clipPathAntiAliased(const SkPath&);

// Sets up the common flags on a paint for antialiasing, effects, etc.
// This is implicitly called by setupPaintFill and setupPaintStroke, but
Expand Down Expand Up @@ -172,6 +173,7 @@ class PlatformContextSkia : public Noncopyable {
// m_canvas that are also in imageBuffer.
void applyClipFromImage(const WebCore::FloatRect&, const SkBitmap&);
#endif
void applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths);

// Defines drawing style.
struct State;
Expand Down
5 changes: 5 additions & 0 deletions WebCore/platform/graphics/wince/GraphicsContextWince.cpp
Expand Up @@ -1219,6 +1219,11 @@ void GraphicsContext::clip(const Path& path)
notImplemented();
}

void GraphicsContext::canvasClip(const Path& path)
{
clip(path);
}

void GraphicsContext::clipOut(const Path&)
{
notImplemented();
Expand Down
5 changes: 5 additions & 0 deletions WebCore/platform/graphics/wx/GraphicsContextWx.cpp
Expand Up @@ -344,6 +344,11 @@ void GraphicsContext::clip(const Path&)
notImplemented();
}

void GraphicsContext::canvasClip(const Path& path)
{
clip(path);
}

void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*)
{
notImplemented();
Expand Down

0 comments on commit b920f7f

Please sign in to comment.