2011-07-28 14:26:00 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2011 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
2016-03-09 02:50:00 +00:00
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/core/SkBitmap.h"
|
|
|
|
#include "include/core/SkCanvas.h"
|
|
|
|
#include "include/core/SkFont.h"
|
|
|
|
#include "include/core/SkFontMetrics.h"
|
|
|
|
#include "include/core/SkPath.h"
|
|
|
|
#include "include/core/SkRegion.h"
|
|
|
|
#include "include/core/SkShader.h"
|
|
|
|
#include "include/effects/SkGradientShader.h"
|
|
|
|
#include "samplecode/Sample.h"
|
|
|
|
#include "src/utils/SkUTF.h"
|
2008-12-17 15:59:43 +00:00
|
|
|
|
2015-07-21 21:14:30 +00:00
|
|
|
#include <math.h>
|
|
|
|
|
2012-05-02 18:03:32 +00:00
|
|
|
static void test_strokerect(SkCanvas* canvas) {
|
|
|
|
int width = 100;
|
|
|
|
int height = 100;
|
|
|
|
|
|
|
|
SkBitmap bitmap;
|
2014-02-17 02:55:57 +00:00
|
|
|
bitmap.allocPixels(SkImageInfo::MakeA8(width*2, height*2));
|
2012-12-06 21:47:40 +00:00
|
|
|
bitmap.eraseColor(SK_ColorTRANSPARENT);
|
2012-05-02 18:03:32 +00:00
|
|
|
|
|
|
|
SkScalar dx = 20;
|
|
|
|
SkScalar dy = 20;
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2012-05-02 18:03:32 +00:00
|
|
|
SkPath path;
|
2012-08-23 18:19:56 +00:00
|
|
|
path.addRect(0.0f, 0.0f,
|
|
|
|
SkIntToScalar(width), SkIntToScalar(height),
|
2012-05-14 16:33:36 +00:00
|
|
|
SkPath::kCW_Direction);
|
|
|
|
SkRect r = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2012-05-02 18:03:32 +00:00
|
|
|
SkCanvas c(bitmap);
|
|
|
|
c.translate(dx, dy);
|
|
|
|
|
|
|
|
SkPaint paint;
|
|
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
|
|
paint.setStrokeWidth(1);
|
|
|
|
|
|
|
|
// use the rect
|
2012-12-06 21:47:40 +00:00
|
|
|
c.clear(SK_ColorTRANSPARENT);
|
2012-05-02 18:03:32 +00:00
|
|
|
c.drawRect(r, paint);
|
2015-08-27 14:41:13 +00:00
|
|
|
canvas->drawBitmap(bitmap, 0, 0, nullptr);
|
2012-05-02 18:03:32 +00:00
|
|
|
|
|
|
|
// use the path
|
2012-12-06 21:47:40 +00:00
|
|
|
c.clear(SK_ColorTRANSPARENT);
|
2012-05-02 18:03:32 +00:00
|
|
|
c.drawPath(path, paint);
|
2015-08-27 14:41:13 +00:00
|
|
|
canvas->drawBitmap(bitmap, SkIntToScalar(2*width), 0, nullptr);
|
2012-05-02 18:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void drawFadingText(SkCanvas* canvas,
|
|
|
|
const char* text, size_t len, SkScalar x, SkScalar y,
|
2019-01-02 17:21:01 +00:00
|
|
|
const SkFont& font, const SkPaint& paint) {
|
2012-05-02 18:03:32 +00:00
|
|
|
// Need a bounds for the text
|
|
|
|
SkRect bounds;
|
2018-11-12 14:35:15 +00:00
|
|
|
SkFontMetrics fm;
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2019-01-02 17:21:01 +00:00
|
|
|
font.getMetrics(&fm);
|
2019-05-07 19:38:46 +00:00
|
|
|
bounds.set(x, y + fm.fTop, x + font.measureText(text, len, SkTextEncoding::kUTF8), y + fm.fBottom);
|
2012-05-02 18:03:32 +00:00
|
|
|
|
|
|
|
// may need to outset bounds a little, to account for hinting and/or
|
|
|
|
// antialiasing
|
|
|
|
bounds.inset(-SkIntToScalar(2), -SkIntToScalar(2));
|
|
|
|
|
2015-08-27 14:41:13 +00:00
|
|
|
canvas->saveLayer(&bounds, nullptr);
|
2019-05-07 19:38:46 +00:00
|
|
|
canvas->drawSimpleText(text, len, SkTextEncoding::kUTF8, x, y, font, paint);
|
2012-05-02 18:03:32 +00:00
|
|
|
|
|
|
|
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.
|
2013-11-25 19:44:07 +00:00
|
|
|
const SkScalar pos[] = { 0, 0.9f, SK_Scalar1 };
|
2012-05-02 18:03:32 +00:00
|
|
|
|
|
|
|
SkPaint p;
|
2019-04-03 14:27:45 +00:00
|
|
|
p.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 3, SkTileMode::kClamp));
|
2016-10-06 00:33:02 +00:00
|
|
|
p.setBlendMode(SkBlendMode::kDstIn);
|
2012-05-02 18:03:32 +00:00
|
|
|
canvas->drawRect(bounds, p);
|
|
|
|
|
|
|
|
canvas->restore();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_text(SkCanvas* canvas) {
|
|
|
|
SkPaint paint;
|
|
|
|
paint.setAntiAlias(true);
|
2019-01-02 17:21:01 +00:00
|
|
|
|
|
|
|
SkFont font;
|
|
|
|
font.setSize(20);
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2012-05-02 18:03:32 +00:00
|
|
|
const char* str = "Hamburgefons";
|
|
|
|
size_t len = strlen(str);
|
|
|
|
SkScalar x = 20;
|
|
|
|
SkScalar y = 20;
|
|
|
|
|
2019-05-07 19:38:46 +00:00
|
|
|
canvas->drawSimpleText(str, len, SkTextEncoding::kUTF8, x, y, font, paint);
|
2012-05-02 18:03:32 +00:00
|
|
|
|
|
|
|
y += 20;
|
|
|
|
|
2019-05-07 19:38:46 +00:00
|
|
|
const SkPoint pts[] = { { x , y },
|
|
|
|
{ x + font.measureText(str, len, SkTextEncoding::kUTF8), y } };
|
2012-05-02 18:03:32 +00:00
|
|
|
const SkColor colors[] = { SK_ColorBLACK, SK_ColorBLACK, 0 };
|
|
|
|
const SkScalar pos[] = { 0, 0.9f, 1 };
|
2016-03-09 02:50:00 +00:00
|
|
|
paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos,
|
2012-05-02 18:03:32 +00:00
|
|
|
SK_ARRAY_COUNT(colors),
|
2019-04-03 14:27:45 +00:00
|
|
|
SkTileMode::kClamp));
|
2019-05-07 19:38:46 +00:00
|
|
|
canvas->drawSimpleText(str, len, SkTextEncoding::kUTF8, x, y, font, paint);
|
2012-05-02 18:03:32 +00:00
|
|
|
|
|
|
|
y += 20;
|
2015-08-27 14:41:13 +00:00
|
|
|
paint.setShader(nullptr);
|
2019-01-02 17:21:01 +00:00
|
|
|
drawFadingText(canvas, str, len, x, y, font, paint);
|
2012-05-02 18:03:32 +00:00
|
|
|
}
|
|
|
|
|
2009-05-13 14:00:33 +00:00
|
|
|
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);
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2009-05-13 14:00:33 +00:00
|
|
|
SkRegion::Iterator iter(rgn);
|
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
for (; !iter.done(); iter.next())
|
|
|
|
{
|
|
|
|
SkRect r;
|
|
|
|
r.set(iter.rect());
|
|
|
|
canvas->drawRect(r, paint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
class RegionView : public Sample {
|
2008-12-17 15:59:43 +00:00
|
|
|
public:
|
2012-08-23 18:19:56 +00:00
|
|
|
RegionView() {
|
2008-12-17 15:59:43 +00:00
|
|
|
fBase.set(100, 100, 150, 150);
|
|
|
|
fRect = fBase;
|
|
|
|
fRect.inset(5, 5);
|
|
|
|
fRect.offset(25, 25);
|
2011-05-05 01:59:48 +00:00
|
|
|
this->setBGColor(0xFFDDDDDD);
|
2008-12-17 15:59:43 +00:00
|
|
|
}
|
|
|
|
|
2012-05-02 18:03:32 +00:00
|
|
|
void build_base_rgn(SkRegion* rgn) {
|
2008-12-17 15:59:43 +00:00
|
|
|
rgn->setRect(fBase);
|
|
|
|
SkIRect r = fBase;
|
|
|
|
r.offset(75, 20);
|
|
|
|
rgn->op(r, SkRegion::kUnion_Op);
|
2012-05-02 18:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void build_rgn(SkRegion* rgn, SkRegion::Op op) {
|
|
|
|
build_base_rgn(rgn);
|
2008-12-17 15:59:43 +00:00
|
|
|
rgn->op(fRect, op);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected:
|
2019-07-03 14:55:44 +00:00
|
|
|
SkString name() override { return SkString("Regions"); }
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2012-05-02 18:03:32 +00:00
|
|
|
static void drawstr(SkCanvas* canvas, const char text[], const SkPoint& loc,
|
|
|
|
bool hilite) {
|
|
|
|
SkPaint paint;
|
|
|
|
paint.setColor(hilite ? SK_ColorRED : 0x40FF0000);
|
2019-01-03 17:59:14 +00:00
|
|
|
SkFont font;
|
|
|
|
font.setSize(SkIntToScalar(20));
|
2019-05-07 19:38:46 +00:00
|
|
|
canvas->drawSimpleText(text, strlen(text), SkTextEncoding::kUTF8, loc.fX, loc.fY, font, paint);
|
2012-05-02 18:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void drawPredicates(SkCanvas* canvas, const SkPoint pts[]) {
|
|
|
|
SkRegion rgn;
|
|
|
|
build_base_rgn(&rgn);
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2012-05-02 18:03:32 +00:00
|
|
|
drawstr(canvas, "Intersects", pts[0], rgn.intersects(fRect));
|
|
|
|
drawstr(canvas, "Contains", pts[1], rgn.contains(fRect));
|
|
|
|
}
|
|
|
|
|
2011-05-05 01:59:48 +00:00
|
|
|
void drawOrig(SkCanvas* canvas, bool bg) {
|
2008-12-17 15:59:43 +00:00
|
|
|
SkRect r;
|
|
|
|
SkPaint paint;
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
|
|
if (bg)
|
|
|
|
paint.setColor(0xFFBBBBBB);
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2012-05-02 18:03:32 +00:00
|
|
|
SkRegion rgn;
|
|
|
|
build_base_rgn(&rgn);
|
|
|
|
paint_rgn(canvas, rgn, paint);
|
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
r.set(fRect);
|
|
|
|
canvas->drawRect(r, paint);
|
|
|
|
}
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2011-05-05 01:59:48 +00:00
|
|
|
void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
|
2008-12-17 15:59:43 +00:00
|
|
|
SkRegion rgn;
|
|
|
|
|
|
|
|
this->build_rgn(&rgn, op);
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
{
|
|
|
|
SkRegion tmp, tmp2(rgn);
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
tmp = tmp2;
|
|
|
|
tmp.translate(5, -3);
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
{
|
|
|
|
char buffer[1000];
|
2015-08-27 14:41:13 +00:00
|
|
|
SkDEBUGCODE(size_t size = ) tmp.writeToMemory(nullptr);
|
2008-12-17 15:59:43 +00:00
|
|
|
SkASSERT(size <= sizeof(buffer));
|
2013-01-07 19:54:40 +00:00
|
|
|
SkDEBUGCODE(size_t size2 = ) tmp.writeToMemory(buffer);
|
2008-12-17 15:59:43 +00:00
|
|
|
SkASSERT(size == size2);
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
SkRegion tmp3;
|
2013-11-05 15:46:56 +00:00
|
|
|
SkDEBUGCODE(size2 = ) tmp3.readFromMemory(buffer, 1000);
|
2008-12-17 15:59:43 +00:00
|
|
|
SkASSERT(size == size2);
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
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);
|
|
|
|
}
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2011-05-05 01:59:48 +00:00
|
|
|
void drawPathOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
|
2008-12-17 15:59:43 +00:00
|
|
|
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);
|
|
|
|
}
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
void onDrawContent(SkCanvas* canvas) override {
|
2012-06-06 12:09:51 +00:00
|
|
|
if (false) { // avoid bit rot, suppress warning
|
|
|
|
test_strokerect(canvas);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (false) { // avoid bit rot, suppress warning
|
|
|
|
test_text(canvas);
|
|
|
|
return;
|
|
|
|
}
|
2018-07-28 14:14:27 +00:00
|
|
|
|
2012-05-02 18:03:32 +00:00
|
|
|
const SkPoint origins[] = {
|
|
|
|
{ 30*SK_Scalar1, 50*SK_Scalar1 },
|
|
|
|
{ 150*SK_Scalar1, 50*SK_Scalar1 },
|
|
|
|
};
|
|
|
|
this->drawPredicates(canvas, origins);
|
2008-12-17 15:59:43 +00:00
|
|
|
|
|
|
|
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 }
|
|
|
|
};
|
|
|
|
|
2019-01-03 17:59:14 +00:00
|
|
|
SkFont font;
|
|
|
|
font.setSize(SK_Scalar1*24);
|
2008-12-17 15:59:43 +00:00
|
|
|
|
|
|
|
this->drawOrig(canvas, false);
|
|
|
|
canvas->save();
|
|
|
|
canvas->translate(SkIntToScalar(200), 0);
|
|
|
|
this->drawRgnOped(canvas, SkRegion::kUnion_Op, SK_ColorBLACK);
|
|
|
|
canvas->restore();
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
canvas->translate(0, SkIntToScalar(200));
|
|
|
|
|
2011-05-19 19:58:58 +00:00
|
|
|
for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); op++) {
|
2019-05-07 19:38:46 +00:00
|
|
|
canvas->drawSimpleText(gOps[op].fName, strlen(gOps[op].fName), SkTextEncoding::kUTF8,
|
2019-01-03 17:59:14 +00:00
|
|
|
SkIntToScalar(75), SkIntToScalar(50), font, SkPaint());
|
2008-12-17 15:59:43 +00:00
|
|
|
|
|
|
|
this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor);
|
|
|
|
|
2011-05-05 01:59:48 +00:00
|
|
|
canvas->save();
|
|
|
|
canvas->translate(0, SkIntToScalar(200));
|
|
|
|
this->drawPathOped(canvas, gOps[op].fOp, gOps[op].fColor);
|
|
|
|
canvas->restore();
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
canvas->translate(SkIntToScalar(200), 0);
|
|
|
|
}
|
|
|
|
}
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
virtual Sample::Click* onFindClickHandler(SkScalar x, SkScalar y,
|
2019-07-08 20:07:57 +00:00
|
|
|
ModifierKey modi) override {
|
2013-12-17 19:22:07 +00:00
|
|
|
return fRect.contains(SkScalarRoundToInt(x),
|
2019-07-12 15:32:43 +00:00
|
|
|
SkScalarRoundToInt(y)) ? new Click() : nullptr;
|
2008-12-17 15:59:43 +00:00
|
|
|
}
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
bool onClick(Click* click) override {
|
2019-07-12 15:32:43 +00:00
|
|
|
fRect.offset(click->fCurr.fX - click->fPrev.fX,
|
|
|
|
click->fCurr.fY - click->fPrev.fY);
|
2008-12-17 15:59:43 +00:00
|
|
|
return true;
|
|
|
|
}
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
private:
|
|
|
|
SkIRect fBase, fRect;
|
2012-08-23 18:19:56 +00:00
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
typedef Sample INHERITED;
|
2008-12-17 15:59:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
DEF_SAMPLE( return new RegionView(); )
|