1/*
2 * Copyright 2013 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 "SkPaintPriv.h"
9
10#include "SkBitmap.h"
11#include "SkColorFilter.h"
12#include "SkPaint.h"
13#include "SkShader.h"
14
15bool isPaintOpaque(const SkPaint* paint,
16                   const SkBitmap* bmpReplacesShader) {
17    // TODO: SkXfermode should have a virtual isOpaque method, which would
18    // make it possible to test modes that do not have a Coeff representation.
19
20    if (!paint) {
21        return bmpReplacesShader ? bmpReplacesShader->isOpaque() : true;
22    }
23
24    SkXfermode::Coeff srcCoeff, dstCoeff;
25    if (SkXfermode::AsCoeff(paint->getXfermode(), &srcCoeff, &dstCoeff)){
26        if (SkXfermode::kDA_Coeff == srcCoeff || SkXfermode::kDC_Coeff == srcCoeff ||
27            SkXfermode::kIDA_Coeff == srcCoeff || SkXfermode::kIDC_Coeff == srcCoeff) {
28            return false;
29        }
30        switch (dstCoeff) {
31        case SkXfermode::kZero_Coeff:
32            return true;
33        case SkXfermode::kISA_Coeff:
34            if (paint->getAlpha() != 255) {
35                break;
36            }
37            if (bmpReplacesShader) {
38                if (!bmpReplacesShader->isOpaque()) {
39                    break;
40                }
41            } else if (paint->getShader() && !paint->getShader()->isOpaque()) {
42                break;
43            }
44            if (paint->getColorFilter() &&
45                ((paint->getColorFilter()->getFlags() &
46                SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
47                break;
48            }
49            return true;
50        case SkXfermode::kSA_Coeff:
51            if (paint->getAlpha() != 0) {
52                break;
53            }
54            if (paint->getColorFilter() &&
55                ((paint->getColorFilter()->getFlags() &
56                SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
57                break;
58            }
59            return true;
60        case SkXfermode::kSC_Coeff:
61            if (paint->getColor() != 0) { // all components must be 0
62                break;
63            }
64            if (bmpReplacesShader || paint->getShader()) {
65                break;
66            }
67            if (paint->getColorFilter() && (
68                (paint->getColorFilter()->getFlags() &
69                SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
70                break;
71            }
72            return true;
73        default:
74            break;
75        }
76    }
77    return false;
78}
79
80bool NeedsDeepCopy(const SkPaint& paint) {
81    /*
82     *  The types below are not yet immutable/reentrant-safe, and so we return
83     *  true if instances of them are present in the paint.
84     *
85     *  Eventually we hope this list will be empty, and we can always return
86     *  false.
87     */
88    return paint.getImageFilter();
89}
90