add SkPath::reverseAddPath()
git-svn-id: http://skia.googlecode.com/svn/trunk@2995 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
d6256557cd
commit
63d73749fb
133
gm/strokefill.cpp
Normal file
133
gm/strokefill.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2011 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"
|
||||
#include "SkTypeface.h"
|
||||
|
||||
static void test10(SkCanvas* canvas) {
|
||||
SkPaint paint;
|
||||
const char text[] = "Hello"; // "Hello";
|
||||
const size_t len = sizeof(text) - 1;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setTextSize(SkIntToScalar(100));
|
||||
SkTypeface* hira = SkTypeface::CreateFromName("Hiragino Maru Gothic Pro",
|
||||
SkTypeface::kNormal);
|
||||
paint.setTypeface(hira);
|
||||
SkScalar x = 180;
|
||||
SkScalar y = 88;
|
||||
|
||||
canvas->drawText(text, len, x, y, paint);
|
||||
paint.setFakeBoldText(true);
|
||||
canvas->drawText(text, len, x, y + 100, paint);
|
||||
paint.setStyle(SkPaint::kStrokeAndFill_Style);
|
||||
paint.setStrokeWidth(5);
|
||||
|
||||
SkPath path;
|
||||
path.setFillType(SkPath::kWinding_FillType);
|
||||
path.addCircle(x, y + 200, 50, SkPath::kCW_Direction);
|
||||
path.addCircle(x, y + 200, 40, SkPath::kCCW_Direction);
|
||||
canvas->drawPath(path, paint);
|
||||
|
||||
SkPath path2;
|
||||
path2.setFillType(SkPath::kWinding_FillType);
|
||||
path2.addCircle(x + 120, y + 200, 50, SkPath::kCCW_Direction);
|
||||
path2.addCircle(x + 120, y + 200, 40, SkPath::kCW_Direction);
|
||||
canvas->drawPath(path2, paint);
|
||||
|
||||
path2.reset();
|
||||
path2.addCircle(x + 240, y + 200, 50, SkPath::kCCW_Direction);
|
||||
canvas->drawPath(path2, paint);
|
||||
|
||||
path2.reset();
|
||||
path2.addCircle(x + 360, y + 200, 50, SkPath::kCW_Direction);
|
||||
canvas->drawPath(path2, paint);
|
||||
}
|
||||
|
||||
static void test_path(SkCanvas* canvas, const SkPath& path) {
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
canvas->drawPath(path, paint);
|
||||
|
||||
paint.setStyle(SkPaint::kStroke_Style);
|
||||
paint.setColor(SK_ColorRED);
|
||||
canvas->drawPath(path, paint);
|
||||
}
|
||||
|
||||
static void test_rev(SkCanvas* canvas, const SkPath& path) {
|
||||
test_path(canvas, path);
|
||||
|
||||
SkPath rev;
|
||||
rev.reverseAddPath(path);
|
||||
canvas->save();
|
||||
canvas->translate(150, 0);
|
||||
test_path(canvas, rev);
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
static void test_rev(SkCanvas* canvas) {
|
||||
SkRect r = { 10, 10, 100, 60 };
|
||||
|
||||
SkPath path;
|
||||
|
||||
path.addRect(r); test_rev(canvas, path);
|
||||
|
||||
canvas->translate(0, 100);
|
||||
path.offset(20, 20);
|
||||
path.addRect(r); test_rev(canvas, path);
|
||||
|
||||
canvas->translate(0, 100);
|
||||
path.reset();
|
||||
path.moveTo(10, 10); path.lineTo(30, 30);
|
||||
path.addOval(r);
|
||||
r.offset(50, 20);
|
||||
path.addOval(r);
|
||||
test_rev(canvas, path);
|
||||
|
||||
SkPaint paint;
|
||||
paint.setTextSize(SkIntToScalar(100));
|
||||
SkTypeface* hira = SkTypeface::CreateFromName("Hiragino Maru Gothic Pro", SkTypeface::kNormal);
|
||||
SkSafeUnref(paint.setTypeface(hira));
|
||||
path.reset();
|
||||
paint.getTextPath("e", 1, 50, 50, &path);
|
||||
canvas->translate(0, 100);
|
||||
test_rev(canvas, path);
|
||||
}
|
||||
|
||||
namespace skiagm {
|
||||
|
||||
class StrokeFillGM : public GM {
|
||||
public:
|
||||
StrokeFillGM() {
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual SkString onShortName() {
|
||||
return SkString("stroke-fill");
|
||||
}
|
||||
|
||||
virtual SkISize onISize() {
|
||||
return make_isize(640, 480);
|
||||
}
|
||||
|
||||
virtual void onDraw(SkCanvas* canvas) {
|
||||
// test10(canvas);
|
||||
test_rev(canvas);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef GM INHERITED;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static GM* MyFactory(void*) { return new StrokeFillGM; }
|
||||
static GMRegistry reg(MyFactory);
|
||||
|
||||
}
|
@ -33,6 +33,7 @@
|
||||
'../gm/shadertext.cpp',
|
||||
'../gm/shadows.cpp',
|
||||
'../gm/shapes.cpp',
|
||||
'../gm/strokefill.cpp',
|
||||
'../gm/strokerects.cpp',
|
||||
'../gm/strokes.cpp',
|
||||
'../gm/tablecolorfilter.cpp',
|
||||
|
@ -526,7 +526,7 @@ public:
|
||||
@param dx The amount to translate the path in X as it is added
|
||||
@param dx The amount to translate the path in Y as it is added
|
||||
*/
|
||||
void addPath(const SkPath& src, SkScalar dx, SkScalar dy);
|
||||
void addPath(const SkPath& src, SkScalar dx, SkScalar dy);
|
||||
|
||||
/** Add a copy of src to the path
|
||||
*/
|
||||
@ -541,6 +541,11 @@ public:
|
||||
*/
|
||||
void addPath(const SkPath& src, const SkMatrix& matrix);
|
||||
|
||||
/**
|
||||
* Same as addPath(), but reverses the src input
|
||||
*/
|
||||
void reverseAddPath(const SkPath& src);
|
||||
|
||||
/** Offset the path by (dx,dy), returning true on success
|
||||
|
||||
@param dx The amount in the X direction to offset the entire path
|
||||
|
@ -1052,6 +1052,53 @@ void SkPath::reversePathTo(const SkPath& path) {
|
||||
}
|
||||
}
|
||||
|
||||
void SkPath::reverseAddPath(const SkPath& src) {
|
||||
this->incReserve(src.fPts.count());
|
||||
|
||||
const SkPoint* startPts = src.fPts.begin();
|
||||
const SkPoint* pts = src.fPts.end();
|
||||
const uint8_t* startVerbs = src.fVerbs.begin();
|
||||
const uint8_t* verbs = src.fVerbs.end();
|
||||
|
||||
bool needMove = true;
|
||||
bool needClose = false;
|
||||
while (verbs > startVerbs) {
|
||||
uint8_t v = *--verbs;
|
||||
int n = gPtsInVerb[v];
|
||||
|
||||
if (needMove) {
|
||||
--pts;
|
||||
this->moveTo(pts->fX, pts->fY);
|
||||
needMove = false;
|
||||
}
|
||||
pts -= n;
|
||||
switch (v) {
|
||||
case kMove_Verb:
|
||||
if (needClose) {
|
||||
this->close();
|
||||
needClose = false;
|
||||
}
|
||||
needMove = true;
|
||||
pts += 1; // so we see the point in "if (needMove)" above
|
||||
break;
|
||||
case kLine_Verb:
|
||||
this->lineTo(pts[0]);
|
||||
break;
|
||||
case kQuad_Verb:
|
||||
this->quadTo(pts[1], pts[0]);
|
||||
break;
|
||||
case kCubic_Verb:
|
||||
this->cubicTo(pts[2], pts[1], pts[0]);
|
||||
break;
|
||||
case kClose_Verb:
|
||||
needClose = true;
|
||||
break;
|
||||
default:
|
||||
SkASSERT(!"unexpected verb");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SkPath::offset(SkScalar dx, SkScalar dy, SkPath* dst) const {
|
||||
|
@ -619,6 +619,14 @@ void SkStroke::strokePath(const SkPath& src, SkPath* dst) const {
|
||||
#endif
|
||||
|
||||
if (fDoFill) {
|
||||
const SkPath* srcPtr = &src;
|
||||
#if 0
|
||||
SkPath tmp;
|
||||
if (fast_is_ccw(src)) {
|
||||
reverse(src, &tmp);
|
||||
srcPtr = tmp;
|
||||
}
|
||||
#endif
|
||||
dst->addPath(src);
|
||||
} else {
|
||||
// Seems like we can assume that a 2-point src would always result in
|
||||
|
Loading…
Reference in New Issue
Block a user