• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 Google LLC
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 "src/image/SkImage_Picture.h"
9 
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkColor.h"
12 #include "include/core/SkColorSpace.h"
13 #include "include/core/SkColorType.h"
14 #include "include/core/SkImage.h"
15 #include "include/core/SkImageGenerator.h"
16 #include "include/core/SkImageInfo.h"
17 #include "include/core/SkMatrix.h"
18 #include "include/core/SkPicture.h"
19 #include "include/core/SkSurfaceProps.h"
20 #include "include/private/base/SkAssert.h"
21 #include "include/private/base/SkMutex.h"
22 #include "include/private/base/SkTFitsIn.h"
23 #include "src/base/SkTLazy.h"
24 #include "src/image/SkImageGeneratorPriv.h"
25 #include "src/image/SkImage_Lazy.h"
26 #include "src/image/SkPictureImageGenerator.h"
27 
28 #include <cstring>
29 #include <memory>
30 #include <utility>
31 
32 class SkPaint;
33 struct SkISize;
34 
Make(sk_sp<SkPicture> picture,const SkISize & dimensions,const SkMatrix * matrix,const SkPaint * paint,SkImages::BitDepth bitDepth,sk_sp<SkColorSpace> colorSpace,SkSurfaceProps props)35 sk_sp<SkImage> SkImage_Picture::Make(sk_sp<SkPicture> picture, const SkISize& dimensions,
36                                      const SkMatrix* matrix, const SkPaint* paint,
37                                      SkImages::BitDepth bitDepth, sk_sp<SkColorSpace> colorSpace,
38                                      SkSurfaceProps props) {
39     auto gen = SkImageGenerators::MakeFromPicture(dimensions, std::move(picture), matrix, paint,
40                                                   bitDepth, std::move(colorSpace), props);
41 
42     SkImage_Lazy::Validator validator(
43             SharedGenerator::Make(std::move(gen)), nullptr, nullptr);
44 
45     return validator ? sk_make_sp<SkImage_Picture>(&validator) : nullptr;
46 }
47 
props() const48 const SkSurfaceProps* SkImage_Picture::props() const {
49     auto pictureIG = static_cast<SkPictureImageGenerator*>(this->generator()->fGenerator.get());
50     return &pictureIG->fProps;
51 }
52 
replay(SkCanvas * canvas) const53 void SkImage_Picture::replay(SkCanvas* canvas) const {
54     auto sharedGenerator = this->generator();
55     SkAutoMutexExclusive mutex(sharedGenerator->fMutex);
56 
57     auto pictureIG = static_cast<SkPictureImageGenerator*>(sharedGenerator->fGenerator.get());
58     canvas->clear(SkColors::kTransparent);
59     canvas->drawPicture(pictureIG->fPicture,
60                         &pictureIG->fMatrix,
61                         pictureIG->fPaint.getMaybeNull());
62 }
63 
getImageKeyValues(uint32_t keyValues[SkTiledImageUtils::kNumImageKeyValues]) const64 bool SkImage_Picture::getImageKeyValues(
65         uint32_t keyValues[SkTiledImageUtils::kNumImageKeyValues]) const {
66 
67     auto sharedGenerator = this->generator();
68     SkAutoMutexExclusive mutex(sharedGenerator->fMutex);
69 
70     auto pictureIG = static_cast<SkPictureImageGenerator*>(sharedGenerator->fGenerator.get());
71     if (pictureIG->fPaint.getMaybeNull()) {
72         // A full paint complicates the potential key too much.
73         return false;
74     }
75 
76     const SkImageInfo& ii = sharedGenerator->getInfo();
77     if (!ii.colorSpace()->isSRGB()) {
78         // We only return key values if the colorSpace is sRGB.
79         return false;
80     }
81 
82     const SkMatrix& m = pictureIG->fMatrix;
83     if (!m.isIdentity() && !m.isTranslate()) {
84         // To keep the key small we only cache simple (<= translation) matrices
85         return false;
86     }
87 
88     bool isU8 = ii.colorType() != kRGBA_F16_SkColorType;
89     uint32_t pixelGeometry = this->props()->pixelGeometry();
90     uint32_t surfacePropFlags = this->props()->flags();
91     int width = ii.width();
92     int height = ii.height();
93     float transX = m.getTranslateX();
94     float transY = m.getTranslateY();
95 
96     SkASSERT(pixelGeometry <= 4);
97     SkASSERT(surfacePropFlags < 8);
98     SkASSERT(SkTFitsIn<uint32_t>(width));
99     SkASSERT(SkTFitsIn<uint32_t>(height));
100     SkASSERT(sizeof(float) == sizeof(uint32_t));
101 
102     // The 0th slot usually holds either the SkBitmap's ID or the image's. In those two cases
103     // slot #1 is zero so we can reuse the 0th slot here.
104     keyValues[0] = (isU8 ? 0x1 : 0x0) |     // 1 bit
105                    (pixelGeometry << 1) |   // 3 bits
106                    (surfacePropFlags << 4); // 3 bits
107     keyValues[1] = pictureIG->fPicture->uniqueID();
108     SkASSERT(keyValues[1] != 0);    // Double check we don't collide w/ bitmap or image keys
109     keyValues[2] = width;
110     keyValues[3] = height;
111     memcpy(&keyValues[4], &transX, sizeof(uint32_t));
112     memcpy(&keyValues[5], &transY, sizeof(uint32_t));
113     return true;
114 }
115