Home | History | Annotate | Download | only in text
      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