| /* | |
| * Copyright 2020 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef GrPixmap_DEFINED | |
| #define GrPixmap_DEFINED | |
| #include "include/core/SkData.h" | |
| #include "include/core/SkPixmap.h" | |
| #include "include/core/SkPoint.h" | |
| #include "include/core/SkRect.h" | |
| #include "include/core/SkRefCnt.h" | |
| #include "include/core/SkSize.h" | |
| #include "include/private/SkTLogic.h" | |
| #include "include/private/SkTo.h" | |
| #include "src/gpu/ganesh/GrImageInfo.h" | |
| #include <cstddef> | |
| #include <utility> | |
| class GrColorInfo; | |
| class SkColorSpace; | |
| enum SkAlphaType : int; | |
| enum class GrColorType; | |
| template <typename T, typename DERIVED> class GrPixmapBase { | |
| public: | |
| const GrImageInfo& info() const { return fInfo; } | |
| const GrColorInfo& colorInfo() const { return fInfo.colorInfo(); } | |
| T* addr() const { return fAddr; } | |
| size_t rowBytes() const { return fRowBytes; } | |
| bool hasPixels() const { return SkToBool(fAddr); } | |
| bool ownsPixels() const { return SkToBool(fPixelStorage); } | |
| sk_sp<SkData> pixelStorage() const { return fPixelStorage; } | |
| int width() const { return fInfo.width(); } | |
| int height() const { return fInfo.height(); } | |
| SkISize dimensions() const { return fInfo.dimensions(); } | |
| GrColorType colorType() const { return fInfo.colorType(); } | |
| SkAlphaType alphaType() const { return fInfo.alphaType(); } | |
| SkColorSpace* colorSpace() const { return fInfo.colorSpace(); } | |
| sk_sp<SkColorSpace> refColorSpace() const { return fInfo.refColorSpace(); } | |
| /** | |
| * Map this pixmap to a rect in a surface of indicated dimensions at offset surfacePt. Clip the | |
| * logical rectangle to the bounds of the surface. If the rect does not intersect the surface | |
| * bounds or is empty then return a default GrPixmap. Otherwise, surfacePt is updated to refer | |
| * to the upper left of the clipped rectangle. The returned pixmap will refer to the portion | |
| * of the original pixmap inside the surface bounds. | |
| */ | |
| DERIVED clip(SkISize surfaceDims, SkIPoint* surfacePt) { | |
| auto bounds = SkIRect::MakeSize(surfaceDims); | |
| auto rect = SkIRect::MakePtSize(*surfacePt, this->dimensions()); | |
| if (!rect.intersect(bounds)) { | |
| return {}; | |
| } | |
| T* addr = static_cast<sknonstd::copy_const_t<char, T>*>(fAddr) + | |
| (rect.fTop - surfacePt->fY) * fRowBytes + | |
| (rect.fLeft - surfacePt->fX) * fInfo.bpp(); | |
| surfacePt->fX = rect.fLeft; | |
| surfacePt->fY = rect.fTop; | |
| return DERIVED{this->info().makeDimensions(rect.size()), addr, fRowBytes}; | |
| } | |
| protected: | |
| GrPixmapBase() = default; | |
| GrPixmapBase(const GrPixmapBase& that) = default; | |
| GrPixmapBase(GrPixmapBase&& that) = default; | |
| GrPixmapBase& operator=(const GrPixmapBase& that) = default; | |
| GrPixmapBase& operator=(GrPixmapBase&& that) = default; | |
| GrPixmapBase(GrImageInfo info, T* addr, size_t rowBytes) | |
| : fAddr(addr), fRowBytes(rowBytes), fInfo(std::move(info)) { | |
| if (fRowBytes < fInfo.minRowBytes() || !addr) { | |
| *this = {}; | |
| } | |
| } | |
| GrPixmapBase(GrImageInfo info, sk_sp<SkData> storage, size_t rowBytes) | |
| : GrPixmapBase(std::move(info), storage->writable_data(), rowBytes) { | |
| fPixelStorage = std::move(storage); | |
| } | |
| private: | |
| T* fAddr = nullptr; | |
| size_t fRowBytes = 0; | |
| GrImageInfo fInfo; | |
| sk_sp<SkData> fPixelStorage; | |
| }; | |
| /** A pixmap with mutable pixels. */ | |
| class GrPixmap : public GrPixmapBase<void, GrPixmap> { | |
| public: | |
| GrPixmap() = default; | |
| GrPixmap(const GrPixmap&) = default; | |
| GrPixmap(GrPixmap&&) = default; | |
| GrPixmap& operator=(const GrPixmap&) = default; | |
| GrPixmap& operator=(GrPixmap&&) = default; | |
| GrPixmap(GrImageInfo info, void* addr, size_t rowBytes) | |
| : GrPixmapBase(std::move(info), addr, rowBytes) {} | |
| /* implicit */ GrPixmap(const SkPixmap& pixmap) | |
| : GrPixmapBase(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes()) {} | |
| /** | |
| * Returns a GrPixmap that owns its backing store. Copies of the pixmap (as GrPixmap or | |
| * GrCPixmap) will share ownership. | |
| */ | |
| static GrPixmap Allocate(const GrImageInfo& info) { | |
| size_t rb = info.minRowBytes(); | |
| size_t size = info.height()*rb; | |
| if (!size) { | |
| return {}; | |
| } | |
| return GrPixmap(info, SkData::MakeUninitialized(size), rb); | |
| } | |
| private: | |
| GrPixmap(GrImageInfo info, sk_sp<SkData> storage, size_t rowBytes) | |
| : GrPixmapBase(std::move(info), std::move(storage), rowBytes) {} | |
| }; | |
| /** | |
| * A pixmap with immutable pixels. Note that this pixmap need not be the unique owner of the pixels | |
| * and thus it is context-dependent whether the pixels could be manipulated externally. | |
| */ | |
| class GrCPixmap : public GrPixmapBase<const void, GrCPixmap> { | |
| public: | |
| GrCPixmap() = default; | |
| GrCPixmap(const GrCPixmap&) = default; | |
| GrCPixmap(GrCPixmap&&) = default; | |
| GrCPixmap& operator=(const GrCPixmap&) = default; | |
| GrCPixmap& operator=(GrCPixmap&&) = default; | |
| /* implicit*/ GrCPixmap(const GrPixmap& pixmap) { | |
| if (auto storage = pixmap.pixelStorage()) { | |
| *this = GrCPixmap(pixmap.info(), std::move(storage), pixmap.rowBytes()); | |
| } else { | |
| *this = GrCPixmap(pixmap.info(), pixmap.addr(), pixmap.rowBytes()); | |
| } | |
| } | |
| /* implicit */ GrCPixmap(const SkPixmap& pixmap) | |
| : GrPixmapBase(pixmap.info(), pixmap.addr(), pixmap.rowBytes()) {} | |
| GrCPixmap(GrImageInfo info, const void* addr, size_t rowBytes) | |
| : GrPixmapBase(std::move(info), addr, rowBytes) {} | |
| private: | |
| GrCPixmap(GrImageInfo info, sk_sp<SkData> storage, size_t rowBytes) | |
| : GrPixmapBase(std::move(info), std::move(storage), rowBytes) {} | |
| }; | |
| #endif |