summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/skia/samplecode/SampleRegion.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/skia/samplecode/SampleRegion.cpp')
-rw-r--r--chromium/third_party/skia/samplecode/SampleRegion.cpp418
1 files changed, 418 insertions, 0 deletions
diff --git a/chromium/third_party/skia/samplecode/SampleRegion.cpp b/chromium/third_party/skia/samplecode/SampleRegion.cpp
new file mode 100644
index 00000000000..54858de7a13
--- /dev/null
+++ b/chromium/third_party/skia/samplecode/SampleRegion.cpp
@@ -0,0 +1,418 @@
+
+/*
+ * 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 "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkImageDecoder.h"
+
+static void test_strokerect(SkCanvas* canvas) {
+ int width = 100;
+ int height = 100;
+
+ SkBitmap bitmap;
+ bitmap.allocPixels(SkImageInfo::MakeA8(width*2, height*2));
+ bitmap.eraseColor(SK_ColorTRANSPARENT);
+
+ SkScalar dx = 20;
+ SkScalar dy = 20;
+
+ SkPath path;
+ path.addRect(0.0f, 0.0f,
+ SkIntToScalar(width), SkIntToScalar(height),
+ SkPath::kCW_Direction);
+ SkRect r = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
+
+ SkCanvas c(bitmap);
+ c.translate(dx, dy);
+
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(1);
+
+ // use the rect
+ c.clear(SK_ColorTRANSPARENT);
+ c.drawRect(r, paint);
+ canvas->drawBitmap(bitmap, 0, 0, NULL);
+
+ // use the path
+ c.clear(SK_ColorTRANSPARENT);
+ c.drawPath(path, paint);
+ canvas->drawBitmap(bitmap, SkIntToScalar(2*width), 0, NULL);
+}
+
+static void drawFadingText(SkCanvas* canvas,
+ const char* text, size_t len, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
+ // Need a bounds for the text
+ SkRect bounds;
+ SkPaint::FontMetrics fm;
+
+ paint.getFontMetrics(&fm);
+ bounds.set(x, y + fm.fTop, x + paint.measureText(text, len), y + fm.fBottom);
+
+ // may need to outset bounds a little, to account for hinting and/or
+ // antialiasing
+ bounds.inset(-SkIntToScalar(2), -SkIntToScalar(2));
+
+ canvas->saveLayer(&bounds, NULL);
+ canvas->drawText(text, len, x, y, paint);
+
+ const SkPoint pts[] = {
+ { bounds.fLeft, y },
+ { bounds.fRight, y }
+ };
+ const SkColor colors[] = { SK_ColorBLACK, SK_ColorBLACK, 0 };
+
+ // pos[1] value is where we start to fade, relative to the width
+ // of our pts[] array.
+ const SkScalar pos[] = { 0, 0.9f, SK_Scalar1 };
+
+ SkShader* s = SkGradientShader::CreateLinear(pts, colors, pos, 3,
+ SkShader::kClamp_TileMode);
+ SkPaint p;
+ p.setShader(s)->unref();
+ p.setXfermodeMode(SkXfermode::kDstIn_Mode);
+ canvas->drawRect(bounds, p);
+
+ canvas->restore();
+}
+
+static void test_text(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setTextSize(20);
+
+ const char* str = "Hamburgefons";
+ size_t len = strlen(str);
+ SkScalar x = 20;
+ SkScalar y = 20;
+
+ canvas->drawText(str, len, x, y, paint);
+
+ y += 20;
+
+ const SkPoint pts[] = { { x, y }, { x + paint.measureText(str, len), y } };
+ const SkColor colors[] = { SK_ColorBLACK, SK_ColorBLACK, 0 };
+ const SkScalar pos[] = { 0, 0.9f, 1 };
+ SkShader* s = SkGradientShader::CreateLinear(pts, colors, pos,
+ SK_ARRAY_COUNT(colors),
+ SkShader::kClamp_TileMode);
+ paint.setShader(s)->unref();
+ canvas->drawText(str, len, x, y, paint);
+
+ y += 20;
+ paint.setShader(NULL);
+ drawFadingText(canvas, str, len, x, y, paint);
+}
+
+#ifdef SK_BUILD_FOR_WIN
+// windows doesn't have roundf
+inline float roundf(float x) { return (x-floor(x))>0.5 ? ceil(x) : floor(x); }
+#endif
+
+#ifdef SK_DEBUG
+static void make_rgn(SkRegion* rgn, int left, int top, int right, int bottom,
+ int count, int32_t runs[]) {
+ SkIRect r;
+ r.set(left, top, right, bottom);
+
+ rgn->debugSetRuns(runs, count);
+ SkASSERT(rgn->getBounds() == r);
+}
+
+static void test_union_bug_1505668(SkRegion* ra, SkRegion* rb, SkRegion* rc) {
+ static int32_t dataA[] = {
+ 0x00000001,
+ 0x000001dd, 2, 0x00000001, 0x0000000c, 0x0000000d, 0x00000025, 0x7fffffff,
+ 0x000001de, 1, 0x00000001, 0x00000025, 0x7fffffff,
+ 0x000004b3, 1, 0x00000001, 0x00000026, 0x7fffffff,
+ 0x000004b4, 1, 0x0000000c, 0x00000026, 0x7fffffff,
+ 0x00000579, 1, 0x00000000, 0x0000013a, 0x7fffffff,
+ 0x000005d8, 1, 0x00000000, 0x0000013b, 0x7fffffff,
+ 0x7fffffff
+ };
+ make_rgn(ra, 0, 1, 315, 1496, SK_ARRAY_COUNT(dataA), dataA);
+
+ static int32_t dataB[] = {
+ 0x000000b6,
+ 0x000000c4, 1, 0x000000a1, 0x000000f0, 0x7fffffff,
+ 0x000000d6, 0, 0x7fffffff,
+ 0x000000e4, 2, 0x00000070, 0x00000079, 0x000000a1, 0x000000b0, 0x7fffffff,
+ 0x000000e6, 0, 0x7fffffff,
+ 0x000000f4, 2, 0x00000070, 0x00000079, 0x000000a1, 0x000000b0, 0x7fffffff,
+ 0x000000f6, 0, 0x7fffffff,
+ 0x00000104, 1, 0x000000a1, 0x000000b0, 0x7fffffff,
+ 0x7fffffff
+ };
+ make_rgn(rb, 112, 182, 240, 260, SK_ARRAY_COUNT(dataB), dataB);
+
+ rc->op(*ra, *rb, SkRegion::kUnion_Op);
+}
+#endif
+
+static void scale_rect(SkIRect* dst, const SkIRect& src, float scale) {
+ dst->fLeft = (int)::roundf(src.fLeft * scale);
+ dst->fTop = (int)::roundf(src.fTop * scale);
+ dst->fRight = (int)::roundf(src.fRight * scale);
+ dst->fBottom = (int)::roundf(src.fBottom * scale);
+}
+
+static void scale_rgn(SkRegion* dst, const SkRegion& src, float scale) {
+ SkRegion tmp;
+ SkRegion::Iterator iter(src);
+
+ for (; !iter.done(); iter.next()) {
+ SkIRect r;
+ scale_rect(&r, iter.rect(), scale);
+ tmp.op(r, SkRegion::kUnion_Op);
+ }
+ dst->swap(tmp);
+}
+
+static void paint_rgn(SkCanvas* canvas, const SkRegion& rgn,
+ const SkPaint& paint) {
+ SkRegion scaled;
+ scale_rgn(&scaled, rgn, 0.5f);
+
+ SkRegion::Iterator iter(rgn);
+
+ for (; !iter.done(); iter.next())
+ {
+ SkRect r;
+ r.set(iter.rect());
+ canvas->drawRect(r, paint);
+ }
+}
+
+class RegionView : public SampleView {
+public:
+ RegionView() {
+ fBase.set(100, 100, 150, 150);
+ fRect = fBase;
+ fRect.inset(5, 5);
+ fRect.offset(25, 25);
+ this->setBGColor(0xFFDDDDDD);
+ }
+
+ void build_base_rgn(SkRegion* rgn) {
+ rgn->setRect(fBase);
+ SkIRect r = fBase;
+ r.offset(75, 20);
+ rgn->op(r, SkRegion::kUnion_Op);
+ }
+
+ void build_rgn(SkRegion* rgn, SkRegion::Op op) {
+ build_base_rgn(rgn);
+ rgn->op(fRect, op);
+ }
+
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "Regions");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ static void drawstr(SkCanvas* canvas, const char text[], const SkPoint& loc,
+ bool hilite) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setTextSize(SkIntToScalar(20));
+ paint.setColor(hilite ? SK_ColorRED : 0x40FF0000);
+ canvas->drawText(text, strlen(text), loc.fX, loc.fY, paint);
+ }
+
+ void drawPredicates(SkCanvas* canvas, const SkPoint pts[]) {
+ SkRegion rgn;
+ build_base_rgn(&rgn);
+
+ drawstr(canvas, "Intersects", pts[0], rgn.intersects(fRect));
+ drawstr(canvas, "Contains", pts[1], rgn.contains(fRect));
+ }
+
+ void drawOrig(SkCanvas* canvas, bool bg) {
+ SkRect r;
+ SkPaint paint;
+
+ paint.setStyle(SkPaint::kStroke_Style);
+ if (bg)
+ paint.setColor(0xFFBBBBBB);
+
+ SkRegion rgn;
+ build_base_rgn(&rgn);
+ paint_rgn(canvas, rgn, paint);
+
+ r.set(fRect);
+ canvas->drawRect(r, paint);
+ }
+
+ void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
+ SkRegion rgn;
+
+ this->build_rgn(&rgn, op);
+
+ {
+ SkRegion tmp, tmp2(rgn);
+
+ tmp = tmp2;
+ tmp.translate(5, -3);
+
+ {
+ char buffer[1000];
+ SkDEBUGCODE(size_t size = ) tmp.writeToMemory(NULL);
+ SkASSERT(size <= sizeof(buffer));
+ SkDEBUGCODE(size_t size2 = ) tmp.writeToMemory(buffer);
+ SkASSERT(size == size2);
+
+ SkRegion tmp3;
+ SkDEBUGCODE(size2 = ) tmp3.readFromMemory(buffer, 1000);
+ SkASSERT(size == size2);
+
+ SkASSERT(tmp3 == tmp);
+ }
+
+ rgn.translate(20, 30, &tmp);
+ SkASSERT(rgn.isEmpty() || tmp != rgn);
+ tmp.translate(-20, -30);
+ SkASSERT(tmp == rgn);
+ }
+
+ this->drawOrig(canvas, true);
+
+ SkPaint paint;
+ paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
+ paint_rgn(canvas, rgn, paint);
+
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setColor(color);
+ paint_rgn(canvas, rgn, paint);
+ }
+
+ void drawPathOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
+ SkRegion rgn;
+ SkPath path;
+
+ this->build_rgn(&rgn, op);
+ rgn.getBoundaryPath(&path);
+
+ this->drawOrig(canvas, true);
+
+ SkPaint paint;
+
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
+ canvas->drawPath(path, paint);
+ paint.setColor(color);
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawPath(path, paint);
+ }
+
+ virtual void onDrawContent(SkCanvas* canvas) {
+ if (false) { // avoid bit rot, suppress warning
+ test_strokerect(canvas);
+ return;
+ }
+ if (false) { // avoid bit rot, suppress warning
+ test_text(canvas);
+ return;
+ }
+#ifdef SK_DEBUG
+ if (true) {
+ SkRegion a, b, c;
+ test_union_bug_1505668(&a, &b, &c);
+
+ if (false) { // draw the result of the test
+ SkPaint paint;
+
+ canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
+ paint.setColor(SK_ColorRED);
+ paint_rgn(canvas, a, paint);
+ paint.setColor(0x800000FF);
+ paint_rgn(canvas, b, paint);
+ paint.setColor(SK_ColorBLACK);
+ paint.setStyle(SkPaint::kStroke_Style);
+ // paint_rgn(canvas, c, paint);
+ return;
+ }
+ }
+#endif
+ const SkPoint origins[] = {
+ { 30*SK_Scalar1, 50*SK_Scalar1 },
+ { 150*SK_Scalar1, 50*SK_Scalar1 },
+ };
+ this->drawPredicates(canvas, origins);
+
+ static const struct {
+ SkColor fColor;
+ const char* fName;
+ SkRegion::Op fOp;
+ } gOps[] = {
+ { SK_ColorBLACK, "Difference", SkRegion::kDifference_Op },
+ { SK_ColorRED, "Intersect", SkRegion::kIntersect_Op },
+ { 0xFF008800, "Union", SkRegion::kUnion_Op },
+ { SK_ColorBLUE, "XOR", SkRegion::kXOR_Op }
+ };
+
+ SkPaint textPaint;
+ textPaint.setAntiAlias(true);
+ textPaint.setTextSize(SK_Scalar1*24);
+
+ this->drawOrig(canvas, false);
+ canvas->save();
+ canvas->translate(SkIntToScalar(200), 0);
+ this->drawRgnOped(canvas, SkRegion::kUnion_Op, SK_ColorBLACK);
+ canvas->restore();
+
+ canvas->translate(0, SkIntToScalar(200));
+
+ for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); op++) {
+ canvas->drawText(gOps[op].fName, strlen(gOps[op].fName), SkIntToScalar(75), SkIntToScalar(50), textPaint);
+
+ this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor);
+
+ canvas->save();
+ canvas->translate(0, SkIntToScalar(200));
+ this->drawPathOped(canvas, gOps[op].fOp, gOps[op].fColor);
+ canvas->restore();
+
+ canvas->translate(SkIntToScalar(200), 0);
+ }
+ }
+
+ virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y,
+ unsigned modi) SK_OVERRIDE {
+ return fRect.contains(SkScalarRoundToInt(x),
+ SkScalarRoundToInt(y)) ? new Click(this) : NULL;
+ }
+
+ virtual bool onClick(Click* click) {
+ fRect.offset(click->fICurr.fX - click->fIPrev.fX,
+ click->fICurr.fY - click->fIPrev.fY);
+ this->inval(NULL);
+ return true;
+ }
+
+private:
+ SkIRect fBase, fRect;
+
+ typedef SampleView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new RegionView; }
+static SkViewRegister reg(MyFactory);