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