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 26namespace android { 27namespace uirenderer { 28 29/** 30 * Utility methods for accessing data within SkPaint, and providing defaults 31 * with optional SkPaint pointers. 32 */ 33class PaintUtils { 34public: 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 */ 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 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()? 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()? 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 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 85 static bool isBlendedShader(const SkShader* shader) { 86 if (shader == nullptr) { 87 return false; 88 } 89 return !shader->isOpaque(); 90 } 91 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 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 120 static inline bool hasTextShadow(const SkPaint* paint) { 121 return getTextShadow(paint, nullptr); 122 } 123 124 static inline SkXfermode::Mode getXfermodeDirect(const SkPaint* paint) { 125 return paint ? getXfermode(paint->getXfermode()) : SkXfermode::kSrcOver_Mode; 126 } 127 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