Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrStencilAndCoverTextContext.h" | 8 #include "GrStencilAndCoverTextContext.h" |
| 9 #include "GrAtlasTextContext.h" | 9 #include "GrAtlasTextContext.h" |
| 10 #include "GrDrawContext.h" | 10 #include "GrDrawContext.h" |
| 11 #include "GrDrawTarget.h" | 11 #include "GrDrawTarget.h" |
| 12 #include "GrPath.h" | 12 #include "GrPath.h" |
| 13 #include "GrPathRange.h" | 13 #include "GrPathRange.h" |
| 14 #include "GrResourceProvider.h" | 14 #include "GrResourceProvider.h" |
| 15 #include "GrTextUtils.h" | |
| 15 #include "SkAutoKern.h" | 16 #include "SkAutoKern.h" |
| 16 #include "SkDraw.h" | 17 #include "SkDraw.h" |
| 17 #include "SkDrawProcs.h" | 18 #include "SkDrawProcs.h" |
| 18 #include "SkGlyphCache.h" | 19 #include "SkGlyphCache.h" |
| 19 #include "SkGpuDevice.h" | 20 #include "SkGpuDevice.h" |
| 20 #include "SkGrPriv.h" | 21 #include "SkGrPriv.h" |
| 21 #include "SkPath.h" | 22 #include "SkPath.h" |
| 22 #include "SkTextBlobRunIterator.h" | 23 #include "SkTextBlobRunIterator.h" |
| 23 #include "SkTextMapStateProc.h" | 24 #include "SkTextMapStateProc.h" |
| 24 #include "SkTextFormatParams.h" | 25 #include "SkTextFormatParams.h" |
| 25 | 26 |
| 26 #include "batches/GrDrawPathBatch.h" | 27 #include "batches/GrDrawPathBatch.h" |
| 27 | 28 |
| 28 template<typename Key, typename Val> static void delete_hash_map_entry(const Key &, Val* val) { | 29 template<typename Key, typename Val> static void delete_hash_map_entry(const Key &, Val* val) { |
| 29 SkASSERT(*val); | 30 SkASSERT(*val); |
| 30 delete *val; | 31 delete *val; |
| 31 } | 32 } |
| 32 | 33 |
| 33 template<typename T> static void delete_hash_table_entry(T* val) { | 34 template<typename T> static void delete_hash_table_entry(T* val) { |
| 34 SkASSERT(*val); | 35 SkASSERT(*val); |
| 35 delete *val; | 36 delete *val; |
| 36 } | 37 } |
| 37 | 38 |
| 38 GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context, | 39 GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context, |
| 39 const SkSurfaceProps& surfaceProps) | 40 const SkSurfaceProps& surfaceProps) |
| 40 : INHERITED(context, surfaceProps), | 41 : INHERITED(context, surfaceProps), |
|
robertphillips
2016/02/10 18:28:45
, fFallbackTextContext(nullptr) - just for parano
joshualitt
2016/02/10 20:06:05
Acknowledged.
| |
| 41 fCacheSize(0) { | 42 fCacheSize(0) { |
| 42 } | 43 } |
| 43 | 44 |
| 44 GrStencilAndCoverTextContext* | 45 GrStencilAndCoverTextContext* |
| 45 GrStencilAndCoverTextContext::Create(GrContext* context, const SkSurfaceProps& s urfaceProps) { | 46 GrStencilAndCoverTextContext::Create(GrContext* context, const SkSurfaceProps& s urfaceProps) { |
| 46 GrStencilAndCoverTextContext* textContext = | 47 GrStencilAndCoverTextContext* textContext = |
| 47 new GrStencilAndCoverTextContext(context, surfaceProps); | 48 new GrStencilAndCoverTextContext(context, surfaceProps); |
| 48 textContext->fFallbackTextContext = GrAtlasTextContext::Create(context, surf aceProps); | 49 textContext->fFallbackTextContext = GrAtlasTextContext::Create(context, surf aceProps); |
| 49 | 50 |
| 50 return textContext; | 51 return textContext; |
| 51 } | 52 } |
| 52 | 53 |
| 53 GrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() { | 54 GrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() { |
| 55 delete fFallbackTextContext; | |
| 54 fBlobIdCache.foreach(delete_hash_map_entry<uint32_t, TextBlob*>); | 56 fBlobIdCache.foreach(delete_hash_map_entry<uint32_t, TextBlob*>); |
| 55 fBlobKeyCache.foreach(delete_hash_table_entry<TextBlob*>); | 57 fBlobKeyCache.foreach(delete_hash_table_entry<TextBlob*>); |
| 56 } | 58 } |
| 57 | 59 |
| 58 bool GrStencilAndCoverTextContext::internalCanDraw(const SkPaint& skPaint) { | 60 bool GrStencilAndCoverTextContext::internalCanDraw(const SkPaint& skPaint) { |
| 59 if (skPaint.getRasterizer()) { | 61 if (skPaint.getRasterizer()) { |
| 60 return false; | 62 return false; |
| 61 } | 63 } |
| 62 if (skPaint.getMaskFilter()) { | 64 if (skPaint.getMaskFilter()) { |
| 63 return false; | 65 return false; |
| 64 } | 66 } |
| 65 if (SkPathEffect* pe = skPaint.getPathEffect()) { | 67 if (SkPathEffect* pe = skPaint.getPathEffect()) { |
| 66 if (pe->asADash(nullptr) != SkPathEffect::kDash_DashType) { | 68 if (pe->asADash(nullptr) != SkPathEffect::kDash_DashType) { |
| 67 return false; | 69 return false; |
| 68 } | 70 } |
| 69 } | 71 } |
| 70 // No hairlines. They would require new paths with customized strokes for ev ery new draw matrix. | 72 // No hairlines. They would require new paths with customized strokes for ev ery new draw matrix. |
| 71 return SkPaint::kStroke_Style != skPaint.getStyle() || 0 != skPaint.getStrok eWidth(); | 73 return SkPaint::kStroke_Style != skPaint.getStyle() || 0 != skPaint.getStrok eWidth(); |
| 72 } | 74 } |
| 73 | 75 |
| 74 void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc, | 76 void GrStencilAndCoverTextContext::drawText(GrDrawContext* dc, |
| 75 const GrClip& clip, | 77 const GrClip& clip, const GrPaint& p aint, |
| 76 const GrPaint& paint, | 78 const SkPaint& skPaint, const SkMatr ix& viewMatrix, |
| 77 const SkPaint& skPaint, | 79 const char text[], size_t byteLength , |
| 78 const SkMatrix& viewMatrix, | 80 SkScalar x, SkScalar y, const SkIRec t& clipBounds) { |
| 79 const char text[], | 81 if (fContext->abandoned()) { |
| 80 size_t byteLength, | 82 return; |
| 81 SkScalar x, SkScalar y, | 83 } else if (this->canDraw(skPaint, viewMatrix)) { |
| 82 const SkIRect& clipBounds) { | 84 TextRun run(skPaint); |
| 83 TextRun run(skPaint); | 85 GrPipelineBuilder pipelineBuilder(paint, dc->accessRenderTarget(), clip) ; |
| 84 GrPipelineBuilder pipelineBuilder(paint, dc->accessRenderTarget(), clip); | 86 run.setText(text, byteLength, x, y); |
| 85 run.setText(text, byteLength, x, y); | 87 run.draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0 , 0, clipBounds, |
| 86 run.draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0, clipBounds, | 88 fFallbackTextContext, skPaint); |
| 87 fFallbackTextContext, skPaint); | 89 return; |
| 90 } else if (fFallbackTextContext->canDraw(skPaint, viewMatrix)) { | |
| 91 fFallbackTextContext->drawText(dc, clip, paint, skPaint, viewMatrix, tex t, | |
| 92 byteLength, x, y, clipBounds); | |
| 93 return; | |
| 94 } | |
| 95 | |
| 96 // fall back to drawing as a path | |
| 97 GrTextUtils::DrawTextAsPath(fContext, dc, clip, skPaint, viewMatrix, text, b yteLength, x, y, | |
| 98 clipBounds); | |
| 88 } | 99 } |
| 89 | 100 |
| 90 void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, | 101 void GrStencilAndCoverTextContext::drawPosText(GrDrawContext* dc, |
| 91 const GrClip& clip, | 102 const GrClip& clip, |
| 92 const GrPaint& paint, | 103 const GrPaint& paint, |
| 93 const SkPaint& skPaint, | 104 const SkPaint& skPaint, |
| 94 const SkMatrix& viewMatrix, | 105 const SkMatrix& viewMatrix, |
| 95 const char text[], | 106 const char text[], |
| 96 size_t byteLength, | 107 size_t byteLength, |
| 97 const SkScalar pos[], | 108 const SkScalar pos[], |
| 98 int scalarsPerPosition, | 109 int scalarsPerPosition, |
| 99 const SkPoint& offset, | 110 const SkPoint& offset, |
| 100 const SkIRect& clipBounds) { | 111 const SkIRect& clipBounds) { |
| 101 TextRun run(skPaint); | 112 if (fContext->abandoned()) { |
| 102 GrPipelineBuilder pipelineBuilder(paint, dc->accessRenderTarget(), clip); | 113 return; |
| 103 run.setPosText(text, byteLength, pos, scalarsPerPosition, offset); | 114 } else if (this->canDraw(skPaint, viewMatrix)) { |
| 104 run.draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0, clipBounds, | 115 TextRun run(skPaint); |
| 105 fFallbackTextContext, skPaint); | 116 GrPipelineBuilder pipelineBuilder(paint, dc->accessRenderTarget(), clip) ; |
| 117 run.setPosText(text, byteLength, pos, scalarsPerPosition, offset); | |
| 118 run.draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0 , 0, clipBounds, | |
| 119 fFallbackTextContext, skPaint); | |
| 120 return; | |
| 121 } else if (fFallbackTextContext->canDraw(skPaint, viewMatrix)) { | |
| 122 fFallbackTextContext->drawPosText(dc, clip, paint, skPaint, viewMatrix, | |
| 123 text, byteLength, pos, | |
| 124 scalarsPerPosition, offset, clipBounds ); | |
| 125 return; | |
| 126 } | |
| 127 | |
| 128 // fall back to drawing as a path | |
| 129 GrTextUtils::DrawPosTextAsPath(fContext, dc, fSurfaceProps, clip, skPaint, v iewMatrix, text, | |
| 130 byteLength, pos, scalarsPerPosition, offset, clipBounds); | |
| 106 } | 131 } |
| 107 | 132 |
| 108 void GrStencilAndCoverTextContext::drawTextBlob(GrDrawContext* dc, | 133 void GrStencilAndCoverTextContext::drawTextBlob(GrDrawContext* dc, |
| 109 const GrClip& clip, const SkPain t& skPaint, | 134 const GrClip& clip, const SkPain t& skPaint, |
| 110 const SkMatrix& viewMatrix, | 135 const SkMatrix& viewMatrix, |
| 111 const SkTextBlob* skBlob, SkScal ar x, SkScalar y, | 136 const SkTextBlob* skBlob, SkScal ar x, SkScalar y, |
| 112 SkDrawFilter* drawFilter, | 137 SkDrawFilter* drawFilter, |
| 113 const SkIRect& clipBounds) { | 138 const SkIRect& clipBounds) { |
| 139 if (fContext->abandoned()) { | |
| 140 return; | |
| 141 } | |
| 142 | |
| 114 if (!this->internalCanDraw(skPaint)) { | 143 if (!this->internalCanDraw(skPaint)) { |
| 115 fFallbackTextContext->drawTextBlob(dc, clip, skPaint, viewMatrix, skBlob , x, y, | 144 fFallbackTextContext->drawTextBlob(dc, clip, skPaint, viewMatrix, skBlob , x, y, |
| 116 drawFilter, clipBounds); | 145 drawFilter, clipBounds); |
| 117 return; | 146 return; |
| 118 } | 147 } |
| 119 | 148 |
| 120 if (drawFilter || skPaint.getPathEffect()) { | 149 if (drawFilter || skPaint.getPathEffect()) { |
| 121 // This draw can't be cached. | 150 // This draw can't be cached. |
|
robertphillips
2016/02/10 18:28:45
This doesn't seem quite right ...
joshualitt
2016/02/10 20:06:05
Acknowledged.
| |
| 122 INHERITED::drawTextBlob(dc, clip, skPaint, viewMatrix, skBlob, x, y, dra wFilter, | 151 fFallbackTextContext->drawTextBlob(dc, clip, skPaint, viewMatrix, skBlob , x, y, drawFilter, |
| 123 clipBounds); | 152 clipBounds); |
| 124 return; | 153 return; |
| 125 } | 154 } |
| 126 | 155 |
| 127 if (fContext->abandoned()) { | |
| 128 return; | |
| 129 } | |
| 130 | |
| 131 GrPaint paint; | 156 GrPaint paint; |
| 132 if (!SkPaintToGrPaint(fContext, skPaint, viewMatrix, &paint)) { | 157 if (!SkPaintToGrPaint(fContext, skPaint, viewMatrix, &paint)) { |
| 133 return; | 158 return; |
| 134 } | 159 } |
| 135 | 160 |
| 136 const TextBlob& blob = this->findOrCreateTextBlob(skBlob, skPaint); | 161 const TextBlob& blob = this->findOrCreateTextBlob(skBlob, skPaint); |
| 137 GrPipelineBuilder pipelineBuilder(paint, dc->accessRenderTarget(), clip); | 162 GrPipelineBuilder pipelineBuilder(paint, dc->accessRenderTarget(), clip); |
| 138 | 163 |
| 139 TextBlob::Iter iter(blob); | 164 TextBlob::Iter iter(blob); |
| 140 for (TextRun* run = iter.get(); run; run = iter.next()) { | 165 for (TextRun* run = iter.get(); run; run = iter.next()) { |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 607 } | 632 } |
| 608 | 633 |
| 609 const SkTextBlob* GrStencilAndCoverTextContext::FallbackBlobBuilder::buildIfNeed ed(int *count) { | 634 const SkTextBlob* GrStencilAndCoverTextContext::FallbackBlobBuilder::buildIfNeed ed(int *count) { |
| 610 *count = fCount; | 635 *count = fCount; |
| 611 if (fCount) { | 636 if (fCount) { |
| 612 this->flush(); | 637 this->flush(); |
| 613 return fBuilder->build(); | 638 return fBuilder->build(); |
| 614 } | 639 } |
| 615 return nullptr; | 640 return nullptr; |
| 616 } | 641 } |
| OLD | NEW |