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 23static 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 33class SkGrayScaleColorFilter : public SkColorFilter { 34public: 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 43class SkChannelMaskColorFilter : public SkColorFilter { 44public: 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 57private: 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 69class Dot2DPathEffect : public Sk2DPathEffect { 70public: 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 77protected: 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 105private: 106 SkScalar fRadius; 107 SkTDArray<SkPoint>* fPts; 108 109 typedef Sk2DPathEffect INHERITED; 110}; 111 112SkFlattenable* Dot2DPathEffect::CreateProc(SkReadBuffer& buffer) { 113 SkMatrix matrix; 114 buffer.readMatrix(&matrix); 115 return SkNEW_ARGS(Dot2DPathEffect, (buffer.readScalar(), matrix, NULL)); 116} 117 118class InverseFillPE : public SkPathEffect { 119public: 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 129protected: 130#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 131 InverseFillPE(SkReadBuffer& buffer) : INHERITED(buffer) {} 132#endif 133 134private: 135 136 typedef SkPathEffect INHERITED; 137}; 138 139SkFlattenable* InverseFillPE::CreateProc(SkReadBuffer& buffer) { 140 return SkNEW(InverseFillPE); 141} 142 143static 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 151static 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 163typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&); 164 165#include "SkXfermode.h" 166 167static 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 179class ClockFaceView : public SkView { 180 SkTypeface* fFace; 181 SkScalar fInterp; 182 SkScalar fDx; 183 184public: 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 195protected: 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 261private: 262 typedef SkView INHERITED; 263}; 264 265////////////////////////////////////////////////////////////////////////////// 266 267static SkView* MyFactory() { return new ClockFaceView; } 268static SkViewRegister reg(MyFactory); 269