1 /* 2 * Copyright 2015 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 "GrTextUtils.h" 9 #include "GrContext.h" 10 #include "SkDrawFilter.h" 11 #include "SkGlyphCache.h" 12 #include "SkGr.h" 13 #include "SkPaint.h" 14 #include "SkTextBlobRunIterator.h" 15 16 void GrTextUtils::Paint::initFilteredColor() { 17 // This mirrors the logic in skpaint_to_grpaint_impl for handling paint colors 18 if (fDstColorSpaceInfo->colorSpace()) { 19 GrColor4f filteredColor = 20 SkColorToUnpremulGrColor4f(fPaint->getColor(), *fDstColorSpaceInfo); 21 if (fPaint->getColorFilter()) { 22 filteredColor = GrColor4f::FromSkColor4f( 23 fPaint->getColorFilter()->filterColor4f(filteredColor.toSkColor4f())); 24 } 25 fFilteredPremulColor = filteredColor.premul().toGrColor(); 26 } else { 27 SkColor filteredSkColor = fPaint->getColor(); 28 if (fPaint->getColorFilter()) { 29 filteredSkColor = fPaint->getColorFilter()->filterColor(filteredSkColor); 30 } 31 fFilteredPremulColor = SkColorToPremulGrColor(filteredSkColor); 32 } 33 } 34 35 36 bool GrTextUtils::RunPaint::modifyForRun(std::function<void(SkPaint*)> paintModFunc) { 37 if (!fModifiedPaint.isValid()) { 38 fModifiedPaint.init(fOriginalPaint->skPaint()); 39 fPaint = fModifiedPaint.get(); 40 } else if (fFilter) { 41 // We have to reset before applying the run because the filter could have arbitrary 42 // changed the paint. 43 *fModifiedPaint.get() = fOriginalPaint->skPaint(); 44 } 45 paintModFunc(fModifiedPaint.get()); 46 47 if (fFilter) { 48 if (!fFilter->filter(fModifiedPaint.get(), SkDrawFilter::kText_Type)) { 49 // A false return from filter() means we should abort the current draw. 50 return false; 51 } 52 // The draw filter could have changed either the paint color or color filter. 53 this->initFilteredColor(); 54 } 55 fModifiedPaint.get()->setFlags(FilterTextFlags(fProps, *fModifiedPaint.get())); 56 return true; 57 } 58 59 uint32_t GrTextUtils::FilterTextFlags(const SkSurfaceProps& surfaceProps, const SkPaint& paint) { 60 uint32_t flags = paint.getFlags(); 61 62 if (!paint.isLCDRenderText() || !paint.isAntiAlias()) { 63 return flags; 64 } 65 66 if (kUnknown_SkPixelGeometry == surfaceProps.pixelGeometry() || ShouldDisableLCD(paint)) { 67 flags &= ~SkPaint::kLCDRenderText_Flag; 68 flags |= SkPaint::kGenA8FromLCD_Flag; 69 } 70 71 return flags; 72 } 73 74 bool GrTextUtils::ShouldDisableLCD(const SkPaint& paint) { 75 return paint.getMaskFilter() || paint.getPathEffect() || 76 paint.isFakeBoldText() || paint.getStyle() != SkPaint::kFill_Style; 77 } 78 79 bool GrTextUtils::PathTextIter::next(const SkGlyph** skGlyph, const SkPath** path, SkScalar* xpos) { 80 SkASSERT(skGlyph); 81 SkASSERT(path); 82 SkASSERT(xpos); 83 if (fText < fStop) { 84 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText); 85 86 fXPos += (fPrevAdvance + fAutoKern.adjust(glyph)) * fScale; 87 SkASSERT(0 == fXYIndex || 1 == fXYIndex); 88 fPrevAdvance = SkFloatToScalar((&glyph.fAdvanceX)[fXYIndex]); 89 90 if (glyph.fWidth) { 91 if (SkMask::kARGB32_Format == glyph.fMaskFormat) { 92 *skGlyph = &glyph; 93 *path = nullptr; 94 } else { 95 *skGlyph = nullptr; 96 *path = fCache->findPath(glyph); 97 } 98 } else { 99 *skGlyph = nullptr; 100 *path = nullptr; 101 } 102 *xpos = fXPos; 103 return true; 104 } 105 return false; 106 } 107