sk_sp<SkFont> SkFont::Testing_CreateFromPaint(const SkPaint& paint) { uint32_t flags = 0; if (paint.isVerticalText()) { flags |= kVertical_Flag; } if (paint.isEmbeddedBitmapText()) { flags |= kEmbeddedBitmaps_Flag; } if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) { flags |= kGenA8FromLCD_Flag; } if (paint.isFakeBoldText()) { flags |= kEmbolden_Flag; } if (SkPaint::kFull_Hinting == paint.getHinting()) { flags |= kEnableByteCodeHints_Flag; } if (paint.isAutohinted()) { flags |= kEnableAutoHints_Flag; } if (paint.isSubpixelText() || paint.isLinearText()) { // this is our default } else { flags |= kUseNonlinearMetrics_Flag; } MaskType maskType = SkFont::kBW_MaskType; if (paint.isAntiAlias()) { maskType = paint.isLCDRenderText() ? kLCD_MaskType : kA8_MaskType; } return Make(sk_ref_sp(paint.getTypeface()), paint.getTextSize(), paint.getTextScaleX(), paint.getTextSkewX(), maskType, flags); }
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 SkPDFDevice::drawPosText(const SkDraw&, const void* text, size_t len, const SkScalar pos[], SkScalar constY, int scalarsPerPos, const SkPaint& paint) { SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos); SkPaint textPaint = calculateTextPaint(paint); updateGSFromPaint(textPaint, true); // Make sure we have a glyph id encoding. SkAutoFree glyphStorage; uint16_t* glyphIDs; size_t numGlyphs; if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) { numGlyphs = paint.textToGlyphs(text, len, NULL); glyphIDs = (uint16_t*)sk_malloc_flags(numGlyphs * 2, SK_MALLOC_TEMP | SK_MALLOC_THROW); glyphStorage.set(glyphIDs); paint.textToGlyphs(text, len, glyphIDs); textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); } else { SkASSERT((len & 1) == 0); numGlyphs = len / 2; glyphIDs = (uint16_t*)text; } SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); fContent.writeText("BT\n"); updateFont(textPaint, glyphIDs[0]); for (size_t i = 0; i < numGlyphs; i++) { SkPDFFont* font = fGraphicStack[fGraphicStackIndex].fFont; uint16_t encodedValue = glyphIDs[i]; if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) { updateFont(textPaint, glyphIDs[i]); i--; continue; } SkScalar x = pos[i * scalarsPerPos]; SkScalar y = scalarsPerPos == 1 ? constY : pos[i * scalarsPerPos + 1]; alignText(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y, NULL); setTextTransform(x, y, textPaint.getTextSkewX()); SkString encodedString = SkPDFString::formatString(&encodedValue, 1, font->multiByteGlyphs()); fContent.writeText(encodedString.c_str()); fContent.writeText(" Tj\n"); } fContent.writeText("ET\n"); }
static void test_cachedfont(skiatest::Reporter* reporter, const SkPaint& paint) { SkAutoTUnref<SkFont> font(SkFont::Testing_CreateFromPaint(paint)); // Currently SkFont resolves null into the default, so only test if paint's is not null if (paint.getTypeface()) { REPORTER_ASSERT(reporter, font->getTypeface() == paint.getTypeface()); } REPORTER_ASSERT(reporter, font->getSize() == paint.getTextSize()); REPORTER_ASSERT(reporter, font->getScaleX() == paint.getTextScaleX()); REPORTER_ASSERT(reporter, font->getSkewX() == paint.getTextSkewX()); REPORTER_ASSERT(reporter, font->isVertical() == paint.isVerticalText()); REPORTER_ASSERT(reporter, font->isEmbolden() == paint.isFakeBoldText()); REPORTER_ASSERT(reporter, font->isUseNonLinearMetrics() == is_use_nonlinear_metrics(paint)); REPORTER_ASSERT(reporter, font->isEnableAutoHints() == is_enable_auto_hints(paint)); REPORTER_ASSERT(reporter, font->isEnableByteCodeHints() == is_enable_bytecode_hints(paint)); }
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(); }
Json::Value SkJSONCanvas::makePaint(const SkPaint& paint) { Json::Value result(Json::objectValue); store_scalar(&result, SKJSONCANVAS_ATTRIBUTE_STROKEWIDTH, paint.getStrokeWidth(), 0.0f); store_scalar(&result, SKJSONCANVAS_ATTRIBUTE_STROKEMITER, paint.getStrokeMiter(), SkPaintDefaults_MiterLimit); store_bool(&result, SKJSONCANVAS_ATTRIBUTE_ANTIALIAS, paint.isAntiAlias(), false); store_scalar(&result, SKJSONCANVAS_ATTRIBUTE_TEXTSIZE, paint.getTextSize(), SkPaintDefaults_TextSize); store_scalar(&result, SKJSONCANVAS_ATTRIBUTE_TEXTSCALEX, paint.getTextScaleX(), SK_Scalar1); store_scalar(&result, SKJSONCANVAS_ATTRIBUTE_TEXTSCALEX, paint.getTextSkewX(), 0.0f); apply_paint_color(paint, &result); apply_paint_style(paint, &result); apply_paint_cap(paint, &result); apply_paint_textalign(paint, &result); apply_paint_patheffect(paint, &result, fSendBinaries); apply_paint_maskfilter(paint, &result, fSendBinaries); apply_paint_shader(paint, &result, fSendBinaries); apply_paint_xfermode(paint, &result, fSendBinaries); apply_paint_imagefilter(paint, &result, fSendBinaries); apply_paint_colorfilter(paint, &result, fSendBinaries); apply_paint_typeface(paint, &result, fSendBinaries); return result; }
// 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 }
void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, SkScalar x, SkScalar y, const SkPaint& paint) { SkPaint textPaint = calculateTextPaint(paint); updateGSFromPaint(textPaint, true); // We want the text in glyph id encoding and a writable buffer, so we end // up making a copy either way. size_t numGlyphs = paint.textToGlyphs(text, len, NULL); uint16_t* glyphIDs = (uint16_t*)sk_malloc_flags(numGlyphs * 2, SK_MALLOC_TEMP | SK_MALLOC_THROW); SkAutoFree autoFreeGlyphIDs(glyphIDs); if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) { paint.textToGlyphs(text, len, glyphIDs); textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); } else { SkASSERT((len & 1) == 0); SkASSERT(len / 2 == numGlyphs); memcpy(glyphIDs, text, len); } SkScalar width; SkScalar* widthPtr = NULL; if (textPaint.isUnderlineText() || textPaint.isStrikeThruText()) widthPtr = &width; SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); alignText(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y, widthPtr); fContent.writeText("BT\n"); setTextTransform(x, y, textPaint.getTextSkewX()); size_t consumedGlyphCount = 0; while (numGlyphs > consumedGlyphCount) { updateFont(textPaint, glyphIDs[consumedGlyphCount]); SkPDFFont* font = fGraphicStack[fGraphicStackIndex].fFont; size_t availableGlyphs = font->glyphsToPDFFontEncoding(glyphIDs + consumedGlyphCount, numGlyphs - consumedGlyphCount); SkString encodedString = SkPDFString::formatString(glyphIDs + consumedGlyphCount, availableGlyphs, font->multiByteGlyphs()); fContent.writeText(encodedString.c_str()); consumedGlyphCount += availableGlyphs; fContent.writeText(" Tj\n"); } fContent.writeText("ET\n"); // Draw underline and/or strikethrough if the paint has them. // drawPosText() and drawTextOnPath() don't draw underline or strikethrough // because the raster versions don't. Use paint instead of textPaint // because we may have changed strokeWidth to do fakeBold text. if (paint.isUnderlineText() || paint.isStrikeThruText()) { SkScalar textSize = paint.getTextSize(); SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); if (paint.isUnderlineText()) { SkScalar top = SkScalarMulAdd(textSize, kStdUnderline_Offset, y); SkRect r = SkRect::MakeXYWH(x, top - height, width, height); drawRect(d, r, paint); } if (paint.isStrikeThruText()) { SkScalar top = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, y); SkRect r = SkRect::MakeXYWH(x, top - height, width, height); drawRect(d, r, paint); } } }
// 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); }