1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/effects/SkLayerDrawLooper.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,381 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2011 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 +#include "SkCanvas.h" 1.12 +#include "SkColor.h" 1.13 +#include "SkReadBuffer.h" 1.14 +#include "SkWriteBuffer.h" 1.15 +#include "SkLayerDrawLooper.h" 1.16 +#include "SkString.h" 1.17 +#include "SkStringUtils.h" 1.18 +#include "SkUnPreMultiply.h" 1.19 + 1.20 +SkLayerDrawLooper::LayerInfo::LayerInfo() { 1.21 + fPaintBits = 0; // ignore our paint fields 1.22 + fColorMode = SkXfermode::kDst_Mode; // ignore our color 1.23 + fOffset.set(0, 0); 1.24 + fPostTranslate = false; 1.25 +} 1.26 + 1.27 +SkLayerDrawLooper::SkLayerDrawLooper() 1.28 + : fRecs(NULL), 1.29 + fTopRec(NULL), 1.30 + fCount(0) { 1.31 +} 1.32 + 1.33 +SkLayerDrawLooper::~SkLayerDrawLooper() { 1.34 + Rec* rec = fRecs; 1.35 + while (rec) { 1.36 + Rec* next = rec->fNext; 1.37 + SkDELETE(rec); 1.38 + rec = next; 1.39 + } 1.40 +} 1.41 + 1.42 +SkPaint* SkLayerDrawLooper::addLayer(const LayerInfo& info) { 1.43 + fCount += 1; 1.44 + 1.45 + Rec* rec = SkNEW(Rec); 1.46 + rec->fNext = fRecs; 1.47 + rec->fInfo = info; 1.48 + fRecs = rec; 1.49 + if (NULL == fTopRec) { 1.50 + fTopRec = rec; 1.51 + } 1.52 + 1.53 + return &rec->fPaint; 1.54 +} 1.55 + 1.56 +void SkLayerDrawLooper::addLayer(SkScalar dx, SkScalar dy) { 1.57 + LayerInfo info; 1.58 + 1.59 + info.fOffset.set(dx, dy); 1.60 + (void)this->addLayer(info); 1.61 +} 1.62 + 1.63 +SkPaint* SkLayerDrawLooper::addLayerOnTop(const LayerInfo& info) { 1.64 + fCount += 1; 1.65 + 1.66 + Rec* rec = SkNEW(Rec); 1.67 + rec->fNext = NULL; 1.68 + rec->fInfo = info; 1.69 + if (NULL == fRecs) { 1.70 + fRecs = rec; 1.71 + } else { 1.72 + SkASSERT(NULL != fTopRec); 1.73 + fTopRec->fNext = rec; 1.74 + } 1.75 + fTopRec = rec; 1.76 + 1.77 + return &rec->fPaint; 1.78 +} 1.79 + 1.80 +SkLayerDrawLooper::Context* SkLayerDrawLooper::createContext(SkCanvas* canvas, void* storage) const { 1.81 + canvas->save(SkCanvas::kMatrix_SaveFlag); 1.82 + return SkNEW_PLACEMENT_ARGS(storage, LayerDrawLooperContext, (this)); 1.83 +} 1.84 + 1.85 +static SkColor xferColor(SkColor src, SkColor dst, SkXfermode::Mode mode) { 1.86 + switch (mode) { 1.87 + case SkXfermode::kSrc_Mode: 1.88 + return src; 1.89 + case SkXfermode::kDst_Mode: 1.90 + return dst; 1.91 + default: { 1.92 + SkPMColor pmS = SkPreMultiplyColor(src); 1.93 + SkPMColor pmD = SkPreMultiplyColor(dst); 1.94 + SkPMColor result = SkXfermode::GetProc(mode)(pmS, pmD); 1.95 + return SkUnPreMultiply::PMColorToColor(result); 1.96 + } 1.97 + } 1.98 +} 1.99 + 1.100 +// Even with kEntirePaint_Bits, we always ensure that the master paint's 1.101 +// text-encoding is respected, since that controls how we interpret the 1.102 +// text/length parameters of a draw[Pos]Text call. 1.103 +void SkLayerDrawLooper::LayerDrawLooperContext::ApplyInfo( 1.104 + SkPaint* dst, const SkPaint& src, const LayerInfo& info) { 1.105 + 1.106 + dst->setColor(xferColor(src.getColor(), dst->getColor(), info.fColorMode)); 1.107 + 1.108 + BitFlags bits = info.fPaintBits; 1.109 + SkPaint::TextEncoding encoding = dst->getTextEncoding(); 1.110 + 1.111 + if (0 == bits) { 1.112 + return; 1.113 + } 1.114 + if (kEntirePaint_Bits == bits) { 1.115 + // we've already computed these, so save it from the assignment 1.116 + uint32_t f = dst->getFlags(); 1.117 + SkColor c = dst->getColor(); 1.118 + *dst = src; 1.119 + dst->setFlags(f); 1.120 + dst->setColor(c); 1.121 + dst->setTextEncoding(encoding); 1.122 + return; 1.123 + } 1.124 + 1.125 + if (bits & kStyle_Bit) { 1.126 + dst->setStyle(src.getStyle()); 1.127 + dst->setStrokeWidth(src.getStrokeWidth()); 1.128 + dst->setStrokeMiter(src.getStrokeMiter()); 1.129 + dst->setStrokeCap(src.getStrokeCap()); 1.130 + dst->setStrokeJoin(src.getStrokeJoin()); 1.131 + } 1.132 + 1.133 + if (bits & kTextSkewX_Bit) { 1.134 + dst->setTextSkewX(src.getTextSkewX()); 1.135 + } 1.136 + 1.137 + if (bits & kPathEffect_Bit) { 1.138 + dst->setPathEffect(src.getPathEffect()); 1.139 + } 1.140 + if (bits & kMaskFilter_Bit) { 1.141 + dst->setMaskFilter(src.getMaskFilter()); 1.142 + } 1.143 + if (bits & kShader_Bit) { 1.144 + dst->setShader(src.getShader()); 1.145 + } 1.146 + if (bits & kColorFilter_Bit) { 1.147 + dst->setColorFilter(src.getColorFilter()); 1.148 + } 1.149 + if (bits & kXfermode_Bit) { 1.150 + dst->setXfermode(src.getXfermode()); 1.151 + } 1.152 + 1.153 + // we don't override these 1.154 +#if 0 1.155 + dst->setTypeface(src.getTypeface()); 1.156 + dst->setTextSize(src.getTextSize()); 1.157 + dst->setTextScaleX(src.getTextScaleX()); 1.158 + dst->setRasterizer(src.getRasterizer()); 1.159 + dst->setLooper(src.getLooper()); 1.160 + dst->setTextEncoding(src.getTextEncoding()); 1.161 + dst->setHinting(src.getHinting()); 1.162 +#endif 1.163 +} 1.164 + 1.165 +// Should we add this to canvas? 1.166 +static void postTranslate(SkCanvas* canvas, SkScalar dx, SkScalar dy) { 1.167 + SkMatrix m = canvas->getTotalMatrix(); 1.168 + m.postTranslate(dx, dy); 1.169 + canvas->setMatrix(m); 1.170 +} 1.171 + 1.172 +SkLayerDrawLooper::LayerDrawLooperContext::LayerDrawLooperContext( 1.173 + const SkLayerDrawLooper* looper) : fCurrRec(looper->fRecs) {} 1.174 + 1.175 +bool SkLayerDrawLooper::LayerDrawLooperContext::next(SkCanvas* canvas, 1.176 + SkPaint* paint) { 1.177 + canvas->restore(); 1.178 + if (NULL == fCurrRec) { 1.179 + return false; 1.180 + } 1.181 + 1.182 + ApplyInfo(paint, fCurrRec->fPaint, fCurrRec->fInfo); 1.183 + 1.184 + canvas->save(SkCanvas::kMatrix_SaveFlag); 1.185 + if (fCurrRec->fInfo.fPostTranslate) { 1.186 + postTranslate(canvas, fCurrRec->fInfo.fOffset.fX, 1.187 + fCurrRec->fInfo.fOffset.fY); 1.188 + } else { 1.189 + canvas->translate(fCurrRec->fInfo.fOffset.fX, 1.190 + fCurrRec->fInfo.fOffset.fY); 1.191 + } 1.192 + fCurrRec = fCurrRec->fNext; 1.193 + 1.194 + return true; 1.195 +} 1.196 + 1.197 +/////////////////////////////////////////////////////////////////////////////// 1.198 + 1.199 +void SkLayerDrawLooper::flatten(SkWriteBuffer& buffer) const { 1.200 + this->INHERITED::flatten(buffer); 1.201 + 1.202 +#ifdef SK_DEBUG 1.203 + { 1.204 + Rec* rec = fRecs; 1.205 + int count = 0; 1.206 + while (rec) { 1.207 + rec = rec->fNext; 1.208 + count += 1; 1.209 + } 1.210 + SkASSERT(count == fCount); 1.211 + } 1.212 +#endif 1.213 + 1.214 + buffer.writeInt(fCount); 1.215 + 1.216 + Rec* rec = fRecs; 1.217 + for (int i = 0; i < fCount; i++) { 1.218 + // Legacy "flagsmask" field -- now ignored, remove when we bump version 1.219 + buffer.writeInt(0); 1.220 + 1.221 + buffer.writeInt(rec->fInfo.fPaintBits); 1.222 + buffer.writeInt(rec->fInfo.fColorMode); 1.223 + buffer.writePoint(rec->fInfo.fOffset); 1.224 + buffer.writeBool(rec->fInfo.fPostTranslate); 1.225 + buffer.writePaint(rec->fPaint); 1.226 + rec = rec->fNext; 1.227 + } 1.228 +} 1.229 + 1.230 +SkFlattenable* SkLayerDrawLooper::CreateProc(SkReadBuffer& buffer) { 1.231 + int count = buffer.readInt(); 1.232 + 1.233 + Builder builder; 1.234 + for (int i = 0; i < count; i++) { 1.235 + LayerInfo info; 1.236 + // Legacy "flagsmask" field -- now ignored, remove when we bump version 1.237 + (void)buffer.readInt(); 1.238 + 1.239 + info.fPaintBits = buffer.readInt(); 1.240 + info.fColorMode = (SkXfermode::Mode)buffer.readInt(); 1.241 + buffer.readPoint(&info.fOffset); 1.242 + info.fPostTranslate = buffer.readBool(); 1.243 + buffer.readPaint(builder.addLayerOnTop(info)); 1.244 + } 1.245 + SkLayerDrawLooper* looper = builder.detachLooper(); 1.246 + SkASSERT(count == looper->fCount); 1.247 + 1.248 +#ifdef SK_DEBUG 1.249 + { 1.250 + Rec* rec = looper->fRecs; 1.251 + int n = 0; 1.252 + while (rec) { 1.253 + rec = rec->fNext; 1.254 + n += 1; 1.255 + } 1.256 + SkASSERT(count == n); 1.257 + } 1.258 +#endif 1.259 + 1.260 + return looper; 1.261 +} 1.262 + 1.263 +#ifndef SK_IGNORE_TO_STRING 1.264 +void SkLayerDrawLooper::toString(SkString* str) const { 1.265 + str->appendf("SkLayerDrawLooper (%d): ", fCount); 1.266 + 1.267 + Rec* rec = fRecs; 1.268 + for (int i = 0; i < fCount; i++) { 1.269 + str->appendf("%d: paintBits: (", i); 1.270 + if (0 == rec->fInfo.fPaintBits) { 1.271 + str->append("None"); 1.272 + } else if (kEntirePaint_Bits == rec->fInfo.fPaintBits) { 1.273 + str->append("EntirePaint"); 1.274 + } else { 1.275 + bool needSeparator = false; 1.276 + SkAddFlagToString(str, SkToBool(kStyle_Bit & rec->fInfo.fPaintBits), "Style", 1.277 + &needSeparator); 1.278 + SkAddFlagToString(str, SkToBool(kTextSkewX_Bit & rec->fInfo.fPaintBits), "TextSkewX", 1.279 + &needSeparator); 1.280 + SkAddFlagToString(str, SkToBool(kPathEffect_Bit & rec->fInfo.fPaintBits), "PathEffect", 1.281 + &needSeparator); 1.282 + SkAddFlagToString(str, SkToBool(kMaskFilter_Bit & rec->fInfo.fPaintBits), "MaskFilter", 1.283 + &needSeparator); 1.284 + SkAddFlagToString(str, SkToBool(kShader_Bit & rec->fInfo.fPaintBits), "Shader", 1.285 + &needSeparator); 1.286 + SkAddFlagToString(str, SkToBool(kColorFilter_Bit & rec->fInfo.fPaintBits), "ColorFilter", 1.287 + &needSeparator); 1.288 + SkAddFlagToString(str, SkToBool(kXfermode_Bit & rec->fInfo.fPaintBits), "Xfermode", 1.289 + &needSeparator); 1.290 + } 1.291 + str->append(") "); 1.292 + 1.293 + static const char* gModeStrings[SkXfermode::kLastMode+1] = { 1.294 + "kClear", "kSrc", "kDst", "kSrcOver", "kDstOver", "kSrcIn", "kDstIn", 1.295 + "kSrcOut", "kDstOut", "kSrcATop", "kDstATop", "kXor", "kPlus", 1.296 + "kMultiply", "kScreen", "kOverlay", "kDarken", "kLighten", "kColorDodge", 1.297 + "kColorBurn", "kHardLight", "kSoftLight", "kDifference", "kExclusion" 1.298 + }; 1.299 + 1.300 + str->appendf("mode: %s ", gModeStrings[rec->fInfo.fColorMode]); 1.301 + 1.302 + str->append("offset: ("); 1.303 + str->appendScalar(rec->fInfo.fOffset.fX); 1.304 + str->append(", "); 1.305 + str->appendScalar(rec->fInfo.fOffset.fY); 1.306 + str->append(") "); 1.307 + 1.308 + str->append("postTranslate: "); 1.309 + if (rec->fInfo.fPostTranslate) { 1.310 + str->append("true "); 1.311 + } else { 1.312 + str->append("false "); 1.313 + } 1.314 + 1.315 + rec->fPaint.toString(str); 1.316 + rec = rec->fNext; 1.317 + } 1.318 +} 1.319 +#endif 1.320 + 1.321 +SkLayerDrawLooper::Builder::Builder() 1.322 + : fRecs(NULL), 1.323 + fTopRec(NULL), 1.324 + fCount(0) { 1.325 +} 1.326 + 1.327 +SkLayerDrawLooper::Builder::~Builder() { 1.328 + Rec* rec = fRecs; 1.329 + while (rec) { 1.330 + Rec* next = rec->fNext; 1.331 + SkDELETE(rec); 1.332 + rec = next; 1.333 + } 1.334 +} 1.335 + 1.336 +SkPaint* SkLayerDrawLooper::Builder::addLayer(const LayerInfo& info) { 1.337 + fCount += 1; 1.338 + 1.339 + Rec* rec = SkNEW(Rec); 1.340 + rec->fNext = fRecs; 1.341 + rec->fInfo = info; 1.342 + fRecs = rec; 1.343 + if (NULL == fTopRec) { 1.344 + fTopRec = rec; 1.345 + } 1.346 + 1.347 + return &rec->fPaint; 1.348 +} 1.349 + 1.350 +void SkLayerDrawLooper::Builder::addLayer(SkScalar dx, SkScalar dy) { 1.351 + LayerInfo info; 1.352 + 1.353 + info.fOffset.set(dx, dy); 1.354 + (void)this->addLayer(info); 1.355 +} 1.356 + 1.357 +SkPaint* SkLayerDrawLooper::Builder::addLayerOnTop(const LayerInfo& info) { 1.358 + fCount += 1; 1.359 + 1.360 + Rec* rec = SkNEW(Rec); 1.361 + rec->fNext = NULL; 1.362 + rec->fInfo = info; 1.363 + if (NULL == fRecs) { 1.364 + fRecs = rec; 1.365 + } else { 1.366 + SkASSERT(NULL != fTopRec); 1.367 + fTopRec->fNext = rec; 1.368 + } 1.369 + fTopRec = rec; 1.370 + 1.371 + return &rec->fPaint; 1.372 +} 1.373 + 1.374 +SkLayerDrawLooper* SkLayerDrawLooper::Builder::detachLooper() { 1.375 + SkLayerDrawLooper* looper = SkNEW(SkLayerDrawLooper); 1.376 + looper->fCount = fCount; 1.377 + looper->fRecs = fRecs; 1.378 + 1.379 + fCount = 0; 1.380 + fRecs = NULL; 1.381 + fTopRec = NULL; 1.382 + 1.383 + return looper; 1.384 +}