bool GrDistanceFieldTextContext::canDraw(const SkPaint& paint, const SkMatrix& viewMatrix) { // TODO: support perspective (need getMaxScale replacement) if (viewMatrix.hasPerspective()) { return false; } SkScalar maxScale = viewMatrix.getMaxScale(); SkScalar scaledTextSize = maxScale*paint.getTextSize(); // Scaling up beyond 2x yields undesireable artifacts if (scaledTextSize > 2*kLargeDFFontSize) { return false; } if (!fEnableDFRendering && !paint.isDistanceFieldTextTEMP() && scaledTextSize < kLargeDFFontSize) { return false; } // rasterizers and mask filters modify alpha, which doesn't // translate well to distance if (paint.getRasterizer() || paint.getMaskFilter() || !fContext->getTextTarget()->caps()->shaderDerivativeSupport()) { return false; } // TODO: add some stroking support if (paint.getStyle() != SkPaint::kFill_Style) { return false; } return true; }
SkStrokeRec::SkStrokeRec(const SkPaint& paint) { switch (paint.getStyle()) { case SkPaint::kFill_Style: fWidth = kStrokeRec_FillStyleWidth; fStrokeAndFill = false; break; case SkPaint::kStroke_Style: fWidth = paint.getStrokeWidth(); fStrokeAndFill = false; break; case SkPaint::kStrokeAndFill_Style: if (0 == paint.getStrokeWidth()) { // hairline+fill == fill fWidth = kStrokeRec_FillStyleWidth; fStrokeAndFill = false; } else { fWidth = paint.getStrokeWidth(); fStrokeAndFill = true; } break; default: SkASSERT(!"unknown paint style"); // fall back on just fill fWidth = kStrokeRec_FillStyleWidth; fStrokeAndFill = false; break; } // copy these from the paint, regardless of our "style" fMiterLimit = paint.getStrokeMiter(); fCap = paint.getStrokeCap(); fJoin = paint.getStrokeJoin(); }
SkStroke::SkStroke(const SkPaint& p, SkScalar width) { fWidth = width; fMiterLimit = p.getStrokeMiter(); fCap = (uint8_t)p.getStrokeCap(); fJoin = (uint8_t)p.getStrokeJoin(); fDoFill = SkToU8(p.getStyle() == SkPaint::kStrokeAndFill_Style); }
bool GrStencilAndCoverTextContext::canDraw(const GrRenderTarget* rt, const GrClip& clip, const GrPaint& paint, const SkPaint& skPaint, const SkMatrix& viewMatrix) { if (skPaint.getRasterizer()) { return false; } if (skPaint.getMaskFilter()) { return false; } if (SkPathEffect* pe = skPaint.getPathEffect()) { if (pe->asADash(NULL) != SkPathEffect::kDash_DashType) { return false; } } // No hairlines unless we can map the 1 px width to the object space. if (skPaint.getStyle() == SkPaint::kStroke_Style && skPaint.getStrokeWidth() == 0 && viewMatrix.hasPerspective()) { return false; } // No color bitmap fonts. SkScalerContext::Rec rec; SkScalerContext::MakeRec(skPaint, &fDeviceProperties, NULL, &rec); return rec.getFormat() != SkMask::kARGB32_Format; }
bool GrDistanceFieldTextContext::canDraw(const SkPaint& paint) { if (!fEnableDFRendering && !paint.isDistanceFieldTextTEMP()) { return false; } // rasterizers and mask filters modify alpha, which doesn't // translate well to distance if (paint.getRasterizer() || paint.getMaskFilter() || !fContext->getTextTarget()->caps()->shaderDerivativeSupport()) { return false; } // TODO: add some stroking support if (paint.getStyle() != SkPaint::kFill_Style) { return false; } // TODO: choose an appropriate maximum scale for distance fields and // enable perspective if (SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix())) { return false; } return true; }
bool GrTextUtils::ShouldDisableLCD(const SkPaint& paint) { return !SkXfermode::AsMode(paint.getXfermode(), nullptr) || paint.getMaskFilter() || paint.getRasterizer() || paint.getPathEffect() || paint.isFakeBoldText() || paint.getStyle() != SkPaint::kFill_Style; }
void SkBaseDevice::drawArc(const SkDraw& draw, const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, const SkPaint& paint) { SkPath path; bool isFillNoPathEffect = SkPaint::kFill_Style == paint.getStyle() && !paint.getPathEffect(); SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter, isFillNoPathEffect); this->drawPath(draw, path, paint); }
TessellationCache::Description::Description(Type type, const Matrix4& transform, const SkPaint& paint) : type(type) , aa(paint.isAntiAlias()) , cap(paint.getStrokeCap()) , style(paint.getStyle()) , strokeWidth(paint.getStrokeWidth()) { PathTessellator::extractTessellationScales(transform, &scaleX, &scaleY); memset(&shape, 0, sizeof(Shape)); }
void OpaqueRegionSkia::didDrawRect(const PlatformContextSkia* context, const SkRect& fillRect, const SkPaint& paint, const SkBitmap* sourceBitmap) { // Any stroking may put alpha in pixels even if the filling part does not. if (paint.getStyle() != SkPaint::kFill_Style) { bool fillsBounds = false; if (!paint.canComputeFastBounds()) didDrawUnbounded(paint); else { SkRect strokeRect; strokeRect = paint.computeFastBounds(fillRect, &strokeRect); didDraw(context, strokeRect, paint, sourceBitmap, fillsBounds, FillOrStroke); } } bool fillsBounds = paint.getStyle() != SkPaint::kStroke_Style; didDraw(context, fillRect, paint, sourceBitmap, fillsBounds, FillOnly); }
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()); }
void SkGLDevice::drawPath(const SkDraw& draw, const SkPath& path, const SkPaint& paint) { TRACE_DRAW("coreDrawPath", this, draw); if (paint.getStyle() == SkPaint::kStroke_Style) { return; } AutoPaintShader shader(this, paint); SkGL::FillPath(path, paint, shader.useTex(), this->updateMatrixClip()); }
bool SkBitmapDevice::onShouldDisableLCD(const SkPaint& paint) const { if (kN32_SkColorType != fBitmap.colorType() || paint.getRasterizer() || paint.getPathEffect() || paint.isFakeBoldText() || paint.getStyle() != SkPaint::kFill_Style || !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)) { return true; } return false; }
void OpaqueRegionSkia::didDrawRect(const PlatformContextSkia* context, const AffineTransform& transform, const SkRect& fillRect, const SkPaint& paint, const SkBitmap* bitmap) { // Any stroking may put alpha in pixels even if the filling part does not. if (paint.getStyle() != SkPaint::kFill_Style) { bool opaque = paintIsOpaque(paint, bitmap); bool fillsBounds = false; if (!paint.canComputeFastBounds()) didDrawUnbounded(paint, opaque); else { SkRect strokeRect; strokeRect = paint.computeFastBounds(fillRect, &strokeRect); didDraw(context, transform, strokeRect, paint, opaque, fillsBounds); } } bool checkFillOnly = true; bool opaque = paintIsOpaque(paint, bitmap, checkFillOnly); bool fillsBounds = paint.getStyle() != SkPaint::kStroke_Style; didDraw(context, transform, fillRect, paint, opaque, fillsBounds); }
void GrTextUtils::DrawPosTextAsPath(GrContext* context, GrDrawContext* dc, const SkSurfaceProps& props, const GrClip& clip, const SkPaint& origPaint, const SkMatrix& viewMatrix, const char text[], size_t byteLength, const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset, const SkIRect& clipBounds) { // setup our std paint, in hopes of getting hits in the cache SkPaint paint(origPaint); SkScalar matrixScale = paint.setupForAsPaths(); SkMatrix matrix; matrix.setScale(matrixScale, matrixScale); // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache. paint.setStyle(SkPaint::kFill_Style); paint.setPathEffect(nullptr); SkPaint::GlyphCacheProc glyphCacheProc = paint.getGlyphCacheProc(true); SkAutoGlyphCache autoCache(paint, &props, nullptr); SkGlyphCache* cache = autoCache.getCache(); const char* stop = text + byteLength; SkTextAlignProc alignProc(paint.getTextAlign()); SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); // Now restore the original settings, so we "draw" with whatever style/stroking. paint.setStyle(origPaint.getStyle()); paint.setPathEffect(origPaint.getPathEffect()); while (text < stop) { const SkGlyph& glyph = glyphCacheProc(cache, &text); if (glyph.fWidth) { const SkPath* path = cache->findPath(glyph); if (path) { SkPoint tmsLoc; tmsProc(pos, &tmsLoc); SkPoint loc; alignProc(tmsLoc, glyph, &loc); matrix[SkMatrix::kMTransX] = loc.fX; matrix[SkMatrix::kMTransY] = loc.fY; GrBlurUtils::drawPathWithMaskFilter(context, dc, clip, *path, paint, viewMatrix, &matrix, clipBounds, false); } } pos += scalarsPerPosition; } }
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); }
bool GrStencilAndCoverTextContext::internalCanDraw(const SkPaint& skPaint) { if (skPaint.getRasterizer()) { return false; } if (skPaint.getMaskFilter()) { return false; } if (SkPathEffect* pe = skPaint.getPathEffect()) { if (pe->asADash(nullptr) != SkPathEffect::kDash_DashType) { return false; } } // No hairlines. They would require new paths with customized strokes for every new draw matrix. return SkPaint::kStroke_Style != skPaint.getStyle() || 0 != skPaint.getStrokeWidth(); }
static void apply_paint_style(const SkPaint& paint, Json::Value* target) { SkPaint::Style style = paint.getStyle(); if (style != SkPaint::kFill_Style) { switch (style) { case SkPaint::kStroke_Style: { Json::Value stroke(SKJSONCANVAS_STYLE_STROKE); (*target)[SKJSONCANVAS_ATTRIBUTE_STYLE] = stroke; break; } case SkPaint::kStrokeAndFill_Style: { Json::Value strokeAndFill(SKJSONCANVAS_STYLE_STROKEANDFILL); (*target)[SKJSONCANVAS_ATTRIBUTE_STYLE] = strokeAndFill; break; } default: SkASSERT(false); } } }
void SkBaseDevice::drawRegion(const SkDraw& draw, const SkRegion& region, const SkPaint& paint) { bool isNonTranslate = draw.fMatrix->getType() & ~(SkMatrix::kTranslate_Mask); bool complexPaint = paint.getStyle() != SkPaint::kFill_Style || paint.getMaskFilter() || paint.getPathEffect(); bool antiAlias = paint.isAntiAlias() && (!is_int(draw.fMatrix->getTranslateX()) || !is_int(draw.fMatrix->getTranslateY())); if (isNonTranslate || complexPaint || antiAlias) { SkPath path; region.getBoundaryPath(&path); return this->drawPath(draw, path, paint, nullptr, false); } SkRegion::Iterator it(region); while (!it.done()) { this->drawRect(draw, SkRect::Make(it.rect()), paint); it.next(); } }
void SkSVGDevice::AutoElement::addPaint(const SkPaint& paint, const Resources& resources) { SkPaint::Style style = paint.getStyle(); if (style == SkPaint::kFill_Style || style == SkPaint::kStrokeAndFill_Style) { this->addAttribute("fill", resources.fPaintServer); if (SK_AlphaOPAQUE != SkColorGetA(paint.getColor())) { this->addAttribute("fill-opacity", svg_opacity(paint.getColor())); } } else { SkASSERT(style == SkPaint::kStroke_Style); this->addAttribute("fill", "none"); } if (style == SkPaint::kStroke_Style || style == SkPaint::kStrokeAndFill_Style) { this->addAttribute("stroke", resources.fPaintServer); SkScalar strokeWidth = paint.getStrokeWidth(); if (strokeWidth == 0) { // Hairline stroke strokeWidth = 1; this->addAttribute("vector-effect", "non-scaling-stroke"); } this->addAttribute("stroke-width", strokeWidth); if (const char* cap = svg_cap(paint.getStrokeCap())) { this->addAttribute("stroke-linecap", cap); } if (const char* join = svg_join(paint.getStrokeJoin())) { this->addAttribute("stroke-linejoin", join); } if (paint.getStrokeJoin() == SkPaint::kMiter_Join) { this->addAttribute("stroke-miterlimit", paint.getStrokeMiter()); } if (SK_AlphaOPAQUE != SkColorGetA(paint.getColor())) { this->addAttribute("stroke-opacity", svg_opacity(paint.getColor())); } } else { SkASSERT(style == SkPaint::kFill_Style); this->addAttribute("stroke", "none"); } }
static void drawAndTest(skiatest::Reporter* reporter, const SkPath& path, const SkPaint& paint, bool shouldDraw) { SkBitmap bm; bm.allocN32Pixels(DIMENSION, DIMENSION); SkASSERT(DIMENSION*4 == bm.rowBytes()); // ensure no padding on each row bm.eraseColor(SK_ColorTRANSPARENT); SkCanvas canvas(bm); SkPaint p(paint); p.setColor(SK_ColorWHITE); canvas.drawPath(path, p); size_t count = DIMENSION * DIMENSION; const SkPMColor* ptr = bm.getAddr32(0, 0); SkPMColor andValue = ~0U; SkPMColor orValue = 0; for (size_t i = 0; i < count; ++i) { SkPMColor c = ptr[i]; andValue &= c; orValue |= c; } // success means we drew everywhere or nowhere (depending on shouldDraw) bool success = shouldDraw ? (~0U == andValue) : (0 == orValue); if (!success) { const char* str; if (shouldDraw) { str = "Path expected to draw everywhere, but didn't. "; } else { str = "Path expected to draw nowhere, but did. "; } ERRORF(reporter, "%s style[%d] cap[%d] join[%d] antialias[%d]" " filltype[%d] ptcount[%d]", str, paint.getStyle(), paint.getStrokeCap(), paint.getStrokeJoin(), paint.isAntiAlias(), path.getFillType(), path.countPoints()); // uncomment this if you want to step in to see the failure // canvas.drawPath(path, p); } }
bool SkBitmapDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) { if (!paint.isLCDRenderText() || !paint.isAntiAlias()) { // we're cool with the paint as is return false; } if (kN32_SkColorType != fBitmap.colorType() || paint.getRasterizer() || paint.getPathEffect() || paint.isFakeBoldText() || paint.getStyle() != SkPaint::kFill_Style || !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)) { // turn off lcd flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag; flags->fHinting = paint.getHinting(); return true; } // we're cool with the paint as is return false; }
void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& path, const SkPaint& paint, const SkMatrix* prePathMatrix, bool pathIsMutable) { NOT_IMPLEMENTED(prePathMatrix != NULL, true); if (paint.getPathEffect()) { // Apply the path effect to path and draw it that way. SkPath noEffectPath; paint.getFillPath(path, &noEffectPath); SkPaint noEffectPaint(paint); SkSafeUnref(noEffectPaint.setPathEffect(NULL)); drawPath(d, noEffectPath, noEffectPaint, NULL, true); return; } updateGSFromPaint(paint, false); SkPDFUtils::EmitPath(path, &fContent); SkPDFUtils::PaintPath(paint.getStyle(), path.getFillType(), &fContent); }
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(); }
// 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; }
void SkPDFDevice::drawRect(const SkDraw& d, const SkRect& r, const SkPaint& paint) { if (paint.getPathEffect()) { // Create a path for the rectangle and apply the path effect to it. SkPath path; path.addRect(r); paint.getFillPath(path, &path); SkPaint noEffectPaint(paint); SkSafeUnref(noEffectPaint.setPathEffect(NULL)); drawPath(d, path, noEffectPaint, NULL, true); return; } updateGSFromPaint(paint, false); // Skia has 0,0 at top left, pdf at bottom left. Do the right thing. SkScalar bottom = r.fBottom < r.fTop ? r.fBottom : r.fTop; SkPDFUtils::AppendRectangle(r.fLeft, bottom, r.width(), r.height(), &fContent); SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType, &fContent); }
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; } }
bool GrTextUtils::CanDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix, const SkSurfaceProps& props, const GrShaderCaps& caps) { // TODO: support perspective (need getMaxScale replacement) if (viewMatrix.hasPerspective()) { return false; } SkScalar maxScale = viewMatrix.getMaxScale(); SkScalar scaledTextSize = maxScale*skPaint.getTextSize(); // Hinted text looks far better at small resolutions // Scaling up beyond 2x yields undesireable artifacts if (scaledTextSize < kMinDFFontSize || scaledTextSize > kLargeDFFontLimit) { return false; } bool useDFT = props.isUseDeviceIndependentFonts(); #if SK_FORCE_DISTANCE_FIELD_TEXT useDFT = true; #endif if (!useDFT && scaledTextSize < kLargeDFFontSize) { return false; } // rasterizers and mask filters modify alpha, which doesn't // translate well to distance if (skPaint.getRasterizer() || skPaint.getMaskFilter() || !caps.shaderDerivativeSupport()) { return false; } // TODO: add some stroking support if (skPaint.getStyle() != SkPaint::kFill_Style) { return false; } return true; }
bool GrStencilAndCoverTextContext::canDraw(const SkPaint& paint) { if (paint.getRasterizer()) { return false; } if (paint.getMaskFilter()) { return false; } if (paint.getPathEffect()) { return false; } // No hairlines unless we can map the 1 px width to the object space. if (paint.getStyle() == SkPaint::kStroke_Style && paint.getStrokeWidth() == 0 && fContext->getMatrix().hasPerspective()) { return false; } // No color bitmap fonts. SkScalerContext::Rec rec; SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec); return rec.getFormat() != SkMask::kARGB32_Format; }
bool SkDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) { if (!paint.isLCDRenderText()) { // we're cool with the paint as is return false; } if (SkBitmap::kARGB_8888_Config != fBitmap.config() || paint.getShader() || paint.getXfermode() || // unless its srcover paint.getMaskFilter() || paint.getRasterizer() || paint.getColorFilter() || paint.getPathEffect() || paint.isFakeBoldText() || paint.getStyle() != SkPaint::kFill_Style) { // turn off lcd flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag; flags->fHinting = paint.getHinting(); return true; } // we're cool with the paint as is return false; }
bool GrTextContext::CanDrawAsDistanceFields(const SkPaint& paint, const SkFont& font, const SkMatrix& viewMatrix, const SkSurfaceProps& props, bool contextSupportsDistanceFieldText, const Options& options) { if (!viewMatrix.hasPerspective()) { SkScalar maxScale = viewMatrix.getMaxScale(); SkScalar scaledTextSize = maxScale * font.getSize(); // Hinted text looks far better at small resolutions // Scaling up beyond 2x yields undesireable artifacts if (scaledTextSize < options.fMinDistanceFieldFontSize || scaledTextSize > options.fMaxDistanceFieldFontSize) { return false; } bool useDFT = props.isUseDeviceIndependentFonts(); #if SK_FORCE_DISTANCE_FIELD_TEXT useDFT = true; #endif if (!useDFT && scaledTextSize < kLargeDFFontSize) { return false; } } // mask filters modify alpha, which doesn't translate well to distance if (paint.getMaskFilter() || !contextSupportsDistanceFieldText) { return false; } // TODO: add some stroking support if (paint.getStyle() != SkPaint::kFill_Style) { return false; } return true; }