From c64599649bab68aedf07959f86fa506fc46fa3c2 Mon Sep 17 00:00:00 2001 From: "reed@android.com" Date: Tue, 25 Aug 2009 19:15:31 +0000 Subject: [PATCH] special case 1x1 bitmaps when drawn as a shader (treat as a solid color) git-svn-id: http://skia.googlecode.com/svn/trunk@336 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/core/SkColorPriv.h | 15 ++++++++ samplecode/SampleDitherBitmap.cpp | 17 ++++++++ samplecode/SampleTinyBitmap.cpp | 81 +++++++++++++++++++++++++++++++++++++++ src/core/SkBitmapProcShader.cpp | 41 +++++++++++++++++++- 4 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 samplecode/SampleTinyBitmap.cpp diff --git a/include/core/SkColorPriv.h b/include/core/SkColorPriv.h index 7658d5b..5129ac6 100644 --- a/include/core/SkColorPriv.h +++ b/include/core/SkColorPriv.h @@ -393,6 +393,21 @@ inline SkPMColor SkPixel16ToPixel32(U16CPU src) return SkPackARGB32(0xFF, r, g, b); } +// similar to SkPixel16ToPixel32, but returns SkColor instead of SkPMColor +static inline SkColor SkPixel16ToColor(U16CPU src) { + SkASSERT(src == SkToU16(src)); + + unsigned r = SkPacked16ToR32(src); + unsigned g = SkPacked16ToG32(src); + unsigned b = SkPacked16ToB32(src); + + SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src)); + SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src)); + SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src)); + + return SkColorSetRGB(r, g, b); +} + /////////////////////////////////////////////////////////////////////////////// typedef uint16_t SkPMColor16; diff --git a/samplecode/SampleDitherBitmap.cpp b/samplecode/SampleDitherBitmap.cpp index 35816a2..e859cda 100644 --- a/samplecode/SampleDitherBitmap.cpp +++ b/samplecode/SampleDitherBitmap.cpp @@ -4,6 +4,22 @@ #include "SkCanvas.h" #include "SkUtils.h" +static void test_pathregion() { + SkPath path; + SkRegion region; + path.moveTo(25071800.f, -141823808.f); + path.lineTo(25075500.f, -141824000.f); + path.lineTo(25075400.f, -141827712.f); + path.lineTo(25071810.f, -141827600.f); + path.close(); + + SkIRect bounds; + path.getBounds().round(&bounds); + SkRegion clip(bounds); + bool result = region.setPath(path, clip); // <-- !! DOWN !! + SkDebugf("----- result %d\n", result); +} + static SkBitmap make_bitmap() { SkBitmap bm; SkColorTable* ctable = new SkColorTable(256); @@ -33,6 +49,7 @@ class DitherBitmapView : public SkView { SkBitmap fBM32; public: DitherBitmapView() { + test_pathregion(); fBM8 = make_bitmap(); fBM8.copyTo(&fBM32, SkBitmap::kARGB_8888_Config); } diff --git a/samplecode/SampleTinyBitmap.cpp b/samplecode/SampleTinyBitmap.cpp new file mode 100644 index 0000000..1563c7a --- /dev/null +++ b/samplecode/SampleTinyBitmap.cpp @@ -0,0 +1,81 @@ +#include "SampleCode.h" +#include "SkColorPriv.h" +#include "SkShader.h" +#include "SkView.h" +#include "SkCanvas.h" +#include "SkUtils.h" + +static SkBitmap make_bitmap() { + SkBitmap bm; + const int N = 1; + SkColorTable* ctable = new SkColorTable(N); + + SkPMColor* c = ctable->lockColors(); + for (int i = 0; i < N; i++) { + c[i] = SkPackARGB32(0x80, 0x80, 0, 0); + } + ctable->unlockColors(true); + bm.setConfig(SkBitmap::kIndex8_Config, 1, 1); + bm.allocPixels(ctable); + ctable->unref(); + + bm.lockPixels(); + for (int y = 0; y < bm.height(); y++) { + uint8_t* p = bm.getAddr8(0, y); + for (int x = 0; x < bm.width(); x++) { + p[x] = 0; + } + } + bm.unlockPixels(); + return bm; +} + +class TinyBitmapView : public SkView { + SkBitmap fBM; +public: + TinyBitmapView() { + fBM = make_bitmap(); + } + +protected: + // overrides from SkEventSink + virtual bool onQuery(SkEvent* evt) { + if (SampleCode::TitleQ(*evt)) { + SampleCode::TitleR(evt, "TinyBitmap"); + return true; + } + return this->INHERITED::onQuery(evt); + } + + void drawBG(SkCanvas* canvas) { + canvas->drawColor(0xFFDDDDDD); + } + + static void setBitmapOpaque(SkBitmap* bm, bool isOpaque) { + SkAutoLockPixels alp(*bm); // needed for ctable + bm->setIsOpaque(isOpaque); + SkColorTable* ctable = bm->getColorTable(); + if (ctable) { + ctable->setIsOpaque(isOpaque); + } + } + + virtual void onDraw(SkCanvas* canvas) { + drawBG(canvas); + + SkShader* s = SkShader::CreateBitmapShader(fBM, SkShader::kRepeat_TileMode, + SkShader::kMirror_TileMode); + SkPaint paint; + paint.setShader(s)->unref(); + canvas->drawPaint(paint); + } + +private: + typedef SkView INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +static SkView* MyFactory() { return new TinyBitmapView; } +static SkViewRegister reg(MyFactory); + diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp index 353388b..cb4d129 100644 --- a/src/core/SkBitmapProcShader.cpp +++ b/src/core/SkBitmapProcShader.cpp @@ -207,14 +207,51 @@ void SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) { /////////////////////////////////////////////////////////////////////////////// +#include "SkUnPreMultiply.h" +#include "SkColorShader.h" + +// returns true and set color if the bitmap can be drawn as a single color +// (for efficiency) +static bool canUseColorShader(const SkBitmap& bm, SkColor* color) { + if (1 != bm.width() || 1 != bm.height()) { + return false; + } + + SkAutoLockPixels alp(bm); + if (!bm.readyToDraw()) { + return false; + } + + switch (bm.config()) { + case SkBitmap::kARGB_8888_Config: + *color = SkUnPreMultiply::PMColorToColor(*bm.getAddr32(0, 0)); + return true; + case SkBitmap::kRGB_565_Config: + *color = SkPixel16ToColor(*bm.getAddr16(0, 0)); + return true; + case SkBitmap::kIndex8_Config: + *color = SkUnPreMultiply::PMColorToColor(bm.getIndex8Color(0, 0)); + return true; + default: // just skip the other configs for now + break; + } + return false; +} + #include "SkTemplatesPriv.h" SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy, void* storage, size_t storageSize) { SkShader* shader; - SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage, - storageSize, (src, tmx, tmy)); + SkColor color; + if (canUseColorShader(src, &color)) { + SK_PLACEMENT_NEW_ARGS(shader, SkColorShader, storage, storageSize, + (color)); + } else { + SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage, + storageSize, (src, tmx, tmy)); + } return shader; } -- 2.7.4