| /* | |
| * Copyright 2010 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "GrTextContext.h" | |
| #include "GrContext.h" | |
| #include "SkAutoKern.h" | |
| #include "SkGlyphCache.h" | |
| #include "GrFontScaler.h" | |
| GrTextContext::GrTextContext(GrContext* context, const SkDeviceProperties& properties) : | |
| fFallbackTextContext(NULL), | |
| fContext(context), fDeviceProperties(properties), fDrawTarget(NULL) { | |
| } | |
| GrTextContext::~GrTextContext() { | |
| SkDELETE(fFallbackTextContext); | |
| } | |
| void GrTextContext::init(const GrPaint& grPaint, const SkPaint& skPaint) { | |
| const GrClipData* clipData = fContext->getClip(); | |
| SkRect devConservativeBound; | |
| clipData->fClipStack->getConservativeBounds( | |
| -clipData->fOrigin.fX, | |
| -clipData->fOrigin.fY, | |
| fContext->getRenderTarget()->width(), | |
| fContext->getRenderTarget()->height(), | |
| &devConservativeBound); | |
| devConservativeBound.roundOut(&fClipRect); | |
| fDrawTarget = fContext->getTextTarget(); | |
| fPaint = grPaint; | |
| fSkPaint = skPaint; | |
| } | |
| bool GrTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint, | |
| const SkMatrix& viewMatrix, | |
| const char text[], size_t byteLength, | |
| SkScalar x, SkScalar y) { | |
| GrTextContext* textContext = this; | |
| do { | |
| if (textContext->canDraw(skPaint, viewMatrix)) { | |
| textContext->onDrawText(paint, skPaint, viewMatrix, text, byteLength, x, y); | |
| return true; | |
| } | |
| textContext = textContext->fFallbackTextContext; | |
| } while (textContext); | |
| return false; | |
| } | |
| bool GrTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint, | |
| const SkMatrix& viewMatrix, | |
| const char text[], size_t byteLength, | |
| const SkScalar pos[], int scalarsPerPosition, | |
| const SkPoint& offset) { | |
| GrTextContext* textContext = this; | |
| do { | |
| if (textContext->canDraw(skPaint, viewMatrix)) { | |
| textContext->onDrawPosText(paint, skPaint, viewMatrix, text, byteLength, pos, | |
| scalarsPerPosition, offset); | |
| return true; | |
| } | |
| textContext = textContext->fFallbackTextContext; | |
| } while (textContext); | |
| return false; | |
| } | |
| //*** change to output positions? | |
| int GrTextContext::MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc, | |
| const char text[], size_t byteLength, SkVector* stopVector) { | |
| SkFixed x = 0, y = 0; | |
| const char* stop = text + byteLength; | |
| SkAutoKern autokern; | |
| int numGlyphs = 0; | |
| while (text < stop) { | |
| // don't need x, y here, since all subpixel variants will have the | |
| // same advance | |
| const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); | |
| x += autokern.adjust(glyph) + glyph.fAdvanceX; | |
| y += glyph.fAdvanceY; | |
| ++numGlyphs; | |
| } | |
| stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y)); | |
| SkASSERT(text == stop); | |
| return numGlyphs; | |
| } | |
| static void GlyphCacheAuxProc(void* data) { | |
| GrFontScaler* scaler = (GrFontScaler*)data; | |
| SkSafeUnref(scaler); | |
| } | |
| GrFontScaler* GrTextContext::GetGrFontScaler(SkGlyphCache* cache) { | |
| void* auxData; | |
| GrFontScaler* scaler = NULL; | |
| if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) { | |
| scaler = (GrFontScaler*)auxData; | |
| } | |
| if (NULL == scaler) { | |
| scaler = SkNEW_ARGS(GrFontScaler, (cache)); | |
| cache->setAuxProc(GlyphCacheAuxProc, scaler); | |
| } | |
| return scaler; | |
| } |