blob: b2feae77a1f1ab0dabd7747ef0525514c47090f9 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SampleCode.h"
9#include "SkView.h"
10#include "SkCanvas.h"
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000011#include "SkFlattenableBuffers.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000012#include "SkGradientShader.h"
13#include "SkPath.h"
14#include "SkRegion.h"
15#include "SkShader.h"
16#include "SkUtils.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000017#include "SkColorPriv.h"
18#include "SkColorFilter.h"
19#include "SkTypeface.h"
20#include "SkAvoidXfermode.h"
21
reed@google.comf2183392011-04-22 14:10:48 +000022static inline SkPMColor rgb2gray(SkPMColor c) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000023 unsigned r = SkGetPackedR32(c);
24 unsigned g = SkGetPackedG32(c);
25 unsigned b = SkGetPackedB32(c);
reed@google.com82065d62011-02-07 15:30:46 +000026
reed@google.com261b8e22011-04-14 17:53:24 +000027 unsigned x = (r * 5 + g * 7 + b * 4) >> 4;
reed@google.com82065d62011-02-07 15:30:46 +000028
reed@android.com8a1c16f2008-12-17 15:59:43 +000029 return SkPackARGB32(0, x, x, x) | (c & (SK_A32_MASK << SK_A32_SHIFT));
30}
31
32class SkGrayScaleColorFilter : public SkColorFilter {
33public:
reed@google.comf2183392011-04-22 14:10:48 +000034 virtual void filterSpan(const SkPMColor src[], int count,
35 SkPMColor result[]) {
36 for (int i = 0; i < count; i++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000037 result[i] = rgb2gray(src[i]);
reed@google.comf2183392011-04-22 14:10:48 +000038 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000039 }
40};
41
42class SkChannelMaskColorFilter : public SkColorFilter {
43public:
reed@google.comf2183392011-04-22 14:10:48 +000044 SkChannelMaskColorFilter(U8CPU redMask, U8CPU greenMask, U8CPU blueMask) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000045 fMask = SkPackARGB32(0xFF, redMask, greenMask, blueMask);
46 }
47
reed@google.comf2183392011-04-22 14:10:48 +000048 virtual void filterSpan(const SkPMColor src[], int count,
49 SkPMColor result[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000050 SkPMColor mask = fMask;
reed@google.comf2183392011-04-22 14:10:48 +000051 for (int i = 0; i < count; i++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000052 result[i] = src[i] & mask;
reed@google.comf2183392011-04-22 14:10:48 +000053 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000054 }
reed@google.com82065d62011-02-07 15:30:46 +000055
reed@android.com8a1c16f2008-12-17 15:59:43 +000056private:
57 SkPMColor fMask;
58};
59
60///////////////////////////////////////////////////////////
61
62#include "SkGradientShader.h"
63#include "SkLayerRasterizer.h"
64#include "SkBlurMaskFilter.h"
65
reed@google.comf2183392011-04-22 14:10:48 +000066static void r0(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000067 p.setMaskFilter(SkBlurMaskFilter::Create(SkIntToScalar(3),
68 SkBlurMaskFilter::kNormal_BlurStyle))->unref();
69 rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
70
71 p.setMaskFilter(NULL);
72 p.setStyle(SkPaint::kStroke_Style);
73 p.setStrokeWidth(SK_Scalar1);
74 rast->addLayer(p);
75
76 p.setAlpha(0x11);
77 p.setStyle(SkPaint::kFill_Style);
reed@android.com0baf1932009-06-24 12:41:42 +000078 p.setXfermodeMode(SkXfermode::kSrc_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +000079 rast->addLayer(p);
80}
81
reed@google.comf2183392011-04-22 14:10:48 +000082static void r1(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000083 rast->addLayer(p);
84
85 p.setAlpha(0x40);
reed@android.com0baf1932009-06-24 12:41:42 +000086 p.setXfermodeMode(SkXfermode::kSrc_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +000087 p.setStyle(SkPaint::kStroke_Style);
88 p.setStrokeWidth(SK_Scalar1*2);
89 rast->addLayer(p);
90}
reed@google.com82065d62011-02-07 15:30:46 +000091
reed@google.comf2183392011-04-22 14:10:48 +000092static void r2(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000093 p.setStyle(SkPaint::kStrokeAndFill_Style);
94 p.setStrokeWidth(SK_Scalar1*4);
95 rast->addLayer(p);
96
97 p.setStyle(SkPaint::kStroke_Style);
98 p.setStrokeWidth(SK_Scalar1*3/2);
reed@android.com0baf1932009-06-24 12:41:42 +000099 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000100 rast->addLayer(p);
101}
102
reed@google.comf2183392011-04-22 14:10:48 +0000103static void r3(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000104 p.setStyle(SkPaint::kStroke_Style);
105 p.setStrokeWidth(SK_Scalar1*3);
106 rast->addLayer(p);
107
108 p.setAlpha(0x20);
109 p.setStyle(SkPaint::kFill_Style);
reed@android.com0baf1932009-06-24 12:41:42 +0000110 p.setXfermodeMode(SkXfermode::kSrc_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000111 rast->addLayer(p);
112}
113
reed@google.comf2183392011-04-22 14:10:48 +0000114static void r4(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000115 p.setAlpha(0x60);
116 rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
117
118 p.setAlpha(0xFF);
reed@android.com0baf1932009-06-24 12:41:42 +0000119 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000120 rast->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
121
122 p.setXfermode(NULL);
123 rast->addLayer(p);
124}
125
126#include "SkDiscretePathEffect.h"
127
reed@google.comf2183392011-04-22 14:10:48 +0000128static void r5(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000129 rast->addLayer(p);
130
131 p.setPathEffect(new SkDiscretePathEffect(SK_Scalar1*4, SK_Scalar1*3))->unref();
reed@android.com0baf1932009-06-24 12:41:42 +0000132 p.setXfermodeMode(SkXfermode::kSrcOut_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000133 rast->addLayer(p);
134}
135
reed@google.comf2183392011-04-22 14:10:48 +0000136static void r6(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000137 rast->addLayer(p);
reed@google.com82065d62011-02-07 15:30:46 +0000138
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139 p.setAntiAlias(false);
140 SkLayerRasterizer* rast2 = new SkLayerRasterizer;
141 r5(rast2, p);
142 p.setRasterizer(rast2)->unref();
reed@android.com0baf1932009-06-24 12:41:42 +0000143 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000144 rast->addLayer(p);
145}
146
147#include "Sk2DPathEffect.h"
148
reed@google.com18dc4772011-08-09 18:47:40 +0000149static SkPathEffect* MakeDotEffect(SkScalar radius, const SkMatrix& matrix) {
150 SkPath path;
151 path.addCircle(0, 0, radius);
152 return new SkPath2DPathEffect(matrix, path);
153}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000154
reed@google.comf2183392011-04-22 14:10:48 +0000155static void r7(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000156 SkMatrix lattice;
157 lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
158 lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
reed@google.com18dc4772011-08-09 18:47:40 +0000159 p.setPathEffect(MakeDotEffect(SK_Scalar1*4, lattice))->unref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000160 rast->addLayer(p);
161}
162
reed@google.comf2183392011-04-22 14:10:48 +0000163static void r8(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000164 rast->addLayer(p);
reed@google.com82065d62011-02-07 15:30:46 +0000165
reed@android.com8a1c16f2008-12-17 15:59:43 +0000166 SkMatrix lattice;
167 lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
168 lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
reed@google.com18dc4772011-08-09 18:47:40 +0000169 p.setPathEffect(MakeDotEffect(SK_Scalar1*2, lattice))->unref();
reed@android.com0baf1932009-06-24 12:41:42 +0000170 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000171 rast->addLayer(p);
172
173 p.setPathEffect(NULL);
174 p.setXfermode(NULL);
175 p.setStyle(SkPaint::kStroke_Style);
176 p.setStrokeWidth(SK_Scalar1);
177 rast->addLayer(p);
178}
179
180class Line2DPathEffect : public Sk2DPathEffect {
181public:
182 Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
183 : Sk2DPathEffect(matrix), fWidth(width) {}
184
reed@google.comfd4be262012-05-25 01:04:12 +0000185 virtual bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec) SK_OVERRIDE {
186 if (this->INHERITED::filterPath(dst, src, rec)) {
187 rec->setStrokeStyle(fWidth);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000188 return true;
189 }
190 return false;
191 }
reed@google.com82065d62011-02-07 15:30:46 +0000192
djsollen@google.comba28d032012-03-26 17:57:35 +0000193 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Line2DPathEffect)
reed@google.comf2183392011-04-22 14:10:48 +0000194
reed@android.com8a1c16f2008-12-17 15:59:43 +0000195protected:
reed@google.comf2183392011-04-22 14:10:48 +0000196 virtual void nextSpan(int u, int v, int ucount, SkPath* dst) {
197 if (ucount > 1) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000198 SkPoint src[2], dstP[2];
199
200 src[0].set(SkIntToScalar(u) + SK_ScalarHalf,
201 SkIntToScalar(v) + SK_ScalarHalf);
202 src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf,
203 SkIntToScalar(v) + SK_ScalarHalf);
204 this->getMatrix().mapPoints(dstP, src, 2);
reed@google.com82065d62011-02-07 15:30:46 +0000205
reed@android.com8a1c16f2008-12-17 15:59:43 +0000206 dst->moveTo(dstP[0]);
207 dst->lineTo(dstP[1]);
208 }
209 }
reed@google.com82065d62011-02-07 15:30:46 +0000210
djsollen@google.com54924242012-03-29 15:18:04 +0000211 Line2DPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000212 fWidth = buffer.readScalar();
213 }
djsollen@google.com54924242012-03-29 15:18:04 +0000214 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
215 this->INHERITED::flatten(buffer);
216 buffer.writeScalar(fWidth);
217 }
reed@google.com82065d62011-02-07 15:30:46 +0000218
reed@android.com8a1c16f2008-12-17 15:59:43 +0000219private:
220 SkScalar fWidth;
221
reed@android.com8a1c16f2008-12-17 15:59:43 +0000222 typedef Sk2DPathEffect INHERITED;
223};
224
reed@google.comf2183392011-04-22 14:10:48 +0000225static void r9(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000226 rast->addLayer(p);
reed@google.com82065d62011-02-07 15:30:46 +0000227
reed@android.com8a1c16f2008-12-17 15:59:43 +0000228 SkMatrix lattice;
229 lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
230 lattice.postRotate(SkIntToScalar(30), 0, 0);
231 p.setPathEffect(new Line2DPathEffect(SK_Scalar1*2, lattice))->unref();
reed@android.com0baf1932009-06-24 12:41:42 +0000232 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000233 rast->addLayer(p);
234
235 p.setPathEffect(NULL);
236 p.setXfermode(NULL);
237 p.setStyle(SkPaint::kStroke_Style);
238 p.setStrokeWidth(SK_Scalar1);
239 rast->addLayer(p);
240}
241
242typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&);
243
244static const raster_proc gRastProcs[] = {
245 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
246};
247
248static const struct {
249 SkColor fMul, fAdd;
250} gLightingColors[] = {
251 { 0x808080, 0x800000 }, // general case
252 { 0x707070, 0x707070 }, // no-pin case
253 { 0xFFFFFF, 0x800000 }, // just-add case
254 { 0x808080, 0x000000 }, // just-mul case
255 { 0xFFFFFF, 0x000000 } // identity case
256};
257
258#include "SkXfermode.h"
259
reed@google.comf2183392011-04-22 14:10:48 +0000260static void apply_shader(SkPaint* paint, int index) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000261 raster_proc proc = gRastProcs[index];
262 if (proc)
263 {
264 SkPaint p;
265 SkLayerRasterizer* rast = new SkLayerRasterizer;
266
267 p.setAntiAlias(true);
268 proc(rast, p);
269 paint->setRasterizer(rast)->unref();
270 }
271
272#if 0
273 SkScalar dir[] = { SK_Scalar1, SK_Scalar1, SK_Scalar1 };
reed@google.com82065d62011-02-07 15:30:46 +0000274 paint->setMaskFilter(SkBlurMaskFilter::CreateEmboss(dir, SK_Scalar1/4, SkIntToScalar(4), SkIntToScalar(3)))->unref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000275#endif
276 paint->setColor(SK_ColorBLUE);
277}
278
279static int gRastIndex;
280
reed@google.comf2183392011-04-22 14:10:48 +0000281class TextEffectView : public SampleView {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000282 SkTypeface* fFace;
283public:
reed@google.comf2183392011-04-22 14:10:48 +0000284 TextEffectView() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000285 fFace = SkTypeface::CreateFromFile("/Users/reed/Downloads/p052024l.pfb");
286 }
reed@google.com82065d62011-02-07 15:30:46 +0000287
reed@google.comf2183392011-04-22 14:10:48 +0000288 virtual ~TextEffectView() {
reed@google.com82065d62011-02-07 15:30:46 +0000289 SkSafeUnref(fFace);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000290 }
291
292protected:
293 // overrides from SkEventSink
reed@google.comf2183392011-04-22 14:10:48 +0000294 virtual bool onQuery(SkEvent* evt) {
295 if (SampleCode::TitleQ(*evt)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000296 SampleCode::TitleR(evt, "Text Effects");
297 return true;
298 }
299 return this->INHERITED::onQuery(evt);
300 }
reed@google.com82065d62011-02-07 15:30:46 +0000301
reed@google.comf2183392011-04-22 14:10:48 +0000302 virtual void onDrawContent(SkCanvas* canvas) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000303 canvas->save();
304// canvas->scale(SK_Scalar1*2, SK_Scalar1*2, 0, 0);
305
reed@android.com8a1c16f2008-12-17 15:59:43 +0000306 SkPaint paint;
reed@google.com82065d62011-02-07 15:30:46 +0000307
reed@android.com8a1c16f2008-12-17 15:59:43 +0000308 paint.setAntiAlias(true);
reed@android.com0bb6d062010-05-17 14:50:04 +0000309 paint.setTextSize(SkIntToScalar(56));
reed@android.com069b8272009-03-04 15:31:48 +0000310 paint.setTypeface(SkTypeface::CreateFromName("sans-serif",
311 SkTypeface::kBold));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000312
reed@android.com0bb6d062010-05-17 14:50:04 +0000313 SkScalar x = SkIntToScalar(20);
314 SkScalar y = paint.getTextSize();
315
316 SkString str("TextEffects");
reed@android.com8a1c16f2008-12-17 15:59:43 +0000317
318 paint.setTypeface(fFace);
reed@google.com82065d62011-02-07 15:30:46 +0000319
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000320 for (size_t i = 0; i < SK_ARRAY_COUNT(gRastProcs); i++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000321 apply_shader(&paint, i);
reed@google.com82065d62011-02-07 15:30:46 +0000322
reed@android.com8a1c16f2008-12-17 15:59:43 +0000323 // paint.setMaskFilter(NULL);
324 // paint.setColor(SK_ColorBLACK);
325
reed@google.comf2183392011-04-22 14:10:48 +0000326#if 1
reed@android.com8a1c16f2008-12-17 15:59:43 +0000327 int index = i % SK_ARRAY_COUNT(gLightingColors);
328 paint.setColorFilter(SkColorFilter::CreateLightingFilter(
329 gLightingColors[index].fMul,
330 gLightingColors[index].fAdd))->unref();
331#endif
reed@google.com82065d62011-02-07 15:30:46 +0000332
reed@android.com8a1c16f2008-12-17 15:59:43 +0000333 canvas->drawText(str.c_str(), str.size(), x, y, paint);
334
reed@android.com8a1c16f2008-12-17 15:59:43 +0000335 y += paint.getFontSpacing();
336 }
337
338 canvas->restore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000339 }
reed@google.com82065d62011-02-07 15:30:46 +0000340
reed@google.comf2183392011-04-22 14:10:48 +0000341 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000342 gRastIndex = (gRastIndex + 1) % SK_ARRAY_COUNT(gRastProcs);
343 this->inval(NULL);
344
345 return this->INHERITED::onFindClickHandler(x, y);
346 }
reed@google.com82065d62011-02-07 15:30:46 +0000347
reed@google.comf2183392011-04-22 14:10:48 +0000348 virtual bool onClick(Click* click) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000349 return this->INHERITED::onClick(click);
350 }
reed@google.com82065d62011-02-07 15:30:46 +0000351
reed@android.com8a1c16f2008-12-17 15:59:43 +0000352private:
reed@google.comf2183392011-04-22 14:10:48 +0000353 typedef SampleView INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000354};
355
356//////////////////////////////////////////////////////////////////////////////
357
358static SkView* MyFactory() { return new TextEffectView; }
359static SkViewRegister reg(MyFactory);
360