void SkStrokeRec::init(const SkPaint& paint, SkPaint::Style style) { switch (style) { 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: SkDEBUGFAIL("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); }
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()))) {}
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 SkPDFDevice::drawPoints(const SkDraw& d, SkCanvas::PointMode mode, size_t count, const SkPoint* points, const SkPaint& paint) { if (count == 0) return; switch (mode) { case SkCanvas::kPolygon_PointMode: updateGSFromPaint(paint, false); SkPDFUtils::MoveTo(points[0].fX, points[0].fY, &fContent); for (size_t i = 1; i < count; i++) { SkPDFUtils::AppendLine(points[i].fX, points[i].fY, &fContent); } SkPDFUtils::StrokePath(&fContent); break; case SkCanvas::kLines_PointMode: updateGSFromPaint(paint, false); for (size_t i = 0; i < count/2; i++) { SkPDFUtils::MoveTo(points[i * 2].fX, points[i * 2].fY, &fContent); SkPDFUtils::AppendLine(points[i * 2 + 1].fX, points[i * 2 + 1].fY, &fContent); SkPDFUtils::StrokePath(&fContent); } break; case SkCanvas::kPoints_PointMode: if (paint.getStrokeCap() == SkPaint::kRound_Cap) { updateGSFromPaint(paint, false); for (size_t i = 0; i < count; i++) { SkPDFUtils::MoveTo(points[i].fX, points[i].fY, &fContent); SkPDFUtils::StrokePath(&fContent); } } else { // PDF won't draw a single point with square/butt caps because // the orientation is ambiguous. Draw a rectangle instead. SkPaint newPaint = paint; newPaint.setStyle(SkPaint::kFill_Style); SkScalar strokeWidth = paint.getStrokeWidth(); SkScalar halfStroke = strokeWidth * SK_ScalarHalf; for (size_t i = 0; i < count; i++) { SkRect r = SkRect::MakeXYWH(points[i].fX, points[i].fY, 0, 0); r.inset(-halfStroke, -halfStroke); drawRect(d, r, newPaint); } } break; default: SkASSERT(false); } }
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 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()); }
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); } }
static void apply_paint_cap(const SkPaint& paint, Json::Value* target) { SkPaint::Cap cap = paint.getStrokeCap(); if (cap != SkPaint::kDefault_Cap) { switch (cap) { case SkPaint::kButt_Cap: { (*target)[SKJSONCANVAS_ATTRIBUTE_CAP] = Json::Value(SKJSONCANVAS_CAP_BUTT); break; } case SkPaint::kRound_Cap: { (*target)[SKJSONCANVAS_ATTRIBUTE_CAP] = Json::Value(SKJSONCANVAS_CAP_ROUND); break; } case SkPaint::kSquare_Cap: { (*target)[SKJSONCANVAS_ATTRIBUTE_CAP] = Json::Value(SKJSONCANVAS_CAP_SQUARE); break; } default: SkASSERT(false); } } }
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(); }
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; } }
/* * Header: * paint flags : 32 * non_def bits : 16 * xfermode enum : 8 * pad zeros : 8 */ static void write_paint(SkWriteBuffer& writer, const SkPaint& paint, unsigned usage) { uint32_t packedFlags = pack_paint_flags(paint.getFlags(), paint.getHinting(), paint.getTextAlign(), paint.getFilterQuality(), paint.getStyle(), paint.getStrokeCap(), paint.getStrokeJoin(), paint.getTextEncoding()); writer.write32(packedFlags); unsigned nondef = compute_nondef(paint, (PaintUsage)usage); const uint8_t pad = 0; writer.write32((nondef << 16) | ((unsigned)paint.getBlendMode() << 8) | pad); CHECK_WRITE_SCALAR(writer, nondef, paint, TextSize); CHECK_WRITE_SCALAR(writer, nondef, paint, TextScaleX); CHECK_WRITE_SCALAR(writer, nondef, paint, TextSkewX); CHECK_WRITE_SCALAR(writer, nondef, paint, StrokeWidth); CHECK_WRITE_SCALAR(writer, nondef, paint, StrokeMiter); if (nondef & kColor_NonDef) { writer.write32(paint.getColor()); } if (nondef & kTypeface_NonDef) { // TODO: explore idea of writing bits indicating "use the prev (or prev N) face" // e.g. 1-N bits is an index into a ring buffer of typefaces SkTypeface* tf = paint.getTypeface(); SkASSERT(tf); writer.writeTypeface(tf); } CHECK_WRITE_FLATTENABLE(writer, nondef, paint, PathEffect); CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Shader); CHECK_WRITE_FLATTENABLE(writer, nondef, paint, MaskFilter); CHECK_WRITE_FLATTENABLE(writer, nondef, paint, ColorFilter); CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Rasterizer); CHECK_WRITE_FLATTENABLE(writer, nondef, paint, ImageFilter); CHECK_WRITE_FLATTENABLE(writer, nondef, paint, DrawLooper); }
SkStrokePathEffect::SkStrokePathEffect(const SkPaint& paint) : fWidth(paint.getStrokeWidth()), fMiter(paint.getStrokeMiter()), fStyle(SkToU8(paint.getStyle())), fJoin(SkToU8(paint.getStrokeJoin())), fCap(SkToU8(paint.getStrokeCap())) { }
// Even with kEntirePaint_Bits, we always ensure that the master paint's // text-encoding is respected, since that controls how we interpret the // text/length parameters of a draw[Pos]Text call. void SkLayerDrawLooper::ApplyInfo(SkPaint* dst, const SkPaint& src, const LayerInfo& info) { uint32_t mask = info.fFlagsMask; dst->setFlags((dst->getFlags() & ~mask) | (src.getFlags() & mask)); dst->setColor(xferColor(src.getColor(), dst->getColor(), info.fColorMode)); BitFlags bits = info.fPaintBits; SkPaint::TextEncoding encoding = dst->getTextEncoding(); if (0 == bits) { return; } if (kEntirePaint_Bits == bits) { // we've already computed these, so save it from the assignment uint32_t f = dst->getFlags(); SkColor c = dst->getColor(); *dst = src; dst->setFlags(f); dst->setColor(c); dst->setTextEncoding(encoding); return; } if (bits & kStyle_Bit) { dst->setStyle(src.getStyle()); dst->setStrokeWidth(src.getStrokeWidth()); dst->setStrokeMiter(src.getStrokeMiter()); dst->setStrokeCap(src.getStrokeCap()); dst->setStrokeJoin(src.getStrokeJoin()); } if (bits & kTextSkewX_Bit) { dst->setTextSkewX(src.getTextSkewX()); } if (bits & kPathEffect_Bit) { dst->setPathEffect(src.getPathEffect()); } if (bits & kMaskFilter_Bit) { dst->setMaskFilter(src.getMaskFilter()); } if (bits & kShader_Bit) { dst->setShader(src.getShader()); } if (bits & kColorFilter_Bit) { dst->setColorFilter(src.getColorFilter()); } if (bits & kXfermode_Bit) { dst->setXfermode(src.getXfermode()); } // we don't override these #if 0 dst->setTypeface(src.getTypeface()); dst->setTextSize(src.getTextSize()); dst->setTextScaleX(src.getTextScaleX()); dst->setRasterizer(src.getRasterizer()); dst->setLooper(src.getLooper()); dst->setTextEncoding(src.getTextEncoding()); dst->setHinting(src.getHinting()); #endif }
// Even with kEntirePaint_Bits, we always ensure that the master paint's // text-encoding is respected, since that controls how we interpret the // text/length parameters of a draw[Pos]Text call. void SkLayerDrawLooper::LayerDrawLooperContext::ApplyInfo( SkPaint* dst, const SkPaint& src, const LayerInfo& info) { SkColor4f srcColor = src.getColor4f(); #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK // The framework may respect the alpha value on the original paint. // Match this legacy behavior. if (src.getAlpha() == 255) { srcColor.fA = dst->getColor4f().fA; } #endif dst->setColor4f(xferColor(srcColor, dst->getColor4f(), (SkBlendMode)info.fColorMode), sk_srgb_singleton()); BitFlags bits = info.fPaintBits; SkPaint::TextEncoding encoding = dst->getTextEncoding(); if (0 == bits) { return; } if (kEntirePaint_Bits == bits) { // we've already computed these, so save it from the assignment uint32_t f = dst->getFlags(); SkColor4f c = dst->getColor4f(); *dst = src; dst->setFlags(f); dst->setColor4f(c, sk_srgb_singleton()); dst->setTextEncoding(encoding); return; } if (bits & kStyle_Bit) { dst->setStyle(src.getStyle()); dst->setStrokeWidth(src.getStrokeWidth()); dst->setStrokeMiter(src.getStrokeMiter()); dst->setStrokeCap(src.getStrokeCap()); dst->setStrokeJoin(src.getStrokeJoin()); } if (bits & kTextSkewX_Bit) { dst->setTextSkewX(src.getTextSkewX()); } if (bits & kPathEffect_Bit) { dst->setPathEffect(src.refPathEffect()); } if (bits & kMaskFilter_Bit) { dst->setMaskFilter(src.refMaskFilter()); } if (bits & kShader_Bit) { dst->setShader(src.refShader()); } if (bits & kColorFilter_Bit) { dst->setColorFilter(src.refColorFilter()); } if (bits & kXfermode_Bit) { dst->setBlendMode(src.getBlendMode()); } // we don't override these #if 0 dst->setTypeface(src.getTypeface()); dst->setTextSize(src.getTextSize()); dst->setTextScaleX(src.getTextScaleX()); dst->setRasterizer(src.getRasterizer()); dst->setLooper(src.getLooper()); dst->setTextEncoding(src.getTextEncoding()); dst->setHinting(src.getHinting()); #endif }
void SkFlatPaint::dump() const { SkPaint defaultPaint; SkFlattenableReadBuffer buffer(fPaintData); SkTypeface* typeface = (SkTypeface*) buffer.readPtr(); char pBuffer[DUMP_BUFFER_SIZE]; char* bufferPtr = pBuffer; bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "paint: "); if (typeface != defaultPaint.getTypeface()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "typeface:%p ", typeface); SkScalar textSize = buffer.readScalar(); if (textSize != defaultPaint.getTextSize()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "textSize:%g ", SkScalarToFloat(textSize)); SkScalar textScaleX = buffer.readScalar(); if (textScaleX != defaultPaint.getTextScaleX()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "textScaleX:%g ", SkScalarToFloat(textScaleX)); SkScalar textSkewX = buffer.readScalar(); if (textSkewX != defaultPaint.getTextSkewX()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "textSkewX:%g ", SkScalarToFloat(textSkewX)); const SkPathEffect* pathEffect = (const SkPathEffect*) buffer.readFlattenable(); if (pathEffect != defaultPaint.getPathEffect()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "pathEffect:%p ", pathEffect); SkDELETE(pathEffect); const SkShader* shader = (const SkShader*) buffer.readFlattenable(); if (shader != defaultPaint.getShader()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "shader:%p ", shader); SkDELETE(shader); const SkXfermode* xfermode = (const SkXfermode*) buffer.readFlattenable(); if (xfermode != defaultPaint.getXfermode()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "xfermode:%p ", xfermode); SkDELETE(xfermode); const SkMaskFilter* maskFilter = (const SkMaskFilter*) buffer.readFlattenable(); if (maskFilter != defaultPaint.getMaskFilter()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "maskFilter:%p ", maskFilter); SkDELETE(maskFilter); const SkColorFilter* colorFilter = (const SkColorFilter*) buffer.readFlattenable(); if (colorFilter != defaultPaint.getColorFilter()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "colorFilter:%p ", colorFilter); SkDELETE(colorFilter); const SkRasterizer* rasterizer = (const SkRasterizer*) buffer.readFlattenable(); if (rasterizer != defaultPaint.getRasterizer()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "rasterizer:%p ", rasterizer); SkDELETE(rasterizer); const SkDrawLooper* drawLooper = (const SkDrawLooper*) buffer.readFlattenable(); if (drawLooper != defaultPaint.getLooper()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "drawLooper:%p ", drawLooper); SkDELETE(drawLooper); unsigned color = buffer.readU32(); if (color != defaultPaint.getColor()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "color:0x%x ", color); SkScalar strokeWidth = buffer.readScalar(); if (strokeWidth != defaultPaint.getStrokeWidth()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "strokeWidth:%g ", SkScalarToFloat(strokeWidth)); SkScalar strokeMiter = buffer.readScalar(); if (strokeMiter != defaultPaint.getStrokeMiter()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "strokeMiter:%g ", SkScalarToFloat(strokeMiter)); unsigned flags = buffer.readU16(); if (flags != defaultPaint.getFlags()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "flags:0x%x ", flags); int align = buffer.readU8(); if (align != defaultPaint.getTextAlign()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "align:0x%x ", align); int strokeCap = buffer.readU8(); if (strokeCap != defaultPaint.getStrokeCap()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "strokeCap:0x%x ", strokeCap); int strokeJoin = buffer.readU8(); if (strokeJoin != defaultPaint.getStrokeJoin()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "align:0x%x ", strokeJoin); int style = buffer.readU8(); if (style != defaultPaint.getStyle()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "style:0x%x ", style); int textEncoding = buffer.readU8(); if (textEncoding != defaultPaint.getTextEncoding()) bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), "textEncoding:0x%x ", textEncoding); SkDebugf("%s\n", pBuffer); }