From 2c675bfc4f401ff607921e64eaf3a3e07329d5d3 Mon Sep 17 00:00:00 2001 From: David Capello Date: Sat, 9 Aug 2014 21:33:38 -0300 Subject: [PATCH] Fix crash in PreviewCommand We cannot use the ui::Graphics internal surface directly when we use raster::convert_image_to_surface() (it expects an Rgba surface). --- src/app/commands/cmd_preview.cpp | 11 ++++- src/app/thumbnail_generator.cpp | 3 +- src/app/ui/context_bar.cpp | 3 +- src/app/ui/editor/editor.cpp | 3 +- src/raster/conversion_she.cpp | 81 +++++++++++++++++++++++++------- src/raster/conversion_she.h | 4 +- 6 files changed, 82 insertions(+), 23 deletions(-) diff --git a/src/app/commands/cmd_preview.cpp b/src/app/commands/cmd_preview.cpp index 5015ae480..881e352c8 100644 --- a/src/app/commands/cmd_preview.cpp +++ b/src/app/commands/cmd_preview.cpp @@ -39,6 +39,9 @@ #include "raster/palette.h" #include "raster/primitives.h" #include "raster/sprite.h" +#include "she/scoped_handle.h" +#include "she/surface.h" +#include "she/system.h" #define PREVIEW_TILED 1 #define PREVIEW_FIT_ON_SCREEN 2 @@ -59,7 +62,8 @@ public: , m_sprite(editor->sprite()) , m_pal(m_sprite->getPalette(editor->frame())) , m_index_bg_color(-1) - , m_doublebuf(Image::create(IMAGE_RGB, JI_SCREEN_W, JI_SCREEN_H)) { + , m_doublebuf(Image::create(IMAGE_RGB, JI_SCREEN_W, JI_SCREEN_H)) + , m_doublesur(she::instance()->createRgbaSurface(JI_SCREEN_W, JI_SCREEN_H)) { // Do not use DocumentWriter (do not lock the document) because we // will call other sub-commands (e.g. previous frame, next frame, // etc.). @@ -230,7 +234,9 @@ protected: break; } - raster::convert_image_to_surface(m_doublebuf, g->getInternalSurface(), 0, 0, m_pal); + raster::convert_image_to_surface(m_doublebuf, m_pal, + m_doublesur, 0, 0, 0, 0, m_doublebuf->width(), m_doublebuf->height()); + g->blit(m_doublesur, 0, 0, 0, 0, m_doublesur->width(), m_doublesur->height()); } private: @@ -247,6 +253,7 @@ private: int m_index_bg_color; base::UniquePtr m_render; base::UniquePtr m_doublebuf; + she::ScopedHandle m_doublesur; filters::TiledMode m_tiled; }; diff --git a/src/app/thumbnail_generator.cpp b/src/app/thumbnail_generator.cpp index 9067ec205..eed6d4e2f 100644 --- a/src/app/thumbnail_generator.cpp +++ b/src/app/thumbnail_generator.cpp @@ -112,7 +112,8 @@ private: m_thumbnail->width(), m_thumbnail->height()); - convert_image_to_surface(m_thumbnail, thumbnail, 0, 0, m_palette); + convert_image_to_surface(m_thumbnail, m_palette, thumbnail, + 0, 0, 0, 0, m_thumbnail->width(), m_thumbnail->height()); m_fileitem->setThumbnail(thumbnail); } diff --git a/src/app/ui/context_bar.cpp b/src/app/ui/context_bar.cpp index 84335c198..82a6e1478 100644 --- a/src/app/ui/context_bar.cpp +++ b/src/app/ui/context_bar.cpp @@ -102,7 +102,8 @@ public: m_bitmap->dispose(); m_bitmap = she::instance()->createRgbaSurface(image->width(), image->height()); - convert_image_to_surface(image, m_bitmap, 0, 0, palette); + convert_image_to_surface(image, palette, m_bitmap, + 0, 0, 0, 0, image->width(), image->height()); invalidate(); } diff --git a/src/app/ui/editor/editor.cpp b/src/app/ui/editor/editor.cpp index 0280edadd..8533263b0 100644 --- a/src/app/ui/editor/editor.cpp +++ b/src/app/ui/editor/editor.cpp @@ -399,7 +399,8 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& rc, in } she::Surface* tmp(she::instance()->createRgbaSurface(width, height)); - convert_image_to_surface(rendered, tmp, 0, 0, m_sprite->getPalette(m_frame)); + convert_image_to_surface(rendered, m_sprite->getPalette(m_frame), + tmp, 0, 0, 0, 0, width, height); g->blit(tmp, 0, 0, dest_x, dest_y, width, height); tmp->dispose(); } diff --git a/src/raster/conversion_she.cpp b/src/raster/conversion_she.cpp index c58bd6312..ce5c5abab 100644 --- a/src/raster/conversion_she.cpp +++ b/src/raster/conversion_she.cpp @@ -85,15 +85,14 @@ uint32_t convert_color_to_surface(color_t } template -void convert_image_to_surface_templ(const Image* image, she::LockedSurface* dst, int x, int y, const Palette* palette, const she::SurfaceFormatData* fd) +void convert_image_to_surface_templ(const Image* image, she::LockedSurface* dst, + int src_x, int src_y, int dst_x, int dst_y, int w, int h, const Palette* palette, const she::SurfaceFormatData* fd) { - const LockImageBits bits(image); + const LockImageBits bits(image, gfx::Rect(src_x, src_y, w, h)); typename LockImageBits::const_iterator src_it = bits.begin(), src_end = bits.end(); - int w = image->width(); - int h = image->height(); - for (int v=0; vgetData(x, y)); + for (int v=0; vgetData(dst_x, dst_y)); for (int u=0; u -void convert_image_to_surface_selector(const Image* image, she::LockedSurface* surface, int x, int y, const Palette* palette, const she::SurfaceFormatData* fd) +void convert_image_to_surface_selector(const Image* image, she::LockedSurface* surface, + int src_x, int src_y, int dst_x, int dst_y, int w, int h, const Palette* palette, const she::SurfaceFormatData* fd) { switch (fd->bitsPerPixel) { - case 8: convert_image_to_surface_templ(image, surface, x, y, palette, fd); break; + + case 8: + convert_image_to_surface_templ(image, surface, src_x, src_y, dst_x, dst_y, w, h, palette, fd); + break; + case 15: - case 16: convert_image_to_surface_templ(image, surface, x, y, palette, fd); break; - case 24: convert_image_to_surface_templ(image, surface, x, y, palette, fd); break; - case 32: convert_image_to_surface_templ(image, surface, x, y, palette, fd); break; + case 16: + convert_image_to_surface_templ(image, surface, src_x, src_y, dst_x, dst_y, w, h, palette, fd); + break; + + case 24: + convert_image_to_surface_templ(image, surface, src_x, src_y, dst_x, dst_y, w, h, palette, fd); + break; + + case 32: + convert_image_to_surface_templ(image, surface, src_x, src_y, dst_x, dst_y, w, h, palette, fd); + break; } } } // anonymous namespace -void convert_image_to_surface(const Image* image, she::Surface* surface, int x, int y, const Palette* palette) +void convert_image_to_surface(const Image* image, const Palette* palette, + she::Surface* surface, int src_x, int src_y, int dst_x, int dst_y, int w, int h) { + gfx::Rect srcBounds(src_x, src_y, w, h); + srcBounds = srcBounds.createIntersect(image->bounds()); + if (srcBounds.isEmpty()) + return; + + src_x = srcBounds.x; + src_y = srcBounds.y; + w = srcBounds.w; + h = srcBounds.h; + + gfx::Rect dstBounds(dst_x, dst_y, w, h); + dstBounds = dstBounds.createIntersect(surface->getClipBounds()); + if (dstBounds.isEmpty()) + return; + + src_x += dstBounds.x - dst_x; + src_y += dstBounds.y - dst_y; + dst_x = dstBounds.x; + dst_y = dstBounds.y; + w = dstBounds.w; + h = dstBounds.h; + she::ScopedSurfaceLock dst(surface); she::SurfaceFormatData fd; dst->getFormat(&fd); switch (image->pixelFormat()) { - case IMAGE_RGB: convert_image_to_surface_selector(image, dst, x, y, palette, &fd); break; - case IMAGE_GRAYSCALE: convert_image_to_surface_selector(image, dst, x, y, palette, &fd); break; - case IMAGE_INDEXED: convert_image_to_surface_selector(image, dst, x, y, palette, &fd); break; - case IMAGE_BITMAP: convert_image_to_surface_selector(image, dst, x, y, palette, &fd); break; + + case IMAGE_RGB: + convert_image_to_surface_selector(image, dst, src_x, src_y, dst_x, dst_y, w, h, palette, &fd); + break; + + case IMAGE_GRAYSCALE: + convert_image_to_surface_selector(image, dst, src_x, src_y, dst_x, dst_y, w, h, palette, &fd); + break; + + case IMAGE_INDEXED: + convert_image_to_surface_selector(image, dst, src_x, src_y, dst_x, dst_y, w, h, palette, &fd); + break; + + case IMAGE_BITMAP: + convert_image_to_surface_selector(image, dst, src_x, src_y, dst_x, dst_y, w, h, palette, &fd); + break; + default: ASSERT(false); throw std::runtime_error("conversion not supported"); diff --git a/src/raster/conversion_she.h b/src/raster/conversion_she.h index 7f68dbe78..210fc7ba6 100644 --- a/src/raster/conversion_she.h +++ b/src/raster/conversion_she.h @@ -28,7 +28,9 @@ namespace raster { class Image; class Palette; - void convert_image_to_surface(const Image* image, she::Surface* surface, int x, int y, const Palette* palette); + void convert_image_to_surface(const Image* image, const Palette* palette, + she::Surface* surface, + int src_x, int src_y, int dst_x, int dst_y, int w, int h); } // namespace raster