From 7b4b334e777e573040569801d3b4ab28a606a127 Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 5 May 2022 19:31:18 +0800 Subject: ... --- src/osx/graphics/quartz/ImageFactory.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'src/osx/graphics/quartz/ImageFactory.cpp') diff --git a/src/osx/graphics/quartz/ImageFactory.cpp b/src/osx/graphics/quartz/ImageFactory.cpp index 7796ef3a..95315e1a 100644 --- a/src/osx/graphics/quartz/ImageFactory.cpp +++ b/src/osx/graphics/quartz/ImageFactory.cpp @@ -1,4 +1,5 @@ #include "cru/osx/graphics/quartz/ImageFactory.h" +#include "cru/common/Exception.h" #include "cru/osx/graphics/quartz/Convert.h" #include "cru/osx/graphics/quartz/Image.h" #include "cru/platform/graphics/Image.h" @@ -20,12 +21,27 @@ std::unique_ptr QuartzImageFactory::DecodeFromStream( CGImageRef cg_image = CGImageSourceCreateImageAtIndex(image_source, 0, nullptr); - QuartzImage* image = - new QuartzImage(GetGraphicsFactory(), this, cg_image, true); - - CFRelease(cg_image); + CFRelease(image_source); CGDataProviderRelease(data_provider); - return std::unique_ptr(image); + return std::unique_ptr( + new QuartzImage(GetGraphicsFactory(), this, cg_image, true)); +} + +std::unique_ptr QuartzImageFactory::CreateBitmap(int width, + int height) { + if (width <= 0) throw Exception(u"Image width should be greater than 0."); + if (height <= 0) throw Exception(u"Image height should be greater than 0."); + + CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); + + auto cg_image = CGImageCreate(width, height, 8, 32, 4 * width, color_space, + kCGImageAlphaLast, nullptr, nullptr, true, + kCGRenderingIntentDefault); + + CGColorSpaceRelease(color_space); + + return std::unique_ptr( + new QuartzImage(GetGraphicsFactory(), this, cg_image, true)); } } // namespace cru::platform::graphics::osx::quartz -- cgit v1.2.3 From 56a8047c4093c928b8551bbacda796382984512e Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 5 May 2022 20:05:35 +0800 Subject: ... --- include/cru/osx/graphics/quartz/Image.h | 7 ++++++- include/cru/platform/graphics/Image.h | 15 +++++++++++++++ src/osx/graphics/quartz/Image.cpp | 31 +++++++++++++++++++++++++++++-- src/osx/graphics/quartz/ImageFactory.cpp | 11 ++++++++++- src/platform/graphics/CMakeLists.txt | 1 + src/platform/graphics/Image.cpp | 15 +++++++++++++++ 6 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 src/platform/graphics/Image.cpp (limited to 'src/osx/graphics/quartz/ImageFactory.cpp') diff --git a/include/cru/osx/graphics/quartz/Image.h b/include/cru/osx/graphics/quartz/Image.h index 458f5db0..5b3aead9 100644 --- a/include/cru/osx/graphics/quartz/Image.h +++ b/include/cru/osx/graphics/quartz/Image.h @@ -9,7 +9,8 @@ namespace cru::platform::graphics::osx::quartz { class QuartzImage : public OsxQuartzResource, public virtual IImage { public: QuartzImage(IGraphicsFactory* graphics_factory, IImageFactory* image_factory, - CGImageRef image, bool auto_release); + CGImageRef image, bool auto_release, + unsigned char* buffer = nullptr); CRU_DELETE_COPY(QuartzImage) CRU_DELETE_MOVE(QuartzImage) @@ -22,11 +23,15 @@ class QuartzImage : public OsxQuartzResource, public virtual IImage { std::unique_ptr CreateWithRect(const Rect& rect) override; + std::unique_ptr CreatePainter() override; + CGImageRef GetCGImage() const { return image_; } private: IImageFactory* image_factory_; CGImageRef image_; bool auto_release_ = false; + + unsigned char* buffer_; }; } // namespace cru::platform::graphics::osx::quartz diff --git a/include/cru/platform/graphics/Image.h b/include/cru/platform/graphics/Image.h index 51e27678..17d2170e 100644 --- a/include/cru/platform/graphics/Image.h +++ b/include/cru/platform/graphics/Image.h @@ -6,5 +6,20 @@ struct CRU_PLATFORM_GRAPHICS_API IImage : public virtual IGraphicsResource { virtual float GetWidth() = 0; virtual float GetHeight() = 0; virtual std::unique_ptr CreateWithRect(const Rect& rect) = 0; + + /** + * \brief Create a painter for this image. + * \remarks Not all image could create a painter. If not this method will + * throw. Currently we only ensure images returned by + * IImageFactory::CreateBitmap or CloneToBitmap can create a painter. + */ + virtual std::unique_ptr CreatePainter() = 0; + + /** + * \brief Create a bitmap image with the same pixels as this image's. + * \remarks This method can be used to create a bitmap image, so you can draw + * on the new bitmap, if the original image can't be directly painted. + */ + virtual std::unique_ptr CloneToBitmap(); }; } // namespace cru::platform::graphics diff --git a/src/osx/graphics/quartz/Image.cpp b/src/osx/graphics/quartz/Image.cpp index db10da76..feddad8c 100644 --- a/src/osx/graphics/quartz/Image.cpp +++ b/src/osx/graphics/quartz/Image.cpp @@ -1,14 +1,17 @@ #include "cru/osx/graphics/quartz/Image.h" +#include "cru/common/Exception.h" #include "cru/osx/graphics/quartz/Convert.h" +#include "cru/osx/graphics/quartz/Painter.h" namespace cru::platform::graphics::osx::quartz { QuartzImage::QuartzImage(IGraphicsFactory* graphics_factory, IImageFactory* image_factory, CGImageRef image, - bool auto_release) + bool auto_release, unsigned char* buffer) : OsxQuartzResource(graphics_factory), image_factory_(image_factory), image_(image), - auto_release_(auto_release) {} + auto_release_(auto_release), + buffer_(buffer) {} QuartzImage::~QuartzImage() { if (auto_release_) { @@ -26,4 +29,28 @@ std::unique_ptr QuartzImage::CreateWithRect(const Rect& rect) { return std::make_unique(GetGraphicsFactory(), image_factory_, new_cg_image, true); } + +std::unique_ptr QuartzImage::CreatePainter() { + if (!buffer_) + throw Exception( + u"Failed to create painter for image because failed to get its " + u"buffer."); + + auto width = CGImageGetWidth(image_); + auto height = CGImageGetHeight(image_); + auto bits_per_component = CGImageGetBitsPerComponent(image_); + auto bytes_per_row = CGImageGetBytesPerRow(image_); + auto color_space = CGImageGetColorSpace(image_); + auto bitmap_info = CGImageGetBitmapInfo(image_); + + auto cg_context = + CGBitmapContextCreate(buffer_, width, height, bits_per_component, + bytes_per_row, color_space, bitmap_info); + + return std::make_unique( + GetGraphicsFactory(), cg_context, true, Size(width, height), + [](QuartzCGContextPainter* painter) { + + }); +} } // namespace cru::platform::graphics::osx::quartz diff --git a/src/osx/graphics/quartz/ImageFactory.cpp b/src/osx/graphics/quartz/ImageFactory.cpp index 95315e1a..a8c17719 100644 --- a/src/osx/graphics/quartz/ImageFactory.cpp +++ b/src/osx/graphics/quartz/ImageFactory.cpp @@ -35,6 +35,15 @@ std::unique_ptr QuartzImageFactory::CreateBitmap(int width, CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); + const auto buffer_size = width * height * 4; + auto buffer = new unsigned char[buffer_size]; + + auto cg_data_provider = CGDataProviderCreateWithData( + nullptr, buffer, buffer_size, + [](void* info, const void* data, size_t size) { + delete[] static_cast(data); + }); + auto cg_image = CGImageCreate(width, height, 8, 32, 4 * width, color_space, kCGImageAlphaLast, nullptr, nullptr, true, kCGRenderingIntentDefault); @@ -42,6 +51,6 @@ std::unique_ptr QuartzImageFactory::CreateBitmap(int width, CGColorSpaceRelease(color_space); return std::unique_ptr( - new QuartzImage(GetGraphicsFactory(), this, cg_image, true)); + new QuartzImage(GetGraphicsFactory(), this, cg_image, true, buffer)); } } // namespace cru::platform::graphics::osx::quartz diff --git a/src/platform/graphics/CMakeLists.txt b/src/platform/graphics/CMakeLists.txt index 1d983188..dc0a429e 100644 --- a/src/platform/graphics/CMakeLists.txt +++ b/src/platform/graphics/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(cru_platform_graphics SHARED ForDllExport.cpp Geometry.cpp + Image.cpp NullPainter.cpp ) target_compile_definitions(cru_platform_graphics PRIVATE CRU_PLATFORM_GRAPHICS_EXPORT_API) diff --git a/src/platform/graphics/Image.cpp b/src/platform/graphics/Image.cpp new file mode 100644 index 00000000..2c787dd7 --- /dev/null +++ b/src/platform/graphics/Image.cpp @@ -0,0 +1,15 @@ +#include "cru/platform/graphics/Image.h" + +#include "cru/platform/graphics/Factory.h" +#include "cru/platform/graphics/ImageFactory.h" +#include "cru/platform/graphics/Painter.h" + +namespace cru::platform::graphics { +std::unique_ptr IImage::CloneToBitmap() { + auto image = GetGraphicsFactory()->GetImageFactory()->CreateBitmap( + GetWidth(), GetHeight()); + auto painter = image->CreatePainter(); + painter->DrawImage(Point{}, this); + return image; +} +} // namespace cru::platform::graphics -- cgit v1.2.3