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 "SkReadBuffer.h" 12 #include "SkWriteBuffer.h" 13 #include "SkGradientShader.h" 14 #include "SkPath.h" 15 #include "SkRegion.h" 16 #include "SkShader.h" 17 #include "SkUtils.h" 18 #include "SkColorPriv.h" 19 #include "SkColorFilter.h" 20 #include "SkTypeface.h" 21 #include "SkAvoidXfermode.h" 22 23 static inline SkPMColor rgb2gray(SkPMColor c) { 24 unsigned r = SkGetPackedR32(c); 25 unsigned g = SkGetPackedG32(c); 26 unsigned b = SkGetPackedB32(c); 27 28 unsigned x = (r * 5 + g * 7 + b * 4) >> 4; 29 30 return SkPackARGB32(0, x, x, x) | (c & (SK_A32_MASK << SK_A32_SHIFT)); 31 } 32 33 class SkGrayScaleColorFilter : public SkColorFilter { 34 public: 35 virtual void filterSpan(const SkPMColor src[], int count, 36 SkPMColor result[]) const SK_OVERRIDE { 37 for (int i = 0; i < count; i++) { 38 result[i] = rgb2gray(src[i]); 39 } 40 } 41 }; 42 43 class SkChannelMaskColorFilter : public SkColorFilter { 44 public: 45 SkChannelMaskColorFilter(U8CPU redMask, U8CPU greenMask, U8CPU blueMask) { 46 fMask = SkPackARGB32(0xFF, redMask, greenMask, blueMask); 47 } 48 49 virtual void filterSpan(const SkPMColor src[], int count, 50 SkPMColor result[]) const SK_OVERRIDE { 51 SkPMColor mask = fMask; 52 for (int i = 0; i < count; i++) { 53 result[i] = src[i] & mask; 54 } 55 } 56 57 private: 58 SkPMColor fMask; 59 }; 60 61 /////////////////////////////////////////////////////////////////////////////// 62 63 #include "SkGradientShader.h" 64 #include "SkLayerRasterizer.h" 65 #include "SkBlurMaskFilter.h" 66 67 #include "Sk2DPathEffect.h" 68 69 class Dot2DPathEffect : public Sk2DPathEffect { 70 public: 71 Dot2DPathEffect(SkScalar radius, const SkMatrix& matrix, 72 SkTDArray<SkPoint>* pts) 73 : Sk2DPathEffect(matrix), fRadius(radius), fPts(pts) {} 74 75 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Dot2DPathEffect) 76 77 protected: 78 virtual void begin(const SkIRect& uvBounds, SkPath* dst) const SK_OVERRIDE { 79 if (fPts) { 80 fPts->reset(); 81 } 82 this->INHERITED::begin(uvBounds, dst); 83 } 84 85 virtual void next(const SkPoint& loc, int u, int v, 86 SkPath* dst) const SK_OVERRIDE { 87 if (fPts) { 88 *fPts->append() = loc; 89 } 90 dst->addCircle(loc.fX, loc.fY, fRadius); 91 } 92 93 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 94 Dot2DPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) { 95 fRadius = buffer.readScalar(); 96 fPts = NULL; 97 } 98 #endif 99 100 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE { 101 buffer.writeMatrix(this->getMatrix()); 102 buffer.writeScalar(fRadius); 103 } 104 105 private: 106 SkScalar fRadius; 107 SkTDArray<SkPoint>* fPts; 108 109 typedef Sk2DPathEffect INHERITED; 110 }; 111 112 SkFlattenable* Dot2DPathEffect::CreateProc(SkReadBuffer& buffer) { 113 SkMatrix matrix; 114 buffer.readMatrix(&matrix); 115 return SkNEW_ARGS(Dot2DPathEffect, (buffer.readScalar(), matrix, NULL)); 116 } 117 118 class InverseFillPE : public SkPathEffect { 119 public: 120 InverseFillPE() {} 121 virtual bool filterPath(SkPath* dst, const SkPath& src, 122 SkStrokeRec*, const SkRect*) const SK_OVERRIDE { 123 *dst = src; 124 dst->setFillType(SkPath::kInverseWinding_FillType); 125 return true; 126 } 127 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(InverseFillPE) 128 129 protected: 130 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 131 InverseFillPE(SkReadBuffer& buffer) : INHERITED(buffer) {} 132 #endif 133 134 private: 135 136 typedef SkPathEffect INHERITED; 137 }; 138 139 SkFlattenable* InverseFillPE::CreateProc(SkReadBuffer& buffer) { 140 return SkNEW(InverseFillPE); 141 } 142 143 static SkPathEffect* makepe(float interp, SkTDArray<SkPoint>* pts) { 144 SkMatrix lattice; 145 SkScalar rad = 3 + SkIntToScalar(4) * (1 - interp); 146 lattice.setScale(rad*2, rad*2, 0, 0); 147 lattice.postSkew(SK_Scalar1/3, 0, 0, 0); 148 return new Dot2DPathEffect(rad, lattice, pts); 149 } 150 151 static void r7(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p, SkScalar interp) { 152 p.setPathEffect(makepe(SkScalarToFloat(interp), NULL))->unref(); 153 rastBuilder->addLayer(p); 154 #if 0 155 p.setPathEffect(new InverseFillPE())->unref(); 156 p.setXfermodeMode(SkXfermode::kSrcIn_Mode); 157 p.setXfermodeMode(SkXfermode::kClear_Mode); 158 p.setAlpha((1 - interp) * 255); 159 rastBuilder->addLayer(p); 160 #endif 161 } 162 163 typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&); 164 165 #include "SkXfermode.h" 166 167 static void apply_shader(SkPaint* paint, float scale) 168 { 169 SkPaint p; 170 SkLayerRasterizer::Builder rastBuilder; 171 172 p.setAntiAlias(true); 173 r7(&rastBuilder, p, scale); 174 paint->setRasterizer(rastBuilder.detachRasterizer())->unref(); 175 176 paint->setColor(SK_ColorBLUE); 177 } 178 179 class ClockFaceView : public SkView { 180 SkTypeface* fFace; 181 SkScalar fInterp; 182 SkScalar fDx; 183 184 public: 185 ClockFaceView() { 186 fFace = SkTypeface::CreateFromFile("/Users/reed/Downloads/p052024l.pfb"); 187 fInterp = 0; 188 fDx = SK_Scalar1/64; 189 } 190 191 virtual ~ClockFaceView() { 192 SkSafeUnref(fFace); 193 } 194 195 protected: 196 // overrides from SkEventSink 197 virtual bool onQuery(SkEvent* evt) { 198 if (SampleCode::TitleQ(*evt)) { 199 SampleCode::TitleR(evt, "Text Effects"); 200 return true; 201 } 202 return this->INHERITED::onQuery(evt); 203 } 204 205 void drawBG(SkCanvas* canvas) { 206 // canvas->drawColor(0xFFDDDDDD); 207 canvas->drawColor(SK_ColorWHITE); 208 } 209 210 static void drawdots(SkCanvas* canvas, const SkPaint& orig) { 211 SkTDArray<SkPoint> pts; 212 SkPathEffect* pe = makepe(0, &pts); 213 214 SkStrokeRec rec(SkStrokeRec::kFill_InitStyle); 215 SkPath path, dstPath; 216 orig.getTextPath("9", 1, 0, 0, &path); 217 pe->filterPath(&dstPath, path, &rec, NULL); 218 219 SkPaint p; 220 p.setAntiAlias(true); 221 p.setStrokeWidth(10); 222 p.setColor(SK_ColorRED); 223 canvas->drawPoints(SkCanvas::kPoints_PointMode, pts.count(), pts.begin(), 224 p); 225 } 226 227 virtual void onDraw(SkCanvas* canvas) { 228 this->drawBG(canvas); 229 230 SkScalar x = SkIntToScalar(20); 231 SkScalar y = SkIntToScalar(300); 232 SkPaint paint; 233 234 paint.setAntiAlias(true); 235 paint.setTextSize(SkIntToScalar(240)); 236 paint.setTypeface(SkTypeface::CreateFromName("sans-serif", 237 SkTypeface::kBold)); 238 239 SkString str("9"); 240 241 paint.setTypeface(fFace); 242 243 apply_shader(&paint, SkScalarToFloat(fInterp)); 244 canvas->drawText(str.c_str(), str.size(), x, y, paint); 245 246 // drawdots(canvas, paint); 247 248 if (false) { 249 fInterp += fDx; 250 if (fInterp > 1) { 251 fInterp = 1; 252 fDx = -fDx; 253 } else if (fInterp < 0) { 254 fInterp = 0; 255 fDx = -fDx; 256 } 257 this->inval(NULL); 258 } 259 } 260 261 private: 262 typedef SkView INHERITED; 263 }; 264 265 ////////////////////////////////////////////////////////////////////////////// 266 267 static SkView* MyFactory() { return new ClockFaceView; } 268 static SkViewRegister reg(MyFactory); 269