本文整理汇总了C++中SkPaint::getTextAlign方法的典型用法代码示例。如果您正苦于以下问题:C++ SkPaint::getTextAlign方法的具体用法?C++ SkPaint::getTextAlign怎么用?C++ SkPaint::getTextAlign使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SkPaint
的用法示例。
在下文中一共展示了SkPaint::getTextAlign方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: drawTestCase
void drawTestCase(SkCanvas* canvas, const char* text, SkScalar y, const SkPaint& paint) {
SkScalar widths[kMaxStringLength];
SkScalar posX[kMaxStringLength];
SkPoint pos[kMaxStringLength];
int length = SkToInt(strlen(text));
SkASSERT(length <= kMaxStringLength);
paint.getTextWidths(text, length, widths);
float originX;
switch (paint.getTextAlign()) {
case SkPaint::kRight_Align: originX = 1; break;
case SkPaint::kCenter_Align: originX = 0.5f; break;
case SkPaint::kLeft_Align: originX = 0; break;
default: SkFAIL("Invalid paint origin"); return;
}
float x = kTextHeight;
for (int i = 0; i < length; ++i) {
posX[i] = x + originX * widths[i];
pos[i].set(posX[i], i ? pos[i - 1].y() + 3 : y + kTextHeight);
x += widths[i];
}
canvas->drawPosTextH(text, length, posX, y, paint);
canvas->drawPosText(text, length, pos, paint);
}
示例2: tface
void SkSVGDevice::AutoElement::addTextAttributes(const SkPaint& paint) {
this->addAttribute("font-size", paint.getTextSize());
if (const char* textAlign = svg_text_align(paint.getTextAlign())) {
this->addAttribute("text-anchor", textAlign);
}
SkString familyName;
SkTHashSet<SkString> familySet;
SkAutoTUnref<const SkTypeface> tface(paint.getTypeface() ?
SkRef(paint.getTypeface()) : SkTypeface::RefDefault());
SkASSERT(tface);
SkTypeface::Style style = tface->style();
if (style & SkTypeface::kItalic) {
this->addAttribute("font-style", "italic");
}
if (style & SkTypeface::kBold) {
this->addAttribute("font-weight", "bold");
}
SkAutoTUnref<SkTypeface::LocalizedStrings> familyNameIter(tface->createFamilyNameIterator());
SkTypeface::LocalizedString familyString;
while (familyNameIter->next(&familyString)) {
if (familySet.contains(familyString.fString)) {
continue;
}
familySet.add(familyString.fString);
familyName.appendf((familyName.isEmpty() ? "%s" : ", %s"), familyString.fString.c_str());
}
if (!familyName.isEmpty()) {
this->addAttribute("font-family", familyName);
}
}
示例3: onDrawText
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);
}
}
示例4: drawTextOnPath
void SkBaseDevice::drawTextOnPath(const SkDraw& draw, const void* text, size_t byteLength,
const SkPath& follow, const SkMatrix* matrix,
const SkPaint& paint) {
SkASSERT(byteLength == 0 || text != nullptr);
// nothing to draw
if (text == nullptr || byteLength == 0 || draw.fRC->isEmpty()) {
return;
}
SkTextToPathIter iter((const char*)text, byteLength, paint, true);
SkPathMeasure meas(follow, false);
SkScalar hOffset = 0;
// need to measure first
if (paint.getTextAlign() != SkPaint::kLeft_Align) {
SkScalar pathLen = meas.getLength();
if (paint.getTextAlign() == SkPaint::kCenter_Align) {
pathLen = SkScalarHalf(pathLen);
}
hOffset += pathLen;
}
const SkPath* iterPath;
SkScalar xpos;
SkMatrix scaledMatrix;
SkScalar scale = iter.getPathScale();
scaledMatrix.setScale(scale, scale);
while (iter.next(&iterPath, &xpos)) {
if (iterPath) {
SkPath tmp;
SkMatrix m(scaledMatrix);
tmp.setIsVolatile(true);
m.postTranslate(xpos + hOffset, 0);
if (matrix) {
m.postConcat(*matrix);
}
morphpath(&tmp, *iterPath, meas, m);
this->drawPath(draw, tmp, iter.getPaint(), nullptr, true);
}
}
}
示例5: onDrawText
void SkOverdrawCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
const SkPaint& paint) {
ProcessOneGlyphBounds processBounds(this);
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
this->getProps(&props);
auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(
paint, &props, SkScalerContextFlags::kNone, &this->getTotalMatrix());
SkFindAndPlaceGlyph::ProcessText(paint.getTextEncoding(), (const char*) text, byteLength,
SkPoint::Make(x, y), SkMatrix(), paint.getTextAlign(),
cache.get(), processBounds);
}
示例6: drawTextOnPath
void SkSVGDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len, const SkPath& path,
const SkMatrix* matrix, const SkPaint& paint) {
SkString pathID = fResourceBucket->addPath();
{
AutoElement defs("defs", fWriter);
AutoElement pathElement("path", fWriter);
pathElement.addAttribute("id", pathID);
pathElement.addPathAttributes(path);
}
{
AutoElement textElement("text", fWriter);
textElement.addTextAttributes(paint);
if (matrix && !matrix->isIdentity()) {
textElement.addAttribute("transform", svg_transform(*matrix));
}
{
AutoElement textPathElement("textPath", fWriter);
textPathElement.addAttribute("xlink:href", SkStringPrintf("#%s", pathID.c_str()));
if (paint.getTextAlign() != SkPaint::kLeft_Align) {
SkASSERT(paint.getTextAlign() == SkPaint::kCenter_Align ||
paint.getTextAlign() == SkPaint::kRight_Align);
textPathElement.addAttribute("startOffset",
paint.getTextAlign() == SkPaint::kCenter_Align ? "50%" : "100%");
}
SVGTextBuilder builder(text, len, paint, SkPoint::Make(0, 0), 0);
textPathElement.addText(builder.text());
}
}
}
示例7: apply_paint_textalign
static void apply_paint_textalign(const SkPaint& paint, Json::Value* target) {
SkPaint::Align textAlign = paint.getTextAlign();
if (textAlign != SkPaint::kLeft_Align) {
switch (textAlign) {
case SkPaint::kCenter_Align: {
(*target)[SKJSONCANVAS_ATTRIBUTE_TEXTALIGN] = SKJSONCANVAS_ALIGN_CENTER;
break;
}
case SkPaint::kRight_Align: {
(*target)[SKJSONCANVAS_ATTRIBUTE_TEXTALIGN] = SKJSONCANVAS_ALIGN_RIGHT;
break;
}
default: SkASSERT(false);
}
}
}
示例8: DrawBmpPosText
void GrTextUtils::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex,
GrBatchFontCache* fontCache,
const SkSurfaceProps& props, const SkPaint& skPaint,
GrColor color,
const SkMatrix& viewMatrix,
const char text[], size_t byteLength,
const SkScalar pos[], int scalarsPerPosition,
const SkPoint& offset) {
SkASSERT(byteLength == 0 || text != nullptr);
SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
// nothing to draw
if (text == nullptr || byteLength == 0) {
return;
}
// Ensure the blob is set for bitmaptext
blob->setHasBitmap();
GrBatchTextStrike* currStrike = nullptr;
// Get GrFontScaler from cache
SkGlyphCache* cache = blob->setupCache(runIndex, props, SkPaint::FakeGamma::On,
skPaint, &viewMatrix);
GrFontScaler* fontScaler = GrTextUtils::GetGrFontScaler(cache);
SkFindAndPlaceGlyph::ProcessPosText(
skPaint.getTextEncoding(), text, byteLength,
offset, viewMatrix, pos, scalarsPerPosition,
skPaint.getTextAlign(), cache,
[&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
position += rounding;
BmpAppendGlyph(
blob, runIndex, fontCache, &currStrike, glyph,
SkScalarFloorToInt(position.fX), SkScalarFloorToInt(position.fY),
color, fontScaler);
}
);
SkGlyphCache::AttachCache(cache);
}
示例9: objectForSkShader
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();
}
示例10: write_paint
/*
* 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);
}
示例11: bCrossing
SkPath TextArt::EnvelopeWarp::warp(const std::string& text, SkTypeface* typeface)
{
SkPath warpedPath;
if (text.empty())
return warpedPath;
//prepare paint
SkPaint paint;
paint.setTextSize(SkIntToScalar(64));
paint.setTypeface(typeface);
paint.setTextAlign(SkPaint::kCenter_Align);
//measure Bottom path to center text on it
SkPathMeasure bMeasure(bSkeleton_, false);
SkScalar hBOffset = 0;
if (paint.getTextAlign() != SkPaint::kLeft_Align)
{
SkScalar pathLen = bMeasure.getLength();
if (paint.getTextAlign() == SkPaint::kCenter_Align)
{
pathLen = SkScalarHalf(pathLen);
}
hBOffset += pathLen;
}
//get text boundaries on normal(non-warped) state
{
SkMatrix scaleMartix;
scaleMartix.setIdentity();
SkTextToPathIter iter(text.c_str(), text.size(), paint, true);
const SkPath* glypthPath;
SkScalar xpos;
SkScalar scale = iter.getPathScale();
scaleMartix.setScale(scale, scale);
while (iter.next(&glypthPath, &xpos))
{
if (glypthPath)
{
//prepare resulting transformatiom Matrix
SkMatrix compositeMatrix(scaleMartix);
compositeMatrix.postTranslate(xpos + hBOffset, 0);
SkPath p;
(*glypthPath).transform(compositeMatrix, &p);
//get normal(without any warps) text boundaries
boundsRect_.join( p.getBounds() );
}
}
}
//center text on Top skeleton
SkPathMeasure tMeasure(tSkeleton_, false);
SkScalar hTOffset = 0;
{
if (paint.getTextAlign() != SkPaint::kLeft_Align)
{
SkScalar pathLen = tMeasure.getLength();
if (paint.getTextAlign() == SkPaint::kCenter_Align)
{
pathLen = SkScalarHalf(pathLen);
}
hTOffset += pathLen;
}
}
//warp text on Bottom and Top skeletons
{
SkTextToPathIter iter(text.c_str(), text.size(), paint, true);
SkScalar xpos;
SkMatrix scaleMartix;
SkScalar scale = iter.getPathScale();
scaleMartix.setScale(scale, scale);
SkPath line;
line.lineTo(SkIntToScalar(100), SkIntToScalar(0));
SkPathMeasure lineMeasure(line, false);
SkPathCrossing bCrossing(bSkeleton_);
SkPathCrossing tCrossing(tSkeleton_);
const SkPath* glypthPathOrig;
while (iter.next(&glypthPathOrig, &xpos))
{
if (glypthPathOrig)
{
SkPath glypthPath;
SkRect glypthBound;
glypthBound = (*glypthPathOrig).getBounds();
glypthPathOrig->offset(-glypthBound.fLeft, 0, &glypthPath);
morph(bSkeleton_, bMeasure, bCrossing,
tSkeleton_, tMeasure, tCrossing,
glypthPath, lineMeasure, scaleMartix,
xpos, hBOffset, hTOffset, warpedPath);
//.........这里部分代码省略.........
示例12: visit
SkScalar SkTextBox::visit(Visitor& visitor, const char text[], size_t len,
const SkPaint& paint) const {
SkScalar marginWidth = fBox.width();
if (marginWidth <= 0 || len == 0) {
return fBox.top();
}
const char* textStop = text + len;
SkScalar x, y, scaledSpacing, height, fontHeight;
SkPaint::FontMetrics metrics;
switch (paint.getTextAlign()) {
case SkPaint::kLeft_Align:
x = 0;
break;
case SkPaint::kCenter_Align:
x = SkScalarHalf(marginWidth);
break;
default:
x = marginWidth;
break;
}
x += fBox.fLeft;
fontHeight = paint.getFontMetrics(&metrics);
scaledSpacing = SkScalarMul(fontHeight, fSpacingMul) + fSpacingAdd;
height = fBox.height();
// compute Y position for first line
{
SkScalar textHeight = fontHeight;
if (fMode == kLineBreak_Mode && fSpacingAlign != kStart_SpacingAlign) {
int count = SkTextLineBreaker::CountLines(text, textStop - text, paint, marginWidth);
SkASSERT(count > 0);
textHeight += scaledSpacing * (count - 1);
}
switch (fSpacingAlign) {
case kStart_SpacingAlign:
y = 0;
break;
case kCenter_SpacingAlign:
y = SkScalarHalf(height - textHeight);
break;
default:
SkASSERT(fSpacingAlign == kEnd_SpacingAlign);
y = height - textHeight;
break;
}
y += fBox.fTop - metrics.fAscent;
}
for (;;) {
size_t trailing;
len = linebreak(text, textStop, paint, marginWidth, &trailing);
if (y + metrics.fDescent + metrics.fLeading > 0) {
visitor(text, len - trailing, x, y, paint);
}
text += len;
if (text >= textStop) {
break;
}
y += scaledSpacing;
if (y + metrics.fAscent >= fBox.fBottom) {
break;
}
}
return y + metrics.fDescent + metrics.fLeading;
}
示例13: onDrawText
void GrDistanceFieldTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip,
const GrPaint& paint,
const SkPaint& skPaint, const SkMatrix& viewMatrix,
const char text[], size_t byteLength,
SkScalar x, SkScalar y,
const SkIRect& regionClipBounds) {
SkASSERT(byteLength == 0 || text != NULL);
// nothing to draw
if (text == NULL || byteLength == 0) {
return;
}
fViewMatrix = viewMatrix;
SkDrawCacheProc glyphCacheProc = skPaint.getDrawCacheProc();
SkAutoGlyphCache autoCache(skPaint, &fDeviceProperties, NULL);
SkGlyphCache* cache = autoCache.getCache();
SkTArray<SkScalar> positions;
const char* textPtr = text;
SkFixed stopX = 0;
SkFixed stopY = 0;
SkFixed origin;
switch (skPaint.getTextAlign()) {
case SkPaint::kRight_Align: origin = SK_Fixed1; break;
case SkPaint::kCenter_Align: origin = SK_FixedHalf; break;
case SkPaint::kLeft_Align: origin = 0; break;
default: SkFAIL("Invalid paint origin"); return;
}
SkAutoKern autokern;
const char* stop = text + byteLength;
while (textPtr < stop) {
// don't need x, y here, since all subpixel variants will have the
// same advance
const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0);
SkFixed width = glyph.fAdvanceX + autokern.adjust(glyph);
positions.push_back(SkFixedToScalar(stopX + SkFixedMul(origin, width)));
SkFixed height = glyph.fAdvanceY;
positions.push_back(SkFixedToScalar(stopY + SkFixedMul(origin, height)));
stopX += width;
stopY += height;
}
SkASSERT(textPtr == stop);
// now adjust starting point depending on alignment
SkScalar alignX = SkFixedToScalar(stopX);
SkScalar alignY = SkFixedToScalar(stopY);
if (skPaint.getTextAlign() == SkPaint::kCenter_Align) {
alignX = SkScalarHalf(alignX);
alignY = SkScalarHalf(alignY);
} else if (skPaint.getTextAlign() == SkPaint::kLeft_Align) {
alignX = 0;
alignY = 0;
}
x -= alignX;
y -= alignY;
SkPoint offset = SkPoint::Make(x, y);
this->onDrawPosText(rt, clip, paint, skPaint, viewMatrix, text, byteLength, positions.begin(),
2, offset, regionClipBounds);
}
示例14: DrawDFText
void GrTextUtils::DrawDFText(GrAtlasTextBlob* blob, int runIndex,
GrBatchFontCache* fontCache, const SkSurfaceProps& props,
const SkPaint& skPaint, GrColor color,
const SkMatrix& viewMatrix,
const char text[], size_t byteLength,
SkScalar x, SkScalar y) {
SkASSERT(byteLength == 0 || text != nullptr);
// nothing to draw
if (text == nullptr || byteLength == 0) {
return;
}
SkPaint::GlyphCacheProc glyphCacheProc = skPaint.getGlyphCacheProc(true);
SkAutoDescriptor desc;
skPaint.getScalerContextDescriptor(&desc, props, SkPaint::FakeGamma::Off, nullptr);
SkGlyphCache* origPaintCache = SkGlyphCache::DetachCache(skPaint.getTypeface(),
desc.getDesc());
SkTArray<SkScalar> positions;
const char* textPtr = text;
SkFixed stopX = 0;
SkFixed stopY = 0;
SkFixed origin = 0;
switch (skPaint.getTextAlign()) {
case SkPaint::kRight_Align: origin = SK_Fixed1; break;
case SkPaint::kCenter_Align: origin = SK_FixedHalf; break;
case SkPaint::kLeft_Align: origin = 0; break;
}
SkAutoKern autokern;
const char* stop = text + byteLength;
while (textPtr < stop) {
// don't need x, y here, since all subpixel variants will have the
// same advance
const SkGlyph& glyph = glyphCacheProc(origPaintCache, &textPtr);
SkFixed width = glyph.fAdvanceX + autokern.adjust(glyph);
positions.push_back(SkFixedToScalar(stopX + SkFixedMul(origin, width)));
SkFixed height = glyph.fAdvanceY;
positions.push_back(SkFixedToScalar(stopY + SkFixedMul(origin, height)));
stopX += width;
stopY += height;
}
SkASSERT(textPtr == stop);
SkGlyphCache::AttachCache(origPaintCache);
// now adjust starting point depending on alignment
SkScalar alignX = SkFixedToScalar(stopX);
SkScalar alignY = SkFixedToScalar(stopY);
if (skPaint.getTextAlign() == SkPaint::kCenter_Align) {
alignX = SkScalarHalf(alignX);
alignY = SkScalarHalf(alignY);
} else if (skPaint.getTextAlign() == SkPaint::kLeft_Align) {
alignX = 0;
alignY = 0;
}
x -= alignX;
y -= alignY;
SkPoint offset = SkPoint::Make(x, y);
DrawDFPosText(blob, runIndex, fontCache, props, skPaint, color, viewMatrix, text, byteLength,
positions.begin(), 2, offset);
}
示例15: draw
void SkTextBox::draw(SkCanvas* canvas, const char text[], size_t len, const SkPaint& paint)
{
SkASSERT(canvas && &paint && (text || len == 0));
SkScalar marginWidth = fBox.width();
if (marginWidth <= 0 || len == 0)
return;
const char* textStop = text + len;
SkScalar x, y, scaledSpacing, height, fontHeight;
SkPaint::FontMetrics metrics;
switch (paint.getTextAlign()) {
case SkPaint::kLeft_Align:
x = 0;
break;
case SkPaint::kCenter_Align:
x = SkScalarHalf(marginWidth);
break;
default:
x = marginWidth;
break;
}
x += fBox.fLeft;
fontHeight = paint.getFontMetrics(&metrics);
scaledSpacing = SkScalarMul(fontHeight, fSpacingMul) + fSpacingAdd;
height = fBox.height();
// compute Y position for first line
{
SkScalar textHeight = fontHeight;
if (fMode == kLineBreak_Mode && fSpacingAlign != kStart_SpacingAlign)
{
int count = SkTextLineBreaker::CountLines(text, textStop - text, paint, marginWidth);
SkASSERT(count > 0);
textHeight += scaledSpacing * (count - 1);
}
switch (fSpacingAlign) {
case kStart_SpacingAlign:
y = 0;
break;
case kCenter_SpacingAlign:
y = SkScalarHalf(height - textHeight);
break;
default:
SkASSERT(fSpacingAlign == kEnd_SpacingAlign);
y = height - textHeight;
break;
}
y += fBox.fTop - metrics.fAscent;
}
for (;;)
{
len = linebreak(text, textStop, paint, marginWidth);
if (y + metrics.fDescent + metrics.fLeading > 0)
canvas->drawText(text, len, x, y, paint);
text += len;
if (text >= textStop)
break;
y += scaledSpacing;
if (y + metrics.fAscent >= height)
break;
}
}