1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 #include "SampleCode.h" 9 #include "SkView.h" 10 #include "SkCanvas.h" 11 #include "Sk64.h" 12 #include "SkCornerPathEffect.h" 13 #include "SkGradientShader.h" 14 #include "SkGraphics.h" 15 #include "SkImageDecoder.h" 16 #include "SkKernel33MaskFilter.h" 17 #include "SkPath.h" 18 #include "SkRandom.h" 19 #include "SkRegion.h" 20 #include "SkShader.h" 21 #include "SkUtils.h" 22 #include "SkColorPriv.h" 23 #include "SkColorFilter.h" 24 #include "SkTime.h" 25 #include "SkTypeface.h" 26 #include "SkXfermode.h" 27 28 #include "SkStream.h" 29 #include "SkXMLParser.h" 30 #include "SkColorPriv.h" 31 #include "SkImageDecoder.h" 32 33 static void setNamedTypeface(SkPaint* paint, const char name[]) { 34 SkTypeface* face = SkTypeface::CreateFromName(name, SkTypeface::kNormal); 35 paint->setTypeface(face); 36 SkSafeUnref(face); 37 } 38 39 #if 0 40 static int newscale(U8CPU a, U8CPU b, int shift) { 41 unsigned prod = a * b + (1 << (shift - 1)); 42 return (prod + (prod >> shift)) >> shift; 43 } 44 45 static void test_srcover565(SkCanvas* canvas) { 46 const int width = 32; 47 SkBitmap bm1, bm2, bm3; 48 bm1.setConfig(SkBitmap::kRGB_565_Config, width, 256); bm1.allocPixels(NULL); 49 bm2.setConfig(SkBitmap::kRGB_565_Config, width, 256); bm2.allocPixels(NULL); 50 bm3.setConfig(SkBitmap::kRGB_565_Config, width, 256); bm3.allocPixels(NULL); 51 52 int rgb = 0x18; 53 int r = rgb >> 3; 54 int g = rgb >> 2; 55 uint16_t dst = SkPackRGB16(r, g, r); 56 for (int alpha = 0; alpha <= 255; alpha++) { 57 SkPMColor pm = SkPreMultiplyARGB(alpha, rgb, rgb, rgb); 58 uint16_t newdst = SkSrcOver32To16(pm, dst); 59 sk_memset16(bm1.getAddr16(0, alpha), newdst, bm1.width()); 60 61 int ia = 255 - alpha; 62 int iscale = SkAlpha255To256(ia); 63 int dr = (SkGetPackedR32(pm) + (r * iscale >> 5)) >> 3; 64 int dg = (SkGetPackedG32(pm) + (g * iscale >> 6)) >> 2; 65 66 sk_memset16(bm2.getAddr16(0, alpha), SkPackRGB16(dr, dg, dr), bm2.width()); 67 68 int dr2 = (SkMulDiv255Round(alpha, rgb) + newscale(r, ia, 5)) >> 3; 69 int dg2 = (SkMulDiv255Round(alpha, rgb) + newscale(g, ia, 6)) >> 2; 70 71 sk_memset16(bm3.getAddr16(0, alpha), SkPackRGB16(dr2, dg2, dr2), bm3.width()); 72 73 // if (mr != dr || mg != dg) 74 { 75 // SkDebugf("[%d] macro [%d %d] inline [%d %d] new [%d %d]\n", alpha, mr, mg, dr, dg, dr2, dg2); 76 } 77 } 78 79 SkScalar dx = SkIntToScalar(width+4); 80 81 canvas->drawBitmap(bm1, 0, 0, NULL); canvas->translate(dx, 0); 82 canvas->drawBitmap(bm2, 0, 0, NULL); canvas->translate(dx, 0); 83 canvas->drawBitmap(bm3, 0, 0, NULL); canvas->translate(dx, 0); 84 85 SkRect rect = { 0, 0, SkIntToScalar(bm1.width()), SkIntToScalar(bm1.height()) }; 86 SkPaint p; 87 p.setARGB(0xFF, rgb, rgb, rgb); 88 canvas->drawRect(rect, p); 89 } 90 #endif 91 92 static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst) { 93 src->setConfig(SkBitmap::kARGB_8888_Config, w, h); 94 src->allocPixels(); 95 src->eraseColor(0); 96 97 SkCanvas c(*src); 98 SkPaint p; 99 SkRect r; 100 SkScalar ww = SkIntToScalar(w); 101 SkScalar hh = SkIntToScalar(h); 102 103 p.setAntiAlias(true); 104 p.setColor(0xFFFFCC44); 105 r.set(0, 0, ww*3/4, hh*3/4); 106 c.drawOval(r, p); 107 108 dst->setConfig(SkBitmap::kARGB_8888_Config, w, h); 109 dst->allocPixels(); 110 dst->eraseColor(0); 111 c.setBitmapDevice(*dst); 112 113 p.setColor(0xFF66AAFF); 114 r.set(ww/3, hh/3, ww*19/20, hh*19/20); 115 c.drawRect(r, p); 116 } 117 118 static uint16_t gBG[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF }; 119 120 class XfermodesView : public SampleView { 121 SkBitmap fBG; 122 SkBitmap fSrcB, fDstB; 123 124 void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha, 125 SkScalar x, SkScalar y) { 126 SkPaint p; 127 128 canvas->drawBitmap(fSrcB, x, y, &p); 129 p.setAlpha(alpha); 130 p.setXfermode(mode); 131 canvas->drawBitmap(fDstB, x, y, &p); 132 } 133 134 public: 135 const static int W = 64; 136 const static int H = 64; 137 XfermodesView() { 138 const int W = 64; 139 const int H = 64; 140 141 fBG.setConfig(SkBitmap::kARGB_4444_Config, 2, 2, 4); 142 fBG.setPixels(gBG); 143 fBG.setIsOpaque(true); 144 145 make_bitmaps(W, H, &fSrcB, &fDstB); 146 } 147 148 protected: 149 // overrides from SkEventSink 150 virtual bool onQuery(SkEvent* evt) { 151 if (SampleCode::TitleQ(*evt)) { 152 SampleCode::TitleR(evt, "Xfermodes"); 153 return true; 154 } 155 return this->INHERITED::onQuery(evt); 156 } 157 158 virtual void onDrawContent(SkCanvas* canvas) { 159 canvas->translate(SkIntToScalar(10), SkIntToScalar(20)); 160 161 const struct { 162 SkXfermode::Mode fMode; 163 const char* fLabel; 164 } gModes[] = { 165 { SkXfermode::kClear_Mode, "Clear" }, 166 { SkXfermode::kSrc_Mode, "Src" }, 167 { SkXfermode::kDst_Mode, "Dst" }, 168 { SkXfermode::kSrcOver_Mode, "SrcOver" }, 169 { SkXfermode::kDstOver_Mode, "DstOver" }, 170 { SkXfermode::kSrcIn_Mode, "SrcIn" }, 171 { SkXfermode::kDstIn_Mode, "DstIn" }, 172 { SkXfermode::kSrcOut_Mode, "SrcOut" }, 173 { SkXfermode::kDstOut_Mode, "DstOut" }, 174 { SkXfermode::kSrcATop_Mode, "SrcATop" }, 175 { SkXfermode::kDstATop_Mode, "DstATop" }, 176 { SkXfermode::kXor_Mode, "Xor" }, 177 178 { SkXfermode::kPlus_Mode, "Plus" }, 179 { SkXfermode::kMultiply_Mode, "Multiply" }, 180 { SkXfermode::kScreen_Mode, "Screen" }, 181 { SkXfermode::kOverlay_Mode, "Overlay" }, 182 { SkXfermode::kDarken_Mode, "Darken" }, 183 { SkXfermode::kLighten_Mode, "Lighten" }, 184 { SkXfermode::kColorDodge_Mode, "ColorDodge" }, 185 { SkXfermode::kColorBurn_Mode, "ColorBurn" }, 186 { SkXfermode::kHardLight_Mode, "HardLight" }, 187 { SkXfermode::kSoftLight_Mode, "SoftLight" }, 188 { SkXfermode::kDifference_Mode, "Difference" }, 189 { SkXfermode::kExclusion_Mode, "Exclusion" }, 190 }; 191 192 const SkScalar w = SkIntToScalar(W); 193 const SkScalar h = SkIntToScalar(H); 194 SkShader* s = SkShader::CreateBitmapShader(fBG, 195 SkShader::kRepeat_TileMode, 196 SkShader::kRepeat_TileMode); 197 SkMatrix m; 198 m.setScale(SkIntToScalar(6), SkIntToScalar(6)); 199 s->setLocalMatrix(m); 200 201 SkPaint labelP; 202 labelP.setAntiAlias(true); 203 labelP.setLCDRenderText(true); 204 labelP.setTextAlign(SkPaint::kCenter_Align); 205 setNamedTypeface(&labelP, "Menlo Regular"); 206 // labelP.setTextSize(SkIntToScalar(11)); 207 208 const int W = 5; 209 210 SkScalar x0 = 0; 211 for (int twice = 0; twice < 2; twice++) { 212 SkScalar x = x0, y = 0; 213 for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) { 214 SkXfermode* mode = SkXfermode::Create(gModes[i].fMode); 215 SkAutoUnref aur(mode); 216 SkRect r; 217 r.set(x, y, x+w, y+h); 218 219 SkPaint p; 220 p.setStyle(SkPaint::kFill_Style); 221 p.setShader(s); 222 canvas->drawRect(r, p); 223 224 canvas->saveLayer(&r, NULL, SkCanvas::kARGB_ClipLayer_SaveFlag); 225 // canvas->save(); 226 draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop); 227 canvas->restore(); 228 229 r.inset(-SK_ScalarHalf, -SK_ScalarHalf); 230 p.setStyle(SkPaint::kStroke_Style); 231 p.setShader(NULL); 232 canvas->drawRect(r, p); 233 234 #if 1 235 canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel), 236 x + w/2, y - labelP.getTextSize()/2, labelP); 237 #endif 238 x += w + SkIntToScalar(10); 239 if ((i % W) == W - 1) { 240 x = x0; 241 y += h + SkIntToScalar(30); 242 } 243 } 244 x0 += SkIntToScalar(400); 245 } 246 s->unref(); 247 } 248 249 private: 250 typedef SampleView INHERITED; 251 }; 252 253 ////////////////////////////////////////////////////////////////////////////// 254 255 static SkView* MyFactory() { return new XfermodesView; } 256 static SkViewRegister reg(MyFactory); 257 258