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