aboutsummaryrefslogtreecommitdiffhomepage
path: root/samplecode
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-09-25 15:37:50 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-09-25 15:37:50 +0000
commit33535f3c48bf723c46f334a93d4a06d782dad30e (patch)
treed5dfb1ec904b1cf48fda20bdd194ffa66c170201 /samplecode
parent8640d5024d57da5508bdf7585849e3b1f1cb365b (diff)
Reimplement drawBitmapRectToRect to correctly handle fraction srcRect.
The prev impl relied on drawBitmap "deducing" the destination rect by applying the computed matrix to the bitmap's bounds. This cannot be done if the srcRect is fractional, and therefore not representable w/ a bitmap. The new impl computes the same matrix, but calls down to the device via drawRect + a bitmap_shader. This allows us to specfiy the dstRect explicitly. The possible down-side is that we now rely on the device subclass to efficiently handle draRect+shader, instead of calling its drawBitmap entry-point. To give the device the chance to handle this differently, I now call through to a new device virtual: drawBitmapRect. The default impl is to create the shader and call drawRect, but a subclass can intercept that. For now, the GPU override of drawBitmapRect is mimicing the old behavior (by rounding the srcRect to an iRect). This preserves its ability to call drawBitmap which handles very-large textures, but shows some gittering/imprecision, due to the rounding. ... this is the same GPU behavior we have before this CL. Review URL: https://codereview.appspot.com/6542065 git-svn-id: http://skia.googlecode.com/svn/trunk@5663 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'samplecode')
-rw-r--r--samplecode/SampleBitmapRect.cpp208
1 files changed, 169 insertions, 39 deletions
diff --git a/samplecode/SampleBitmapRect.cpp b/samplecode/SampleBitmapRect.cpp
index ba7efbf16e..18208fb1a3 100644
--- a/samplecode/SampleBitmapRect.cpp
+++ b/samplecode/SampleBitmapRect.cpp
@@ -30,37 +30,78 @@
class GrContext;
#endif
+#define INT_SIZE 64
+#define SCALAR_SIZE SkIntToScalar(INT_SIZE)
-static void make_bitmap(SkBitmap* bitmap, GrContext* ctx) {
- SkCanvas canvas;
-
-#if SK_SUPPORT_GPU
- if (ctx) {
- SkDevice* dev = new SkGpuDevice(ctx, SkBitmap::kARGB_8888_Config, 64, 64);
- canvas.setDevice(dev)->unref();
- *bitmap = dev->accessBitmap(false);
- } else
-#endif
- {
- bitmap->setConfig(SkBitmap::kARGB_8888_Config, 64, 64);
- bitmap->allocPixels();
- canvas.setBitmapDevice(*bitmap);
- }
+static void make_bitmap(SkBitmap* bitmap) {
+ bitmap->setConfig(SkBitmap::kARGB_8888_Config, INT_SIZE, INT_SIZE);
+ bitmap->allocPixels();
+ SkCanvas canvas(*bitmap);
canvas.drawColor(SK_ColorRED);
SkPaint paint;
paint.setAntiAlias(true);
- const SkPoint pts[] = { { 0, 0 }, { 64, 64 } };
+ const SkPoint pts[] = { { 0, 0 }, { SCALAR_SIZE, SCALAR_SIZE } };
const SkColor colors[] = { SK_ColorWHITE, SK_ColorBLUE };
paint.setShader(SkGradientShader::CreateLinear(pts, colors, NULL, 2,
SkShader::kClamp_TileMode))->unref();
- canvas.drawCircle(32, 32, 32, paint);
+ canvas.drawCircle(SCALAR_SIZE/2, SCALAR_SIZE/2, SCALAR_SIZE/2, paint);
+}
+
+static SkPoint unit_vec(int degrees) {
+ SkScalar rad = SkDegreesToRadians(SkIntToScalar(degrees));
+ SkScalar s, c;
+ s = SkScalarSinCos(rad, &c);
+ return SkPoint::Make(c, s);
+}
+
+static void bounce(SkScalar* value, SkScalar* delta, SkScalar min, SkScalar max) {
+ *value += *delta;
+ if (*value < min) {
+ *value = min;
+ *delta = - *delta;
+ } else if (*value > max) {
+ *value = max;
+ *delta = - *delta;
+ }
+}
+
+static void bounce_pt(SkPoint* pt, SkVector* vec, const SkRect& limit) {
+ bounce(&pt->fX, &vec->fX, limit.fLeft, limit.fRight);
+ bounce(&pt->fY, &vec->fY, limit.fTop, limit.fBottom);
}
class BitmapRectView : public SampleView {
+ SkPoint fSrcPts[2];
+ SkPoint fSrcVec[2];
+ SkRect fSrcLimit;
+ SkRect fDstR[2];
+
+ void bounce() {
+ bounce_pt(&fSrcPts[0], &fSrcVec[0], fSrcLimit);
+ bounce_pt(&fSrcPts[1], &fSrcVec[1], fSrcLimit);
+ }
+
public:
BitmapRectView() {
this->setBGColor(SK_ColorGRAY);
+
+ fSrcPts[0].set(0, 0);
+ fSrcPts[1].set(SCALAR_SIZE, SCALAR_SIZE);
+
+ fSrcVec[0] = unit_vec(30);
+ fSrcVec[1] = unit_vec(107);
+
+ fSrcLimit.set(-SCALAR_SIZE/4, -SCALAR_SIZE/4,
+ SCALAR_SIZE*5/4, SCALAR_SIZE*5/4);
+
+ fDstR[0] = SkRect::MakeXYWH(SkIntToScalar(10), SkIntToScalar(100),
+ SkIntToScalar(250), SkIntToScalar(300));
+ fDstR[1] = fDstR[0];
+ fDstR[1].offset(fDstR[0].width() * 5/4, 0);
+
+ fSrcPts[0].set(32, 32);
+ fSrcPts[1].set(90, 90);
}
protected:
@@ -74,45 +115,134 @@ protected:
}
virtual void onDrawContent(SkCanvas* canvas) {
- GrContext* ctx = SampleCode::GetGr();
-
- const SkIRect src[] = {
- { 0, 0, 32, 32 },
- { 0, 0, 80, 80 },
- { 32, 32, 96, 96 },
- { -32, -32, 32, 32, }
- };
+ SkRect srcR;
+ srcR.set(fSrcPts[0], fSrcPts[1]);
+ srcR = SkRect::MakeXYWH(fSrcPts[0].fX, fSrcPts[0].fY, 32, 32);
+ srcR.offset(-srcR.width()/2, -srcR.height()/2);
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
- paint.setColor(ctx ? SK_ColorGREEN : SK_ColorYELLOW);
+ paint.setColor(SK_ColorYELLOW);
SkBitmap bitmap;
- make_bitmap(&bitmap, ctx);
+ make_bitmap(&bitmap);
+
+ canvas->translate(20, 20);
+
+ canvas->drawBitmap(bitmap, 0, 0, &paint);
+ canvas->drawRect(srcR, paint);
+
+ for (int i = 0; i < 2; ++i) {
+ paint.setFilterBitmap(1 == i);
+ canvas->drawBitmapRectToRect(bitmap, &srcR, fDstR[i], &paint);
+ canvas->drawRect(fDstR[i], paint);
+ }
+
+ this->bounce();
+ this->inval(NULL);
+ }
+
+private:
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static void make_big_bitmap(SkBitmap* bm) {
+ static const char gText[] =
+ "We the people, in order to form a more perfect union, establish justice,"
+ " ensure domestic tranquility, provide for the common defense, promote the"
+ " general welfare and ensure the blessings of liberty to ourselves and our"
+ " posterity, do ordain and establish this constitution for the United"
+ " States of America.";
+
+ const int BIG_H = 120;
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setTextSize(SkIntToScalar(BIG_H));
+
+ const int BIG_W = SkScalarRoundToInt(paint.measureText(gText, strlen(gText)));
+
+ bm->setConfig(SkBitmap::kARGB_8888_Config, BIG_W, BIG_H);
+ bm->allocPixels();
+ bm->eraseColor(SK_ColorWHITE);
+
+ SkCanvas canvas(*bm);
+
+ canvas.drawText(gText, strlen(gText), 0, paint.getTextSize()*4/5, paint);
+}
+
+class BitmapRectView2 : public SampleView {
+ SkBitmap fBitmap;
+
+ SkRect fSrcR;
+ SkRect fLimitR;
+ SkScalar fDX;
+ SkRect fDstR[2];
+
+ void bounceMe() {
+ SkScalar width = fSrcR.width();
+ bounce(&fSrcR.fLeft, &fDX, fLimitR.fLeft, fLimitR.fRight - width);
+ fSrcR.fRight = fSrcR.fLeft + width;
+ }
+
+public:
+ BitmapRectView2() {
+ make_big_bitmap(&fBitmap);
- SkRect dstR = { 0, 200, 128, 380 };
+ this->setBGColor(SK_ColorGRAY);
- canvas->translate(16, 40);
- for (size_t i = 0; i < SK_ARRAY_COUNT(src); i++) {
- SkRect srcR;
- srcR.set(src[i]);
+ fSrcR.fLeft = 0;
+ fSrcR.fTop = 0;
+ fSrcR.fRight = SkIntToScalar(fBitmap.height()) * 3;
+ fSrcR.fBottom = SkIntToScalar(fBitmap.height());
- canvas->drawBitmap(bitmap, 0, 0, &paint);
- canvas->drawBitmapRect(bitmap, &src[i], dstR, &paint);
+ fLimitR.set(0, 0,
+ SkIntToScalar(fBitmap.width()),
+ SkIntToScalar(fBitmap.height()));
- canvas->drawRect(dstR, paint);
- canvas->drawRect(srcR, paint);
+ fDX = SK_Scalar1;
- canvas->translate(160, 0);
+ fDstR[0] = SkRect::MakeXYWH(SkIntToScalar(20), SkIntToScalar(20),
+ SkIntToScalar(600), SkIntToScalar(200));
+ fDstR[1] = fDstR[0];
+ fDstR[1].offset(0, fDstR[0].height() * 5/4);
+ }
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "BigBitmapRect");
+ return true;
}
+ return this->INHERITED::onQuery(evt);
}
+
+ virtual void onDrawContent(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setColor(SK_ColorYELLOW);
+ for (int i = 0; i < 2; ++i) {
+ paint.setFilterBitmap(1 == i);
+ canvas->drawBitmapRectToRect(fBitmap, &fSrcR, fDstR[i], &paint);
+ canvas->drawRect(fDstR[i], paint);
+ }
+
+ this->bounceMe();
+ this->inval(NULL);
+ }
+
private:
typedef SkView INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
-static SkView* MyFactory() { return new BitmapRectView; }
-static SkViewRegister reg(MyFactory);
+static SkView* F0() { return new BitmapRectView; }
+static SkView* F1() { return new BitmapRectView2; }
+static SkViewRegister gR0(F0);
+static SkViewRegister gR1(F1);