bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix) { if (!this->INHERITED::setContext(device, paint, matrix)) { return false; } SkColor c; unsigned a; if (fInheritColor) { c = paint.getColor(); a = SkColorGetA(c); } else { c = fColor; a = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha())); } unsigned r = SkColorGetR(c); unsigned g = SkColorGetG(c); unsigned b = SkColorGetB(c); // we want this before we apply any alpha fColor16 = SkPack888ToRGB16(r, g, b); if (a != 255) { a = SkAlpha255To256(a); r = SkAlphaMul(r, a); g = SkAlphaMul(g, a); b = SkAlphaMul(b, a); } fPMColor = SkPackARGB32(a, r, g, b); return true; }
static bool Supports(const SkPixmap& dst, const SkPixmap& src, const SkPaint& paint) { if (dst.colorType() != src.colorType()) { return false; } if (dst.info().gammaCloseToSRGB() != src.info().gammaCloseToSRGB()) { return false; } if (paint.getMaskFilter() || paint.getColorFilter() || paint.getImageFilter()) { return false; } if (0xFF != paint.getAlpha()) { return false; } SkBlendMode mode = paint.getBlendMode(); if (SkBlendMode::kSrc == mode) { return true; } if (SkBlendMode::kSrcOver == mode && src.isOpaque()) { return true; } // At this point memcpy can't be used. The following check for using SrcOver. if (dst.colorType() != kN32_SkColorType || !dst.info().gammaCloseToSRGB()) { return false; } return SkBlendMode::kSrcOver == mode; }
void SkBaseDevice::drawImageLattice(const SkImage* image, const SkCanvas::Lattice& lattice, const SkRect& dst, const SkPaint& paint) { SkLatticeIter iter(lattice, dst); SkRect srcR, dstR; SkColor c; bool isFixedColor = false; const SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType); while (iter.next(&srcR, &dstR, &isFixedColor, &c)) { if (isFixedColor || (srcR.width() <= 1.0f && srcR.height() <= 1.0f && image->readPixels(info, &c, 4, srcR.fLeft, srcR.fTop))) { // Fast draw with drawRect, if this is a patch containing a single color // or if this is a patch containing a single pixel. if (0 != c || !paint.isSrcOver()) { SkPaint paintCopy(paint); int alpha = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha())); paintCopy.setColor(SkColorSetA(c, alpha)); this->drawRect(dstR, paintCopy); } } else { this->drawImageRect(image, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint); } } }
bool DCShader::asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& viewM, const SkMatrix* localMatrix, GrColor* color, GrFragmentProcessor** fp) const { *fp = SkNEW_ARGS(DCFP, (fDeviceMatrix)); *color = GrColorPackA4(paint.getAlpha()); return true; }
virtual void onDraw(int loops, SkCanvas* canvas) { const SkIPoint dim = this->getSize(); SkRandom rand; SkPaint paint(fPaint); this->setupPaint(&paint); // explicitly need these paint.setAlpha(fPaint.getAlpha()); paint.setAntiAlias(kBW != fFQ); paint.setLCDRenderText(kLCD == fFQ); const SkScalar x0 = SkIntToScalar(-10); const SkScalar y0 = SkIntToScalar(-10); paint.setTextSize(SkIntToScalar(12)); for (int i = 0; i < loops; i++) { SkScalar x = x0 + rand.nextUScalar1() * dim.fX; SkScalar y = y0 + rand.nextUScalar1() * dim.fY; canvas->drawString(fText, x, y, paint); } paint.setTextSize(SkIntToScalar(48)); for (int i = 0; i < loops / 4 ; i++) { SkScalar x = x0 + rand.nextUScalar1() * dim.fX; SkScalar y = y0 + rand.nextUScalar1() * dim.fY; canvas->drawString(fText, x, y, paint); } }
void SkGL::SetPaint(const SkPaint& paint, bool isPremul, bool justAlpha) { if (justAlpha) { SkGL::SetAlpha(paint.getAlpha()); } else { SkGL::SetColor(paint.getColor()); } GLenum sm = GL_ONE; GLenum dm = GL_ONE_MINUS_SRC_ALPHA; SkXfermode* mode = paint.getXfermode(); SkXfermode::Coeff sc, dc; if (mode && mode->asCoeff(&sc, &dc)) { sm = gXfermodeCoeff2Blend[sc]; dm = gXfermodeCoeff2Blend[dc]; } // hack for text, which is not-premul (afaik) if (!isPremul) { if (GL_ONE == sm) { sm = GL_SRC_ALPHA; } } glEnable(GL_BLEND); glBlendFunc(sm, dm); if (paint.isDither()) { glEnable(GL_DITHER); } else { glDisable(GL_DITHER); } }
/** * Draw a single path element of the clip stack into the accumulation bitmap */ void GrSWMaskHelper::draw(const SkPath& path, const SkStrokeRec& stroke, SkRegion::Op op, bool antiAlias, uint8_t alpha) { SkPaint paint; if (stroke.isHairlineStyle()) { paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(SK_Scalar1); } else { if (stroke.isFillStyle()) { paint.setStyle(SkPaint::kFill_Style); } else { paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeJoin(stroke.getJoin()); paint.setStrokeCap(stroke.getCap()); paint.setStrokeWidth(stroke.getWidth()); } } paint.setAntiAlias(antiAlias); if (SkRegion::kReplace_Op == op && 0xFF == alpha) { SkASSERT(0xFF == paint.getAlpha()); fDraw.drawPathCoverage(path, paint); } else { paint.setXfermodeMode(op_to_mode(op)); paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha)); fDraw.drawPath(path, paint); } }
bool draw(SkCanvas* canvas, const SkString& newText, SkScalar x, SkScalar y, SkPaint& paint) { SkScalar scale; if (fInterp.timeToValues(SkTime::GetMSecs(), &scale) == SkInterpolator::kFreezeEnd_Result) { canvas->drawText(newText.c_str(), newText.size(), x, y, paint); return false; } else { U8 alpha = paint.getAlpha(); SkScalar above, below; (void)paint.measureText(nil, 0, &above, &below); SkScalar height = below - above; SkScalar dy = SkScalarMul(height, scale); if (scale < 0) height = -height; // draw the old paint.setAlpha((U8)SkScalarMul(alpha, SK_Scalar1 - SkScalarAbs(scale))); canvas->drawText(fOldText.c_str(), fOldText.size(), x, y - dy, paint); // draw the new paint.setAlpha((U8)SkScalarMul(alpha, SkScalarAbs(scale))); canvas->drawText(newText.c_str(), newText.size(), x, y + height - dy, paint); // restore the paint paint.setAlpha(alpha); return true; } }
static bool Supports(const SkPixmap& dst, const SkPixmap& src, const SkPaint& paint) { if (dst.colorType() != src.colorType()) { return false; } if (dst.info().profileType() != src.info().profileType()) { return false; } if (paint.getMaskFilter() || paint.getColorFilter() || paint.getImageFilter()) { return false; } if (0xFF != paint.getAlpha()) { return false; } SkXfermode::Mode mode; if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) { return false; } if (SkXfermode::kSrc_Mode == mode) { return true; } if (SkXfermode::kSrcOver_Mode == mode && src.isOpaque()) { return true; } return false; }
SkPDFGraphicState::SkPDFGraphicState(const SkPaint& p) : fStrokeWidth(p.getStrokeWidth()) , fStrokeMiter(p.getStrokeMiter()) , fAlpha(p.getAlpha()) , fStrokeCap(SkToU8(p.getStrokeCap())) , fStrokeJoin(SkToU8(p.getStrokeJoin())) , fMode(SkToU8(mode_for_pdf(p.getXfermode()))) {}
bool SkTransparentShader::setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix) { fDevice = &device; fAlpha = paint.getAlpha(); return this->INHERITED::setContext(device, paint, matrix); }
void onDraw(SkCanvas* canvas) override { const struct { SkISize size; SkScalar scaleX, scaleY; SkScalar opacity; } configs[] = { { SkISize::Make(200, 100), 1, 1, 1 }, { SkISize::Make(200, 200), 1, 1, 1 }, { SkISize::Make(200, 200), 1, 2, 1 }, { SkISize::Make(400, 200), 2, 2, 1 }, { SkISize::Make(200, 100), 1, 1, 0.9f }, { SkISize::Make(200, 200), 1, 1, 0.75f }, { SkISize::Make(200, 200), 1, 2, 0.5f }, { SkISize::Make(400, 200), 2, 2, 0.25f }, { SkISize::Make(200, 200), 0.5f, 1, 1 }, { SkISize::Make(200, 200), 1, 0.5f, 1 }, { SkISize::Make(200, 200), 0.5f, 0.5f, 1 }, { SkISize::Make(200, 200), 2, 2, 1 }, { SkISize::Make(200, 100), -1, 1, 1 }, { SkISize::Make(200, 100), 1, -1, 1 }, { SkISize::Make(200, 100), -1, -1, 1 }, { SkISize::Make(200, 100), -1, -1, 0.5f }, }; const unsigned kDrawsPerRow = 4; const SkScalar kDrawSize = 250; for (size_t i = 0; i < SK_ARRAY_COUNT(configs); ++i) { SkPaint p; p.setAlpha(SkScalarRoundToInt(255 * configs[i].opacity)); SkMatrix m = SkMatrix::MakeScale(configs[i].scaleX, configs[i].scaleY); if (configs[i].scaleX < 0) { m.postTranslate(SkIntToScalar(configs[i].size.width()), 0); } if (configs[i].scaleY < 0) { m.postTranslate(0, SkIntToScalar(configs[i].size.height())); } SkAutoTDelete<SkImageGenerator> gen( SkImageGenerator::NewFromPicture(configs[i].size, fPicture.get(), &m, p.getAlpha() != 255 ? &p : nullptr)); SkBitmap bm; gen->generateBitmap(&bm); const SkScalar x = kDrawSize * (i % kDrawsPerRow); const SkScalar y = kDrawSize * (i / kDrawsPerRow); p.setColor(0xfff0f0f0); p.setAlpha(255); canvas->drawRect(SkRect::MakeXYWH(x, y, SkIntToScalar(bm.width()), SkIntToScalar(bm.height())), p); canvas->drawBitmap(bm, x, y); } }
bool SkColorShader::asNewEffect(GrContext* context, const SkPaint& paint, const SkMatrix* localMatrix, GrColor* grColor, GrEffectRef** grEffect) const { *grEffect = NULL; SkColor skColor = fColor; U8CPU newA = SkMulDiv255Round(SkColorGetA(fColor), paint.getAlpha()); *grColor = SkColor2GrColor(SkColorSetA(skColor, newA)); return true; }
Sprite_D32_XferFilter(const SkBitmap& source, const SkPaint& paint) : SkSpriteBlitter(source) { fColorFilter = paint.getColorFilter(); SkSafeRef(fColorFilter); fXfermode = paint.getXfermode(); SkSafeRef(fXfermode); fBufferSize = 0; fBuffer = NULL; unsigned flags32 = 0; if (255 != paint.getAlpha()) { flags32 |= SkBlitRow::kGlobalAlpha_Flag32; } if (!source.isOpaque()) { flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32; } fProc32 = SkBlitRow::Factory32(flags32); fAlpha = paint.getAlpha(); }
virtual const char* onGetName() { fName.printf("text_%g", SkScalarToFloat(fPaint.getTextSize())); if (fDoPos) { fName.append("_pos"); } fName.appendf("_%s", fontQualityName(fPaint)); if (SK_ColorBLACK != fPaint.getColor()) { fName.appendf("_%02X", fPaint.getAlpha()); } else { fName.append("_BK"); } return fName.c_str(); }
sk_sp<SkPDFDict> SkPDFGraphicState::GetGraphicStateForPaint(SkPDFCanon* canon, const SkPaint& p) { SkASSERT(canon); if (SkPaint::kFill_Style == p.getStyle()) { SkPDFFillGraphicState fillKey = {p.getAlpha(), pdf_blend_mode(p.getBlendMode())}; auto& fillMap = canon->fFillGSMap; if (sk_sp<SkPDFDict>* statePtr = fillMap.find(fillKey)) { return *statePtr; } auto state = sk_make_sp<SkPDFDict>(); state->reserve(2); state->insertScalar("ca", fillKey.fAlpha / 255.0f); state->insertName("BM", as_pdf_blend_mode_name((SkBlendMode)fillKey.fBlendMode)); fillMap.set(fillKey, state); return state; } else { SkPDFStrokeGraphicState strokeKey = { p.getStrokeWidth(), p.getStrokeMiter(), SkToU8(p.getStrokeCap()), SkToU8(p.getStrokeJoin()), p.getAlpha(), pdf_blend_mode(p.getBlendMode())}; auto& sMap = canon->fStrokeGSMap; if (sk_sp<SkPDFDict>* statePtr = sMap.find(strokeKey)) { return *statePtr; } auto state = sk_make_sp<SkPDFDict>(); state->reserve(8); state->insertScalar("CA", strokeKey.fAlpha / 255.0f); state->insertScalar("ca", strokeKey.fAlpha / 255.0f); state->insertInt("LC", to_stroke_cap(strokeKey.fStrokeCap)); state->insertInt("LJ", to_stroke_join(strokeKey.fStrokeJoin)); state->insertScalar("LW", strokeKey.fStrokeWidth); state->insertScalar("ML", strokeKey.fStrokeMiter); state->insertBool("SA", true); // SA = Auto stroke adjustment. state->insertName("BM", as_pdf_blend_mode_name((SkBlendMode)strokeKey.fBlendMode)); sMap.set(strokeKey, state); return state; } }
/** * Draw a single path element of the clip stack into the accumulation bitmap */ void GrSWMaskHelper::drawPath(const SkPath& path, const GrStyle& style, SkRegion::Op op, bool antiAlias, uint8_t alpha) { SkPaint paint; paint.setPathEffect(sk_ref_sp(style.pathEffect())); style.strokeRec().applyToPaint(&paint); paint.setAntiAlias(antiAlias); if (SkRegion::kReplace_Op == op && 0xFF == alpha) { SkASSERT(0xFF == paint.getAlpha()); fDraw.drawPathCoverage(path, paint); } else { paint.setXfermodeMode(op_to_mode(op)); paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha)); fDraw.drawPath(path, paint); } }
static bool Supports(const SkPixmap& dst, const SkPixmap& src, const SkPaint& paint) { // the caller has already inspected the colorspace on src and dst SkASSERT(!SkColorSpaceXformSteps::Required(src.colorSpace(), dst.colorSpace())); if (dst.colorType() != src.colorType()) { return false; } if (paint.getMaskFilter() || paint.getColorFilter() || paint.getImageFilter()) { return false; } if (0xFF != paint.getAlpha()) { return false; } SkBlendMode mode = paint.getBlendMode(); return SkBlendMode::kSrc == mode || (SkBlendMode::kSrcOver == mode && src.isOpaque()); }
static bool Supports(const SkPixmap& dst, const SkPixmap& src, const SkPaint& paint) { if (dst.colorType() != src.colorType()) { return false; } if (!SkColorSpace::Equals(dst.colorSpace(), src.colorSpace())) { return false; } if (paint.getMaskFilter() || paint.getColorFilter() || paint.getImageFilter()) { return false; } if (0xFF != paint.getAlpha()) { return false; } SkBlendMode mode = paint.getBlendMode(); return SkBlendMode::kSrc == mode || (SkBlendMode::kSrcOver == mode && src.isOpaque()); }
bool SkShader::setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix) { SkASSERT(!this->setContextHasBeenCalled()); const SkMatrix* m = &matrix; SkMatrix total; fPaintAlpha = paint.getAlpha(); if (this->hasLocalMatrix()) { total.setConcat(matrix, this->getLocalMatrix()); m = &total; } if (m->invert(&fTotalInverse)) { fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); SkDEBUGCODE(fInSetContext = true;) return true;
/** * Draw a single path element of the clip stack into the accumulation bitmap */ void GrSWMaskHelper::drawShape(const GrShape& shape, SkRegion::Op op, GrAA aa, uint8_t alpha) { SkPaint paint; paint.setPathEffect(shape.style().refPathEffect()); shape.style().strokeRec().applyToPaint(&paint); paint.setAntiAlias(GrAA::kYes == aa); SkPath path; shape.asPath(&path); if (SkRegion::kReplace_Op == op && 0xFF == alpha) { SkASSERT(0xFF == paint.getAlpha()); fDraw.drawPathCoverage(path, paint); } else { paint.setBlendMode(op_to_mode(op)); paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha)); fDraw.drawPath(path, paint); } }
bool SkShader::setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix) { const SkMatrix* m = &matrix; SkMatrix total; fDeviceConfig = SkToU8(device.getConfig()); fPaintAlpha = paint.getAlpha(); if (fLocalMatrix) { total.setConcat(matrix, *fLocalMatrix); m = &total; } if (m->invert(&fTotalInverse)) { fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); return true; } return false; }
static void paint_write(const SkPaint& paint, SkFlattenableWriteBuffer& buffer) { buffer.writeBool(paint.isAntiAlias()); buffer.write8(paint.getStyle()); buffer.write8(paint.getAlpha()); if (paint.getStyle() != SkPaint::kFill_Style) { buffer.writeScalar(paint.getStrokeWidth()); buffer.writeScalar(paint.getStrokeMiter()); buffer.write8(paint.getStrokeCap()); buffer.write8(paint.getStrokeJoin()); } buffer.writeFlattenable(paint.getMaskFilter()); buffer.writeFlattenable(paint.getPathEffect()); buffer.writeFlattenable(paint.getRasterizer()); buffer.writeFlattenable(paint.getXfermode()); }
const char* onGetName() override { fName.printf("text_%g", SkScalarToFloat(fPaint.getTextSize())); if (fDoPos) { fName.append("_pos"); } fName.appendf("_%s", fontQualityName(fPaint)); if (SK_ColorBLACK == fPaint.getColor()) { fName.append("_BK"); } else if (SK_ColorWHITE == fPaint.getColor()) { fName.append("_WT"); } else { fName.appendf("_%02X", fPaint.getAlpha()); } if (fDoColorEmoji) { fName.append("_ColorEmoji"); } return fName.c_str(); }
bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix) { if (!this->INHERITED::setContext(device, paint, matrix)) { return false; } SkColor c; unsigned a; if (fInheritColor) { c = paint.getColor(); a = SkColorGetA(c); } else { c = fColor; a = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha())); } unsigned r = SkColorGetR(c); unsigned g = SkColorGetG(c); unsigned b = SkColorGetB(c); // we want this before we apply any alpha fColor16 = SkPack888ToRGB16(r, g, b); if (a != 255) { r = SkMulDiv255Round(r, a); g = SkMulDiv255Round(g, a); b = SkMulDiv255Round(b, a); } fPMColor = SkPackARGB32(a, r, g, b); fFlags = kConstInY32_Flag; if (255 == a) { fFlags |= kOpaqueAlpha_Flag; if (paint.isDither() == false) { fFlags |= kHasSpan16_Flag; } } return true; }
// Returns true if all pixels painted will be opaque. static inline bool paintIsOpaque(const SkPaint& paint, const SkBitmap* bitmap = 0, bool checkFillOnly = false) { if (paint.getAlpha() < 0xFF) return false; if (!checkFillOnly && paint.getStyle() != SkPaint::kFill_Style && paint.isAntiAlias()) return false; SkShader* shader = paint.getShader(); if (shader && !shader->isOpaque()) return false; if (bitmap && !bitmap->isOpaque()) return false; if (paint.getLooper()) return false; if (paint.getImageFilter()) return false; if (paint.getMaskFilter()) return false; SkColorFilter* colorFilter = paint.getColorFilter(); if (colorFilter && !(colorFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag)) return false; return true; }
bool SkPerlinNoiseShader::asFragmentProcessor(GrContext* context, const SkPaint& paint, const SkMatrix& viewM, const SkMatrix* externalLocalMatrix, GrColor* paintColor, GrFragmentProcessor** fp) const { SkASSERT(context); *paintColor = SkColor2GrColorJustAlpha(paint.getColor()); SkMatrix localMatrix = this->getLocalMatrix(); if (externalLocalMatrix) { localMatrix.preConcat(*externalLocalMatrix); } SkMatrix matrix = viewM; matrix.preConcat(localMatrix); if (0 == fNumOctaves) { if (kFractalNoise_Type == fType) { uint32_t alpha = paint.getAlpha() >> 1; uint32_t rgb = alpha >> 1; *paintColor = GrColorPackRGBA(rgb, rgb, rgb, alpha); } else {
/** * Draw a single path element of the clip stack into the accumulation bitmap */ void GrSWMaskHelper::draw(const SkPath& path, const SkStrokeRec& stroke, SkRegion::Op op, bool antiAlias, uint8_t alpha) { SkPaint paint; if (stroke.isHairlineStyle()) { paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(SK_Scalar1); } else { if (stroke.isFillStyle()) { paint.setStyle(SkPaint::kFill_Style); } else { paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeJoin(stroke.getJoin()); paint.setStrokeCap(stroke.getCap()); paint.setStrokeWidth(stroke.getWidth()); } } paint.setAntiAlias(antiAlias); SkTBlitterAllocator allocator; SkBlitter* blitter = nullptr; if (kBlitter_CompressionMode == fCompressionMode) { SkASSERT(fCompressedBuffer.get()); blitter = SkTextureCompressor::CreateBlitterForFormat( fPixels.width(), fPixels.height(), fCompressedBuffer.get(), &allocator, fCompressedFormat); } if (SkRegion::kReplace_Op == op && 0xFF == alpha) { SkASSERT(0xFF == paint.getAlpha()); fDraw.drawPathCoverage(path, paint, blitter); } else { paint.setXfermodeMode(op_to_mode(op)); paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha)); fDraw.drawPath(path, paint, blitter); } }
static void drawStretchyPatch(SkCanvas* canvas, SkIRect& src, const SkRect& dst, const SkBitmap& bitmap, const SkPaint& paint, SkColor initColor, uint32_t colorHint, bool hasXfer) { if (colorHint != android::Res_png_9patch::NO_COLOR) { ((SkPaint*)&paint)->setColor(modAlpha(colorHint, paint.getAlpha())); canvas->drawRect(dst, paint); ((SkPaint*)&paint)->setColor(initColor); } else if (src.width() == 1 && src.height() == 1) { SkColor c; if (!getColor(bitmap, src.fLeft, src.fTop, &c)) { goto SLOW_CASE; } if (0 != c || hasXfer) { SkColor prev = paint.getColor(); ((SkPaint*)&paint)->setColor(c); canvas->drawRect(dst, paint); ((SkPaint*)&paint)->setColor(prev); } } else { SLOW_CASE: canvas->drawBitmapRect(bitmap, &src, dst, &paint); } }
static bool just_solid_color(const SkPaint& p) { return SK_AlphaOPAQUE == p.getAlpha() && !p.getColorFilter() && !p.getShader(); }