GrTextContext.cpp revision aab626c3670205d02ca42bb34a540f550cb75dc2
1/*
2 * Copyright 2010 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrTextContext.h"
9#include "GrContext.h"
10
11#include "SkAutoKern.h"
12#include "SkGlyphCache.h"
13#include "GrFontScaler.h"
14
15GrTextContext::GrTextContext(GrContext* context, const SkDeviceProperties& properties) :
16                            fFallbackTextContext(NULL),
17                            fContext(context), fDeviceProperties(properties), fDrawTarget(NULL) {
18}
19
20GrTextContext::~GrTextContext() {
21    SkDELETE(fFallbackTextContext);
22}
23
24void GrTextContext::init(const GrPaint& grPaint, const SkPaint& skPaint) {
25    const GrClipData* clipData = fContext->getClip();
26
27    SkRect devConservativeBound;
28    clipData->fClipStack->getConservativeBounds(
29                                     -clipData->fOrigin.fX,
30                                     -clipData->fOrigin.fY,
31                                     fContext->getRenderTarget()->width(),
32                                     fContext->getRenderTarget()->height(),
33                                     &devConservativeBound);
34
35    devConservativeBound.roundOut(&fClipRect);
36
37    fDrawTarget = fContext->getTextTarget();
38
39    fPaint = grPaint;
40    fSkPaint = skPaint;
41}
42
43bool GrTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
44                             const char text[], size_t byteLength,
45                             SkScalar x, SkScalar y) {
46
47    GrTextContext* textContext = this;
48    do {
49        if (textContext->canDraw(skPaint)) {
50            textContext->onDrawText(paint, skPaint, text, byteLength, x, y);
51            return true;
52        }
53        textContext = textContext->fFallbackTextContext;
54    } while (textContext);
55
56    return false;
57}
58
59bool GrTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
60                                const char text[], size_t byteLength,
61                                const SkScalar pos[], int scalarsPerPosition,
62                                const SkPoint& offset) {
63
64    GrTextContext* textContext = this;
65    do {
66        if (textContext->canDraw(skPaint)) {
67            textContext->onDrawPosText(paint, skPaint, text, byteLength, pos, scalarsPerPosition,
68                                     offset);
69            return true;
70        }
71        textContext = textContext->fFallbackTextContext;
72    } while (textContext);
73
74    return false;
75}
76
77
78//*** change to output positions?
79void GrTextContext::MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
80                                const char text[], size_t byteLength, SkVector* stopVector) {
81    SkFixed     x = 0, y = 0;
82    const char* stop = text + byteLength;
83
84    SkAutoKern  autokern;
85
86    while (text < stop) {
87        // don't need x, y here, since all subpixel variants will have the
88        // same advance
89        const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
90
91        x += autokern.adjust(glyph) + glyph.fAdvanceX;
92        y += glyph.fAdvanceY;
93    }
94    stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
95
96    SkASSERT(text == stop);
97}
98
99static void GlyphCacheAuxProc(void* data) {
100    GrFontScaler* scaler = (GrFontScaler*)data;
101    SkSafeUnref(scaler);
102}
103
104GrFontScaler* GrTextContext::GetGrFontScaler(SkGlyphCache* cache) {
105    void* auxData;
106    GrFontScaler* scaler = NULL;
107
108    if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
109        scaler = (GrFontScaler*)auxData;
110    }
111    if (NULL == scaler) {
112        scaler = SkNEW_ARGS(GrFontScaler, (cache));
113        cache->setAuxProc(GlyphCacheAuxProc, scaler);
114    }
115
116    return scaler;
117}
118