| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2015 Google Inc. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license that can be | |
| 5 * found in the LICENSE file. | |
| 6 */ | |
| 7 | |
| 8 #include "SkAndroidSDKCanvas.h" | |
| 9 | |
| 10 #include "SkColorFilter.h" | |
| 11 #include "SkPaint.h" | |
| 12 #include "SkPathEffect.h" | |
| 13 #include "SkShader.h" | |
| 14 #include "SkTLazy.h" | |
| 15 | |
| 16 namespace { | |
| 17 | |
| 18 /** Discard SkShaders not exposed by the Android Java API. */ | |
| 19 | |
| 20 void CheckShader(SkPaint* paint) { | |
| 21 SkShader* shader = paint->getShader(); | |
| 22 if (!shader) { | |
| 23 return; | |
| 24 } | |
| 25 | |
| 26 if (shader->isABitmap()) { | |
| 27 return; | |
| 28 } | |
| 29 if (shader->asACompose(nullptr)) { | |
| 30 return; | |
| 31 } | |
| 32 SkShader::GradientType gtype = shader->asAGradient(nullptr); | |
| 33 if (gtype == SkShader::kLinear_GradientType || | |
| 34 gtype == SkShader::kRadial_GradientType || | |
| 35 gtype == SkShader::kSweep_GradientType) { | |
| 36 return; | |
| 37 } | |
| 38 paint->setShader(nullptr); | |
| 39 } | |
| 40 | |
| 41 void Filter(SkPaint* paint) { | |
| 42 | |
| 43 uint32_t flags = paint->getFlags(); | |
| 44 flags &= ~SkPaint::kLCDRenderText_Flag; | |
| 45 paint->setFlags(flags); | |
| 46 | |
| 47 // Android doesn't support Xfermodes above kLighten_Mode | |
| 48 SkXfermode::Mode mode; | |
| 49 SkXfermode::AsMode(paint->getXfermode(), &mode); | |
| 50 if (mode > SkXfermode::kLighten_Mode) { | |
| 51 paint->setXfermode(nullptr); | |
| 52 } | |
| 53 | |
| 54 // Force bilinear scaling or none | |
| 55 if (paint->getFilterQuality() != kNone_SkFilterQuality) { | |
| 56 paint->setFilterQuality(kLow_SkFilterQuality); | |
| 57 } | |
| 58 | |
| 59 CheckShader(paint); | |
| 60 | |
| 61 // Android SDK only supports mode & matrix color filters | |
| 62 // (and, again, no modes above kLighten_Mode). | |
| 63 SkColorFilter* cf = paint->getColorFilter(); | |
| 64 if (cf) { | |
| 65 SkColor color; | |
| 66 SkXfermode::Mode mode; | |
| 67 SkScalar srcColorMatrix[20]; | |
| 68 bool isMode = cf->asColorMode(&color, &mode); | |
| 69 if (isMode && mode > SkXfermode::kLighten_Mode) { | |
| 70 paint->setColorFilter( | |
| 71 SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcOver_Mode
)); | |
| 72 } else if (!isMode && !cf->asColorMatrix(srcColorMatrix)) { | |
| 73 paint->setColorFilter(nullptr); | |
| 74 } | |
| 75 } | |
| 76 | |
| 77 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | |
| 78 SkPathEffect* pe = paint->getPathEffect(); | |
| 79 if (pe && !pe->exposedInAndroidJavaAPI()) { | |
| 80 paint->setPathEffect(nullptr); | |
| 81 } | |
| 82 #endif | |
| 83 | |
| 84 // TODO: Android doesn't support all the flags that can be passed to | |
| 85 // blur filters; we need plumbing to get them out. | |
| 86 | |
| 87 paint->setImageFilter(nullptr); | |
| 88 paint->setLooper(nullptr); | |
| 89 }; | |
| 90 | |
| 91 } // namespace | |
| 92 | |
| 93 #define FILTER(p) \ | |
| 94 SkPaint filteredPaint(p); \ | |
| 95 Filter(&filteredPaint); | |
| 96 | |
| 97 #define FILTER_PTR(p) \ | |
| 98 SkTLazy<SkPaint> lazyPaint; \ | |
| 99 SkPaint* filteredPaint = (SkPaint*) p; \ | |
| 100 if (p) { \ | |
| 101 filteredPaint = lazyPaint.set(*p); \ | |
| 102 Filter(filteredPaint); \ | |
| 103 } | |
| 104 | |
| 105 | |
| 106 SkAndroidSDKCanvas::SkAndroidSDKCanvas() : fProxyTarget(nullptr) { } | |
| 107 | |
| 108 void SkAndroidSDKCanvas::reset(SkCanvas* newTarget) { fProxyTarget = newTarget;
} | |
| 109 | |
| 110 void SkAndroidSDKCanvas::onDrawPaint(const SkPaint& paint) { | |
| 111 FILTER(paint); | |
| 112 fProxyTarget->drawPaint(filteredPaint); | |
| 113 } | |
| 114 void SkAndroidSDKCanvas::onDrawPoints(PointMode pMode, | |
| 115 size_t count, | |
| 116 const SkPoint pts[], | |
| 117 const SkPaint& paint) { | |
| 118 FILTER(paint); | |
| 119 fProxyTarget->drawPoints(pMode, count, pts, filteredPaint); | |
| 120 } | |
| 121 void SkAndroidSDKCanvas::onDrawOval(const SkRect& r, const SkPaint& paint) { | |
| 122 FILTER(paint); | |
| 123 fProxyTarget->drawOval(r, filteredPaint); | |
| 124 } | |
| 125 void SkAndroidSDKCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) { | |
| 126 FILTER(paint); | |
| 127 fProxyTarget->drawRect(r, filteredPaint); | |
| 128 } | |
| 129 void SkAndroidSDKCanvas::onDrawRRect(const SkRRect& r, const SkPaint& paint) { | |
| 130 FILTER(paint); | |
| 131 fProxyTarget->drawRRect(r, filteredPaint); | |
| 132 } | |
| 133 void SkAndroidSDKCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { | |
| 134 FILTER(paint); | |
| 135 fProxyTarget->drawPath(path, filteredPaint); | |
| 136 } | |
| 137 void SkAndroidSDKCanvas::onDrawBitmap(const SkBitmap& bitmap, | |
| 138 SkScalar left, | |
| 139 SkScalar top, | |
| 140 const SkPaint* paint) { | |
| 141 FILTER_PTR(paint); | |
| 142 fProxyTarget->drawBitmap(bitmap, left, top, filteredPaint); | |
| 143 } | |
| 144 void SkAndroidSDKCanvas::onDrawBitmapRect(const SkBitmap& bitmap, | |
| 145 const SkRect* src, | |
| 146 const SkRect& dst, | |
| 147 const SkPaint* paint, | |
| 148 SkCanvas::SrcRectConstraint c
onstraint) { | |
| 149 FILTER_PTR(paint); | |
| 150 fProxyTarget->legacy_drawBitmapRect(bitmap, src, dst, filteredPaint, constra
int); | |
| 151 } | |
| 152 void SkAndroidSDKCanvas::onDrawBitmapNine(const SkBitmap& bitmap, | |
| 153 const SkIRect& center, | |
| 154 const SkRect& dst, | |
| 155 const SkPaint* paint) { | |
| 156 FILTER_PTR(paint); | |
| 157 fProxyTarget->drawBitmapNine(bitmap, center, dst, filteredPaint); | |
| 158 } | |
| 159 void SkAndroidSDKCanvas::onDrawVertices(VertexMode vMode, | |
| 160 int vertexCount, | |
| 161 const SkPoint vertices[], | |
| 162 const SkPoint texs[], const SkColor colors[], SkXfermode* xM
ode, | |
| 163 const uint16_t indices[], int indexCount, | |
| 164 const SkPaint& paint) { | |
| 165 FILTER(paint); | |
| 166 fProxyTarget->drawVertices(vMode, vertexCount, vertices, texs, colors, | |
| 167 xMode, indices, indexCount, filteredPaint); | |
| 168 } | |
| 169 | |
| 170 void SkAndroidSDKCanvas::onDrawDRRect(const SkRRect& outer, | |
| 171 const SkRRect& inner, | |
| 172 const SkPaint& paint) { | |
| 173 FILTER(paint); | |
| 174 fProxyTarget->drawDRRect(outer, inner, filteredPaint); | |
| 175 } | |
| 176 | |
| 177 void SkAndroidSDKCanvas::onDrawText(const void* text, | |
| 178 size_t byteLength, | |
| 179 SkScalar x, | |
| 180 SkScalar y, | |
| 181 const SkPaint& paint) { | |
| 182 FILTER(paint); | |
| 183 fProxyTarget->drawText(text, byteLength, x, y, filteredPaint); | |
| 184 } | |
| 185 void SkAndroidSDKCanvas::onDrawPosText(const void* text, | |
| 186 size_t byteLength, | |
| 187 const SkPoint pos[], | |
| 188 const SkPaint& paint) { | |
| 189 FILTER(paint); | |
| 190 fProxyTarget->drawPosText(text, byteLength, pos, filteredPaint); | |
| 191 } | |
| 192 void SkAndroidSDKCanvas::onDrawPosTextH(const void* text, | |
| 193 size_t byteLength, | |
| 194 const SkScalar xpos[], | |
| 195 SkScalar constY, | |
| 196 const SkPaint& paint) { | |
| 197 FILTER(paint); | |
| 198 fProxyTarget->drawPosTextH(text, byteLength, xpos, constY, filteredPaint); | |
| 199 } | |
| 200 void SkAndroidSDKCanvas::onDrawTextOnPath(const void* text, | |
| 201 size_t byteLength, | |
| 202 const SkPath& path, | |
| 203 const SkMatrix* matrix, | |
| 204 const SkPaint& paint) { | |
| 205 FILTER(paint); | |
| 206 fProxyTarget->drawTextOnPath(text, byteLength, path, matrix, filteredPaint); | |
| 207 } | |
| 208 void SkAndroidSDKCanvas::onDrawTextBlob(const SkTextBlob* blob, | |
| 209 SkScalar x, | |
| 210 SkScalar y, | |
| 211 const SkPaint& paint) { | |
| 212 FILTER(paint); | |
| 213 fProxyTarget->drawTextBlob(blob, x, y, filteredPaint); | |
| 214 } | |
| 215 | |
| 216 void SkAndroidSDKCanvas::onDrawPatch(const SkPoint cubics[12], | |
| 217 const SkColor colors[4], | |
| 218 const SkPoint texCoords[4], | |
| 219 SkXfermode* xmode, | |
| 220 const SkPaint& paint) { | |
| 221 FILTER(paint); | |
| 222 fProxyTarget->drawPatch(cubics, colors, texCoords, xmode, filteredPaint); | |
| 223 } | |
| 224 | |
| 225 | |
| 226 void SkAndroidSDKCanvas::onDrawImage(const SkImage* image, | |
| 227 SkScalar x, | |
| 228 SkScalar y, | |
| 229 const SkPaint* paint) { | |
| 230 FILTER_PTR(paint); | |
| 231 fProxyTarget->drawImage(image, x, y, filteredPaint); | |
| 232 } | |
| 233 | |
| 234 void SkAndroidSDKCanvas::onDrawImageRect(const SkImage* image, | |
| 235 const SkRect* in, | |
| 236 const SkRect& out, | |
| 237 const SkPaint* paint, | |
| 238 SrcRectConstraint constraint) { | |
| 239 FILTER_PTR(paint); | |
| 240 fProxyTarget->legacy_drawImageRect(image, in, out, filteredPaint, constraint
); | |
| 241 } | |
| 242 | |
| 243 void SkAndroidSDKCanvas::onDrawPicture(const SkPicture* picture, | |
| 244 const SkMatrix* matrix, | |
| 245 const SkPaint* paint) { | |
| 246 FILTER_PTR(paint); | |
| 247 fProxyTarget->drawPicture(picture, matrix, filteredPaint); | |
| 248 } | |
| 249 | |
| 250 void SkAndroidSDKCanvas::onDrawAtlas(const SkImage* atlas, | |
| 251 const SkRSXform xform[], | |
| 252 const SkRect tex[], | |
| 253 const SkColor colors[], | |
| 254 int count, | |
| 255 SkXfermode::Mode mode, | |
| 256 const SkRect* cullRect, | |
| 257 const SkPaint* paint) { | |
| 258 FILTER_PTR(paint); | |
| 259 fProxyTarget->drawAtlas(atlas, xform, tex, colors, count, mode, cullRect, | |
| 260 filteredPaint); | |
| 261 } | |
| 262 | |
| 263 void SkAndroidSDKCanvas::onDrawImageNine(const SkImage* image, | |
| 264 const SkIRect& center, | |
| 265 const SkRect& dst, | |
| 266 const SkPaint* paint) { | |
| 267 FILTER_PTR(paint); | |
| 268 fProxyTarget->drawImageNine(image, center, dst, filteredPaint); | |
| 269 } | |
| 270 | |
| 271 | |
| 272 void SkAndroidSDKCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* ma
trix) { | |
| 273 fProxyTarget->drawDrawable(drawable, matrix); | |
| 274 } | |
| 275 | |
| 276 SkISize SkAndroidSDKCanvas::getBaseLayerSize() const { | |
| 277 return fProxyTarget->getBaseLayerSize(); | |
| 278 } | |
| 279 bool SkAndroidSDKCanvas::getClipBounds(SkRect* rect) const { | |
| 280 return fProxyTarget->getClipBounds(rect); | |
| 281 } | |
| 282 bool SkAndroidSDKCanvas::getClipDeviceBounds(SkIRect* rect) const { | |
| 283 return fProxyTarget->getClipDeviceBounds(rect); | |
| 284 } | |
| 285 | |
| 286 bool SkAndroidSDKCanvas::isClipEmpty() const { return fProxyTarget->isClipEmpty(
); } | |
| 287 bool SkAndroidSDKCanvas::isClipRect() const { return fProxyTarget->isClipRect();
} | |
| 288 | |
| 289 SkSurface* SkAndroidSDKCanvas::onNewSurface(const SkImageInfo& info, | |
| 290 const SkSurfaceProps& props
) { | |
| 291 return fProxyTarget->newSurface(info, &props); | |
| 292 } | |
| 293 | |
| 294 bool SkAndroidSDKCanvas::onPeekPixels(SkPixmap* pmap) { | |
| 295 SkASSERT(pmap); | |
| 296 SkImageInfo info; | |
| 297 size_t rowBytes; | |
| 298 const void* addr = fProxyTarget->peekPixels(&info, &rowBytes); | |
| 299 if (addr) { | |
| 300 pmap->reset(info, addr, rowBytes); | |
| 301 return true; | |
| 302 } | |
| 303 return false; | |
| 304 } | |
| 305 | |
| 306 bool SkAndroidSDKCanvas::onAccessTopLayerPixels(SkPixmap* pmap) { | |
| 307 SkASSERT(pmap); | |
| 308 SkImageInfo info; | |
| 309 size_t rowBytes; | |
| 310 const void* addr = fProxyTarget->accessTopLayerPixels(&info, &rowBytes, null
ptr); | |
| 311 if (addr) { | |
| 312 pmap->reset(info, addr, rowBytes); | |
| 313 return true; | |
| 314 } | |
| 315 return false; | |
| 316 } | |
| 317 | |
| 318 void SkAndroidSDKCanvas::willSave() { | |
| 319 fProxyTarget->save(); | |
| 320 } | |
| 321 | |
| 322 SkCanvas::SaveLayerStrategy SkAndroidSDKCanvas::getSaveLayerStrategy(const SaveL
ayerRec& rec) { | |
| 323 fProxyTarget->saveLayer(rec); | |
| 324 return SkCanvas::kNoLayer_SaveLayerStrategy; | |
| 325 } | |
| 326 | |
| 327 void SkAndroidSDKCanvas::willRestore() { | |
| 328 fProxyTarget->restore(); | |
| 329 } | |
| 330 | |
| 331 void SkAndroidSDKCanvas::didRestore() { } | |
| 332 | |
| 333 void SkAndroidSDKCanvas::didConcat(const SkMatrix& m) { | |
| 334 fProxyTarget->concat(m); | |
| 335 } | |
| 336 | |
| 337 void SkAndroidSDKCanvas::didSetMatrix(const SkMatrix& m) { | |
| 338 fProxyTarget->setMatrix(m); | |
| 339 } | |
| 340 | |
| 341 void SkAndroidSDKCanvas::onClipRect(const SkRect& rect, | |
| 342 SkRegion::Op op, | |
| 343 ClipEdgeStyle style) { | |
| 344 fProxyTarget->clipRect(rect, op, style); | |
| 345 } | |
| 346 | |
| 347 void SkAndroidSDKCanvas::onClipRRect(const SkRRect& rrect, | |
| 348 SkRegion::Op op, | |
| 349 ClipEdgeStyle style) { | |
| 350 fProxyTarget->clipRRect(rrect, op, style); | |
| 351 } | |
| 352 | |
| 353 void SkAndroidSDKCanvas::onClipPath(const SkPath& path, | |
| 354 SkRegion::Op op, | |
| 355 ClipEdgeStyle style) { | |
| 356 fProxyTarget->clipPath(path, op, style); | |
| 357 } | |
| 358 | |
| 359 void SkAndroidSDKCanvas::onClipRegion(const SkRegion& region, SkRegion::Op op) { | |
| 360 fProxyTarget->clipRegion(region, op); | |
| 361 } | |
| 362 | |
| 363 void SkAndroidSDKCanvas::onDiscard() { fProxyTarget->discard(); } | |
| 364 | |
| 365 | |
| OLD | NEW |