diff options
Diffstat (limited to 'gm')
-rw-r--r-- | gm/Android.mk | 31 | ||||
-rw-r--r-- | gm/bitmapfilters.cpp | 116 | ||||
-rw-r--r-- | gm/filltypes.cpp | 83 | ||||
-rw-r--r-- | gm/gm.h | 45 | ||||
-rw-r--r-- | gm/gm_files.mk | 8 | ||||
-rw-r--r-- | gm/gmmain.cpp | 197 | ||||
-rw-r--r-- | gm/gradients.cpp | 113 | ||||
-rw-r--r-- | gm/shapes.cpp | 126 | ||||
-rw-r--r-- | gm/tilemodes.cpp | 155 | ||||
-rw-r--r-- | gm/xfermodes.cpp | 188 |
10 files changed, 1062 insertions, 0 deletions
diff --git a/gm/Android.mk b/gm/Android.mk new file mode 100644 index 0000000..6ce1dae --- /dev/null +++ b/gm/Android.mk @@ -0,0 +1,31 @@ + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + filltypes.cpp \ + gradients.cpp \ + tilemodes.cpp \ + bitmapfilters.cpp \ + xfermodes.cpp \ + gmmain.cpp + +# additional optional class for this tool +LOCAL_SRC_FILES += \ + ../src/utils/SkUnitMappers.cpp + +LOCAL_SHARED_LIBRARIES := libcutils libskia +LOCAL_C_INCLUDES := \ + external/skia/include/config \ + external/skia/include/core \ + external/skia/include/images \ + external/skia/include/utils \ + external/skia/include/effects + +#LOCAL_CFLAGS := + +LOCAL_MODULE := skia_gm + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_EXECUTABLE) diff --git a/gm/bitmapfilters.cpp b/gm/bitmapfilters.cpp new file mode 100644 index 0000000..0487fe6 --- /dev/null +++ b/gm/bitmapfilters.cpp @@ -0,0 +1,116 @@ +#include "gm.h" + +namespace skiagm { + +static void make_bm(SkBitmap* bm) { + const SkColor colors[] = { + SK_ColorRED, SK_ColorGREEN, + SK_ColorBLUE, SK_ColorWHITE + }; + SkColorTable* ctable = new SkColorTable(colors, 4); + bm->setConfig(SkBitmap::kIndex8_Config, 2, 2); + bm->allocPixels(ctable); + ctable->unref(); + + *bm->getAddr8(0, 0) = 0; + *bm->getAddr8(1, 0) = 1; + *bm->getAddr8(0, 1) = 2; + *bm->getAddr8(1, 1) = 3; +} + +static SkScalar draw_bm(SkCanvas* canvas, const SkBitmap& bm, + SkScalar x, SkScalar y, SkPaint* paint) { + canvas->drawBitmap(bm, x, y, paint); + return SkIntToScalar(bm.width()) * 5/4; +} + +static SkScalar draw_set(SkCanvas* c, const SkBitmap& bm, SkScalar x, + SkPaint* p) { + x += draw_bm(c, bm, x, 0, p); + p->setFilterBitmap(true); + x += draw_bm(c, bm, x, 0, p); + p->setDither(true); + return x + draw_bm(c, bm, x, 0, p); +} + +static const char* gConfigNames[] = { + "unknown config", + "A1", + "A8", + "Index8", + "565", + "4444", + "8888" +}; + +static SkScalar draw_row(SkCanvas* canvas, const SkBitmap& bm) { + SkAutoCanvasRestore acr(canvas, true); + + SkPaint paint; + SkScalar x = 0; + const int scale = 32; + + paint.setAntiAlias(true); + const char* name = gConfigNames[bm.config()]; + canvas->drawText(name, strlen(name), x, SkIntToScalar(bm.height())*scale*5/8, + paint); + canvas->translate(SkIntToScalar(48), 0); + + canvas->scale(SkIntToScalar(scale), SkIntToScalar(scale)); + + x += draw_set(canvas, bm, 0, &paint); + paint.reset(); + paint.setAlpha(0x80); + draw_set(canvas, bm, x, &paint); + return x * scale / 3; +} + +class FilterGM : public GM { +public: + SkBitmap fBM8, fBM4444, fBM16, fBM32; + + FilterGM() { + make_bm(&fBM8); + fBM8.copyTo(&fBM4444, SkBitmap::kARGB_4444_Config); + fBM8.copyTo(&fBM16, SkBitmap::kRGB_565_Config); + fBM8.copyTo(&fBM32, SkBitmap::kARGB_8888_Config); + } + +protected: + virtual SkString onShortName() { + return SkString("bitmapfilters"); + } + + virtual SkISize onISize() { + return make_isize(540, 330); + } + + virtual void onDraw(SkCanvas* canvas) { + canvas->drawColor(0xFFDDDDDD); + + SkScalar x = SkIntToScalar(10); + SkScalar y = SkIntToScalar(10); + + canvas->translate(x, y); + y = draw_row(canvas, fBM8); + canvas->translate(0, y); + y = draw_row(canvas, fBM4444); + canvas->translate(0, y); + y = draw_row(canvas, fBM16); + canvas->translate(0, y); + draw_row(canvas, fBM32); + } + +private: + typedef GM INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +static GM* MyFactory(void*) { return new FilterGM; } +static GMRegistry reg(MyFactory); + +} + + + diff --git a/gm/filltypes.cpp b/gm/filltypes.cpp new file mode 100644 index 0000000..e723f16 --- /dev/null +++ b/gm/filltypes.cpp @@ -0,0 +1,83 @@ +#include "gm.h" + +namespace skiagm { + +class FillTypeGM : public GM { + SkPath fPath; +public: + FillTypeGM() { + const SkScalar radius = SkIntToScalar(45); + fPath.addCircle(SkIntToScalar(50), SkIntToScalar(50), radius); + fPath.addCircle(SkIntToScalar(100), SkIntToScalar(100), radius); + } + +protected: + virtual SkString onShortName() { + return SkString("filltypes"); + } + + virtual SkISize onISize() { + return make_isize(835, 840); + } + + void showPath(SkCanvas* canvas, int x, int y, SkPath::FillType ft, + SkScalar scale, const SkPaint& paint) { + + const SkRect r = { 0, 0, SkIntToScalar(150), SkIntToScalar(150) }; + + canvas->save(); + canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); + canvas->clipRect(r); + canvas->drawColor(SK_ColorWHITE); + fPath.setFillType(ft); + canvas->translate(r.centerX(), r.centerY()); + canvas->scale(scale, scale); + canvas->translate(-r.centerX(), -r.centerY()); + canvas->drawPath(fPath, paint); + canvas->restore(); + } + + void showFour(SkCanvas* canvas, SkScalar scale, const SkPaint& paint) { + showPath(canvas, 0, 0, SkPath::kWinding_FillType, + scale, paint); + showPath(canvas, 200, 0, SkPath::kEvenOdd_FillType, + scale, paint); + showPath(canvas, 00, 200, SkPath::kInverseWinding_FillType, + scale, paint); + showPath(canvas, 200, 200, SkPath::kInverseEvenOdd_FillType, + scale, paint); + } + + virtual void onDraw(SkCanvas* canvas) { + canvas->drawColor(0xFFDDDDDD); + + canvas->translate(SkIntToScalar(20), SkIntToScalar(20)); + + SkPaint paint; + const SkScalar scale = SkIntToScalar(5)/4; + + paint.setAntiAlias(false); + + showFour(canvas, SK_Scalar1, paint); + canvas->translate(SkIntToScalar(450), 0); + showFour(canvas, scale, paint); + + paint.setAntiAlias(true); + + canvas->translate(SkIntToScalar(-450), SkIntToScalar(450)); + showFour(canvas, SK_Scalar1, paint); + canvas->translate(SkIntToScalar(450), 0); + showFour(canvas, scale, paint); + } + +private: + typedef GM INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +static GM* MyFactory(void*) { return new FillTypeGM; } +static GMRegistry reg(MyFactory); + +} + @@ -0,0 +1,45 @@ +#ifndef skiagm_DEFINED +#define skiagm_DEFINED + +#include "SkCanvas.h" +#include "SkPaint.h" +#include "SkRefCnt.h" +#include "SkSize.h" +#include "SkString.h" +#include "SkTRegistry.h" + +namespace skiagm { + + static inline SkISize make_isize(int w, int h) { + SkISize sz; + sz.set(w, h); + return sz; + } + + class GM { + public: + GM(); + virtual ~GM(); + + void draw(SkCanvas*); + SkISize getISize() { return this->onISize(); } + const char* shortName() { + if (fShortName.size() == 0) { + fShortName = this->onShortName(); + } + return fShortName.c_str(); + } + + protected: + virtual void onDraw(SkCanvas*) = 0; + virtual SkISize onISize() = 0; + virtual SkString onShortName() = 0; + + private: + SkString fShortName; + }; + + typedef SkTRegistry<GM*, void*> GMRegistry; +} + +#endif diff --git a/gm/gm_files.mk b/gm/gm_files.mk new file mode 100644 index 0000000..50eb311 --- /dev/null +++ b/gm/gm_files.mk @@ -0,0 +1,8 @@ +SOURCE := \ + bitmapfilters.cpp \ + filltypes.cpp \ + gradients.cpp \ + shapes.cpp \ + tilemodes.cpp \ + xfermodes.cpp \ + gmmain.cpp diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp new file mode 100644 index 0000000..59f6c64 --- /dev/null +++ b/gm/gmmain.cpp @@ -0,0 +1,197 @@ +#include "gm.h" +#include "SkColorPriv.h" +#include "SkGraphics.h" +#include "SkImageDecoder.h" +#include "SkImageEncoder.h" + +using namespace skiagm; + +// need to explicitly declare this, or we get some weird infinite loop llist +template GMRegistry* GMRegistry::gHead; + +class Iter { +public: + Iter() { + fReg = GMRegistry::Head(); + } + + GM* next() { + if (fReg) { + GMRegistry::Factory fact = fReg->factory(); + fReg = fReg->next(); + return fact(0); + } + return NULL; + } + + static int Count() { + const GMRegistry* reg = GMRegistry::Head(); + int count = 0; + while (reg) { + count += 1; + reg = reg->next(); + } + return count; + } + +private: + const GMRegistry* fReg; +}; + +static SkString make_name(const char shortName[], const char configName[]) { + SkString name(shortName); + name.appendf("_%s", configName); + return name; +} + +static SkString make_filename(const char path[], const SkString& name) { + SkString filename(path); + if (filename.size() && filename[filename.size() - 1] != '/') { + filename.append("/"); + } + filename.appendf("%s.png", name.c_str()); + return filename; +} + +/* since PNG insists on unpremultiplying our alpha, we take no precision chances + and force all pixels to be 100% opaque, otherwise on compare we may not get + a perfect match. + */ +static void force_all_opaque(const SkBitmap& bitmap) { + SkAutoLockPixels lock(bitmap); + for (int y = 0; y < bitmap.height(); y++) { + for (int x = 0; x < bitmap.width(); x++) { + *bitmap.getAddr32(x, y) |= (SK_A32_MASK << SK_A32_SHIFT); + } + } +} + +static bool write_bitmap(const SkString& path, const SkBitmap& bitmap) { + SkBitmap copy; + bitmap.copyTo(©, SkBitmap::kARGB_8888_Config); + force_all_opaque(copy); + return SkImageEncoder::EncodeFile(path.c_str(), copy, + SkImageEncoder::kPNG_Type, 100); +} + +static void compare(const SkBitmap& target, const SkBitmap& base, + const SkString& name) { + SkBitmap copy; + const SkBitmap* bm = ⌖ + if (target.config() != SkBitmap::kARGB_8888_Config) { + target.copyTo(©, SkBitmap::kARGB_8888_Config); + bm = © + } + + force_all_opaque(*bm); + + const int w = bm->width(); + const int h = bm->height(); + if (w != base.width() || h != base.height()) { + SkDebugf("---- dimensions mismatch for %s base [%d %d] current [%d %d]\n", + name.c_str(), base.width(), base.height(), w, h); + return; + } + + SkAutoLockPixels bmLock(*bm); + SkAutoLockPixels baseLock(base); + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + SkPMColor c0 = *base.getAddr32(x, y); + SkPMColor c1 = *bm->getAddr32(x, y); + if (c0 != c1) { + SkDebugf("----- pixel mismatch for %s at [%d %d] base 0x%08X current 0x%08X\n", + name.c_str(), x, y, c0, c1); + return; + } + } + } +} + +static const struct { + SkBitmap::Config fConfig; + bool fUsePicture; + const char* fName; +} gRec[] = { + { SkBitmap::kARGB_8888_Config, false, "8888" }, + { SkBitmap::kARGB_4444_Config, false, "4444" }, + { SkBitmap::kRGB_565_Config, false, "565" }, +}; + +int main (int argc, char * const argv[]) { + SkAutoGraphics ag; + + const char* writePath = NULL; // if non-null, where we write the originals + const char* readPath = NULL; // if non-null, were we read from to compare + + char* const* stop = argv + argc; + for (++argv; argv < stop; ++argv) { + if (strcmp(*argv, "-w") == 0) { + argv++; + if (argv < stop && **argv) { + writePath = *argv; + } + } else if (strcmp(*argv, "-r") == 0) { + argv++; + if (argv < stop && **argv) { + readPath = *argv; + } + } + } + + Iter iter; + GM* gm; + + while ((gm = iter.next()) != NULL) { + SkISize size = gm->getISize(); + SkDebugf("creating... %s [%d %d]\n", gm->shortName(), + size.width(), size.height()); + + SkBitmap bitmap; + for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) { + bitmap.setConfig(gRec[i].fConfig, size.width(), size.height()); + bitmap.allocPixels(); + bitmap.eraseColor(0); + SkCanvas canvas(bitmap); + + gm->draw(&canvas); + + SkString name = make_name(gm->shortName(), gRec[i].fName); + + if (writePath) { + SkString path = make_filename(writePath, name); + bool success = write_bitmap(path, bitmap); + if (!success) { + fprintf(stderr, "FAILED to write %s\n", path.c_str()); + } + } else if (readPath) { + SkString path = make_filename(readPath, name); + SkBitmap orig; + bool success = SkImageDecoder::DecodeFile(path.c_str(), &orig, + SkBitmap::kARGB_8888_Config, + SkImageDecoder::kDecodePixels_Mode, NULL); + if (success) { + compare(bitmap, orig, name); + } else { + fprintf(stderr, "FAILED to read %s\n", path.c_str()); + } + } + } + SkDELETE(gm); + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +using namespace skiagm; + +GM::GM() {} +GM::~GM() {} + +void GM::draw(SkCanvas* canvas) { + this->onDraw(canvas); +} + + diff --git a/gm/gradients.cpp b/gm/gradients.cpp new file mode 100644 index 0000000..aed4e0b --- /dev/null +++ b/gm/gradients.cpp @@ -0,0 +1,113 @@ +#include "gm.h" +#include "SkGradientShader.h" + +namespace skiagm { + +struct GradData { + int fCount; + const SkColor* fColors; + const SkScalar* fPos; +}; + +static const SkColor gColors[] = { + SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK +}; +static const SkScalar gPos0[] = { 0, SK_Scalar1 }; +static const SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 }; +static const SkScalar gPos2[] = { + 0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1 +}; + +static const GradData gGradData[] = { + { 2, gColors, NULL }, + { 2, gColors, gPos0 }, + { 2, gColors, gPos1 }, + { 5, gColors, NULL }, + { 5, gColors, gPos2 } +}; + +static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data, + SkShader::TileMode tm, SkUnitMapper* mapper) { + return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos, + data.fCount, tm, mapper); +} + +static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data, + SkShader::TileMode tm, SkUnitMapper* mapper) { + SkPoint center; + center.set(SkScalarAve(pts[0].fX, pts[1].fX), + SkScalarAve(pts[0].fY, pts[1].fY)); + return SkGradientShader::CreateRadial(center, center.fX, data.fColors, + data.fPos, data.fCount, tm, mapper); +} + +static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data, + SkShader::TileMode tm, SkUnitMapper* mapper) { + SkPoint center; + center.set(SkScalarAve(pts[0].fX, pts[1].fX), + SkScalarAve(pts[0].fY, pts[1].fY)); + return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors, + data.fPos, data.fCount, mapper); +} + +typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data, + SkShader::TileMode tm, SkUnitMapper* mapper); +static const GradMaker gGradMakers[] = { + MakeLinear, MakeRadial, MakeSweep +}; + +/////////////////////////////////////////////////////////////////////////////// + +class GradientsGM : public GM { +public: + GradientsGM() {} + +protected: + SkString onShortName() { + return SkString("gradients"); + } + + SkISize onISize() { return make_isize(640, 380); } + + void drawBG(SkCanvas* canvas) { + canvas->drawColor(0xFFDDDDDD); + } + + virtual void onDraw(SkCanvas* canvas) { + this->drawBG(canvas); + + SkPoint pts[2] = { + { 0, 0 }, + { SkIntToScalar(100), SkIntToScalar(100) } + }; + SkShader::TileMode tm = SkShader::kClamp_TileMode; + SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) }; + SkPaint paint; + paint.setAntiAlias(true); + + canvas->translate(SkIntToScalar(20), SkIntToScalar(20)); + for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) { + canvas->save(); + for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) { + SkShader* shader = gGradMakers[j](pts, gGradData[i], tm, NULL); + paint.setShader(shader); + canvas->drawRect(r, paint); + shader->unref(); + canvas->translate(0, SkIntToScalar(120)); + } + canvas->restore(); + canvas->translate(SkIntToScalar(120), 0); + } + } + +private: + typedef GM INHERITED; +}; + +/////////////////////////////////////////////////////////////////////////////// + +static GM* MyFactory(void*) { return new GradientsGM; } +static GMRegistry reg(MyFactory); + +} + diff --git a/gm/shapes.cpp b/gm/shapes.cpp new file mode 100644 index 0000000..b3d4863 --- /dev/null +++ b/gm/shapes.cpp @@ -0,0 +1,126 @@ +#include "gm.h" +#include "SkPicture.h" +#include "SkRectShape.h" +#include "SkGroupShape.h" + +namespace skiagm { + +static SkRect make_rect(int l, int t, int r, int b) { + SkRect rect; + rect.set(SkIntToScalar(l), SkIntToScalar(t), + SkIntToScalar(r), SkIntToScalar(b)); + return rect; +} + +static SkShape* make_shape0(bool red) { + SkRectShape* s = new SkRectShape; + s->setRect(make_rect(10, 10, 90, 90)); + if (red) { + s->paint().setColor(SK_ColorRED); + } + return s; +} + +static SkShape* make_shape1() { + SkRectShape* s = new SkRectShape; + s->setOval(make_rect(10, 10, 90, 90)); + s->paint().setColor(SK_ColorBLUE); + return s; +} + +static SkShape* make_shape2() { + SkRectShape* s = new SkRectShape; + s->setRRect(make_rect(10, 10, 90, 90), + SkIntToScalar(20), SkIntToScalar(20)); + s->paint().setColor(SK_ColorGREEN); + return s; +} + +/////////////////////////////////////////////////////////////////////////////// + +class ShapesGM : public GM { + SkGroupShape fGroup; + SkMatrixRef* fMatrixRefs[4]; +public: + ShapesGM() { + SkMatrix m; + fGroup.appendShape(make_shape0(false))->unref(); + m.setRotate(SkIntToScalar(30), SkIntToScalar(50), SkIntToScalar(50)); + m.postTranslate(0, SkIntToScalar(120)); + fGroup.appendShape(make_shape0(true), m)->unref(); + + m.setTranslate(SkIntToScalar(120), 0); + fGroup.appendShape(make_shape1(), m)->unref(); + m.postTranslate(0, SkIntToScalar(120)); + fGroup.appendShape(make_shape2(), m)->unref(); + + for (size_t i = 0; i < SK_ARRAY_COUNT(fMatrixRefs); i++) { + SkSafeRef(fMatrixRefs[i] = fGroup.getShapeMatrixRef(i)); + } + } + + virtual ~ShapesGM() { + for (size_t i = 0; i < SK_ARRAY_COUNT(fMatrixRefs); i++) { + SkSafeUnref(fMatrixRefs[i]); + } + } + +protected: + virtual SkString onShortName() { + return SkString("shapes"); + } + + virtual SkISize onISize() { + return make_isize(380, 480); + } + + void drawBG(SkCanvas* canvas) { + canvas->drawColor(0xFFDDDDDD); + } + + virtual void onDraw(SkCanvas* canvas) { + this->drawBG(canvas); + + SkMatrix saveM = *fMatrixRefs[3]; + SkScalar c = SkIntToScalar(50); + fMatrixRefs[3]->preRotate(SkIntToScalar(30), c, c); + + SkMatrix matrix; + + SkGroupShape* gs = new SkGroupShape; + SkAutoUnref aur(gs); + gs->appendShape(&fGroup); + matrix.setScale(-SK_Scalar1, SK_Scalar1); + matrix.postTranslate(SkIntToScalar(220), SkIntToScalar(240)); + gs->appendShape(&fGroup, matrix); + matrix.setTranslate(SkIntToScalar(240), 0); + matrix.preScale(SK_Scalar1*2, SK_Scalar1*2); + gs->appendShape(&fGroup, matrix); + +#if 0 + canvas->drawShape(gs); +#else + SkPicture pict; + SkCanvas* cv = pict.beginRecording(1000, 1000); + cv->scale(SK_ScalarHalf, SK_ScalarHalf); + cv->drawShape(gs); + cv->translate(SkIntToScalar(680), SkIntToScalar(480)); + cv->scale(-SK_Scalar1, SK_Scalar1); + cv->drawShape(gs); + pict.endRecording(); + canvas->drawPicture(pict); +#endif + + *fMatrixRefs[3] = saveM; +} + +private: + typedef GM INHERITED; +}; + +/////////////////////////////////////////////////////////////////////////////// + +static GM* MyFactory(void*) { return new ShapesGM; } +static GMRegistry reg(MyFactory); + +} diff --git a/gm/tilemodes.cpp b/gm/tilemodes.cpp new file mode 100644 index 0000000..d836ea5 --- /dev/null +++ b/gm/tilemodes.cpp @@ -0,0 +1,155 @@ +#include "gm.h" +#include "SkPath.h" +#include "SkRegion.h" +#include "SkShader.h" +#include "SkUtils.h" +#include "SkColorPriv.h" +#include "SkColorFilter.h" +#include "SkTypeface.h" + +// effects +#include "SkGradientShader.h" +#include "SkUnitMappers.h" +#include "SkBlurDrawLooper.h" + +namespace skiagm { + +static void makebm(SkBitmap* bm, SkBitmap::Config config, int w, int h) { + bm->setConfig(config, w, h); + bm->allocPixels(); + bm->eraseColor(0); + + SkCanvas canvas(*bm); + SkPoint pts[] = { { 0, 0 }, { SkIntToScalar(w), SkIntToScalar(h)} }; + SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE }; + SkScalar pos[] = { 0, SK_Scalar1/2, SK_Scalar1 }; + SkPaint paint; + + SkUnitMapper* um = NULL; + + um = new SkCosineMapper; +// um = new SkDiscreteMapper(12); + + SkAutoUnref au(um); + + paint.setDither(true); + paint.setShader(SkGradientShader::CreateLinear(pts, colors, pos, + SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode, um))->unref(); + canvas.drawPaint(paint); +} + +static void setup(SkPaint* paint, const SkBitmap& bm, bool filter, + SkShader::TileMode tmx, SkShader::TileMode tmy) { + SkShader* shader = SkShader::CreateBitmapShader(bm, tmx, tmy); + paint->setShader(shader)->unref(); + paint->setFilterBitmap(filter); +} + +static const SkBitmap::Config gConfigs[] = { + SkBitmap::kARGB_8888_Config, + SkBitmap::kRGB_565_Config, + SkBitmap::kARGB_4444_Config +}; +static const int gWidth = 32; +static const int gHeight = 32; + +class TilingGM : public GM { + SkBlurDrawLooper fLooper; +public: + TilingGM() + : fLooper(SkIntToScalar(1), SkIntToScalar(2), SkIntToScalar(2), + 0x88000000) { + for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); i++) { + makebm(&fTexture[i], gConfigs[i], gWidth, gHeight); + } + } + + SkBitmap fTexture[SK_ARRAY_COUNT(gConfigs)]; + +protected: + SkString onShortName() { + return SkString("tilemodes"); + } + + SkISize onISize() { return make_isize(880, 560); } + + void drawBG(SkCanvas* canvas) { + canvas->drawColor(SK_ColorWHITE); + } + + virtual void onDraw(SkCanvas* canvas) { + this->drawBG(canvas); + + SkRect r = { 0, 0, SkIntToScalar(gWidth*2), SkIntToScalar(gHeight*2) }; + + static const char* gConfigNames[] = { "8888", "565", "4444" }; + + static const bool gFilters[] = { false, true }; + static const char* gFilterNames[] = { "point", "bilinear" }; + + static const SkShader::TileMode gModes[] = { SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode, SkShader::kMirror_TileMode }; + static const char* gModeNames[] = { "C", "R", "M" }; + + SkScalar y = SkIntToScalar(24); + SkScalar x = SkIntToScalar(10); + + for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) { + for (size_t ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) { + SkPaint p; + SkString str; + p.setAntiAlias(true); + p.setDither(true); + p.setLooper(&fLooper); + str.printf("[%s,%s]", gModeNames[kx], gModeNames[ky]); + + p.setTextAlign(SkPaint::kCenter_Align); + canvas->drawText(str.c_str(), str.size(), x + r.width()/2, y, p); + + x += r.width() * 4 / 3; + } + } + + y += SkIntToScalar(16); + + for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); i++) { + for (size_t j = 0; j < SK_ARRAY_COUNT(gFilters); j++) { + x = SkIntToScalar(10); + for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) { + for (size_t ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) { + SkPaint paint; + setup(&paint, fTexture[i], gFilters[j], gModes[kx], gModes[ky]); + paint.setDither(true); + + canvas->save(); + canvas->translate(x, y); + canvas->drawRect(r, paint); + canvas->restore(); + + x += r.width() * 4 / 3; + } + } + { + SkPaint p; + SkString str; + p.setAntiAlias(true); + p.setLooper(&fLooper); + str.printf("%s, %s", gConfigNames[i], gFilterNames[j]); + canvas->drawText(str.c_str(), str.size(), x, y + r.height() * 2 / 3, p); + } + + y += r.height() * 4 / 3; + } + } + } + +private: + typedef GM INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +static GM* MyFactory(void*) { return new TilingGM; } +static GMRegistry reg(MyFactory); + +} + diff --git a/gm/xfermodes.cpp b/gm/xfermodes.cpp new file mode 100644 index 0000000..5a43f4a --- /dev/null +++ b/gm/xfermodes.cpp @@ -0,0 +1,188 @@ +#include "gm.h" +#include "SkBitmap.h" +#include "SkShader.h" +#include "SkXfermode.h" + +namespace skiagm { + +static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst) { + src->setConfig(SkBitmap::kARGB_8888_Config, w, h); + src->allocPixels(); + src->eraseColor(0); + + SkCanvas c(*src); + SkPaint p; + SkRect r; + SkScalar ww = SkIntToScalar(w); + SkScalar hh = SkIntToScalar(h); + + p.setAntiAlias(true); + p.setColor(0xFFFFCC44); + r.set(0, 0, ww*3/4, hh*3/4); + c.drawOval(r, p); + + dst->setConfig(SkBitmap::kARGB_8888_Config, w, h); + dst->allocPixels(); + dst->eraseColor(0); + c.setBitmapDevice(*dst); + + p.setColor(0xFF66AAFF); + r.set(ww/3, hh/3, ww*19/20, hh*19/20); + c.drawRect(r, p); +} + +static uint16_t gBG[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF }; + +class XfermodesGM : public GM { + SkBitmap fBitmap; + SkBitmap fBG; + SkBitmap fSrcB, fDstB; + + void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha) { + SkPaint p; + + canvas->drawBitmap(fSrcB, 0, 0, &p); + p.setAlpha(alpha); + p.setXfermode(mode); + canvas->drawBitmap(fDstB, 0, 0, &p); + } + +public: + XfermodesGM() { + const int W = 64; + const int H = 64; + + fBitmap.setConfig(SkBitmap::kARGB_8888_Config, W, H); + fBitmap.allocPixels(); + + fBG.setConfig(SkBitmap::kARGB_4444_Config, 2, 2, 4); + fBG.setPixels(gBG); + fBG.setIsOpaque(true); + + make_bitmaps(W, H, &fSrcB, &fDstB); + } + +protected: + virtual SkString onShortName() { + return SkString("xfermodes"); + } + + virtual SkISize onISize() { + return make_isize(790, 480); + } + + void drawBG(SkCanvas* canvas) { + canvas->drawColor(SK_ColorWHITE); + return; + SkShader* s = SkShader::CreateBitmapShader(fBG, + SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode); + SkPaint p; + SkMatrix m; + + p.setShader(s)->unref(); + m.setScale(SkIntToScalar(8), SkIntToScalar(8)); + s->setLocalMatrix(m); + canvas->drawPaint(p); + } + + virtual void onDraw(SkCanvas* canvas) { + this->drawBG(canvas); + + const struct { + SkXfermode::Mode fMode; + const char* fLabel; + } gModes[] = { + { SkXfermode::kClear_Mode, "Clear" }, + { SkXfermode::kSrc_Mode, "Src" }, + { SkXfermode::kDst_Mode, "Dst" }, + { SkXfermode::kSrcOver_Mode, "SrcOver" }, + { SkXfermode::kDstOver_Mode, "DstOver" }, + { SkXfermode::kSrcIn_Mode, "SrcIn" }, + { SkXfermode::kDstIn_Mode, "DstIn" }, + { SkXfermode::kSrcOut_Mode, "SrcOut" }, + { SkXfermode::kDstOut_Mode, "DstOut" }, + { SkXfermode::kSrcATop_Mode, "SrcATop" }, + { SkXfermode::kDstATop_Mode, "DstATop" }, + { SkXfermode::kXor_Mode, "Xor" }, + + { SkXfermode::kPlus_Mode, "Plus" }, + { SkXfermode::kMultiply_Mode, "Multiply" }, + { SkXfermode::kScreen_Mode, "Screen" }, + { SkXfermode::kOverlay_Mode, "Overlay" }, + { SkXfermode::kDarken_Mode, "Darken" }, + { SkXfermode::kLighten_Mode, "Lighten" }, + { SkXfermode::kColorDodge_Mode, "ColorDodge" }, + { SkXfermode::kColorBurn_Mode, "ColorBurn" }, + { SkXfermode::kHardLight_Mode, "HardLight" }, + { SkXfermode::kSoftLight_Mode, "SoftLight" }, + { SkXfermode::kDifference_Mode, "Difference" }, + { SkXfermode::kExclusion_Mode, "Exclusion" }, + }; + + canvas->translate(SkIntToScalar(10), SkIntToScalar(20)); + + SkCanvas c(fBitmap); + const SkScalar w = SkIntToScalar(fBitmap.width()); + const SkScalar h = SkIntToScalar(fBitmap.height()); + SkShader* s = SkShader::CreateBitmapShader(fBG, + SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode); + SkMatrix m; + m.setScale(SkIntToScalar(6), SkIntToScalar(6)); + s->setLocalMatrix(m); + + SkPaint labelP; + labelP.setAntiAlias(true); + labelP.setTextAlign(SkPaint::kCenter_Align); + + const int W = 5; + + SkScalar x0 = 0; + for (int twice = 0; twice < 2; twice++) { + SkScalar x = x0, y = 0; + for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) { + SkXfermode* mode = SkXfermode::Create(gModes[i].fMode); + + fBitmap.eraseColor(0); + draw_mode(&c, mode, twice ? 0x88 : 0xFF); + SkSafeUnref(mode); + + SkPaint p; + SkRect r; + r.set(x, y, x+w, y+h); + r.inset(-SK_ScalarHalf, -SK_ScalarHalf); + p.setStyle(SkPaint::kStroke_Style); + canvas->drawRect(r, p); + p.setStyle(SkPaint::kFill_Style); + p.setShader(s); + r.inset(SK_ScalarHalf, SK_ScalarHalf); + canvas->drawRect(r, p); + + canvas->drawBitmap(fBitmap, x, y, NULL); + + canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel), + x + w/2, y - labelP.getTextSize()/2, labelP); + + x += w + SkIntToScalar(10); + if ((i % W) == W - 1) { + x = x0; + y += h + SkIntToScalar(30); + } + } + x0 += SkIntToScalar(400); + } + s->unref(); + } + +private: + typedef GM INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +static GM* MyFactory(void*) { return new XfermodesGM; } +static GMRegistry reg(MyFactory); + +} + |