1 /* 2 * Copyright 2012 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 "GrSWMaskHelper.h" 9 10 #include "GrContext.h" 11 #include "GrContextPriv.h" 12 #include "GrShape.h" 13 #include "GrSurfaceContext.h" 14 #include "GrTextureProxy.h" 15 16 /* 17 * Convert a boolean operation into a transfer mode code 18 */ 19 static SkBlendMode op_to_mode(SkRegion::Op op) { 20 21 static const SkBlendMode modeMap[] = { 22 SkBlendMode::kDstOut, // kDifference_Op 23 SkBlendMode::kModulate, // kIntersect_Op 24 SkBlendMode::kSrcOver, // kUnion_Op 25 SkBlendMode::kXor, // kXOR_Op 26 SkBlendMode::kClear, // kReverseDifference_Op 27 SkBlendMode::kSrc, // kReplace_Op 28 }; 29 30 return modeMap[op]; 31 } 32 33 /** 34 * Draw a single rect element of the clip stack into the accumulation bitmap 35 */ 36 void GrSWMaskHelper::drawRect(const SkRect& rect, const SkMatrix& matrix, SkRegion::Op op, GrAA aa, 37 uint8_t alpha) { 38 SkPaint paint; 39 paint.setBlendMode(op_to_mode(op)); 40 paint.setAntiAlias(GrAA::kYes == aa); 41 paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha)); 42 43 SkMatrix translatedMatrix = matrix; 44 translatedMatrix.postTranslate(fTranslate.fX, fTranslate.fY); 45 fDraw.fMatrix = &translatedMatrix; 46 47 fDraw.drawRect(rect, paint); 48 } 49 50 /** 51 * Draw a single path element of the clip stack into the accumulation bitmap 52 */ 53 void GrSWMaskHelper::drawShape(const GrShape& shape, const SkMatrix& matrix, SkRegion::Op op, 54 GrAA aa, uint8_t alpha) { 55 SkPaint paint; 56 paint.setPathEffect(shape.style().refPathEffect()); 57 shape.style().strokeRec().applyToPaint(&paint); 58 paint.setAntiAlias(GrAA::kYes == aa); 59 60 SkMatrix translatedMatrix = matrix; 61 translatedMatrix.postTranslate(fTranslate.fX, fTranslate.fY); 62 fDraw.fMatrix = &translatedMatrix; 63 64 SkPath path; 65 shape.asPath(&path); 66 if (SkRegion::kReplace_Op == op && 0xFF == alpha) { 67 SkASSERT(0xFF == paint.getAlpha()); 68 fDraw.drawPathCoverage(path, paint); 69 } else { 70 paint.setBlendMode(op_to_mode(op)); 71 paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha)); 72 fDraw.drawPath(path, paint); 73 } 74 }; 75 76 bool GrSWMaskHelper::init(const SkIRect& resultBounds) { 77 // We will need to translate draws so the bound's UL corner is at the origin 78 fTranslate = {-SkIntToScalar(resultBounds.fLeft), -SkIntToScalar(resultBounds.fTop)}; 79 SkIRect bounds = SkIRect::MakeWH(resultBounds.width(), resultBounds.height()); 80 81 const SkImageInfo bmImageInfo = SkImageInfo::MakeA8(bounds.width(), bounds.height()); 82 if (!fPixels->tryAlloc(bmImageInfo)) { 83 return false; 84 } 85 fPixels->erase(0); 86 87 sk_bzero(&fDraw, sizeof(fDraw)); 88 fDraw.fDst = *fPixels; 89 fRasterClip.setRect(bounds); 90 fDraw.fRC = &fRasterClip; 91 return true; 92 } 93 94 sk_sp<GrTextureProxy> GrSWMaskHelper::toTextureProxy(GrContext* context, SkBackingFit fit) { 95 GrSurfaceDesc desc; 96 desc.fOrigin = kTopLeft_GrSurfaceOrigin; 97 desc.fWidth = fPixels->width(); 98 desc.fHeight = fPixels->height(); 99 desc.fConfig = kAlpha_8_GrPixelConfig; 100 101 sk_sp<GrSurfaceContext> sContext = context->contextPriv().makeDeferredSurfaceContext( 102 desc, 103 GrMipMapped::kNo, 104 fit, 105 SkBudgeted::kYes); 106 if (!sContext || !sContext->asTextureProxy()) { 107 return nullptr; 108 } 109 110 SkImageInfo ii = SkImageInfo::MakeA8(desc.fWidth, desc.fHeight); 111 if (!sContext->writePixels(ii, fPixels->addr(), fPixels->rowBytes(), 0, 0)) { 112 return nullptr; 113 } 114 115 return sContext->asTextureProxyRef(); 116 } 117