DEF_TEST(Color4f_shader, reporter) { struct { sk_sp<SkShader> (*fFact)(); bool fSupports4f; float fTolerance; } recs[] = { { make_color_sh, true, 1.0f/255 }, // PMColor 4f gradients are interpolated in 255-multiplied values, so we need a // slightly relaxed tolerance to accommodate the cumulative precision deviation. { make_grad_sh, true, 1.001f/255 }, { make_image_sh, false, 1.0f/255 }, { make_cf_sh, true, 1.0f/255 }, }; SkPaint paint; for (const auto& rec : recs) { uint32_t storage[300]; paint.setShader(rec.fFact()); // Encourage 4f context selection. At some point we may need // to instantiate two separate contexts for optimal 4b/4f selection. const SkShader::ContextRec contextRec(paint, SkMatrix::I(), nullptr, SkShader::ContextRec::kPM4f_DstType); SkASSERT(paint.getShader()->contextSize(contextRec) <= sizeof(storage)); SkShader::Context* ctx = paint.getShader()->createContext(contextRec, storage); if (rec.fSupports4f) { const int N = 100; SkPM4f buffer4f[N]; ctx->shadeSpan4f(0, 0, buffer4f, N); SkPMColor buffer4b[N]; ctx->shadeSpan(0, 0, buffer4b, N); REPORTER_ASSERT(reporter, compare_spans(buffer4f, buffer4b, N, rec.fTolerance)); } ctx->~Context(); } }
void DrawTargetSkia::MaskSurface(const Pattern &aSource, SourceSurface *aMask, Point aOffset, const DrawOptions &aOptions) { MarkChanged(); AutoPaintSetup paint(mCanvas.get(), aOptions, aSource); TempBitmap bitmap = GetBitmapForSurface(aMask); if (bitmap.mBitmap.colorType() == kAlpha_8_SkColorType) { mCanvas->drawBitmap(bitmap.mBitmap, aOffset.x, aOffset.y, &paint.mPaint); } else { SkPaint maskPaint; TempBitmap tmpBitmap; SetPaintPattern(maskPaint, SurfacePattern(aMask, ExtendMode::CLAMP), tmpBitmap); SkMatrix transform = maskPaint.getShader()->getLocalMatrix(); transform.postTranslate(SkFloatToScalar(aOffset.x), SkFloatToScalar(aOffset.y)); maskPaint.getShader()->setLocalMatrix(transform); SkLayerRasterizer::Builder builder; builder.addLayer(maskPaint); SkAutoTUnref<SkRasterizer> raster(builder.detachRasterizer()); paint.mPaint.setRasterizer(raster.get()); IntSize size = aMask->GetSize(); Rect rect = Rect(aOffset.x, aOffset.y, size.width, size.height); mCanvas->drawRect(RectToSkRect(rect), paint.mPaint); } }
void DrawTargetSkia::MaskSurface(const Pattern &aSource, SourceSurface *aMask, Point aOffset, const DrawOptions &aOptions) { MarkChanged(); AutoPaintSetup paint(mCanvas.get(), aOptions, aSource); SkPaint maskPaint; TempBitmap tmpBitmap; SetPaintPattern(maskPaint, SurfacePattern(aMask, ExtendMode::CLAMP), tmpBitmap); SkMatrix transform = maskPaint.getShader()->getLocalMatrix(); transform.postTranslate(SkFloatToScalar(aOffset.x), SkFloatToScalar(aOffset.y)); maskPaint.getShader()->setLocalMatrix(transform); SkLayerRasterizer *raster = new SkLayerRasterizer(); raster->addLayer(maskPaint); SkSafeUnref(paint.mPaint.setRasterizer(raster)); IntSize size = aMask->GetSize(); Rect rect = Rect(aOffset.x, aOffset.y, size.width, size.height); mCanvas->drawRect(RectToSkRect(rect), paint.mPaint); }
bool SkPaintPriv::ShouldDither(const SkPaint& p, SkColorType dstCT) { // The paint dither flag can veto. if (!p.isDither()) { return false; } // We always dither 565 or 4444 when requested. if (dstCT == kRGB_565_SkColorType || dstCT == kARGB_4444_SkColorType) { return true; } // Otherwise, dither is only needed for non-const paints. return p.getImageFilter() || p.getMaskFilter() || !p.getShader() || !as_SB(p.getShader())->isConstant(); }
void onDrawContent(SkCanvas* canvas) override { const int nu = 10; const int nv = 10; SkPaint paint; paint.setDither(true); paint.setFilterQuality(kLow_SkFilterQuality); canvas->translate(DX, DY); Patch patch; paint.setShader(fShader0); if (fSize0.fX == 0) { fSize0.fX = 1; } if (fSize0.fY == 0) { fSize0.fY = 1; } patch.setBounds(fSize0.fX, fSize0.fY); patch.setPatch(fPts); drawpatches(canvas, paint, nu, nv, &patch); paint.setShader(nullptr); paint.setAntiAlias(true); paint.setStrokeWidth(SkIntToScalar(5)); canvas->drawPoints(SkCanvas::kPoints_PointMode, SK_ARRAY_COUNT(fPts), fPts, paint); canvas->translate(0, SkIntToScalar(300)); paint.setAntiAlias(false); paint.setShader(fShader1); if (true) { SkMatrix m; m.setSkew(1, 0); SkShader* s = SkShader::CreateLocalMatrixShader(paint.getShader(), m); paint.setShader(s)->unref(); } if (true) { SkMatrix m; m.setRotate(fAngle); SkShader* s = SkShader::CreateLocalMatrixShader(paint.getShader(), m); paint.setShader(s)->unref(); } patch.setBounds(fSize1.fX, fSize1.fY); drawpatches(canvas, paint, nu, nv, &patch); }
SkPaint SkColorSpaceXformer::apply(const SkPaint& src) { const AutoCachePurge autoPurge(this); SkPaint dst = src; // All SkColorSpaces have the same black point. if (src.getColor() & 0xffffff) { dst.setColor(this->apply(src.getColor())); } if (auto shader = src.getShader()) { dst.setShader(this->apply(shader)); } if (auto cf = src.getColorFilter()) { dst.setColorFilter(this->apply(cf)); } if (auto looper = src.getDrawLooper()) { dst.setDrawLooper(looper->makeColorSpace(this)); } if (auto imageFilter = src.getImageFilter()) { dst.setImageFilter(this->apply(imageFilter)); } return dst; }
void GrBlurUtils::drawPathWithMaskFilter(GrContext* context, GrDrawContext* drawContext, const GrClip& clip, const SkPath& origPath, const SkPaint& paint, const SkMatrix& origViewMatrix, const SkMatrix* prePathMatrix, const SkIRect& clipBounds, bool pathIsMutable) { SkASSERT(!pathIsMutable || origPath.isVolatile()); GrStyle style(paint); // If we have a prematrix, apply it to the path, optimizing for the case // where the original path can in fact be modified in place (even though // its parameter type is const). const SkPath* path = &origPath; SkTLazy<SkPath> tmpPath; SkMatrix viewMatrix = origViewMatrix; if (prePathMatrix) { // Styling, blurs, and shading are supposed to be applied *after* the prePathMatrix. if (!paint.getMaskFilter() && !paint.getShader() && !style.applies()) { viewMatrix.preConcat(*prePathMatrix); } else { SkPath* result = pathIsMutable ? const_cast<SkPath*>(path) : tmpPath.init(); pathIsMutable = true; path->transform(*prePathMatrix, result); path = result; result->setIsVolatile(true); } } // at this point we're done with prePathMatrix SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
bool SkPaint2GrPaint(GrContext* context, GrRenderTarget* rt, const SkPaint& skPaint, const SkMatrix& viewM, bool constantColor, GrPaint* grPaint) { SkShader* shader = skPaint.getShader(); if (NULL == shader) { return SkPaint2GrPaintNoShader(context, rt, skPaint, SkColor2GrColor(skPaint.getColor()), constantColor, grPaint); } GrColor paintColor = SkColor2GrColor(skPaint.getColor()); // Start a new block here in order to preserve our context state after calling // asFragmentProcessor(). Since these calls get passed back to the client, we don't really // want them messing around with the context. { // Allow the shader to modify paintColor and also create an effect to be installed as // the first color effect on the GrPaint. GrFragmentProcessor* fp = NULL; if (!shader->asFragmentProcessor(context, skPaint, viewM, NULL, &paintColor, grPaint->getProcessorDataManager(), &fp)) { return false; } if (fp) { grPaint->addColorProcessor(fp)->unref(); constantColor = false; } } // The grcolor is automatically set when calling asFragmentProcessor. // If the shader can be seen as an effect it returns true and adds its effect to the grpaint. return SkPaint2GrPaintNoShader(context, rt, skPaint, paintColor, constantColor, grPaint); }
void SkOverdrawCanvas::onDrawPaint(const SkPaint& paint) { if (0 == paint.getColor() && !paint.getColorFilter() && !paint.getShader()) { // This is a clear, ignore it. } else { fList[0]->onDrawPaint(this->overdrawPaint(paint)); } }
SkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkPixmap& device, const SkPaint& paint) : INHERITED(device, paint) { SkASSERT(paint.getShader() == nullptr); SkASSERT(paint.getColorFilter() == nullptr); SkASSERT(paint.isSrcOver()); SkASSERT(paint.getColor() == SK_ColorBLACK); }
/* Hit a few SkPicture::Analysis cases not handled elsewhere. */ static void test_analysis(skiatest::Reporter* reporter) { SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(100, 100); { canvas->drawRect(SkRect::MakeWH(10, 10), SkPaint ()); } sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture()); REPORTER_ASSERT(reporter, !picture->willPlayBackBitmaps()); canvas = recorder.beginRecording(100, 100); { SkPaint paint; // CreateBitmapShader is too smart for us; an empty (or 1x1) bitmap shader // gets optimized into a non-bitmap form, so we create a 2x2 bitmap here. SkBitmap bitmap; bitmap.allocPixels(SkImageInfo::MakeN32Premul(2, 2)); bitmap.eraseColor(SK_ColorBLUE); *(bitmap.getAddr32(0, 0)) = SK_ColorGREEN; paint.setShader(SkShader::MakeBitmapShader(bitmap, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode)); REPORTER_ASSERT(reporter, paint.getShader()->isABitmap()); canvas->drawRect(SkRect::MakeWH(10, 10), paint); } REPORTER_ASSERT(reporter, recorder.finishRecordingAsPicture()->willPlayBackBitmaps()); }
bool SkPaintToGrPaintWithTexture(GrContext* context, const SkPaint& paint, const SkMatrix& viewM, const GrFragmentProcessor* fp, bool textureIsAlphaOnly, GrPaint* grPaint) { SkAutoTUnref<const GrFragmentProcessor> shaderFP; if (textureIsAlphaOnly) { if (const SkShader* shader = paint.getShader()) { shaderFP.reset(shader->asFragmentProcessor(context, viewM, nullptr, paint.getFilterQuality())); if (!shaderFP) { return false; } const GrFragmentProcessor* fpSeries[] = { shaderFP.get(), fp }; shaderFP.reset(GrFragmentProcessor::RunInSeries(fpSeries, 2)); } else { shaderFP.reset(GrFragmentProcessor::MulOutputByInputUnpremulColor(fp)); } } else { shaderFP.reset(GrFragmentProcessor::MulOutputByInputAlpha(fp)); } return SkPaintToGrPaintReplaceShader(context, paint, shaderFP.get(), grPaint); }
bool SkPaintToGrPaintWithTexture(GrContext* context, const GrColorSpaceInfo& colorSpaceInfo, const SkPaint& paint, const SkMatrix& viewM, std::unique_ptr<GrFragmentProcessor> fp, bool textureIsAlphaOnly, GrPaint* grPaint) { std::unique_ptr<GrFragmentProcessor> shaderFP; if (textureIsAlphaOnly) { if (const auto* shader = as_SB(paint.getShader())) { shaderFP = shader->asFragmentProcessor(GrFPArgs( context, &viewM, nullptr, paint.getFilterQuality(), &colorSpaceInfo)); if (!shaderFP) { return false; } std::unique_ptr<GrFragmentProcessor> fpSeries[] = { std::move(shaderFP), std::move(fp) }; shaderFP = GrFragmentProcessor::RunInSeries(fpSeries, 2); } else { shaderFP = GrFragmentProcessor::MakeInputPremulAndMulByOutput(std::move(fp)); } } else { shaderFP = GrFragmentProcessor::MulChildByInputAlpha(std::move(fp)); } return SkPaintToGrPaintReplaceShader(context, colorSpaceInfo, paint, std::move(shaderFP), grPaint); }
SkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint) : INHERITED(device, paint) { SkASSERT(paint.getShader() == NULL); SkASSERT(paint.getColorFilter() == NULL); SkASSERT(paint.getXfermode() == NULL); SkASSERT(paint.getColor() == SK_ColorBLACK); }
static void apply_paint_shader(const SkPaint& paint, Json::Value* target, bool sendBinaries) { SkFlattenable* shader = paint.getShader(); if (shader != nullptr) { Json::Value jsonShader; flatten(shader, &jsonShader, sendBinaries); (*target)[SKJSONCANVAS_ATTRIBUTE_SHADER] = jsonShader; } }
void addBitmapFromPaint(const SkPaint& paint) { SkShader* shader = paint.getShader(); if (shader) { SkBitmap bm; if (shader->asABitmap(&bm, NULL, NULL)) { fPRSet->add(bm.pixelRef()); } } }
// Regression test for leaking refs held by optional arguments. DEF_TEST(Recorder_RefLeaking, r) { // We use SaveLayer to test: // - its SkRect argument is optional and SkRect is POD. Just testing that that works. // - its SkPaint argument is optional and SkPaint is not POD. The bug was here. SkRect bounds = SkRect::MakeWH(320, 240); SkPaint paint; paint.setShader(SkShader::CreateEmptyShader())->unref(); REPORTER_ASSERT(r, paint.getShader()->unique()); { SkRecord record; SkRecorder recorder(&record, 1920, 1080); recorder.saveLayer(&bounds, &paint); REPORTER_ASSERT(r, !paint.getShader()->unique()); } REPORTER_ASSERT(r, paint.getShader()->unique()); }
static bool fold_opacity_layer_color_to_paint(const SkPaint& layerPaint, bool isSaveLayer, SkPaint* paint) { // We assume layerPaint is always from a saveLayer. If isSaveLayer is // true, we assume paint is too. // The alpha folding can proceed if the filter layer paint does not have properties which cause // the resulting filter layer to be "blended" in complex ways to the parent layer. For example, // looper drawing unmodulated filter layer twice and then modulating the result produces // different image to drawing modulated filter layer twice. // TODO: most likely the looper and only some xfer modes are the hard constraints if (paint->getXfermode() || paint->getLooper()) { return false; } if (!isSaveLayer && paint->getImageFilter()) { // For normal draws, the paint color is used as one input for the color for the draw. Image // filter will operate on the result, and thus we can not change the input. // For layer saves, the image filter is applied to the layer contents. The layer is then // modulated with the paint color, so it's fine to proceed with the fold for saveLayer // paints with image filters. return false; } if (paint->getColorFilter()) { // Filter input depends on the paint color. // Here we could filter the color if we knew the draw is going to be uniform color. This // should be detectable as drawPath/drawRect/.. without a shader being uniform, while // drawBitmap/drawSprite or a shader being non-uniform. However, current matchers don't // give the type out easily, so just do not optimize that at the moment. return false; } const uint32_t layerColor = layerPaint.getColor(); // The layer paint color must have only alpha component. if (SK_ColorTRANSPARENT != SkColorSetA(layerColor, SK_AlphaTRANSPARENT)) { return false; } // The layer paint can not have any effects. if (layerPaint.getPathEffect() || layerPaint.getShader() || layerPaint.getXfermode() || layerPaint.getMaskFilter() || layerPaint.getColorFilter() || layerPaint.getRasterizer() || layerPaint.getLooper() || layerPaint.getImageFilter()) { return false; } paint->setAlpha(SkMulDiv255Round(paint->getAlpha(), SkColorGetA(layerColor))); return true; }
static bool HasAnyEffect(const SkPaint& paint) { return paint.getPathEffect() || paint.getShader() || paint.getXfermode() || paint.getMaskFilter() || paint.getColorFilter() || paint.getRasterizer() || paint.getLooper() || paint.getImageFilter(); }
// Is the supplied paint simply a color? static bool is_simple(const SkPaint& p) { return NULL == p.getPathEffect() && NULL == p.getShader() && NULL == p.getXfermode() && NULL == p.getMaskFilter() && NULL == p.getColorFilter() && NULL == p.getRasterizer() && NULL == p.getLooper() && NULL == p.getImageFilter(); }
void addBitmapFromPaint(const SkPaint& paint) { SkShader* shader = paint.getShader(); if (shader) { SkBitmap bm; // Check whether the shader is a gradient in order to short-circuit // call to asABitmap to prevent generation of bitmaps from // gradient shaders, which implement asABitmap. if (SkShader::kNone_GradientType == shader->asAGradient(NULL) && shader->asABitmap(&bm, NULL, NULL)) { fPRSet->add(bm.pixelRef()); } } }
virtual void onDraw(SkCanvas* canvas) { canvas->translate(10, 10); SkPaint paint; install(&paint, SkPerlinNoiseShader::kFractalNoise_Type, 0.1f, 0.1f, 2, 0, false); const SkScalar w = SkIntToScalar(fSize.width()); const SkScalar h = SkIntToScalar(fSize.height()); SkRect r = SkRect::MakeWH(w, h); canvas->drawRect(r, paint); canvas->save(); canvas->translate(w * 5/4, 0); canvas->drawRect(r, paint); canvas->restore(); canvas->save(); canvas->translate(0, h + 10); canvas->scale(2, 2); canvas->drawRect(r, paint); canvas->restore(); canvas->save(); canvas->translate(w + 100, h + 10); canvas->scale(2, 2); canvas->drawRect(r, paint); canvas->restore(); // The next row should draw the same as the previous, even though we are using a local // matrix instead of the canvas. canvas->translate(0, h * 2 + 10); SkMatrix lm; lm.setScale(2, 2); paint.setShader(paint.getShader()->newWithLocalMatrix(lm))->unref(); r.fRight += r.width(); r.fBottom += r.height(); canvas->save(); canvas->translate(0, h + 10); canvas->drawRect(r, paint); canvas->restore(); canvas->save(); canvas->translate(w + 100, h + 10); canvas->drawRect(r, paint); canvas->restore(); }
static uint16_t compute_nondef(const SkPaint& paint, PaintUsage usage) { // kRespectsStroke_PaintUsage is only valid if other bits are also set SkASSERT(0 != (usage & ~kRespectsStroke_PaintUsage)); const SkScalar kTextSize_Default = 12; const SkScalar kTextScaleX_Default = 1; const SkScalar kTextSkewX_Default = 0; const SkScalar kStrokeWidth_Default = 0; const SkScalar kStrokeMiter_Default = 4; const SkColor kColor_Default = SK_ColorBLACK; unsigned bits = (paint.getColor() != kColor_Default) ? kColor_NonDef : 0; if (usage & kText_PaintUsage) { bits |= (paint.getTextSize() != kTextSize_Default ? kTextSize_NonDef : 0); bits |= (paint.getTextScaleX() != kTextScaleX_Default ? kTextScaleX_NonDef : 0); bits |= (paint.getTextSkewX() != kTextSkewX_Default ? kTextSkewX_NonDef : 0); bits |= (paint.getTypeface() ? kTypeface_NonDef : 0); } // TODO: kImage_PaintUsage only needs the shader/maskfilter IF its colortype is kAlpha_8 if (usage & (kVertices_PaintUsage | kDrawPaint_PaintUsage | kImage_PaintUsage | kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_PaintUsage)) { bits |= (paint.getShader() ? kShader_NonDef : 0); } if (usage & (kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_PaintUsage)) { bits |= (paint.getPathEffect() ? kPathEffect_NonDef : 0); bits |= (paint.getRasterizer() ? kRasterizer_NonDef : 0); if (paint.getStyle() != SkPaint::kFill_Style || (usage & kRespectsStroke_PaintUsage)) { bits |= (paint.getStrokeWidth() != kStrokeWidth_Default ? kStrokeWidth_NonDef : 0); bits |= (paint.getStrokeMiter() != kStrokeMiter_Default ? kStrokeMiter_NonDef : 0); } } if (usage & (kText_PaintUsage | kGeometry_PaintUsage | kImage_PaintUsage | kTextBlob_PaintUsage)) { bits |= (paint.getMaskFilter() ? kMaskFilter_NonDef : 0); } bits |= (paint.getColorFilter() ? kColorFilter_NonDef : 0); bits |= (paint.getImageFilter() ? kImageFilter_NonDef : 0); bits |= (paint.getDrawLooper() ? kDrawLooper_NonDef : 0); return SkToU16(bits); }
void GrBlurUtils::drawPathWithMaskFilter(GrContext* context, GrDrawContext* drawContext, const GrClip& clip, const SkPath& origSrcPath, const SkPaint& paint, const SkMatrix& origViewMatrix, const SkMatrix* prePathMatrix, const SkIRect& clipBounds, bool pathIsMutable) { SkASSERT(!pathIsMutable || origSrcPath.isVolatile()); GrStrokeInfo strokeInfo(paint); // comment out the line below to determine if it is the reason that the chrome mac perf bot // has begun crashing // strokeInfo.setResScale(SkDraw::ComputeResScaleForStroking(origViewMatrix)); // If we have a prematrix, apply it to the path, optimizing for the case // where the original path can in fact be modified in place (even though // its parameter type is const). SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath); SkTLazy<SkPath> tmpPath; SkTLazy<SkPath> effectPath; SkPathEffect* pathEffect = paint.getPathEffect(); SkMatrix viewMatrix = origViewMatrix; if (prePathMatrix) { // stroking, path effects, and blurs are supposed to be applied *after* the prePathMatrix. // The pre-path-matrix also should not affect shading. if (!paint.getMaskFilter() && !pathEffect && !paint.getShader() && (strokeInfo.isFillStyle() || strokeInfo.isHairlineStyle())) { viewMatrix.preConcat(*prePathMatrix); } else { SkPath* result = pathPtr; if (!pathIsMutable) { result = tmpPath.init(); result->setIsVolatile(true); pathIsMutable = true; } // should I push prePathMatrix on our MV stack temporarily, instead // of applying it here? See SkDraw.cpp pathPtr->transform(*prePathMatrix, result); pathPtr = result; } } // at this point we're done with prePathMatrix SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
void SkBaseDevice::drawTextRSXform(const void* text, size_t len, const SkRSXform xform[], const SkPaint& paint) { CountTextProc proc = nullptr; switch (paint.getTextEncoding()) { case SkPaint::kUTF8_TextEncoding: proc = SkUTF8_CountUTF8Bytes; break; case SkPaint::kUTF16_TextEncoding: proc = count_utf16; break; case SkPaint::kUTF32_TextEncoding: proc = return_4; break; case SkPaint::kGlyphID_TextEncoding: proc = return_2; break; } SkPaint localPaint(paint); SkShader* shader = paint.getShader(); SkMatrix localM, currM; const void* stopText = (const char*)text + len; while ((const char*)text < (const char*)stopText) { localM.setRSXform(*xform++); currM.setConcat(this->ctm(), localM); SkAutoDeviceCTMRestore adc(this, currM); // We want to rotate each glyph by the rsxform, but we don't want to rotate "space" // (i.e. the shader that cares about the ctm) so we have to undo our little ctm trick // with a localmatrixshader so that the shader draws as if there was no change to the ctm. if (shader) { SkMatrix inverse; if (localM.invert(&inverse)) { localPaint.setShader(shader->makeWithLocalMatrix(inverse)); } else { localPaint.setShader(nullptr); // can't handle this xform } } int subLen = proc((const char*)text); this->drawText(text, subLen, 0, 0, localPaint); text = (const char*)text + subLen; } }
bool NeedsDeepCopy(const SkPaint& paint) { /* * The types below are not yet immutable/reentrant-safe, and so we return * true if instances of them are present in the paint. * * Eventually we hope this list will be empty, and we can always return * false. */ return false #ifdef SK_SUPPORT_LEGACY_SHADER_LOCALMATRIX || paint.getShader() #endif #ifdef SK_SUPPORT_LEGACY_LAYERRASTERIZER_API || paint.getRasterizer() #endif || paint.getImageFilter() ; }
Resources SkSVGDevice::AutoElement::addResources(const SkDraw& draw, const SkPaint& paint) { Resources resources(paint); // FIXME: this is a weak heuristic and we end up with LOTS of redundant clips. bool hasClip = !draw.fClipStack->isWideOpen(); bool hasShader = SkToBool(paint.getShader()); if (hasClip || hasShader) { AutoElement defs("defs", fWriter); if (hasClip) { this->addClipResources(draw, &resources); } if (hasShader) { this->addShaderResources(paint, &resources); } } return resources; }
PassRefPtr<JSONObject> LoggingCanvas::objectForSkPaint(const SkPaint& paint) { RefPtr<JSONObject> paintItem = JSONObject::create(); paintItem->setNumber("textSize", paint.getTextSize()); paintItem->setNumber("textScaleX", paint.getTextScaleX()); paintItem->setNumber("textSkewX", paint.getTextSkewX()); if (SkShader* shader = paint.getShader()) paintItem->setObject("shader", objectForSkShader(*shader)); paintItem->setString("color", stringForSkColor(paint.getColor())); paintItem->setNumber("strokeWidth", paint.getStrokeWidth()); paintItem->setNumber("strokeMiter", paint.getStrokeMiter()); paintItem->setString("flags", stringForSkPaintFlags(paint)); paintItem->setString("filterLevel", filterQualityName(paint.getFilterQuality())); paintItem->setString("textAlign", textAlignName(paint.getTextAlign())); paintItem->setString("strokeCap", strokeCapName(paint.getStrokeCap())); paintItem->setString("strokeJoin", strokeJoinName(paint.getStrokeJoin())); paintItem->setString("styleName", styleName(paint.getStyle())); paintItem->setString("textEncoding", textEncodingName(paint.getTextEncoding())); paintItem->setString("hinting", hintingName(paint.getHinting())); return paintItem.release(); }
int SkFontHost::ComputeGammaFlag(const SkPaint& paint) { if (paint.getShader() == NULL) { SkColor c = paint.getColor(); int r = SkColorGetR(c); int g = SkColorGetG(c); int b = SkColorGetB(c); int luminance = (r * 2 + g * 5 + b) >> 3; if (luminance <= BLACK_GAMMA_THRESHOLD) { // printf("------ black gamma for [%d %d %d]\n", r, g, b); return SkScalerContext::kGammaForBlack_Flag; } if (luminance >= WHITE_GAMMA_THRESHOLD) { // printf("------ white gamma for [%d %d %d]\n", r, g, b); return SkScalerContext::kGammaForWhite_Flag; } }
// 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; }