special case 1x1 bitmaps when drawn as a shader (treat as a solid color)
authorreed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 25 Aug 2009 19:15:31 +0000 (19:15 +0000)
committerreed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 25 Aug 2009 19:15:31 +0000 (19:15 +0000)
git-svn-id: http://skia.googlecode.com/svn/trunk@336 2bbb7eff-a529-9590-31e7-b0007b416f81

include/core/SkColorPriv.h
samplecode/SampleDitherBitmap.cpp
samplecode/SampleTinyBitmap.cpp [new file with mode: 0644]
src/core/SkBitmapProcShader.cpp

index 7658d5b..5129ac6 100644 (file)
@@ -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;
index 35816a2..e859cda 100644 (file)
@@ -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 (file)
index 0000000..1563c7a
--- /dev/null
@@ -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);
+
index 353388b..cb4d129 100644 (file)
@@ -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;
 }