GrTextContext.cpp revision 6e8cd9671958c69babde9338c5c18a4c3d895575
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" 146e8cd9671958c69babde9338c5c18a4c3d895575joshualitt#include "SkDrawProcs.h" 15e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org#include "SkGlyphCache.h" 166e8cd9671958c69babde9338c5c18a4c3d895575joshualitt#include "SkGpuDevice.h" 176e8cd9671958c69babde9338c5c18a4c3d895575joshualitt#include "SkTextMapStateProc.h" 186e8cd9671958c69babde9338c5c18a4c3d895575joshualitt#include "SkTextToPathIter.h" 196e8cd9671958c69babde9338c5c18a4c3d895575joshualitt 206e8cd9671958c69babde9338c5c18a4c3d895575joshualittGrTextContext::GrTextContext(GrContext* context, SkGpuDevice* gpuDevice, 216e8cd9671958c69babde9338c5c18a4c3d895575joshualitt const SkDeviceProperties& properties) 226e8cd9671958c69babde9338c5c18a4c3d895575joshualitt : fFallbackTextContext(NULL) 236e8cd9671958c69babde9338c5c18a4c3d895575joshualitt , fContext(context) 246e8cd9671958c69babde9338c5c18a4c3d895575joshualitt , fGpuDevice(gpuDevice) 256e8cd9671958c69babde9338c5c18a4c3d895575joshualitt , fDeviceProperties(properties) 266e8cd9671958c69babde9338c5c18a4c3d895575joshualitt , fDrawTarget(NULL) { 27cbbc481e918c0d32454455626235f67106f216a1commit-bot@chromium.org} 28375ff85e96cf0f8438ea0b11be67e85474e42c29tomhudson@google.com 298c27a188a0b216021d439eb627622d17b9f78343jvanverthGrTextContext::~GrTextContext() { 308c27a188a0b216021d439eb627622d17b9f78343jvanverth SkDELETE(fFallbackTextContext); 318c27a188a0b216021d439eb627622d17b9f78343jvanverth} 328c27a188a0b216021d439eb627622d17b9f78343jvanverth 33570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualittvoid GrTextContext::init(GrRenderTarget* rt, const GrClip& clip, const GrPaint& grPaint, 346e8cd9671958c69babde9338c5c18a4c3d895575joshualitt const SkPaint& skPaint, const SkIRect& regionClipBounds) { 35570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt fClip = clip; 36beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.com 3725d9c154087d2132a51d1ca74a104726f60ef380joshualitt fRenderTarget.reset(SkRef(rt)); 3825d9c154087d2132a51d1ca74a104726f60ef380joshualitt 396e8cd9671958c69babde9338c5c18a4c3d895575joshualitt fRegionClipBounds = regionClipBounds; 40570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt fClip.getConservativeBounds(fRenderTarget->width(), fRenderTarget->height(), &fClipRect); 41beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.com 42cbbc481e918c0d32454455626235f67106f216a1commit-bot@chromium.org fDrawTarget = fContext->getTextTarget(); 43cbbc481e918c0d32454455626235f67106f216a1commit-bot@chromium.org 44cbbc481e918c0d32454455626235f67106f216a1commit-bot@chromium.org fPaint = grPaint; 45cbbc481e918c0d32454455626235f67106f216a1commit-bot@chromium.org fSkPaint = skPaint; 46ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 47e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org 486e8cd9671958c69babde9338c5c18a4c3d895575joshualittvoid GrTextContext::drawText(GrRenderTarget* rt, const GrClip& clip, const GrPaint& paint, 49570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt const SkPaint& skPaint, const SkMatrix& viewMatrix, 508c27a188a0b216021d439eb627622d17b9f78343jvanverth const char text[], size_t byteLength, 516e8cd9671958c69babde9338c5c18a4c3d895575joshualitt SkScalar x, SkScalar y, const SkIRect& clipBounds) { 525f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt if (!fContext->getTextTarget()) { 536e8cd9671958c69babde9338c5c18a4c3d895575joshualitt return; 545f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt } 558c27a188a0b216021d439eb627622d17b9f78343jvanverth 56aab626c3670205d02ca42bb34a540f550cb75dc2jvanverth GrTextContext* textContext = this; 57aab626c3670205d02ca42bb34a540f550cb75dc2jvanverth do { 585531d51ce7426bdae7563547326fcf0bf926a083joshualitt if (textContext->canDraw(skPaint, viewMatrix)) { 596e8cd9671958c69babde9338c5c18a4c3d895575joshualitt textContext->onDrawText(rt, clip, paint, skPaint, viewMatrix, text, byteLength, x, y, 606e8cd9671958c69babde9338c5c18a4c3d895575joshualitt clipBounds); 616e8cd9671958c69babde9338c5c18a4c3d895575joshualitt return; 62aab626c3670205d02ca42bb34a540f550cb75dc2jvanverth } 63aab626c3670205d02ca42bb34a540f550cb75dc2jvanverth textContext = textContext->fFallbackTextContext; 64aab626c3670205d02ca42bb34a540f550cb75dc2jvanverth } while (textContext); 65aab626c3670205d02ca42bb34a540f550cb75dc2jvanverth 666e8cd9671958c69babde9338c5c18a4c3d895575joshualitt // fall back to drawing as a path 676e8cd9671958c69babde9338c5c18a4c3d895575joshualitt this->drawTextAsPath(skPaint, viewMatrix, text, byteLength, x, y, clipBounds); 688c27a188a0b216021d439eb627622d17b9f78343jvanverth} 698c27a188a0b216021d439eb627622d17b9f78343jvanverth 706e8cd9671958c69babde9338c5c18a4c3d895575joshualittvoid GrTextContext::drawPosText(GrRenderTarget* rt, const GrClip& clip, const GrPaint& paint, 71570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt const SkPaint& skPaint, const SkMatrix& viewMatrix, 728c27a188a0b216021d439eb627622d17b9f78343jvanverth const char text[], size_t byteLength, 738c27a188a0b216021d439eb627622d17b9f78343jvanverth const SkScalar pos[], int scalarsPerPosition, 746e8cd9671958c69babde9338c5c18a4c3d895575joshualitt const SkPoint& offset, const SkIRect& clipBounds) { 755f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt if (!fContext->getTextTarget()) { 766e8cd9671958c69babde9338c5c18a4c3d895575joshualitt return; 775f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt } 788c27a188a0b216021d439eb627622d17b9f78343jvanverth 798c27a188a0b216021d439eb627622d17b9f78343jvanverth GrTextContext* textContext = this; 808c27a188a0b216021d439eb627622d17b9f78343jvanverth do { 815531d51ce7426bdae7563547326fcf0bf926a083joshualitt if (textContext->canDraw(skPaint, viewMatrix)) { 82570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt textContext->onDrawPosText(rt, clip, paint, skPaint, viewMatrix, text, byteLength, pos, 836e8cd9671958c69babde9338c5c18a4c3d895575joshualitt scalarsPerPosition, offset, clipBounds); 846e8cd9671958c69babde9338c5c18a4c3d895575joshualitt return; 858c27a188a0b216021d439eb627622d17b9f78343jvanverth } 868c27a188a0b216021d439eb627622d17b9f78343jvanverth textContext = textContext->fFallbackTextContext; 878c27a188a0b216021d439eb627622d17b9f78343jvanverth } while (textContext); 888c27a188a0b216021d439eb627622d17b9f78343jvanverth 896e8cd9671958c69babde9338c5c18a4c3d895575joshualitt // fall back to drawing as a path 906e8cd9671958c69babde9338c5c18a4c3d895575joshualitt this->drawPosTextAsPath(skPaint, viewMatrix, text, byteLength, pos, scalarsPerPosition, offset, 916e8cd9671958c69babde9338c5c18a4c3d895575joshualitt clipBounds); 928c27a188a0b216021d439eb627622d17b9f78343jvanverth} 938c27a188a0b216021d439eb627622d17b9f78343jvanverth 946e8cd9671958c69babde9338c5c18a4c3d895575joshualittvoid GrTextContext::drawTextAsPath(const SkPaint& skPaint, const SkMatrix& viewMatrix, 956e8cd9671958c69babde9338c5c18a4c3d895575joshualitt const char text[], size_t byteLength, SkScalar x, SkScalar y, 966e8cd9671958c69babde9338c5c18a4c3d895575joshualitt const SkIRect& clipBounds) { 976e8cd9671958c69babde9338c5c18a4c3d895575joshualitt SkTextToPathIter iter(text, byteLength, skPaint, true); 986e8cd9671958c69babde9338c5c18a4c3d895575joshualitt 996e8cd9671958c69babde9338c5c18a4c3d895575joshualitt SkMatrix matrix; 1006e8cd9671958c69babde9338c5c18a4c3d895575joshualitt matrix.setScale(iter.getPathScale(), iter.getPathScale()); 1016e8cd9671958c69babde9338c5c18a4c3d895575joshualitt matrix.postTranslate(x, y); 1026e8cd9671958c69babde9338c5c18a4c3d895575joshualitt 1036e8cd9671958c69babde9338c5c18a4c3d895575joshualitt const SkPath* iterPath; 1046e8cd9671958c69babde9338c5c18a4c3d895575joshualitt SkScalar xpos, prevXPos = 0; 1056e8cd9671958c69babde9338c5c18a4c3d895575joshualitt 1066e8cd9671958c69babde9338c5c18a4c3d895575joshualitt while (iter.next(&iterPath, &xpos)) { 1076e8cd9671958c69babde9338c5c18a4c3d895575joshualitt matrix.postTranslate(xpos - prevXPos, 0); 1086e8cd9671958c69babde9338c5c18a4c3d895575joshualitt if (iterPath) { 1096e8cd9671958c69babde9338c5c18a4c3d895575joshualitt const SkPaint& pnt = iter.getPaint(); 1106e8cd9671958c69babde9338c5c18a4c3d895575joshualitt fGpuDevice->internalDrawPath(*iterPath, pnt, viewMatrix, &matrix, clipBounds, false); 1116e8cd9671958c69babde9338c5c18a4c3d895575joshualitt } 1126e8cd9671958c69babde9338c5c18a4c3d895575joshualitt prevXPos = xpos; 1136e8cd9671958c69babde9338c5c18a4c3d895575joshualitt } 1146e8cd9671958c69babde9338c5c18a4c3d895575joshualitt} 1156e8cd9671958c69babde9338c5c18a4c3d895575joshualitt 1166e8cd9671958c69babde9338c5c18a4c3d895575joshualittvoid GrTextContext::drawPosTextAsPath(const SkPaint& origPaint, const SkMatrix& viewMatrix, 1176e8cd9671958c69babde9338c5c18a4c3d895575joshualitt const char text[], size_t byteLength, 1186e8cd9671958c69babde9338c5c18a4c3d895575joshualitt const SkScalar pos[], int scalarsPerPosition, 1196e8cd9671958c69babde9338c5c18a4c3d895575joshualitt const SkPoint& offset, const SkIRect& clipBounds) { 1206e8cd9671958c69babde9338c5c18a4c3d895575joshualitt // setup our std paint, in hopes of getting hits in the cache 1216e8cd9671958c69babde9338c5c18a4c3d895575joshualitt SkPaint paint(origPaint); 1226e8cd9671958c69babde9338c5c18a4c3d895575joshualitt SkScalar matrixScale = paint.setupForAsPaths(); 1236e8cd9671958c69babde9338c5c18a4c3d895575joshualitt 1246e8cd9671958c69babde9338c5c18a4c3d895575joshualitt SkMatrix matrix; 1256e8cd9671958c69babde9338c5c18a4c3d895575joshualitt matrix.setScale(matrixScale, matrixScale); 1266e8cd9671958c69babde9338c5c18a4c3d895575joshualitt 1276e8cd9671958c69babde9338c5c18a4c3d895575joshualitt // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache. 1286e8cd9671958c69babde9338c5c18a4c3d895575joshualitt paint.setStyle(SkPaint::kFill_Style); 1296e8cd9671958c69babde9338c5c18a4c3d895575joshualitt paint.setPathEffect(NULL); 1306e8cd9671958c69babde9338c5c18a4c3d895575joshualitt 1316e8cd9671958c69babde9338c5c18a4c3d895575joshualitt SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 1326e8cd9671958c69babde9338c5c18a4c3d895575joshualitt SkAutoGlyphCache autoCache(paint, NULL, NULL); 1336e8cd9671958c69babde9338c5c18a4c3d895575joshualitt SkGlyphCache* cache = autoCache.getCache(); 1346e8cd9671958c69babde9338c5c18a4c3d895575joshualitt 1356e8cd9671958c69babde9338c5c18a4c3d895575joshualitt const char* stop = text + byteLength; 1366e8cd9671958c69babde9338c5c18a4c3d895575joshualitt SkTextAlignProc alignProc(paint.getTextAlign()); 1376e8cd9671958c69babde9338c5c18a4c3d895575joshualitt SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); 1386e8cd9671958c69babde9338c5c18a4c3d895575joshualitt 1396e8cd9671958c69babde9338c5c18a4c3d895575joshualitt // Now restore the original settings, so we "draw" with whatever style/stroking. 1406e8cd9671958c69babde9338c5c18a4c3d895575joshualitt paint.setStyle(origPaint.getStyle()); 1416e8cd9671958c69babde9338c5c18a4c3d895575joshualitt paint.setPathEffect(origPaint.getPathEffect()); 1426e8cd9671958c69babde9338c5c18a4c3d895575joshualitt 1436e8cd9671958c69babde9338c5c18a4c3d895575joshualitt while (text < stop) { 1446e8cd9671958c69babde9338c5c18a4c3d895575joshualitt const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 1456e8cd9671958c69babde9338c5c18a4c3d895575joshualitt if (glyph.fWidth) { 1466e8cd9671958c69babde9338c5c18a4c3d895575joshualitt const SkPath* path = cache->findPath(glyph); 1476e8cd9671958c69babde9338c5c18a4c3d895575joshualitt if (path) { 1486e8cd9671958c69babde9338c5c18a4c3d895575joshualitt SkPoint tmsLoc; 1496e8cd9671958c69babde9338c5c18a4c3d895575joshualitt tmsProc(pos, &tmsLoc); 1506e8cd9671958c69babde9338c5c18a4c3d895575joshualitt SkPoint loc; 1516e8cd9671958c69babde9338c5c18a4c3d895575joshualitt alignProc(tmsLoc, glyph, &loc); 1526e8cd9671958c69babde9338c5c18a4c3d895575joshualitt 1536e8cd9671958c69babde9338c5c18a4c3d895575joshualitt matrix[SkMatrix::kMTransX] = loc.fX; 1546e8cd9671958c69babde9338c5c18a4c3d895575joshualitt matrix[SkMatrix::kMTransY] = loc.fY; 1556e8cd9671958c69babde9338c5c18a4c3d895575joshualitt fGpuDevice->internalDrawPath(*path, paint, viewMatrix, &matrix, clipBounds, false); 1566e8cd9671958c69babde9338c5c18a4c3d895575joshualitt } 1576e8cd9671958c69babde9338c5c18a4c3d895575joshualitt } 1586e8cd9671958c69babde9338c5c18a4c3d895575joshualitt pos += scalarsPerPosition; 1596e8cd9671958c69babde9338c5c18a4c3d895575joshualitt } 1606e8cd9671958c69babde9338c5c18a4c3d895575joshualitt} 1618c27a188a0b216021d439eb627622d17b9f78343jvanverth 162e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org//*** change to output positions? 16373f105345066b1f22f15ba6575cb3800dd9313b8jvanverthint GrTextContext::MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc, 164e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org const char text[], size_t byteLength, SkVector* stopVector) { 165e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org SkFixed x = 0, y = 0; 166e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org const char* stop = text + byteLength; 167e5d7015cde3b6f2a3929b8e378822e3d7be223d4skia.committer@gmail.com 168e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org SkAutoKern autokern; 169e5d7015cde3b6f2a3929b8e378822e3d7be223d4skia.committer@gmail.com 17073f105345066b1f22f15ba6575cb3800dd9313b8jvanverth int numGlyphs = 0; 171e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org while (text < stop) { 172e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org // don't need x, y here, since all subpixel variants will have the 173e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org // same advance 174e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 175e5d7015cde3b6f2a3929b8e378822e3d7be223d4skia.committer@gmail.com 176e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org x += autokern.adjust(glyph) + glyph.fAdvanceX; 177e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org y += glyph.fAdvanceY; 17873f105345066b1f22f15ba6575cb3800dd9313b8jvanverth ++numGlyphs; 179e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org } 180e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y)); 181e5d7015cde3b6f2a3929b8e378822e3d7be223d4skia.committer@gmail.com 182e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org SkASSERT(text == stop); 18373f105345066b1f22f15ba6575cb3800dd9313b8jvanverth 18473f105345066b1f22f15ba6575cb3800dd9313b8jvanverth return numGlyphs; 185e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org} 186e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org 187e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.orgstatic void GlyphCacheAuxProc(void* data) { 188e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org GrFontScaler* scaler = (GrFontScaler*)data; 189e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org SkSafeUnref(scaler); 190e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org} 191e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org 192e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.orgGrFontScaler* GrTextContext::GetGrFontScaler(SkGlyphCache* cache) { 193e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org void* auxData; 194e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org GrFontScaler* scaler = NULL; 195e5d7015cde3b6f2a3929b8e378822e3d7be223d4skia.committer@gmail.com 196e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) { 197e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org scaler = (GrFontScaler*)auxData; 198e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org } 199e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org if (NULL == scaler) { 200733f5f5dbca10fc6385ec3c77b3e9ff78227dac7jvanverth scaler = SkNEW_ARGS(GrFontScaler, (cache)); 201e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org cache->setAuxProc(GlyphCacheAuxProc, scaler); 202e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org } 203e5d7015cde3b6f2a3929b8e378822e3d7be223d4skia.committer@gmail.com 204e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org return scaler; 205e8612d9a8d616c2ed0195421a0675e10b0c2d230commit-bot@chromium.org} 206