02939ce4bd
Fix these class of warnings: - unused functions - unused locals - sign mismatch - missing function prototypes - missing newline at end of file - 64 to 32 bit truncation The changes prefer to link in dead code in the debug build with 'if (false)' than to comment it out, but trivial cases are commented out or sometimes deleted if it appears to be a copy/paste error. Review URL: https://codereview.appspot.com/6301044 git-svn-id: http://skia.googlecode.com/svn/trunk@4183 2bbb7eff-a529-9590-31e7-b0007b416f81
419 lines
12 KiB
C++
419 lines
12 KiB
C++
|
|
/*
|
|
* 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.setConfig(SkBitmap::kA8_Config, width*2, height*2);
|
|
bitmap.allocPixels();
|
|
bitmap.eraseColor(0);
|
|
|
|
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(0);
|
|
c.drawRect(r, paint);
|
|
canvas->drawBitmap(bitmap, 0, 0, NULL);
|
|
|
|
// use the path
|
|
c.clear(0);
|
|
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, SkFloatToScalar(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,
|
|
size_t 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];
|
|
size_t size = tmp.flatten(NULL);
|
|
SkASSERT(size <= sizeof(buffer));
|
|
size_t size2 = tmp.flatten(buffer);
|
|
SkASSERT(size == size2);
|
|
|
|
SkRegion tmp3;
|
|
size2 = tmp3.unflatten(buffer);
|
|
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) {
|
|
return fRect.contains(SkScalarRound(x), SkScalarRound(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);
|
|
|