void GrBitmapTextContext::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) { SkASSERT(byteLength == 0 || text != NULL); // nothing to draw if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) { return; } this->init(rt, clip, paint, skPaint); SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &viewMatrix); SkGlyphCache* cache = autoCache.getCache(); GrFontScaler* fontScaler = GetGrFontScaler(cache); // transform our starting point { SkPoint loc; viewMatrix.mapXY(x, y, &loc); x = loc.fX; y = loc.fY; } // need to measure first int numGlyphs; if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) { SkVector stopVector; numGlyphs = MeasureText(cache, glyphCacheProc, text, byteLength, &stopVector); SkScalar stopX = stopVector.fX; SkScalar stopY = stopVector.fY; if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) { stopX = SkScalarHalf(stopX); stopY = SkScalarHalf(stopY); } x -= stopX; y -= stopY; } else { numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL); } fTotalVertexCount = kVerticesPerGlyph*numGlyphs; const char* stop = text + byteLength; SkAutoKern autokern; SkFixed fxMask = ~0; SkFixed fyMask = ~0; SkScalar halfSampleX, halfSampleY; if (cache->isSubpixel()) { halfSampleX = halfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound); SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(viewMatrix); if (kX_SkAxisAlignment == baseline) { fyMask = 0; halfSampleY = SK_ScalarHalf; } else if (kY_SkAxisAlignment == baseline) { fxMask = 0; halfSampleX = SK_ScalarHalf; } } else { halfSampleX = halfSampleY = SK_ScalarHalf; } Sk48Dot16 fx = SkScalarTo48Dot16(x + halfSampleX); Sk48Dot16 fy = SkScalarTo48Dot16(y + halfSampleY); // if we have RGB, then we won't have any SkShaders so no need to use a localmatrix, but for // performance reasons we just invert here instead if (!viewMatrix.invert(&fLocalMatrix)) { SkDebugf("Cannot invert viewmatrix\n"); return; } while (text < stop) { const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask); fx += autokern.adjust(glyph); if (glyph.fWidth) { this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), glyph.getSubXFixed(), glyph.getSubYFixed(), GrGlyph::kCoverage_MaskStyle), Sk48Dot16FloorToInt(fx), Sk48Dot16FloorToInt(fy), fontScaler); } fx += glyph.fAdvanceX; fy += glyph.fAdvanceY; } this->finish(); }
void GrBitmapTextContext::onDrawText(const GrPaint& paint, const SkPaint& skPaint, const char text[], size_t byteLength, SkScalar x, SkScalar y) { SkASSERT(byteLength == 0 || text != NULL); // nothing to draw if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) { return; } this->init(paint, skPaint); SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix()); SkGlyphCache* cache = autoCache.getCache(); GrFontScaler* fontScaler = GetGrFontScaler(cache); // transform our starting point { SkPoint loc; fContext->getMatrix().mapXY(x, y, &loc); x = loc.fX; y = loc.fY; } // need to measure first int numGlyphs; if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) { SkVector stopVector; numGlyphs = MeasureText(cache, glyphCacheProc, text, byteLength, &stopVector); SkScalar stopX = stopVector.fX; SkScalar stopY = stopVector.fY; if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) { stopX = SkScalarHalf(stopX); stopY = SkScalarHalf(stopY); } x -= stopX; y -= stopY; } else { numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL); } fTotalVertexCount = kVerticesPerGlyph*numGlyphs; const char* stop = text + byteLength; SkAutoKern autokern; SkFixed fxMask = ~0; SkFixed fyMask = ~0; SkFixed halfSampleX, halfSampleY; if (cache->isSubpixel()) { halfSampleX = halfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits); SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(fContext->getMatrix()); if (kX_SkAxisAlignment == baseline) { fyMask = 0; halfSampleY = SK_FixedHalf; } else if (kY_SkAxisAlignment == baseline) { fxMask = 0; halfSampleX = SK_FixedHalf; } } else {
void GrBitmapTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip, const GrPaint& paint, const SkPaint& skPaint, const SkMatrix& viewMatrix, const char text[], size_t byteLength, const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset) { SkASSERT(byteLength == 0 || text != NULL); SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); // nothing to draw if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) { return; } this->init(rt, clip, paint, skPaint); SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &viewMatrix); SkGlyphCache* cache = autoCache.getCache(); GrFontScaler* fontScaler = GetGrFontScaler(cache); // if we have RGB, then we won't have any SkShaders so no need to use a localmatrix, but for // performance reasons we just invert here instead if (!viewMatrix.invert(&fLocalMatrix)) { SkDebugf("Cannot invert viewmatrix\n"); return; } int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL); fTotalVertexCount = kVerticesPerGlyph*numGlyphs; const char* stop = text + byteLength; SkTextAlignProc alignProc(fSkPaint.getTextAlign()); SkTextMapStateProc tmsProc(viewMatrix, offset, scalarsPerPosition); SkScalar halfSampleX = 0, halfSampleY = 0; if (cache->isSubpixel()) { // maybe we should skip the rounding if linearText is set SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(viewMatrix); SkFixed fxMask = ~0; SkFixed fyMask = ~0; if (kX_SkAxisAlignment == baseline) { fyMask = 0; halfSampleY = SK_ScalarHalf; } else if (kY_SkAxisAlignment == baseline) { fxMask = 0; halfSampleX = SK_ScalarHalf; } if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { while (text < stop) { SkPoint tmsLoc; tmsProc(pos, &tmsLoc); Sk48Dot16 fx = SkScalarTo48Dot16(tmsLoc.fX + halfSampleX); Sk48Dot16 fy = SkScalarTo48Dot16(tmsLoc.fY + halfSampleY); const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask); if (glyph.fWidth) { this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), glyph.getSubXFixed(), glyph.getSubYFixed(), GrGlyph::kCoverage_MaskStyle), Sk48Dot16FloorToInt(fx), Sk48Dot16FloorToInt(fy), fontScaler); } pos += scalarsPerPosition; } } else { while (text < stop) { const char* currentText = text; const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0); if (metricGlyph.fWidth) { SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;) SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;) SkPoint tmsLoc; tmsProc(pos, &tmsLoc); SkPoint alignLoc; alignProc(tmsLoc, metricGlyph, &alignLoc); Sk48Dot16 fx = SkScalarTo48Dot16(alignLoc.fX + halfSampleX); Sk48Dot16 fy = SkScalarTo48Dot16(alignLoc.fY + halfSampleY); // have to call again, now that we've been "aligned" const SkGlyph& glyph = glyphCacheProc(cache, ¤tText, fx & fxMask, fy & fyMask); // the assumption is that the metrics haven't changed SkASSERT(prevAdvX == glyph.fAdvanceX); SkASSERT(prevAdvY == glyph.fAdvanceY); SkASSERT(glyph.fWidth); this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), glyph.getSubXFixed(), glyph.getSubYFixed(), GrGlyph::kCoverage_MaskStyle), Sk48Dot16FloorToInt(fx), Sk48Dot16FloorToInt(fy), fontScaler); }
void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint, const char text[], size_t byteLength, SkScalar x, SkScalar y) { SkASSERT(byteLength == 0 || text != NULL); // nothing to draw if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) { return; } this->init(paint, skPaint); if (NULL == fDrawTarget) { return; } SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix()); SkGlyphCache* cache = autoCache.getCache(); GrFontScaler* fontScaler = GetGrFontScaler(cache); if (NULL == fStrike) { fStrike = fContext->getFontCache()->getStrike(fontScaler, false); } // transform our starting point { SkPoint loc; fContext->getMatrix().mapXY(x, y, &loc); x = loc.fX; y = loc.fY; } // need to measure first if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) { SkVector stop; MeasureText(cache, glyphCacheProc, text, byteLength, &stop); SkScalar stopX = stop.fX; SkScalar stopY = stop.fY; if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) { stopX = SkScalarHalf(stopX); stopY = SkScalarHalf(stopY); } x -= stopX; y -= stopY; } const char* stop = text + byteLength; // allocate vertices SkASSERT(NULL == fVertices); bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat(); if (useColorVerts) { fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>( SK_ARRAY_COUNT(gTextVertexWithColorAttribs)); } else { fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( SK_ARRAY_COUNT(gTextVertexAttribs)); } int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL); bool success = fDrawTarget->reserveVertexAndIndexSpace(4*numGlyphs, 0, &fVertices, NULL); GrAlwaysAssert(success); SkAutoKern autokern; SkFixed fxMask = ~0; SkFixed fyMask = ~0; SkFixed halfSampleX, halfSampleY; if (cache->isSubpixel()) { halfSampleX = halfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits); SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(fContext->getMatrix()); if (kX_SkAxisAlignment == baseline) { fyMask = 0; halfSampleY = SK_FixedHalf; } else if (kY_SkAxisAlignment == baseline) { fxMask = 0; halfSampleX = SK_FixedHalf; } } else {