complextext
323 void Font::drawComplexText(GraphicsContext* gc, TextRun const& run, 324 FloatPoint const& point, int, int) const 325 { 326 SkCanvas* canvas = gc->platformContext()->mCanvas; 327 SkPaint paint; 328 329 if (!setupForText(&paint, gc, primaryFont())) { 330 return; 331 } 332 333 // go to chars, instead of glyphs, which was set by setupForText() 334 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); 335 336 canvas->drawText(run.characters(), run.length() << 1, 337 SkFloatToScalar(point.x()), SkFloatToScalar(point.y()), 338 paint); 339 }
1703 void SkCanvas::drawText(const void* text, size_t byteLength, 1704 SkScalar x, SkScalar y, const SkPaint& paint) { 1705 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 1706 1707 while (iter.next()) { 1708 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 1709 iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); 1710 DrawTextDecorations(iter, dfp.paint(), 1711 static_cast<const char*>(text), byteLength, x, y); 1712 } 1713 1714 LOOPER_END 1715 }
321 void SkDevice::drawText(const SkDraw& draw, const void* text, size_t len, 322 SkScalar x, SkScalar y, const SkPaint& paint) { 323 draw.drawText((const char*)text, len, x, y, paint); 324 }
1524 void SkDraw::drawText(const char text[], size_t byteLength, 1525 SkScalar x, SkScalar y, const SkPaint& paint) const { 1526 SkASSERT(byteLength == 0 || text != NULL); 1527 1528 SkDEBUGCODE(this->validate();) 1529 1530 // nothing to draw 1531 if (text == NULL || byteLength == 0 || fRC->isEmpty()) { 1532 return; 1533 } 1534 1535 if (/*paint.isLinearText() ||*/ 1536 (fMatrix->hasPerspective())) { 1537 this->drawText_asPaths(text, byteLength, x, y, paint); 1538 return; 1539 } 1540 1541 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 1542 1543 const SkMatrix* matrix = fMatrix; 1544 if (hasCustomD1GProc(*this)) { 1545 // only support the fMVMatrix (for now) for the GPU case, which also 1546 // sets the fD1GProc 1547 if (fMVMatrix) { 1548 matrix = fMVMatrix; 1549 } 1550 } 1551 1552 SkAutoGlyphCache autoCache(paint, matrix); 1553 SkGlyphCache* cache = autoCache.getCache(); 1554 1555 // transform our starting point 1556 { 1557 SkPoint loc; 1558 matrix->mapXY(x, y, &loc); 1559 x = loc.fX; 1560 y = loc.fY; 1561 } 1562 1563 // need to measure first 1564 if (paint.getTextAlign() != SkPaint::kLeft_Align) { 1565 SkVector stop; 1566 1567 measure_text(cache, glyphCacheProc, text, byteLength, &stop); 1568 1569 SkScalar stopX = stop.fX; 1570 SkScalar stopY = stop.fY; 1571 1572 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 1573 stopX = SkScalarHalf(stopX); 1574 stopY = SkScalarHalf(stopY); 1575 } 1576 x -= stopX; 1577 y -= stopY; 1578 } 1579 1580 SkFixed fx = SkScalarToFixed(x); 1581 SkFixed fy = SkScalarToFixed(y); 1582 const char* stop = text + byteLength; 1583 1584 SkFixed fxMask = ~0; 1585 SkFixed fyMask = ~0; 1586 if (cache->isSubpixel()) { 1587 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*matrix); 1588 if (kX_SkAxisAlignment == baseline) { 1589 fyMask = 0; 1590 } else if (kY_SkAxisAlignment == baseline) { 1591 fxMask = 0; 1592 } 1593 1594 // apply bias here to avoid adding 1/2 the sampling frequency in the loop 1595 fx += SK_FixedHalf >> SkGlyph::kSubBits; 1596 fy += SK_FixedHalf >> SkGlyph::kSubBits; 1597 } else { 1598 fx += SK_FixedHalf; 1599 fy += SK_FixedHalf; 1600 } 1601 1602 SkAAClipBlitter aaBlitter; 1603 SkAutoBlitterChoose blitterChooser; 1604 SkBlitter* blitter = NULL; 1605 if (needsRasterTextBlit(*this)) { 1606 blitterChooser.choose(*fBitmap, *matrix, paint); 1607 blitter = blitterChooser.get(); 1608 if (fRC->isAA()) { 1609 aaBlitter.init(blitter, &fRC->aaRgn()); 1610 blitter = &aaBlitter; 1611 } 1612 } 1613 1614 SkAutoKern autokern; 1615 SkDraw1Glyph d1g; 1616 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache); 1617 1618 while (text < stop) { 1619 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask); 1620 1621 fx += autokern.adjust(glyph); 1622 1623 if (glyph.fWidth) { 1624 proc(d1g, fx, fy, glyph); 1625 } 1626 fx += glyph.fAdvanceX; 1627 fy += glyph.fAdvanceY; 1628 } 1629 }
254 inline const SimpleFontData* Font::primaryFont() const 255 { 256 ASSERT(m_fontList); 257 return m_fontList->primarySimpleFontData(this); 258 }
58 const SimpleFontData* primarySimpleFontData(const Font* f) 59 { 60 ASSERT(isMainThread()); 61 if (!m_cachedPrimarySimpleFontData) 62 m_cachedPrimarySimpleFontData = primaryFontData(f)->fontDataForCharacter(' '); 63 return m_cachedPrimarySimpleFontData; 64 }
91 static bool setupForText(SkPaint* paint, GraphicsContext* gc, 92 const SimpleFontData* font) { 93 int mode = gc->textDrawingMode() & (TextModeFill | TextModeStroke); 94 if (!mode) 95 return false; 96 97 paint->setVerticalText(font->platformData().orientation() == Vertical); 98 99 FloatSize shadowOffset; 100 float shadowBlur; 101 Color shadowColor; 102 ColorSpace shadowColorSpace; 103 104 if (RenderSkinAndroid::DrawableResolution() >= RenderSkinAndroid::HighRes) 105 paint->setAutohinted(false); 106 107 bool hasShadow = gc->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace); 108 bool hasBothStrokeAndFill = 109 (mode & (TextModeStroke | TextModeFill)) == (TextModeStroke | TextModeFill); 110 if (hasShadow || hasBothStrokeAndFill) { 111 SkLayerDrawLooper* looper = new SkLayerDrawLooper; 112 paint->setLooper(looper)->unref(); 113 114 // The layerDrawLooper uses at the root paint to determine the text 115 // encoding so we need to make sure it is properly configured. 116 updateForFont(paint, font); 117 118 // Specify the behavior of the looper 119 SkLayerDrawLooper::LayerInfo info; 120 info.fPaintBits = SkLayerDrawLooper::kEntirePaint_Bits; 121 info.fColorMode = SkXfermode::kSrc_Mode; 122 info.fFlagsMask = SkPaint::kAllFlags; 123 124 // The paint is only valid until the looper receives another call to 125 // addLayer(). Therefore, we must cache certain state for later use. 126 bool hasFillPaint = false; 127 bool hasStrokePaint = false; 128 SkScalar strokeWidth; 129 130 if ((mode & TextModeStroke) && gc->willStroke()) { 131 strokeWidth = setupStroke(looper->addLayer(info), gc, font)->getStrokeWidth(); 132 hasStrokePaint = true; 133 } 134 if ((mode & TextModeFill) && gc->willFill()) { 135 setupFill(looper->addLayer(info), gc, font); 136 hasFillPaint = true; 137 } 138 139 if (hasShadow) { 140 SkPaint shadowPaint; 141 SkPoint offset; 142 if (gc->setupShadowPaint(&shadowPaint, &offset)) { 143 144 // add an offset to the looper when creating a shadow layer 145 info.fOffset.set(offset.fX, offset.fY); 146 147 SkPaint* p = looper->addLayer(info); 148 *p = shadowPaint; 149 150 // Currently, only GraphicsContexts associated with the 151 // HTMLCanvasElement have shadows ignore transforms set. This 152 // allows us to distinguish between CSS and Canvas shadows which 153 // have different rendering specifications. 154 if (gc->shadowsIgnoreTransforms()) { 155 SkColorFilter* cf = SkColorFilter::CreateModeFilter(p->getColor(), 156 SkXfermode::kSrcIn_Mode); 157 p->setColorFilter(cf)->unref(); 158 } else { // in CSS 159 p->setShader(NULL); 160 } 161 162 if (hasStrokePaint && !hasFillPaint) { 163 // stroke the shadow if we have stroke but no fill 164 p->setStyle(SkPaint::kStroke_Style); 165 p->setStrokeWidth(strokeWidth); 166 } 167 updateForFont(p, font); 168 } 169 } 170 } else if (mode & TextModeFill) { 171 (void)setupFill(paint, gc, font); 172 } else if (mode & TextModeStroke) { 173 (void)setupStroke(paint, gc, font); 174 } else { 175 return false; 176 } 177 return true; 178 }>