From 591670558768f6fe97ccf74b6424c6c90f73fdc8 Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Sat, 9 Nov 2013 01:37:30 +0000 Subject: add GM case nonclosedpaths. The 2 bugs below showed some non-closed paths which are easy to get wrong rendering results. So add a GM case for this kind paths to avoid potential bugs to be introduced. BUG=skia:1782 BUG=skia:1811 R=bsalomon@google.com, caryclark@google.com, reed@google.com, robertphillips@google.com Author: yunchao.he@intel.com Review URL: https://codereview.chromium.org/64173009 git-svn-id: http://skia.googlecode.com/svn/trunk@12206 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gm/nonclosedpaths.cpp | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 gm/nonclosedpaths.cpp (limited to 'gm/nonclosedpaths.cpp') diff --git a/gm/nonclosedpaths.cpp b/gm/nonclosedpaths.cpp new file mode 100644 index 0000000000..bc37c54a83 --- /dev/null +++ b/gm/nonclosedpaths.cpp @@ -0,0 +1,145 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gm.h" +#include "SkCanvas.h" +#include "SkPath.h" + +namespace skiagm { + +// This GM tests a grab-bag of non-closed paths. All these paths look like +// closed rects, but they don't call path.close(). Depending on the stroke +// settings these slightly different paths give widely different results. +class NonClosedPathsGM: public GM { +public: + NonClosedPathsGM() {} + + enum ClosureType { + TotallyNonClosed, // The last point doesn't coincide with the first one in the contour. + // The path looks not closed at all. + + FakeCloseCorner, // The last point coincides with the first one at a corner. + // The path looks closed, but final rendering has 2 ends with cap. + + FakeCloseMiddle, // The last point coincides with the first one in the middle of a line. + // The path looks closed, and the final rendering looks closed too. + + kClosureTypeCount + }; + +protected: + virtual SkString onShortName() SK_OVERRIDE { + return SkString("nonclosedpaths"); + } + + // 12 * 18 + 3 cases, every case is 100 * 100 pixels. + virtual SkISize onISize() SK_OVERRIDE { + return SkISize::Make(1220, 1920); + } + + // Use rect-like geometry for non-closed path, for right angles make it + // easier to show the visual difference of lineCap and lineJoin. + static void MakePath(SkPath* path, ClosureType type) { + if (FakeCloseMiddle == type) { + path->moveTo(30, 50); + path->lineTo(30, 30); + } else { + path->moveTo(30, 30); + } + path->lineTo(70, 30); + path->lineTo(70, 70); + path->lineTo(30, 70); + path->lineTo(30, 50); + if (FakeCloseCorner == type) { + path->lineTo(30, 30); + } + } + + // Set the location for the current test on the canvas + static void SetLocation(SkCanvas* canvas, int counter, int lineNum) { + SkScalar x = SK_Scalar1 * 100 * (counter % lineNum) + 10 + SK_Scalar1 / 4; + SkScalar y = SK_Scalar1 * 100 * (counter / lineNum) + 10 + 3 * SK_Scalar1 / 4; + canvas->translate(x, y); + } + + virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { + // Stroke widths are: + // 0(may use hairline rendering), 10(common case for stroke-style) + // 40 and 50(>= geometry width/height, make the contour filled in fact) + static const int kStrokeWidth[] = {0, 10, 40, 50}; + size_t numWidths = SK_ARRAY_COUNT(kStrokeWidth); + + static const SkPaint::Style kStyle[] = { + SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style + }; + + static const SkPaint::Cap kCap[] = { + SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap + }; + + static const SkPaint::Join kJoin[] = { + SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join + }; + + static const ClosureType kType[] = { + TotallyNonClosed, FakeCloseCorner, FakeCloseMiddle + }; + + int counter = 0; + SkPaint paint; + paint.setAntiAlias(true); + + // For stroke style painter and fill-and-stroke style painter + for (size_t type = 0; type < kClosureTypeCount; ++type) { + for (size_t style = 0; style < SK_ARRAY_COUNT(kStyle); ++style) { + for (size_t cap = 0; cap < SK_ARRAY_COUNT(kCap); ++cap) { + for (size_t join = 0; join < SK_ARRAY_COUNT(kJoin); ++join) { + for (size_t width = 0; width < numWidths; ++width) { + canvas->save(); + SetLocation(canvas, counter, SkPaint::kJoinCount * numWidths); + + SkPath path; + MakePath(&path, kType[type]); + + paint.setStyle(kStyle[style]); + paint.setStrokeCap(kCap[cap]); + paint.setStrokeJoin(kJoin[join]); + paint.setStrokeWidth(SkIntToScalar(kStrokeWidth[width])); + + canvas->drawPath(path, paint); + canvas->restore(); + ++counter; + } + } + } + } + } + + // For fill style painter + paint.setStyle(SkPaint::kFill_Style); + for (size_t type = 0; type < kClosureTypeCount; ++type) { + canvas->save(); + SetLocation(canvas, counter, SkPaint::kJoinCount * numWidths); + + SkPath path; + MakePath(&path, kType[type]); + + canvas->drawPath(path, paint); + canvas->restore(); + ++counter; + } + } + +private: + typedef GM INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +DEF_GM(return new NonClosedPathsGM;) + +} -- cgit v1.2.3