| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2010 Google Inc. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license that can be | |
| 5 * found in the LICENSE file. | |
| 6 */ | |
| 7 | |
| 8 #include "GrTextContext.h" | |
| 9 #include "GrContext.h" | |
| 10 #include "GrFontScaler.h" | |
| 11 #include "GrTextUtils.h" | |
| 12 | |
| 13 #include "SkDrawFilter.h" | |
| 14 #include "SkGlyphCache.h" | |
| 15 #include "SkGrPriv.h" | |
| 16 #include "SkTextBlobRunIterator.h" | |
| 17 | |
| 18 GrTextContext::GrTextContext(GrContext* context, const SkSurfaceProps& surfacePr
ops) | |
| 19 : fFallbackTextContext(nullptr) | |
| 20 , fContext(context) | |
| 21 , fSurfaceProps(surfaceProps) { | |
| 22 } | |
| 23 | |
| 24 GrTextContext::~GrTextContext() { | |
| 25 delete fFallbackTextContext; | |
| 26 } | |
| 27 | |
| 28 void GrTextContext::drawText(GrDrawContext* dc, | |
| 29 const GrClip& clip, const GrPaint& paint, | |
| 30 const SkPaint& skPaint, const SkMatrix& viewMatrix, | |
| 31 const char text[], size_t byteLength, | |
| 32 SkScalar x, SkScalar y, const SkIRect& clipBounds)
{ | |
| 33 if (fContext->abandoned()) { | |
| 34 return; | |
| 35 } | |
| 36 | |
| 37 GrTextContext* textContext = this; | |
| 38 do { | |
| 39 if (textContext->canDraw(skPaint, viewMatrix)) { | |
| 40 textContext->onDrawText(dc, clip, paint, skPaint, viewMatrix, | |
| 41 text, byteLength, x, y, clipBounds); | |
| 42 return; | |
| 43 } | |
| 44 textContext = textContext->fFallbackTextContext; | |
| 45 } while (textContext); | |
| 46 | |
| 47 // fall back to drawing as a path | |
| 48 GrTextUtils::DrawTextAsPath(fContext, dc, clip, skPaint, viewMatrix, text, b
yteLength, x, y, | |
| 49 clipBounds); | |
| 50 } | |
| 51 | |
| 52 void GrTextContext::drawPosText(GrDrawContext* dc, | |
| 53 const GrClip& clip, const GrPaint& paint, | |
| 54 const SkPaint& skPaint, const SkMatrix& viewMatr
ix, | |
| 55 const char text[], size_t byteLength, | |
| 56 const SkScalar pos[], int scalarsPerPosition, | |
| 57 const SkPoint& offset, const SkIRect& clipBounds
) { | |
| 58 if (fContext->abandoned()) { | |
| 59 return; | |
| 60 } | |
| 61 | |
| 62 GrTextContext* textContext = this; | |
| 63 do { | |
| 64 if (textContext->canDraw(skPaint, viewMatrix)) { | |
| 65 textContext->onDrawPosText(dc, clip, paint, skPaint, viewMatrix, | |
| 66 text, byteLength, pos, | |
| 67 scalarsPerPosition, offset, clipBounds); | |
| 68 return; | |
| 69 } | |
| 70 textContext = textContext->fFallbackTextContext; | |
| 71 } while (textContext); | |
| 72 | |
| 73 // fall back to drawing as a path | |
| 74 GrTextUtils::DrawPosTextAsPath(fContext, dc, fSurfaceProps, clip, skPaint, v
iewMatrix, text, | |
| 75 byteLength, pos, scalarsPerPosition, offset,
clipBounds); | |
| 76 } | |
| 77 | |
| 78 bool GrTextContext::ShouldDisableLCD(const SkPaint& paint) { | |
| 79 if (!SkXfermode::AsMode(paint.getXfermode(), nullptr) || | |
| 80 paint.getMaskFilter() || | |
| 81 paint.getRasterizer() || | |
| 82 paint.getPathEffect() || | |
| 83 paint.isFakeBoldText() || | |
| 84 paint.getStyle() != SkPaint::kFill_Style) | |
| 85 { | |
| 86 return true; | |
| 87 } | |
| 88 return false; | |
| 89 } | |
| 90 | |
| 91 uint32_t GrTextContext::FilterTextFlags(const SkSurfaceProps& surfaceProps, cons
t SkPaint& paint) { | |
| 92 uint32_t flags = paint.getFlags(); | |
| 93 | |
| 94 if (!paint.isLCDRenderText() || !paint.isAntiAlias()) { | |
| 95 return flags; | |
| 96 } | |
| 97 | |
| 98 if (kUnknown_SkPixelGeometry == surfaceProps.pixelGeometry() || ShouldDisabl
eLCD(paint)) { | |
| 99 flags &= ~SkPaint::kLCDRenderText_Flag; | |
| 100 flags |= SkPaint::kGenA8FromLCD_Flag; | |
| 101 } | |
| 102 | |
| 103 return flags; | |
| 104 } | |
| 105 | |
| 106 void GrTextContext::drawTextBlob(GrDrawContext* dc, | |
| 107 const GrClip& clip, const SkPaint& skPaint, | |
| 108 const SkMatrix& viewMatrix, const SkTextBlob* b
lob, | |
| 109 SkScalar x, SkScalar y, | |
| 110 SkDrawFilter* drawFilter, const SkIRect& clipBo
unds) { | |
| 111 SkPaint runPaint = skPaint; | |
| 112 | |
| 113 SkTextBlobRunIterator it(blob); | |
| 114 for (;!it.done(); it.next()) { | |
| 115 size_t textLen = it.glyphCount() * sizeof(uint16_t); | |
| 116 const SkPoint& offset = it.offset(); | |
| 117 // applyFontToPaint() always overwrites the exact same attributes, | |
| 118 // so it is safe to not re-seed the paint for this reason. | |
| 119 it.applyFontToPaint(&runPaint); | |
| 120 | |
| 121 if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Typ
e)) { | |
| 122 // A false return from filter() means we should abort the current dr
aw. | |
| 123 runPaint = skPaint; | |
| 124 continue; | |
| 125 } | |
| 126 | |
| 127 runPaint.setFlags(FilterTextFlags(fSurfaceProps, runPaint)); | |
| 128 | |
| 129 GrPaint grPaint; | |
| 130 if (!SkPaintToGrPaint(fContext, runPaint, viewMatrix, &grPaint)) { | |
| 131 return; | |
| 132 } | |
| 133 | |
| 134 switch (it.positioning()) { | |
| 135 case SkTextBlob::kDefault_Positioning: | |
| 136 this->drawText(dc, clip, grPaint, runPaint, viewMatrix, (const char
*)it.glyphs(), | |
| 137 textLen, x + offset.x(), y + offset.y(), clipBounds); | |
| 138 break; | |
| 139 case SkTextBlob::kHorizontal_Positioning: | |
| 140 this->drawPosText(dc, clip, grPaint, runPaint, viewMatrix, (const ch
ar*)it.glyphs(), | |
| 141 textLen, it.pos(), 1, SkPoint::Make(x, y + offset.
y()), clipBounds); | |
| 142 break; | |
| 143 case SkTextBlob::kFull_Positioning: | |
| 144 this->drawPosText(dc, clip, grPaint, runPaint, viewMatrix, (const ch
ar*)it.glyphs(), | |
| 145 textLen, it.pos(), 2, SkPoint::Make(x, y), clipBou
nds); | |
| 146 break; | |
| 147 default: | |
| 148 SkFAIL("unhandled positioning mode"); | |
| 149 } | |
| 150 | |
| 151 if (drawFilter) { | |
| 152 // A draw filter may change the paint arbitrarily, so we must re-see
d in this case. | |
| 153 runPaint = skPaint; | |
| 154 } | |
| 155 } | |
| 156 } | |
| 157 | |
| 158 static void GlyphCacheAuxProc(void* data) { | |
| 159 GrFontScaler* scaler = (GrFontScaler*)data; | |
| 160 SkSafeUnref(scaler); | |
| 161 } | |
| 162 | |
| 163 GrFontScaler* GrTextContext::GetGrFontScaler(SkGlyphCache* cache) { | |
| 164 void* auxData; | |
| 165 GrFontScaler* scaler = nullptr; | |
| 166 | |
| 167 if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) { | |
| 168 scaler = (GrFontScaler*)auxData; | |
| 169 } | |
| 170 if (nullptr == scaler) { | |
| 171 scaler = new GrFontScaler(cache); | |
| 172 cache->setAuxProc(GlyphCacheAuxProc, scaler); | |
| 173 } | |
| 174 | |
| 175 return scaler; | |
| 176 } | |
| OLD | NEW |