1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2010 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */
7ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
8375ff85e96cf0f8438ea0b11be67e85474e42c29tomhudson@google.com#include "GrTextContext.h"
9e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org#include "GrContext.h"
10570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt#include "GrDrawTarget.h"
11570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt#include "GrFontScaler.h"
12e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org
13e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org#include "SkAutoKern.h"
149c328187d9dee33736b77dc14dfb59529d948bb1joshualitt#include "SkDrawFilter.h"
156e8cd9671958c69babde9338c5c18a4c3d895575joshualitt#include "SkDrawProcs.h"
16e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org#include "SkGlyphCache.h"
176e8cd9671958c69babde9338c5c18a4c3d895575joshualitt#include "SkGpuDevice.h"
189c328187d9dee33736b77dc14dfb59529d948bb1joshualitt#include "SkTextBlob.h"
196e8cd9671958c69babde9338c5c18a4c3d895575joshualitt#include "SkTextMapStateProc.h"
206e8cd9671958c69babde9338c5c18a4c3d895575joshualitt#include "SkTextToPathIter.h"
216e8cd9671958c69babde9338c5c18a4c3d895575joshualitt
226e8cd9671958c69babde9338c5c18a4c3d895575joshualittGrTextContext::GrTextContext(GrContext* context, SkGpuDevice* gpuDevice,
236e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                             const SkDeviceProperties& properties)
246e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    : fFallbackTextContext(NULL)
256e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    , fContext(context)
266e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    , fGpuDevice(gpuDevice)
276e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    , fDeviceProperties(properties)
286e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    , fDrawTarget(NULL) {
29cbbc481e918c0d32454455626235f67106f216a1commit-bot@chromium.org}
30375ff85e96cf0f8438ea0b11be67e85474e42c29tomhudson@google.com
318c27a188a0b216021d439eb627622d17b9f78343jvanverthGrTextContext::~GrTextContext() {
328c27a188a0b216021d439eb627622d17b9f78343jvanverth    SkDELETE(fFallbackTextContext);
338c27a188a0b216021d439eb627622d17b9f78343jvanverth}
348c27a188a0b216021d439eb627622d17b9f78343jvanverth
35570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualittvoid GrTextContext::init(GrRenderTarget* rt, const GrClip& clip, const GrPaint& grPaint,
366e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                         const SkPaint& skPaint, const SkIRect& regionClipBounds) {
37570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt    fClip = clip;
38beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.com
3925d9c154087d2132a51d1ca74a104726f60ef380joshualitt    fRenderTarget.reset(SkRef(rt));
4025d9c154087d2132a51d1ca74a104726f60ef380joshualitt
416e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    fRegionClipBounds = regionClipBounds;
42570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt    fClip.getConservativeBounds(fRenderTarget->width(), fRenderTarget->height(), &fClipRect);
43beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.com
44cbbc481e918c0d32454455626235f67106f216a1commit-bot@chromium.org    fDrawTarget = fContext->getTextTarget();
45cbbc481e918c0d32454455626235f67106f216a1commit-bot@chromium.org
46cbbc481e918c0d32454455626235f67106f216a1commit-bot@chromium.org    fPaint = grPaint;
47cbbc481e918c0d32454455626235f67106f216a1commit-bot@chromium.org    fSkPaint = skPaint;
48ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
49e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org
506e8cd9671958c69babde9338c5c18a4c3d895575joshualittvoid GrTextContext::drawText(GrRenderTarget* rt, const GrClip& clip, const GrPaint& paint,
51570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt                             const SkPaint& skPaint, const SkMatrix& viewMatrix,
528c27a188a0b216021d439eb627622d17b9f78343jvanverth                             const char text[], size_t byteLength,
536e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                             SkScalar x, SkScalar y, const SkIRect& clipBounds) {
545f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt    if (!fContext->getTextTarget()) {
556e8cd9671958c69babde9338c5c18a4c3d895575joshualitt        return;
565f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt    }
578c27a188a0b216021d439eb627622d17b9f78343jvanverth
58aab626c3670205d02ca42bb34a540f550cb75dc2jvanverth    GrTextContext* textContext = this;
59aab626c3670205d02ca42bb34a540f550cb75dc2jvanverth    do {
60e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        if (textContext->canDraw(rt, clip, paint, skPaint, viewMatrix)) {
616e8cd9671958c69babde9338c5c18a4c3d895575joshualitt            textContext->onDrawText(rt, clip, paint, skPaint, viewMatrix, text, byteLength, x, y,
626e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                                    clipBounds);
636e8cd9671958c69babde9338c5c18a4c3d895575joshualitt            return;
64aab626c3670205d02ca42bb34a540f550cb75dc2jvanverth        }
65aab626c3670205d02ca42bb34a540f550cb75dc2jvanverth        textContext = textContext->fFallbackTextContext;
66aab626c3670205d02ca42bb34a540f550cb75dc2jvanverth    } while (textContext);
67aab626c3670205d02ca42bb34a540f550cb75dc2jvanverth
686e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    // fall back to drawing as a path
6979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt    SkASSERT(fGpuDevice);
706e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    this->drawTextAsPath(skPaint, viewMatrix, text, byteLength, x, y, clipBounds);
718c27a188a0b216021d439eb627622d17b9f78343jvanverth}
728c27a188a0b216021d439eb627622d17b9f78343jvanverth
736e8cd9671958c69babde9338c5c18a4c3d895575joshualittvoid GrTextContext::drawPosText(GrRenderTarget* rt, const GrClip& clip, const GrPaint& paint,
74570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt                                const SkPaint& skPaint, const SkMatrix& viewMatrix,
758c27a188a0b216021d439eb627622d17b9f78343jvanverth                                const char text[], size_t byteLength,
768c27a188a0b216021d439eb627622d17b9f78343jvanverth                                const SkScalar pos[], int scalarsPerPosition,
776e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                                const SkPoint& offset, const SkIRect& clipBounds) {
785f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt    if (!fContext->getTextTarget()) {
796e8cd9671958c69babde9338c5c18a4c3d895575joshualitt        return;
805f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt    }
818c27a188a0b216021d439eb627622d17b9f78343jvanverth
828c27a188a0b216021d439eb627622d17b9f78343jvanverth    GrTextContext* textContext = this;
838c27a188a0b216021d439eb627622d17b9f78343jvanverth    do {
84e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        if (textContext->canDraw(rt, clip, paint, skPaint, viewMatrix)) {
85570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt            textContext->onDrawPosText(rt, clip, paint, skPaint, viewMatrix, text, byteLength, pos,
866e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                                       scalarsPerPosition, offset, clipBounds);
876e8cd9671958c69babde9338c5c18a4c3d895575joshualitt            return;
888c27a188a0b216021d439eb627622d17b9f78343jvanverth        }
898c27a188a0b216021d439eb627622d17b9f78343jvanverth        textContext = textContext->fFallbackTextContext;
908c27a188a0b216021d439eb627622d17b9f78343jvanverth    } while (textContext);
918c27a188a0b216021d439eb627622d17b9f78343jvanverth
926e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    // fall back to drawing as a path
9379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt    SkASSERT(fGpuDevice);
946e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    this->drawPosTextAsPath(skPaint, viewMatrix, text, byteLength, pos, scalarsPerPosition, offset,
956e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                            clipBounds);
968c27a188a0b216021d439eb627622d17b9f78343jvanverth}
978c27a188a0b216021d439eb627622d17b9f78343jvanverth
989c328187d9dee33736b77dc14dfb59529d948bb1joshualittvoid GrTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, const SkPaint& skPaint,
999c328187d9dee33736b77dc14dfb59529d948bb1joshualitt                                 const SkMatrix& viewMatrix, const SkTextBlob* blob,
1009c328187d9dee33736b77dc14dfb59529d948bb1joshualitt                                 SkScalar x, SkScalar y,
1019c328187d9dee33736b77dc14dfb59529d948bb1joshualitt                                 SkDrawFilter* drawFilter, const SkIRect& clipBounds) {
102e68f7362b1e00e88688906de6384e4e5a83076d0cdalton    SkPaint runPaint = skPaint;
1039c328187d9dee33736b77dc14dfb59529d948bb1joshualitt
104e68f7362b1e00e88688906de6384e4e5a83076d0cdalton    SkTextBlob::RunIterator it(blob);
105e68f7362b1e00e88688906de6384e4e5a83076d0cdalton    for (;!it.done(); it.next()) {
106e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        size_t textLen = it.glyphCount() * sizeof(uint16_t);
107e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        const SkPoint& offset = it.offset();
108e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        // applyFontToPaint() always overwrites the exact same attributes,
109e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        // so it is safe to not re-seed the paint for this reason.
110e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        it.applyFontToPaint(&runPaint);
111e68f7362b1e00e88688906de6384e4e5a83076d0cdalton
112e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Type)) {
113e68f7362b1e00e88688906de6384e4e5a83076d0cdalton            // A false return from filter() means we should abort the current draw.
114e68f7362b1e00e88688906de6384e4e5a83076d0cdalton            runPaint = skPaint;
115e68f7362b1e00e88688906de6384e4e5a83076d0cdalton            continue;
1169c328187d9dee33736b77dc14dfb59529d948bb1joshualitt        }
117e68f7362b1e00e88688906de6384e4e5a83076d0cdalton
118e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        runPaint.setFlags(fGpuDevice->filterTextFlags(runPaint));
119e68f7362b1e00e88688906de6384e4e5a83076d0cdalton
120e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        GrPaint grPaint;
121bed83a66f5fa5821a3a08da32157a6155960b15ebsalomon        if (!SkPaint2GrPaint(fContext, fRenderTarget, runPaint, viewMatrix, true, &grPaint)) {
122bed83a66f5fa5821a3a08da32157a6155960b15ebsalomon            return;
123bed83a66f5fa5821a3a08da32157a6155960b15ebsalomon        }
124e68f7362b1e00e88688906de6384e4e5a83076d0cdalton
125e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        switch (it.positioning()) {
126e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        case SkTextBlob::kDefault_Positioning:
127e68f7362b1e00e88688906de6384e4e5a83076d0cdalton            this->drawText(rt, clip, grPaint, runPaint, viewMatrix, (const char *)it.glyphs(),
128e68f7362b1e00e88688906de6384e4e5a83076d0cdalton                           textLen, x + offset.x(), y + offset.y(), clipBounds);
129e68f7362b1e00e88688906de6384e4e5a83076d0cdalton            break;
130e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        case SkTextBlob::kHorizontal_Positioning:
131e68f7362b1e00e88688906de6384e4e5a83076d0cdalton            this->drawPosText(rt, clip, grPaint, runPaint, viewMatrix, (const char*)it.glyphs(),
132e68f7362b1e00e88688906de6384e4e5a83076d0cdalton                              textLen, it.pos(), 1, SkPoint::Make(x, y + offset.y()), clipBounds);
133e68f7362b1e00e88688906de6384e4e5a83076d0cdalton            break;
134e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        case SkTextBlob::kFull_Positioning:
135e68f7362b1e00e88688906de6384e4e5a83076d0cdalton            this->drawPosText(rt, clip, grPaint, runPaint, viewMatrix, (const char*)it.glyphs(),
136e68f7362b1e00e88688906de6384e4e5a83076d0cdalton                              textLen, it.pos(), 2, SkPoint::Make(x, y), clipBounds);
137e68f7362b1e00e88688906de6384e4e5a83076d0cdalton            break;
138e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        default:
139e68f7362b1e00e88688906de6384e4e5a83076d0cdalton            SkFAIL("unhandled positioning mode");
140e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        }
141e68f7362b1e00e88688906de6384e4e5a83076d0cdalton
142e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        if (drawFilter) {
143e68f7362b1e00e88688906de6384e4e5a83076d0cdalton            // A draw filter may change the paint arbitrarily, so we must re-seed in this case.
144e68f7362b1e00e88688906de6384e4e5a83076d0cdalton            runPaint = skPaint;
145e68f7362b1e00e88688906de6384e4e5a83076d0cdalton        }
146e68f7362b1e00e88688906de6384e4e5a83076d0cdalton    }
1479c328187d9dee33736b77dc14dfb59529d948bb1joshualitt}
1489c328187d9dee33736b77dc14dfb59529d948bb1joshualitt
1496e8cd9671958c69babde9338c5c18a4c3d895575joshualittvoid GrTextContext::drawTextAsPath(const SkPaint& skPaint, const SkMatrix& viewMatrix,
1506e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                                   const char text[], size_t byteLength, SkScalar x, SkScalar y,
1516e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                                   const SkIRect& clipBounds) {
1526e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    SkTextToPathIter iter(text, byteLength, skPaint, true);
1536e8cd9671958c69babde9338c5c18a4c3d895575joshualitt
1546e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    SkMatrix    matrix;
1556e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    matrix.setScale(iter.getPathScale(), iter.getPathScale());
1566e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    matrix.postTranslate(x, y);
1576e8cd9671958c69babde9338c5c18a4c3d895575joshualitt
1586e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    const SkPath* iterPath;
1596e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    SkScalar xpos, prevXPos = 0;
1606e8cd9671958c69babde9338c5c18a4c3d895575joshualitt
1616e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    while (iter.next(&iterPath, &xpos)) {
1626e8cd9671958c69babde9338c5c18a4c3d895575joshualitt        matrix.postTranslate(xpos - prevXPos, 0);
1636e8cd9671958c69babde9338c5c18a4c3d895575joshualitt        if (iterPath) {
1646e8cd9671958c69babde9338c5c18a4c3d895575joshualitt            const SkPaint& pnt = iter.getPaint();
1656e8cd9671958c69babde9338c5c18a4c3d895575joshualitt            fGpuDevice->internalDrawPath(*iterPath, pnt, viewMatrix, &matrix, clipBounds, false);
1666e8cd9671958c69babde9338c5c18a4c3d895575joshualitt        }
1676e8cd9671958c69babde9338c5c18a4c3d895575joshualitt        prevXPos = xpos;
1686e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    }
1696e8cd9671958c69babde9338c5c18a4c3d895575joshualitt}
1706e8cd9671958c69babde9338c5c18a4c3d895575joshualitt
1716e8cd9671958c69babde9338c5c18a4c3d895575joshualittvoid GrTextContext::drawPosTextAsPath(const SkPaint& origPaint, const SkMatrix& viewMatrix,
1726e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                                      const char text[], size_t byteLength,
1736e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                                      const SkScalar pos[], int scalarsPerPosition,
1746e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                                      const SkPoint& offset, const SkIRect& clipBounds) {
1756e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    // setup our std paint, in hopes of getting hits in the cache
1766e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    SkPaint paint(origPaint);
1776e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    SkScalar matrixScale = paint.setupForAsPaths();
1786e8cd9671958c69babde9338c5c18a4c3d895575joshualitt
1796e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    SkMatrix matrix;
1806e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    matrix.setScale(matrixScale, matrixScale);
1816e8cd9671958c69babde9338c5c18a4c3d895575joshualitt
1826e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache.
1836e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    paint.setStyle(SkPaint::kFill_Style);
1846e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    paint.setPathEffect(NULL);
1856e8cd9671958c69babde9338c5c18a4c3d895575joshualitt
1866e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
1876e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    SkAutoGlyphCache    autoCache(paint, NULL, NULL);
1886e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    SkGlyphCache*       cache = autoCache.getCache();
1896e8cd9671958c69babde9338c5c18a4c3d895575joshualitt
1906e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    const char*        stop = text + byteLength;
1916e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    SkTextAlignProc    alignProc(paint.getTextAlign());
1926e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition);
1936e8cd9671958c69babde9338c5c18a4c3d895575joshualitt
1946e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    // Now restore the original settings, so we "draw" with whatever style/stroking.
1956e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    paint.setStyle(origPaint.getStyle());
1966e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    paint.setPathEffect(origPaint.getPathEffect());
1976e8cd9671958c69babde9338c5c18a4c3d895575joshualitt
1986e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    while (text < stop) {
1996e8cd9671958c69babde9338c5c18a4c3d895575joshualitt        const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
2006e8cd9671958c69babde9338c5c18a4c3d895575joshualitt        if (glyph.fWidth) {
2016e8cd9671958c69babde9338c5c18a4c3d895575joshualitt            const SkPath* path = cache->findPath(glyph);
2026e8cd9671958c69babde9338c5c18a4c3d895575joshualitt            if (path) {
2036e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                SkPoint tmsLoc;
2046e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                tmsProc(pos, &tmsLoc);
2056e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                SkPoint loc;
2066e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                alignProc(tmsLoc, glyph, &loc);
2076e8cd9671958c69babde9338c5c18a4c3d895575joshualitt
2086e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                matrix[SkMatrix::kMTransX] = loc.fX;
2096e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                matrix[SkMatrix::kMTransY] = loc.fY;
2106e8cd9671958c69babde9338c5c18a4c3d895575joshualitt                fGpuDevice->internalDrawPath(*path, paint, viewMatrix, &matrix, clipBounds, false);
2116e8cd9671958c69babde9338c5c18a4c3d895575joshualitt            }
2126e8cd9671958c69babde9338c5c18a4c3d895575joshualitt        }
2136e8cd9671958c69babde9338c5c18a4c3d895575joshualitt        pos += scalarsPerPosition;
2146e8cd9671958c69babde9338c5c18a4c3d895575joshualitt    }
2156e8cd9671958c69babde9338c5c18a4c3d895575joshualitt}
2168c27a188a0b216021d439eb627622d17b9f78343jvanverth
217e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org//*** change to output positions?
21873f105345066b1f22f15ba6575cb3800dd9313b8jvanverthint GrTextContext::MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
219e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org                                const char text[], size_t byteLength, SkVector* stopVector) {
220e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org    SkFixed     x = 0, y = 0;
221e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org    const char* stop = text + byteLength;
222e5d7015cde3b6f2a3929b8e378822e3d7be223d4skia.committer@gmail.com
223e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org    SkAutoKern  autokern;
224e5d7015cde3b6f2a3929b8e378822e3d7be223d4skia.committer@gmail.com
22573f105345066b1f22f15ba6575cb3800dd9313b8jvanverth    int numGlyphs = 0;
226e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org    while (text < stop) {
227e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org        // don't need x, y here, since all subpixel variants will have the
228e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org        // same advance
229e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org        const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
230e5d7015cde3b6f2a3929b8e378822e3d7be223d4skia.committer@gmail.com
231e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org        x += autokern.adjust(glyph) + glyph.fAdvanceX;
232e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org        y += glyph.fAdvanceY;
23373f105345066b1f22f15ba6575cb3800dd9313b8jvanverth        ++numGlyphs;
234e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org    }
235e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org    stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
236e5d7015cde3b6f2a3929b8e378822e3d7be223d4skia.committer@gmail.com
237e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org    SkASSERT(text == stop);
23873f105345066b1f22f15ba6575cb3800dd9313b8jvanverth
23973f105345066b1f22f15ba6575cb3800dd9313b8jvanverth    return numGlyphs;
240e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org}
241e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org
242e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.orgstatic void GlyphCacheAuxProc(void* data) {
243e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org    GrFontScaler* scaler = (GrFontScaler*)data;
244e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org    SkSafeUnref(scaler);
245e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org}
246e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org
247e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.orgGrFontScaler* GrTextContext::GetGrFontScaler(SkGlyphCache* cache) {
248e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org    void* auxData;
249e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org    GrFontScaler* scaler = NULL;
250e5d7015cde3b6f2a3929b8e378822e3d7be223d4skia.committer@gmail.com
251e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org    if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
252e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org        scaler = (GrFontScaler*)auxData;
253e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org    }
254e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org    if (NULL == scaler) {
255733f5f5dbca10fc6385ec3c77b3e9ff78227dac7jvanverth        scaler = SkNEW_ARGS(GrFontScaler, (cache));
256e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org        cache->setAuxProc(GlyphCacheAuxProc, scaler);
257e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org    }
258e5d7015cde3b6f2a3929b8e378822e3d7be223d4skia.committer@gmail.com
259e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org    return scaler;
260e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org}
261