From 8cfdf01ff953b47fdd5c29ebd54fea8a7a9be83e Mon Sep 17 00:00:00 2001 From: "agl@chromium.org" Date: Mon, 6 Dec 2010 18:52:40 +0000 Subject: [PATCH] Correctly handle SkPath::kInverseWinding_FillType Fix for http://code.google.com/p/skia/issues/detail?id=87 Even when SkPath::kInverseWinding_FillType is given, Skia left some lines not filled(cleared) in one case. Patch-by: morrita http://codereview.appspot.com/3443041 git-svn-id: http://skia.googlecode.com/svn/trunk@630 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/core/SkScan_AntiPath.cpp | 10 ++++++ src/core/SkScan_Path.cpp | 8 +++++ tests/FillPathTest.cpp | 60 ++++++++++++++++++++++++++++++++++++ tests/tests_files.mk | 1 + 4 files changed, 79 insertions(+) create mode 100644 tests/FillPathTest.cpp diff --git a/src/core/SkScan_AntiPath.cpp b/src/core/SkScan_AntiPath.cpp index 21fd5c99b7..fb33ab0fbd 100644 --- a/src/core/SkScan_AntiPath.cpp +++ b/src/core/SkScan_AntiPath.cpp @@ -82,6 +82,7 @@ public: void flush(); virtual void blitH(int x, int y, int width); + virtual void blitRect(int x, int y, int width, int height); private: SkAlphaRuns fRuns; @@ -189,6 +190,15 @@ void SuperBlitter::blitH(int x, int y, int width) #endif } +void SuperBlitter::blitRect(int x, int y, int width, int height) +{ + for (int i = 0; i < height; ++i) { + blitH(x, y + i, width); + } + + flush(); +} + /////////////////////////////////////////////////////////////////////////////// class MaskSuperBlitter : public BaseSuperBlitter { diff --git a/src/core/SkScan_Path.cpp b/src/core/SkScan_Path.cpp index 38f16e61e5..b1ba7dfb13 100644 --- a/src/core/SkScan_Path.cpp +++ b/src/core/SkScan_Path.cpp @@ -508,6 +508,14 @@ void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitte #endif if (count < 2) { + if (path.isInverseFillType()) { + const SkIRect& clipRect = clipRgn.getBounds(); + blitter->blitRect(clipRect.fLeft << shiftEdgesUp, + clipRect.fTop << shiftEdgesUp, + clipRect.width() << shiftEdgesUp, + clipRect.height() << shiftEdgesUp); + } + return; } diff --git a/tests/FillPathTest.cpp b/tests/FillPathTest.cpp new file mode 100644 index 0000000000..ffc9f8ec3a --- /dev/null +++ b/tests/FillPathTest.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2010 The Chromium Authors. All rights reserved. + * + * 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 + * + * 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. + */ + +#include "Test.h" +#include "SkRegion.h" +#include "SkPath.h" +#include "SkScan.h" +#include "SkBlitter.h" + +namespace { + +struct FakeBlitter : public SkBlitter { + FakeBlitter() + : m_blitCount(0) + {} + + virtual void blitH(int x, int y, int width) { + m_blitCount++; + } + + int m_blitCount; +}; + +} + +// http://code.google.com/p/skia/issues/detail?id=87 +// Lines which is not clipped by boundary based clipping, +// but skipped after tessellation, should be cleared by the blitter. +static void TestFillPathInverse(skiatest::Reporter* reporter) { + FakeBlitter blitter; + SkRegion clip; + SkPath path; + int height = 100; + int width = 200; + int expected_lines = 5; + clip.setRect(0, height - expected_lines, width, height); + path.moveTo(0.0, 0.0); + path.quadTo(width/2, height, width, 0.0); + path.close(); + path.setFillType(SkPath::kInverseWinding_FillType); + SkScan::FillPath(path, clip, &blitter); + + REPORTER_ASSERT(reporter, blitter.m_blitCount == expected_lines); +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("FillPath", FillPathTestClass, TestFillPathInverse) diff --git a/tests/tests_files.mk b/tests/tests_files.mk index f6f8f511da..19dfdc374d 100644 --- a/tests/tests_files.mk +++ b/tests/tests_files.mk @@ -3,6 +3,7 @@ SOURCE := \ BlitRowTest.cpp \ ClipCubicTest.cpp \ ClipperTest.cpp \ + FillPathTest.cpp \ FlateTest.cpp \ GeometryTest.cpp \ MathTest.cpp \