1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2014 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrStencilAndCoverTextContext.h" 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrAtlasTextContext.h" 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrContext.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrPath.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrPathRange.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrRenderTargetContext.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrResourceProvider.h" 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrTextUtils.h" 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkAutoKern.h" 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkDraw.h" 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkDrawFilter.h" 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkDrawProcs.h" 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkGlyphCache.h" 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkGr.h" 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPath.h" 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPointPriv.h" 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTextBlobRunIterator.h" 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTextFormatParams.h" 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTextMapStateProc.h" 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "ops/GrDrawPathOp.h" 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate<typename Key, typename Val> static void delete_hash_map_entry(const Key&, Val* val) { 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(*val); 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot delete *val; 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate<typename T> static void delete_hash_table_entry(T* val) { 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(*val); 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot delete *val; 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrAtlasTextContext* fallbackTextContext) 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : fFallbackTextContext(fallbackTextContext) 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fCacheSize(0) { 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrStencilAndCoverTextContext* 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrStencilAndCoverTextContext::Create(GrAtlasTextContext* fallbackTextContext) { 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return new GrStencilAndCoverTextContext(fallbackTextContext);; 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() { 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBlobIdCache.foreach(delete_hash_map_entry<uint32_t, TextBlob*>); 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBlobKeyCache.foreach(delete_hash_table_entry<TextBlob*>); 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool GrStencilAndCoverTextContext::internalCanDraw(const SkPaint& skPaint) { 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (skPaint.getMaskFilter()) { 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkPathEffect* pe = skPaint.getPathEffect()) { 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (pe->asADash(nullptr) != SkPathEffect::kDash_DashType) { 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // No hairlines. They would require new paths with customized strokes for every new draw matrix. 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkPaint::kStroke_Style != skPaint.getStyle() || 0 != skPaint.getStrokeWidth(); 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrStencilAndCoverTextContext::drawText(GrContext* context, GrRenderTargetContext* rtc, 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrClip& clip, const SkPaint& skPaint, 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix& viewMatrix, const SkSurfaceProps& props, 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char text[], size_t byteLength, SkScalar x, 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar y, const SkIRect& clipBounds) { 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (context->abandoned()) { 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (this->canDraw(skPaint, viewMatrix)) { 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (skPaint.getTextSize() > 0) { 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot TextRun run(skPaint); 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot run.setText(text, byteLength, x, y); 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot run.draw(context, rtc, clip, viewMatrix, props, 0, 0, clipBounds, fFallbackTextContext, 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot skPaint); 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFallbackTextContext->drawText(context, rtc->textTarget(), clip, skPaint, viewMatrix, props, 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot text, byteLength, x, y, clipBounds); 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrStencilAndCoverTextContext::drawPosText(GrContext* context, GrRenderTargetContext* rtc, 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrClip& clip, const SkPaint& skPaint, 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix& viewMatrix, 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkSurfaceProps& props, const char text[], 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t byteLength, const SkScalar pos[], 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int scalarsPerPosition, const SkPoint& offset, 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkIRect& clipBounds) { 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (context->abandoned()) { 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (this->canDraw(skPaint, viewMatrix)) { 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (skPaint.getTextSize() > 0) { 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot TextRun run(skPaint); 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot run.setPosText(text, byteLength, pos, scalarsPerPosition, offset); 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot run.draw(context, rtc, clip, viewMatrix, props, 0, 0, clipBounds, fFallbackTextContext, 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot skPaint); 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFallbackTextContext->drawPosText(context, rtc->textTarget(), clip, skPaint, viewMatrix, props, 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot text, byteLength, pos, scalarsPerPosition, offset, 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot clipBounds); 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrStencilAndCoverTextContext::uncachedDrawTextBlob(GrContext* context, 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrRenderTargetContext* rtc, 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrClip& clip, 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPaint& skPaint, 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix& viewMatrix, 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkSurfaceProps& props, 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkTextBlob* blob, 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar x, SkScalar y, 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDrawFilter* drawFilter, 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkIRect& clipBounds) { 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrTextUtils::Paint paint(&skPaint, &rtc->colorSpaceInfo()); 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrTextUtils::RunPaint runPaint(&paint, drawFilter, props); 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTextBlobRunIterator it(blob); 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (;!it.done(); it.next()) { 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!runPaint.modifyForRun(it)) { 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t textLen = it.glyphCount() * sizeof(uint16_t); 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint& offset = it.offset(); 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (it.positioning()) { 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkTextBlob::kDefault_Positioning: 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawText(context, rtc, clip, runPaint, viewMatrix, props, 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (const char*)it.glyphs(), textLen, x + offset.x(), y + offset.y(), 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot clipBounds); 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkTextBlob::kHorizontal_Positioning: 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawPosText(context, rtc, clip, runPaint, viewMatrix, props, 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (const char*)it.glyphs(), textLen, it.pos(), 1, 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint::Make(x, y + offset.y()), clipBounds); 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkTextBlob::kFull_Positioning: 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawPosText(context, rtc, clip, runPaint, viewMatrix, props, 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (const char*)it.glyphs(), textLen, it.pos(), 2, 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint::Make(x, y), clipBounds); 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrStencilAndCoverTextContext::drawTextBlob(GrContext* context, GrRenderTargetContext* rtc, 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrClip& clip, const SkPaint& skPaint, 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix& viewMatrix, 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkSurfaceProps& props, 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkTextBlob* skBlob, SkScalar x, SkScalar y, 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDrawFilter* drawFilter, 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkIRect& clipBounds) { 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (context->abandoned()) { 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!this->internalCanDraw(skPaint)) { 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFallbackTextContext->drawTextBlob(context, rtc->textTarget(), clip, skPaint, viewMatrix, 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot props, skBlob, x, y, drawFilter, clipBounds); 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (drawFilter || skPaint.getPathEffect()) { 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This draw can't be cached. 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->uncachedDrawTextBlob(context, rtc, clip, skPaint, viewMatrix, props, skBlob, x, y, 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot drawFilter, clipBounds); 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const TextBlob& blob = this->findOrCreateTextBlob(skBlob, skPaint); 176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot TextBlob::Iter iter(blob); 178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (TextRun *run = iter.get(), *nextRun; run; run = nextRun) { 179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot nextRun = iter.next(); 180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot run->draw(context, rtc, clip, viewMatrix, props, x, y, clipBounds, fFallbackTextContext, 181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot skPaint); 182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot run->releaseGlyphCache(); 183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic inline int style_key_cnt(const GrStyle& style) { 187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int cnt = GrStyle::KeySize(style, GrStyle::Apply::kPathEffectAndStrokeRec); 188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We should be able to make a key because we filtered out arbitrary path effects. 189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(cnt > 0); 190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return cnt; 191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic inline void write_style_key(uint32_t* dst, const GrStyle& style) { 194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Pass 1 for the scale since the GPU will apply the style not GrStyle::applyToPath(). 195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrStyle::WriteKey(dst, style, GrStyle::Apply::kPathEffectAndStrokeRec, SK_Scalar1); 196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst GrStencilAndCoverTextContext::TextBlob& 199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrStencilAndCoverTextContext::findOrCreateTextBlob(const SkTextBlob* skBlob, 200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPaint& skPaint) { 201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The font-related parameters are baked into the text blob and will override this skPaint, so 202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // the only remaining properties that can affect a TextBlob are the ones related to stroke. 203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkPaint::kFill_Style == skPaint.getStyle()) { // Fast path. 204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (TextBlob** found = fBlobIdCache.find(skBlob->uniqueID())) { 205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUList.remove(*found); 206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUList.addToTail(*found); 207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return **found; 208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot TextBlob* blob = new TextBlob(skBlob->uniqueID(), skBlob, skPaint); 210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->purgeToFit(*blob); 211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBlobIdCache.set(skBlob->uniqueID(), blob); 212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUList.addToTail(blob); 213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCacheSize += blob->cpuMemorySize(); 214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return *blob; 215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrStyle style(skPaint); 217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkSTArray<4, uint32_t, true> key; 218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot key.reset(1 + style_key_cnt(style)); 219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot key[0] = skBlob->uniqueID(); 220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot write_style_key(&key[1], style); 221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (TextBlob** found = fBlobKeyCache.find(key)) { 222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUList.remove(*found); 223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUList.addToTail(*found); 224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return **found; 225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot TextBlob* blob = new TextBlob(key, skBlob, skPaint); 227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->purgeToFit(*blob); 228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBlobKeyCache.set(blob); 229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUList.addToTail(blob); 230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCacheSize += blob->cpuMemorySize(); 231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return *blob; 232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrStencilAndCoverTextContext::purgeToFit(const TextBlob& blob) { 236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static const size_t maxCacheSize = 4 * 1024 * 1024; // Allow up to 4 MB for caching text blobs. 237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t maxSizeForNewBlob = maxCacheSize - blob.cpuMemorySize(); 239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (fCacheSize && fCacheSize > maxSizeForNewBlob) { 240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot TextBlob* lru = fLRUList.head(); 241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (1 == lru->key().count()) { 242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // 1-length keys are unterstood to be the blob id. 243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBlobIdCache.remove(lru->key()[0]); 244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBlobKeyCache.remove(lru->key()); 246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLRUList.remove(lru); 248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCacheSize -= lru->cpuMemorySize(); 249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot delete lru; 250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//////////////////////////////////////////////////////////////////////////////////////////////////// 254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrStencilAndCoverTextContext::TextBlob::init(const SkTextBlob* skBlob, 256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPaint& skPaint) { 257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCpuMemorySize = sizeof(TextBlob); 258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint runPaint(skPaint); 259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (SkTextBlobRunIterator iter(skBlob); !iter.done(); iter.next()) { 260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot iter.applyFontToPaint(&runPaint); // No need to re-seed the paint. 261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (runPaint.getTextSize() <= 0) { 262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot TextRun* run = this->addToTail(runPaint); 265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* text = reinterpret_cast<const char*>(iter.glyphs()); 267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t byteLength = sizeof(uint16_t) * iter.glyphCount(); 268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint& runOffset = iter.offset(); 269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (iter.positioning()) { 271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkTextBlob::kDefault_Positioning: 272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot run->setText(text, byteLength, runOffset.fX, runOffset.fY); 273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkTextBlob::kHorizontal_Positioning: 275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot run->setPosText(text, byteLength, iter.pos(), 1, SkPoint::Make(0, runOffset.fY)); 276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkTextBlob::kFull_Positioning: 278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot run->setPosText(text, byteLength, iter.pos(), 2, SkPoint::Make(0, 0)); 279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCpuMemorySize += run->computeSizeInCache(); 283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//////////////////////////////////////////////////////////////////////////////////////////////////// 287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrStencilAndCoverTextContext::FallbackBlobBuilder { 289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FallbackBlobBuilder() : fBuffIdx(0), fCount(0) {} 291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool isInitialized() const { return fBuilder != nullptr; } 293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void init(const SkPaint& font, SkScalar textRatio); 295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void appendGlyph(uint16_t glyphId, const SkPoint& pos); 297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkTextBlob> makeIfNeeded(int* count); 299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot enum { kWriteBufferSize = 1024 }; 302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void flush(); 304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkTextBlobBuilder> fBuilder; 306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint fFont; 307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fBuffIdx; 308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fCount; 309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint16_t fGlyphIds[kWriteBufferSize]; 310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint fPositions[kWriteBufferSize]; 311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//////////////////////////////////////////////////////////////////////////////////////////////////// 314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke) 316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : fStyle(fontAndStroke) 317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fFont(fontAndStroke) 318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fTotalGlyphCount(0) 319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fFallbackGlyphCount(0) 320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fDetachedGlyphCache(nullptr) 321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fLastDrawnGlyphsID(SK_InvalidUniqueID) { 322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fFont.getTextSize() > 0); 323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!fStyle.hasNonDashPathEffect()); // Arbitrary path effects not supported. 324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!fStyle.isSimpleHairline()); // Hairlines are not supported. 325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Setting to "fill" ensures that no strokes get baked into font outlines. (We use the GPU path 327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // rendering API for stroking). 328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFont.setStyle(SkPaint::kFill_Style); 329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fFont.isFakeBoldText() && fStyle.isSimpleFill()) { 331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkStrokeRec& stroke = fStyle.strokeRec(); 332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Instead of letting fake bold get baked into the glyph outlines, do it with GPU stroke. 333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar fakeBoldScale = SkScalarInterpFunc(fFont.getTextSize(), 334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kStdFakeBoldInterpKeys, 335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kStdFakeBoldInterpValues, 336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kStdFakeBoldInterpLength); 337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar extra = fFont.getTextSize() * fakeBoldScale; 338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkStrokeRec strokeRec(SkStrokeRec::kFill_InitStyle); 340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot strokeRec.setStrokeStyle(stroke.needToApply() ? stroke.getWidth() + extra : extra, 341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot true /*strokeAndFill*/); 342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fStyle = GrStyle(strokeRec, fStyle.refPathEffect()); 343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFont.setFakeBoldText(false); 344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fFont.getPathEffect() && !fStyle.isDashed()) { 347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkStrokeRec& stroke = fStyle.strokeRec(); 348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We can draw the glyphs from canonically sized paths. 349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTextRatio = fFont.getTextSize() / SkPaint::kCanonicalTextSizeForPaths; 350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fFont.getTextSize(); 351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Compensate for the glyphs being scaled by fTextRatio. 353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fStyle.isSimpleFill()) { 354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkStrokeRec strokeRec(SkStrokeRec::kFill_InitStyle); 355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot strokeRec.setStrokeStyle(stroke.getWidth() / fTextRatio, 356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()); 357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fStyle = GrStyle(strokeRec, fStyle.refPathEffect()); 358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFont.setLinearText(true); 361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFont.setLCDRenderText(false); 362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFont.setAutohinted(false); 363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFont.setHinting(SkPaint::kNo_Hinting); 364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFont.setSubpixelText(true); 365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFont.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths)); 366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fUsingRawGlyphPaths = SK_Scalar1 == fFont.getTextScaleX() && 368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 0 == fFont.getTextSkewX() && 369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot !fFont.isFakeBoldText() && 370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot !fFont.isVerticalText(); 371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTextRatio = fTextInverseRatio = 1.0f; 373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fUsingRawGlyphPaths = false; 374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Generate the key that will be used to cache the GPU glyph path objects. 377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fUsingRawGlyphPaths && fStyle.isSimpleFill()) { 378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static const GrUniqueKey::Domain kRawFillPathGlyphDomain = GrUniqueKey::GenerateDomain(); 379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkTypeface* typeface = fFont.getTypeface(); 381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrUniqueKey::Builder builder(&fGlyphPathsKey, kRawFillPathGlyphDomain, 1); 382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID() : 0; 383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static const GrUniqueKey::Domain kPathGlyphDomain = GrUniqueKey::GenerateDomain(); 385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int styleDataCount = GrStyle::KeySize(fStyle, GrStyle::Apply::kPathEffectAndStrokeRec); 387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Key should be valid since we opted out of drawing arbitrary path effects. 388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(styleDataCount >= 0); 389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fUsingRawGlyphPaths) { 390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkTypeface* typeface = fFont.getTypeface(); 391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain, 2 + styleDataCount); 392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID() : 0; 393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot reinterpret_cast<uint32_t&>(builder[1]) = styleDataCount; 394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (styleDataCount) { 395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot write_style_key(&builder[2], fStyle); 396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkGlyphCache* glyphCache = this->getGlyphCache(); 399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkTypeface* typeface = glyphCache->getScalerContext()->getTypeface(); 400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkDescriptor* desc = &glyphCache->getDescriptor(); 401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int descDataCount = (desc->getLength() + 3) / 4; 402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain, 403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 2 + styleDataCount + descDataCount); 404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID() : 0; 405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot reinterpret_cast<uint32_t&>(builder[1]) = styleDataCount | (descDataCount << 16); 406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (styleDataCount) { 407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot write_style_key(&builder[2], fStyle); 408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memcpy(&builder[2 + styleDataCount], desc, desc->getLength()); 410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrStencilAndCoverTextContext::TextRun::~TextRun() { 415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->releaseGlyphCache(); 416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t byteLength, 419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar x, SkScalar y) { 420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(byteLength == 0 || text != nullptr); 421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkGlyphCache* glyphCache = this->getGlyphCache(); 423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(fFont.getTextEncoding(), 424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFont.isDevKernText(), 425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot true); 426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTotalGlyphCount = fFont.countText(text, byteLength); 428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTransformType, 429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTotalGlyphCount)); 430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* stop = text + byteLength; 432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Measure first if needed. 434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fFont.getTextAlign() != SkPaint::kLeft_Align) { 435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar stopX = 0; 436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar stopY = 0; 437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* textPtr = text; 439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (textPtr < stop) { 440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We don't need x, y here, since all subpixel variants will have the 441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // same advance. 442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkGlyph& glyph = glyphCacheProc(glyphCache, &textPtr); 443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot stopX += SkFloatToScalar(glyph.fAdvanceX); 445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot stopY += SkFloatToScalar(glyph.fAdvanceY); 446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(textPtr == stop); 448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar alignX = stopX * fTextRatio; 450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar alignY = stopY * fTextRatio; 451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fFont.getTextAlign() == SkPaint::kCenter_Align) { 453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot alignX = SkScalarHalf(alignX); 454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot alignY = SkScalarHalf(alignY); 455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot x -= alignX; 458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot y -= alignY; 459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoKern autokern; 462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FallbackBlobBuilder fallback; 464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (text < stop) { 465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkGlyph& glyph = glyphCacheProc(glyphCache, &text); 466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot x += autokern.adjust(glyph) * fTextRatio; 467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (glyph.fWidth) { 468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->appendGlyph(glyph, SkPoint::Make(x, y), &fallback); 469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot x += SkFloatToScalar(glyph.fAdvanceX) * fTextRatio; 472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot y += SkFloatToScalar(glyph.fAdvanceY) * fTextRatio; 473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFallbackTextBlob = fallback.makeIfNeeded(&fFallbackGlyphCount); 476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t byteLength, 479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar pos[], int scalarsPerPosition, 480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint& offset) { 481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(byteLength == 0 || text != nullptr); 482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkGlyphCache* glyphCache = this->getGlyphCache(); 485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(fFont.getTextEncoding(), 486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFont.isDevKernText(), 487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot true); 488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTotalGlyphCount = fFont.countText(text, byteLength); 490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTransformType, 491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTotalGlyphCount)); 492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* stop = text + byteLength; 494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); 496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTextAlignProc alignProc(fFont.getTextAlign()); 497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FallbackBlobBuilder fallback; 498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (text < stop) { 499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkGlyph& glyph = glyphCacheProc(glyphCache, &text); 500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (glyph.fWidth) { 501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint tmsLoc; 502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot tmsProc(pos, &tmsLoc); 503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint loc; 504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot alignProc(tmsLoc, glyph, &loc); 505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->appendGlyph(glyph, loc, &fallback); 507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pos += scalarsPerPosition; 509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFallbackTextBlob = fallback.makeIfNeeded(&fFallbackGlyphCount); 512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<GrPathRange> GrStencilAndCoverTextContext::TextRun::createGlyphs( 515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrResourceProvider* resourceProvider) const { 516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<GrPathRange> glyphs = 517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot resourceProvider->findByUniqueKey<GrPathRange>(fGlyphPathsKey); 518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!glyphs) { 519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fUsingRawGlyphPaths) { 520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalerContextEffects noeffects; 521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyphs = resourceProvider->createGlyphs(fFont.getTypeface(), noeffects, 522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot nullptr, fStyle); 523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkGlyphCache* cache = this->getGlyphCache(); 525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyphs = resourceProvider->createGlyphs(cache->getScalerContext()->getTypeface(), 526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot cache->getScalerContext()->getEffects(), 527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot &cache->getDescriptor(), 528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fStyle); 529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot resourceProvider->assignUniqueKeyToResource(fGlyphPathsKey, glyphs.get()); 531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return glyphs; 533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotinline void GrStencilAndCoverTextContext::TextRun::appendGlyph(const SkGlyph& glyph, 536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint& pos, 537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FallbackBlobBuilder* fallback) { 538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Stick the glyphs we can't draw into the fallback text blob. 539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkMask::kARGB32_Format == glyph.fMaskFormat) { 540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fallback->isInitialized()) { 541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fallback->init(fFont, fTextRatio); 542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fallback->appendGlyph(glyph.getGlyphID(), pos); 544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fInstanceData->append(glyph.getGlyphID(), fTextInverseRatio * pos.x(), 546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTextInverseRatio * pos.y()); 547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx, 551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrRenderTargetContext* renderTargetContext, 552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrClip& clip, const SkMatrix& viewMatrix, 553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkSurfaceProps& props, SkScalar x, 554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar y, const SkIRect& clipBounds, 555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrAtlasTextContext* fallbackTextContext, 556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPaint& originalSkPaint) const { 557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fInstanceData); 558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fInstanceData->count()) { 560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<GrPathRange> glyphs(this->createGlyphs(ctx->contextPriv().resourceProvider())); 561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fLastDrawnGlyphsID != glyphs->uniqueID()) { 562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Either this is the first draw or the glyphs object was purged since last draw. 563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyphs->loadPathsIfNeeded(fInstanceData->indices(), fInstanceData->count()); 564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLastDrawnGlyphsID = glyphs->uniqueID(); 565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrPaint grPaint; 568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!SkPaintToGrPaint(ctx, renderTargetContext->colorSpaceInfo(), originalSkPaint, 569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot viewMatrix, &grPaint)) { 570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Don't compute a bounding box. For dst copy texture, we'll opt instead for it to just copy 574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // the entire dst. Realistically this is a moot point, because any context that supports 575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // NV_path_rendering will also support NV_blend_equation_advanced. 576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // For clipping we'll just skip any optimizations based on the bounds. This does, however, 577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // hurt GrOp combining. 578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRect bounds = SkRect::MakeIWH(renderTargetContext->width(), 579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot renderTargetContext->height()); 580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The run's "font" overrides the anti-aliasing of the passed in SkPaint! 582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrAAType aaType = GrChooseAAType(this->aa(), renderTargetContext->fsaaType(), 583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrAllowMixedSamples::kYes, *renderTargetContext->caps()); 584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<GrDrawOp> op = GrDrawPathRangeOp::Make( 586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot viewMatrix, fTextRatio, fTextInverseRatio * x, fTextInverseRatio * y, 587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::move(grPaint), GrPathRendering::kWinding_FillType, aaType, glyphs.get(), 588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fInstanceData.get(), bounds); 589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot renderTargetContext->addDrawOp(clip, std::move(op)); 591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fFallbackTextBlob) { 594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint fallbackSkPaint(originalSkPaint); 595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fStyle.strokeRec().applyToPaint(&fallbackSkPaint); 596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fStyle.isSimpleFill()) { 597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fallbackSkPaint.setStrokeWidth(fStyle.strokeRec().getWidth() * fTextRatio); 598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fallbackTextContext->drawTextBlob(ctx, renderTargetContext->textTarget(), clip, 601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fallbackSkPaint, viewMatrix, props, 602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFallbackTextBlob.get(), x, y, nullptr, clipBounds); 603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkGlyphCache* GrStencilAndCoverTextContext::TextRun::getGlyphCache() const { 607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fDetachedGlyphCache) { 608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDetachedGlyphCache = SkGlyphCache::DetachCacheUsingPaint(fFont, nullptr, 609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalerContextFlags::kNone, 610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot nullptr); 611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fDetachedGlyphCache; 613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrStencilAndCoverTextContext::TextRun::releaseGlyphCache() const { 617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fDetachedGlyphCache) { 618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkGlyphCache::AttachCache(fDetachedGlyphCache); 619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDetachedGlyphCache = nullptr; 620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsize_t GrStencilAndCoverTextContext::TextRun::computeSizeInCache() const { 624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t size = sizeof(TextRun) + fGlyphPathsKey.size(); 625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The instance data always reserves enough space for every glyph. 626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size += (fTotalGlyphCount + fFallbackGlyphCount) * (sizeof(uint16_t) + 2 * sizeof(float)); 627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fInstanceData) { 628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size += sizeof(InstanceData); 629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fFallbackTextBlob) { 631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size += sizeof(SkTextBlob); 632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return size; 634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//////////////////////////////////////////////////////////////////////////////////////////////////// 637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrStencilAndCoverTextContext::FallbackBlobBuilder::init(const SkPaint& font, 639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar textRatio) { 640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!this->isInitialized()); 641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBuilder.reset(new SkTextBlobBuilder); 642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFont = font; 643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFont.setTextAlign(SkPaint::kLeft_Align); // The glyph positions will already account for align. 644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFont.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // No need for subpixel positioning with bitmap glyphs. TODO: revisit if non-bitmap color glyphs 646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // show up and https://code.google.com/p/skia/issues/detail?id=4408 gets resolved. 647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFont.setSubpixelText(false); 648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFont.setTextSize(fFont.getTextSize() * textRatio); 649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBuffIdx = 0; 650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrStencilAndCoverTextContext::FallbackBlobBuilder::appendGlyph(uint16_t glyphId, 653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint& pos) { 654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this->isInitialized()); 655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fBuffIdx >= kWriteBufferSize) { 656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->flush(); 657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fGlyphIds[fBuffIdx] = glyphId; 659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPositions[fBuffIdx] = pos; 660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBuffIdx++; 661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCount++; 662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrStencilAndCoverTextContext::FallbackBlobBuilder::flush() { 665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(this->isInitialized()); 666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fBuffIdx <= kWriteBufferSize); 667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fBuffIdx) { 668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 670fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This will automatically merge with previous runs since we use the same font. 671fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkTextBlobBuilder::RunBuffer& buff = fBuilder->allocRunPos(fFont, fBuffIdx); 672fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memcpy(buff.glyphs, fGlyphIds, fBuffIdx * sizeof(uint16_t)); 673fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memcpy(buff.pos, SkPointPriv::AsScalars(fPositions[0]), fBuffIdx * 2 * sizeof(SkScalar)); 674fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBuffIdx = 0; 675fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 676fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 677fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkTextBlob> GrStencilAndCoverTextContext::FallbackBlobBuilder::makeIfNeeded(int *count) { 678fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *count = fCount; 679fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fCount) { 680fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->flush(); 681fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fBuilder->make(); 682fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 683fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 684fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 685