1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #ifndef PAINT_UTILS_H 17 #define PAINT_UTILS_H 18 19 #include <utils/Blur.h> 20 21 #include <SkColorFilter.h> 22 #include <SkDrawLooper.h> 23 #include <SkShader.h> 24 #include <SkXfermode.h> 25 26 namespace android { 27 namespace uirenderer { 28 29 /** 30 * Utility methods for accessing data within SkPaint, and providing defaults 31 * with optional SkPaint pointers. 32 */ 33 class PaintUtils { 34 public: 35 36 /** 37 * Safely retrieves the mode from the specified xfermode. If the specified 38 * xfermode is null, the mode is assumed to be SkXfermode::kSrcOver_Mode. 39 */ getXfermode(SkXfermode * mode)40 static inline SkXfermode::Mode getXfermode(SkXfermode* mode) { 41 SkXfermode::Mode resultMode; 42 if (!SkXfermode::AsMode(mode, &resultMode)) { 43 resultMode = SkXfermode::kSrcOver_Mode; 44 } 45 return resultMode; 46 } 47 getFilter(const SkPaint * paint)48 static inline GLenum getFilter(const SkPaint* paint) { 49 if (!paint || paint->getFilterQuality() != kNone_SkFilterQuality) { 50 return GL_LINEAR; 51 } 52 return GL_NEAREST; 53 } 54 55 // TODO: move to a method on android:Paint? replace with SkPaint::nothingToDraw()? paintWillNotDraw(const SkPaint & paint)56 static inline bool paintWillNotDraw(const SkPaint& paint) { 57 return paint.getAlpha() == 0 58 && !paint.getColorFilter() 59 && getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode; 60 } 61 62 // TODO: move to a method on android:Paint? replace with SkPaint::nothingToDraw()? paintWillNotDrawText(const SkPaint & paint)63 static inline bool paintWillNotDrawText(const SkPaint& paint) { 64 return paint.getAlpha() == 0 65 && paint.getLooper() == nullptr 66 && !paint.getColorFilter() 67 && getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode; 68 } 69 isOpaquePaint(const SkPaint * paint)70 static bool isOpaquePaint(const SkPaint* paint) { 71 if (!paint) return true; // default (paintless) behavior is SrcOver, black 72 73 if (paint->getAlpha() != 0xFF 74 || PaintUtils::isBlendedShader(paint->getShader()) 75 || PaintUtils::isBlendedColorFilter(paint->getColorFilter())) { 76 return false; 77 } 78 79 // Only let simple srcOver / src blending modes declare opaque, since behavior is clear. 80 SkXfermode::Mode mode = getXfermode(paint->getXfermode()); 81 return mode == SkXfermode::Mode::kSrcOver_Mode 82 || mode == SkXfermode::Mode::kSrc_Mode; 83 } 84 isBlendedShader(const SkShader * shader)85 static bool isBlendedShader(const SkShader* shader) { 86 if (shader == nullptr) { 87 return false; 88 } 89 return !shader->isOpaque(); 90 } 91 isBlendedColorFilter(const SkColorFilter * filter)92 static bool isBlendedColorFilter(const SkColorFilter* filter) { 93 if (filter == nullptr) { 94 return false; 95 } 96 return (filter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag) == 0; 97 } 98 99 struct TextShadow { 100 SkScalar radius; 101 float dx; 102 float dy; 103 SkColor color; 104 }; 105 getTextShadow(const SkPaint * paint,TextShadow * textShadow)106 static inline bool getTextShadow(const SkPaint* paint, TextShadow* textShadow) { 107 SkDrawLooper::BlurShadowRec blur; 108 if (paint && paint->getLooper() && paint->getLooper()->asABlurShadow(&blur)) { 109 if (textShadow) { 110 textShadow->radius = Blur::convertSigmaToRadius(blur.fSigma); 111 textShadow->dx = blur.fOffset.fX; 112 textShadow->dy = blur.fOffset.fY; 113 textShadow->color = blur.fColor; 114 } 115 return true; 116 } 117 return false; 118 } 119 hasTextShadow(const SkPaint * paint)120 static inline bool hasTextShadow(const SkPaint* paint) { 121 return getTextShadow(paint, nullptr); 122 } 123 getXfermodeDirect(const SkPaint * paint)124 static inline SkXfermode::Mode getXfermodeDirect(const SkPaint* paint) { 125 return paint ? getXfermode(paint->getXfermode()) : SkXfermode::kSrcOver_Mode; 126 } 127 getAlphaDirect(const SkPaint * paint)128 static inline int getAlphaDirect(const SkPaint* paint) { 129 return paint ? paint->getAlpha() : 255; 130 } 131 132 }; // class PaintUtils 133 134 } /* namespace uirenderer */ 135 } /* namespace android */ 136 137 #endif /* PAINT_UTILS_H */ 138