virtual void onDrawContent(SkCanvas* canvas) { canvas->translate(SkIntToScalar(10), SkIntToScalar(20)); if (false) { SkPaint paint; paint.setAntiAlias(true); paint.setTextSize(50); paint.setTypeface(SkTypeface::CreateFromName("Arial Unicode MS", SkTypeface::kNormal)); SkSafeUnref(paint.getTypeface()); char buffer[10]; size_t len = SkUTF8_FromUnichar(0x8500, buffer); canvas->drawText(buffer, len, 40, 40, paint); return; } if (false) { SkPaint paint; paint.setAntiAlias(true); SkRect r0 = { 0, 0, 10.5f, 20 }; SkRect r1 = { 10.5f, 10, 20, 30 }; paint.setColor(SK_ColorRED); canvas->drawRect(r0, paint); paint.setColor(SK_ColorBLUE); canvas->drawRect(r1, paint); return; } const struct { SkXfermode::Mode fMode; const char* fLabel; } gModes[] = { { SkXfermode::kClear_Mode, "Clear" }, { SkXfermode::kSrc_Mode, "Src" }, { SkXfermode::kDst_Mode, "Dst" }, { SkXfermode::kSrcOver_Mode, "SrcOver" }, { SkXfermode::kDstOver_Mode, "DstOver" }, { SkXfermode::kSrcIn_Mode, "SrcIn" }, { SkXfermode::kDstIn_Mode, "DstIn" }, { SkXfermode::kSrcOut_Mode, "SrcOut" }, { SkXfermode::kDstOut_Mode, "DstOut" }, { SkXfermode::kSrcATop_Mode, "SrcATop" }, { SkXfermode::kDstATop_Mode, "DstATop" }, { SkXfermode::kXor_Mode, "Xor" }, { SkXfermode::kPlus_Mode, "Plus" }, /*{ SkXfermode::kModulate_Mode, "Modulate" }, { SkXfermode::kScreen_Mode, "Screen" }, { SkXfermode::kOverlay_Mode, "Overlay" }, { SkXfermode::kDarken_Mode, "Darken" }, { SkXfermode::kLighten_Mode, "Lighten" }, { SkXfermode::kColorDodge_Mode, "ColorDodge" }, { SkXfermode::kColorBurn_Mode, "ColorBurn" }, { SkXfermode::kHardLight_Mode, "HardLight" }, { SkXfermode::kSoftLight_Mode, "SoftLight" }, { SkXfermode::kDifference_Mode, "Difference" }, { SkXfermode::kExclusion_Mode, "Exclusion" },*/ }; const SkScalar w = SkIntToScalar(W); const SkScalar h = SkIntToScalar(H); SkMatrix m; m.setScale(SkIntToScalar(6), SkIntToScalar(6)); SkShader* s = SkShader::CreateBitmapShader(fBG, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &m); SkPaint labelP; labelP.setAntiAlias(true); labelP.setLCDRenderText(true); labelP.setTextAlign(SkPaint::kCenter_Align); setNamedTypeface(&labelP, "Menlo Regular"); const int W = 5; SkScalar x0 = 0; for (int twice = 0; twice < 2; twice++) { SkScalar x = x0, y = 0; for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) { SkXfermode* mode = SkXfermode::Create(gModes[i].fMode); SkAutoUnref aur(mode); SkRect r; r.set(x, y, x+w, y+h); SkPaint p; p.setStyle(SkPaint::kFill_Style); p.setShader(s); canvas->drawRect(r, p); canvas->saveLayer(&r, NULL); draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop); canvas->restore(); r.inset(-SK_ScalarHalf, -SK_ScalarHalf); p.setStyle(SkPaint::kStroke_Style); p.setShader(NULL); canvas->drawRect(r, p); canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel), x + w/2, y - labelP.getTextSize()/2, labelP); x += w + SkIntToScalar(10); if ((i % W) == W - 1) { x = x0; y += h + SkIntToScalar(30); } } x0 += SkIntToScalar(400); } s->unref(); }
// Need a quick way to know a maximum distance between drawText calls to know if // they are part of the same logical phrase when searching. By crude // inspection, half the point size seems a good guess at the width of a space // character. static inline SkScalar approximateSpaceWidth(const SkPaint& paint) { return SkScalarHalf(paint.getTextSize()); }
void onDraw(SkCanvas* canvas) override { if (!fImage) { this->setupImage(canvas); } SkRect dstRect = { 0, 0, SkIntToScalar(64), SkIntToScalar(64)}; static const int kMaxSrcRectSize = 1 << (SkNextLog2(gBmpSize) + 2); static const int kPadX = 30; static const int kPadY = 40; SkPaint paint; paint.setAlpha(0x20); canvas->drawBitmapRect(fLargeBitmap, SkRect::MakeIWH(gSize, gSize), &paint); canvas->translate(SK_Scalar1 * kPadX / 2, SK_Scalar1 * kPadY / 2); SkPaint blackPaint; SkScalar titleHeight = SK_Scalar1 * 24; blackPaint.setColor(SK_ColorBLACK); blackPaint.setTextSize(titleHeight); blackPaint.setAntiAlias(true); sk_tool_utils::set_portable_typeface(&blackPaint); SkString title; title.printf("Bitmap size: %d x %d", gBmpSize, gBmpSize); canvas->drawText(title.c_str(), title.size(), 0, titleHeight, blackPaint); canvas->translate(0, SK_Scalar1 * kPadY / 2 + titleHeight); int rowCount = 0; canvas->save(); for (int w = 1; w <= kMaxSrcRectSize; w *= 4) { for (int h = 1; h <= kMaxSrcRectSize; h *= 4) { SkIRect srcRect = SkIRect::MakeXYWH((gBmpSize - w) / 2, (gBmpSize - h) / 2, w, h); fProc(canvas, fImage.get(), fLargeBitmap, srcRect, dstRect); SkString label; label.appendf("%d x %d", w, h); blackPaint.setAntiAlias(true); blackPaint.setStyle(SkPaint::kFill_Style); blackPaint.setTextSize(SK_Scalar1 * 10); SkScalar baseline = dstRect.height() + blackPaint.getTextSize() + SK_Scalar1 * 3; canvas->drawText(label.c_str(), label.size(), 0, baseline, blackPaint); blackPaint.setStyle(SkPaint::kStroke_Style); blackPaint.setStrokeWidth(SK_Scalar1); blackPaint.setAntiAlias(false); canvas->drawRect(dstRect, blackPaint); canvas->translate(dstRect.width() + SK_Scalar1 * kPadX, 0); ++rowCount; if ((dstRect.width() + kPadX) * rowCount > gSize) { canvas->restore(); canvas->translate(0, dstRect.height() + SK_Scalar1 * kPadY); canvas->save(); rowCount = 0; } } } { // test the following code path: // SkGpuDevice::drawPath() -> SkGpuDevice::drawWithMaskFilter() SkIRect srcRect; SkPaint paint; SkBitmap bm; bm = make_chessbm(5, 5); paint.setFilterQuality(kLow_SkFilterQuality); srcRect.setXYWH(1, 1, 3, 3); SkMaskFilter* mf = SkBlurMaskFilter::Create( kNormal_SkBlurStyle, SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(5)), SkBlurMaskFilter::kHighQuality_BlurFlag | SkBlurMaskFilter::kIgnoreTransform_BlurFlag); paint.setMaskFilter(mf)->unref(); canvas->drawBitmapRect(bm, srcRect, dstRect, &paint); } }
SkScalar dir[] = { SK_Scalar1, SK_Scalar1, SK_Scalar1 }; paint->setMaskFilter(SkBlurMaskFilter::CreateEmboss(dir, SK_Scalar1/4, SkIntToScalar(4), SkIntToScalar(3)))->unref(); #endif paint->setColor(SK_ColorBLUE); } DEF_SIMPLE_GM(texteffects, canvas, 460, 680) { canvas->save(); SkPaint paint; paint.setAntiAlias(true); sk_tool_utils::set_portable_typeface(&paint); paint.setTextSize(SkIntToScalar(56)); SkScalar x = SkIntToScalar(20); SkScalar y = paint.getTextSize(); SkString str("Hamburgefons"); for (int i = 0; i < static_cast<int>(SK_ARRAY_COUNT(gRastProcs)); i++) { apply_shader(&paint, i); // paint.setMaskFilter(nullptr); // paint.setColor(SK_ColorBLACK); canvas->drawText(str.c_str(), str.size(), x, y, paint); y += paint.getFontSpacing(); } canvas->restore();
void draw(SkCanvas* canvas) { SkPaint paint; SkDebugf("12 %c= default text size\n", 12 == paint.getTextSize() ? '=' : '!'); }
// 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 }
virtual void onDraw(SkCanvas* canvas) { canvas->translate(SkIntToScalar(10), SkIntToScalar(20)); const struct { SkXfermode::Mode fMode; const char* fLabel; } gModes[] = { { SkXfermode::kClear_Mode, "Clear" }, { SkXfermode::kSrc_Mode, "Src" }, { SkXfermode::kDst_Mode, "Dst" }, { SkXfermode::kSrcOver_Mode, "SrcOver" }, { SkXfermode::kDstOver_Mode, "DstOver" }, { SkXfermode::kSrcIn_Mode, "SrcIn" }, { SkXfermode::kDstIn_Mode, "DstIn" }, { SkXfermode::kSrcOut_Mode, "SrcOut" }, { SkXfermode::kDstOut_Mode, "DstOut" }, { SkXfermode::kSrcATop_Mode, "SrcATop" }, { SkXfermode::kDstATop_Mode, "DstATop" }, { SkXfermode::kXor_Mode, "Xor" }, { SkXfermode::kPlus_Mode, "Plus" }, { SkXfermode::kMultiply_Mode, "Multiply" }, { SkXfermode::kScreen_Mode, "Screen" }, { SkXfermode::kOverlay_Mode, "Overlay" }, { SkXfermode::kDarken_Mode, "Darken" }, { SkXfermode::kLighten_Mode, "Lighten" }, { SkXfermode::kColorDodge_Mode, "ColorDodge" }, { SkXfermode::kColorBurn_Mode, "ColorBurn" }, { SkXfermode::kHardLight_Mode, "HardLight" }, { SkXfermode::kSoftLight_Mode, "SoftLight" }, { SkXfermode::kDifference_Mode, "Difference" }, { SkXfermode::kExclusion_Mode, "Exclusion" }, }; const SkScalar w = SkIntToScalar(W); const SkScalar h = SkIntToScalar(H); SkShader* s = SkShader::CreateBitmapShader(fBG, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); SkMatrix m; m.setScale(SkIntToScalar(6), SkIntToScalar(6)); s->setLocalMatrix(m); SkPaint labelP; labelP.setAntiAlias(true); labelP.setTextAlign(SkPaint::kCenter_Align); const int W = 5; SkScalar x0 = 0; for (int twice = 0; twice < 2; twice++) { SkScalar x = x0, y = 0; for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) { SkXfermode* mode = SkXfermode::Create(gModes[i].fMode); SkAutoUnref aur(mode); SkRect r; r.set(x, y, x+w, y+h); SkPaint p; p.setStyle(SkPaint::kFill_Style); p.setShader(s); canvas->drawRect(r, p); canvas->saveLayer(&r, NULL, SkCanvas::kARGB_ClipLayer_SaveFlag); draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop); canvas->restore(); r.inset(-SK_ScalarHalf, -SK_ScalarHalf); p.setStyle(SkPaint::kStroke_Style); p.setShader(NULL); canvas->drawRect(r, p); #if 1 canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel), x + w/2, y - labelP.getTextSize()/2, labelP); #endif x += w + SkIntToScalar(10); if ((i % W) == W - 1) { x = x0; y += h + SkIntToScalar(30); } } x0 += SkIntToScalar(400); } s->unref(); }
virtual void onDrawContent(SkCanvas* canvas) { canvas->translate(fPaint.getTextSize(), fPaint.getTextSize()); doMeasure(canvas, fPaint, "Hamburgefons"); }
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); }
virtual const char* onGetName() { fName.printf("shadermask", SkScalarToFloat(fPaint.getTextSize())); fName.appendf("_%s", fontQualityName(fPaint)); fName.appendf("_%02X", fPaint.getAlpha()); return fName.c_str(); }
const SkTextBlob* makeBlob(unsigned blobIndex) { SkTextBlobBuilder builder; SkPaint font; font.setTextEncoding(SkPaint::kGlyphID_TextEncoding); font.setAntiAlias(true); font.setSubpixelText(true); font.setTypeface(fTypeface); for (unsigned l = 0; l < SK_ARRAY_COUNT(blobConfigs[blobIndex]); ++l) { unsigned currentGlyph = 0; for (unsigned c = 0; c < SK_ARRAY_COUNT(blobConfigs[blobIndex][l]); ++c) { const BlobCfg* cfg = &blobConfigs[blobIndex][l][c]; unsigned count = cfg->count; if (count > fGlyphs.count() - currentGlyph) { count = fGlyphs.count() - currentGlyph; } if (0 == count) { break; } font.setTextSize(kFontSize * cfg->scale); const SkScalar advanceX = font.getTextSize() * 0.85f; const SkScalar advanceY = font.getTextSize() * 1.5f; SkPoint offset = SkPoint::Make(currentGlyph * advanceX + c * advanceX, advanceY * l); switch (cfg->pos) { case kDefault_Pos: { const SkTextBlobBuilder::RunBuffer& buf = builder.allocRun(font, count, offset.x(), offset.y()); memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t)); } break; case kScalar_Pos: { const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPosH(font, count, offset.y()); SkTDArray<SkScalar> pos; for (unsigned i = 0; i < count; ++i) { *pos.append() = offset.x() + i * advanceX; } memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t)); memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar)); } break; case kPoint_Pos: { const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPos(font, count); SkTDArray<SkScalar> pos; for (unsigned i = 0; i < count; ++i) { *pos.append() = offset.x() + i * advanceX; *pos.append() = offset.y() + i * (advanceY / count); } memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t)); memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar) * 2); } break; default: SkFAIL("unhandled pos value"); } currentGlyph += count; } } return builder.build(); }