static void drawBaseline(SkCanvas* canvas, const SkPaint& paint, SkScalar x, SkScalar y) { SkScalar total = paint.measureText(gText, gLen); SkPaint p; p.setAntiAlias(true); p.setColor(0x80FF0000); canvas->drawLine(x, y, paint.isVerticalText() ? x : x + total, paint.isVerticalText() ? y + total : y, p); p.setColor(0xFF0000FF); SkScalar adv[gLen]; int numChars = paint.getTextWidths(gText, gLen, adv, nullptr); for (int i = 0; i < numChars; ++i) { canvas->drawCircle(x, y, SK_Scalar1 * 3 / 2, p); if (paint.isVerticalText()) { y += adv[i]; } else { x += adv[i]; } } canvas->drawCircle(x, y, SK_Scalar1 * 3 / 2, p); }
void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkPaint& paint) { size_t points = paint.countText(text, byteLength); if (0 == points) return; bool fast = !paint.isVerticalText() && paint.canComputeFastBounds(); addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H); int paintIndex = this->addPaint(paint); addText(text, byteLength); addInt(points); #ifdef SK_DEBUG_SIZE size_t start = fWriter.size(); #endif if (fast) { addFontMetricsTopBottom(paint, paintIndex - 1, constY, constY); } addScalar(constY); fWriter.writeMul4(xpos, points * sizeof(SkScalar)); #ifdef SK_DEBUG_SIZE fPointBytes += fWriter.size() - start; fPointWrites += points; #endif validate(); }
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); }
void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint) { bool fast = !paint.isVerticalText() && paint.canComputeFastBounds(); addDraw(fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT); int paintIndex = addPaint(paint); addText(text, byteLength); addScalar(x); addScalar(y); if (fast) { addFontMetricsTopBottom(paint, paintIndex - 1, y, y); } validate(); }
void SkBBoxRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint) { SkRect bbox; paint.measureText(text, byteLength, &bbox); SkPaint::FontMetrics metrics; paint.getFontMetrics(&metrics); // Vertical and aligned text need to be offset if (paint.isVerticalText()) { SkScalar h = bbox.fBottom - bbox.fTop; if (paint.getTextAlign() == SkPaint::kCenter_Align) { bbox.fTop -= h / 2; bbox.fBottom -= h / 2; } // Pad top and bottom with max extents from FontMetrics bbox.fBottom += metrics.fBottom; bbox.fTop += metrics.fTop; } else { SkScalar w = bbox.fRight - bbox.fLeft; if (paint.getTextAlign() == SkPaint::kCenter_Align) { bbox.fLeft -= w / 2; bbox.fRight -= w / 2; } else if (paint.getTextAlign() == SkPaint::kRight_Align) { bbox.fLeft -= w; bbox.fRight -= w; } // Set vertical bounds to max extents from font metrics bbox.fTop = metrics.fTop; bbox.fBottom = metrics.fBottom; } // Pad horizontal bounds on each side by half of max vertical extents (this is sort of // arbitrary, but seems to produce reasonable results, if there were a way of getting max // glyph X-extents to pad by, that may be better here, but FontMetrics fXMin and fXMax seem // incorrect on most platforms (too small in Linux, never even set in Windows). SkScalar pad = (metrics.fBottom - metrics.fTop) / 2; bbox.fLeft -= pad; bbox.fRight += pad; bbox.fLeft += x; bbox.fRight += x; bbox.fTop += y; bbox.fBottom += y; if (this->transformBounds(bbox, &paint)) { INHERITED::onDrawText(text, byteLength, x, y, paint); } }
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)); }
String LoggingCanvas::stringForSkPaintFlags(const SkPaint& paint) { if (!paint.getFlags()) return "none"; String flagsString = ""; appendFlagToString(&flagsString, paint.isAntiAlias(), "AntiAlias"); appendFlagToString(&flagsString, paint.isDither(), "Dither"); appendFlagToString(&flagsString, paint.isUnderlineText(), "UnderlinText"); appendFlagToString(&flagsString, paint.isStrikeThruText(), "StrikeThruText"); appendFlagToString(&flagsString, paint.isFakeBoldText(), "FakeBoldText"); appendFlagToString(&flagsString, paint.isLinearText(), "LinearText"); appendFlagToString(&flagsString, paint.isSubpixelText(), "SubpixelText"); appendFlagToString(&flagsString, paint.isDevKernText(), "DevKernText"); appendFlagToString(&flagsString, paint.isLCDRenderText(), "LCDRenderText"); appendFlagToString(&flagsString, paint.isEmbeddedBitmapText(), "EmbeddedBitmapText"); appendFlagToString(&flagsString, paint.isAutohinted(), "Autohinted"); appendFlagToString(&flagsString, paint.isVerticalText(), "VerticalText"); appendFlagToString(&flagsString, paint.getFlags() & SkPaint::kGenA8FromLCD_Flag, "GenA8FromLCD"); return flagsString; }
void SkPictureRecord::drawPosText(const void* text, size_t byteLength, const SkPoint pos[], const SkPaint& paint) { size_t points = paint.countText(text, byteLength); if (0 == points) return; bool canUseDrawH = true; SkScalar minY = pos[0].fY; SkScalar maxY = pos[0].fY; // check if the caller really should have used drawPosTextH() { const SkScalar firstY = pos[0].fY; for (size_t index = 1; index < points; index++) { if (pos[index].fY != firstY) { canUseDrawH = false; if (pos[index].fY < minY) { minY = pos[index].fY; } else if (pos[index].fY > maxY) { maxY = pos[index].fY; } } } } bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds(); bool fast = canUseDrawH && fastBounds; if (fast) { addDraw(DRAW_POS_TEXT_H_TOP_BOTTOM); } else if (canUseDrawH) { addDraw(DRAW_POS_TEXT_H); } else if (fastBounds) { addDraw(DRAW_POS_TEXT_TOP_BOTTOM); } else { addDraw(DRAW_POS_TEXT); } int paintIndex = addPaint(paint); addText(text, byteLength); addInt(points); #ifdef SK_DEBUG_SIZE size_t start = fWriter.size(); #endif if (canUseDrawH) { if (fast) { addFontMetricsTopBottom(paint, paintIndex - 1, pos[0].fY, pos[0].fY); } addScalar(pos[0].fY); SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar)); for (size_t index = 0; index < points; index++) *xptr++ = pos[index].fX; } else { fWriter.writeMul4(pos, points * sizeof(SkPoint)); if (fastBounds) { addFontMetricsTopBottom(paint, paintIndex - 1, minY, maxY); } } #ifdef SK_DEBUG_SIZE fPointBytes += fWriter.size() - start; fPointWrites += points; #endif validate(); }