/* Copyright (C) 2009 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef _H_CANVAS #define _H_CANVAS #include "common.h" #include "debug.h" #include "cairo.h" #include "red.h" #include "cache.hpp" #include "shared_cache.hpp" #include "canvas_utils.h" #include "glz_decoded_image.h" #include "glz_decoder.h" enum CanvasType { CANVAS_TYPE_INVALID, CANVAS_TYPE_CAIRO, CANVAS_TYPE_GL, CANVAS_TYPE_GDI, }; struct QRegion; class PixmapCacheTreat { public: static inline cairo_surface_t *get(cairo_surface_t *surf) { return cairo_surface_reference(surf); } static inline void release(cairo_surface_t *surf) { cairo_surface_destroy(surf); } static const char* name() { return "pixmap";} }; typedef SharedCache PixmapCache; class CachedPalette { public: CachedPalette(Palette* palette) : _refs(1) { int size = sizeof(Palette) + palette->num_ents * sizeof(uint32_t); CachedPalette **ptr = (CachedPalette **)new uint8_t[size + sizeof(CachedPalette *)]; *ptr = this; _palette = (Palette*)(ptr + 1); memcpy(_palette, palette, size); } CachedPalette* ref() { _refs++; return this; } void unref() { if (--_refs == 0) { delete this; } } static void unref(Palette *pal) { CachedPalette **ptr = (CachedPalette **)pal; (*(ptr - 1))->unref(); } Palette* palette() { return _palette;} private: ~CachedPalette() { delete[] (uint8_t *)((CachedPalette **)_palette - 1); } private: int _refs; Palette* _palette; }; class PaletteCacheTreat { public: static inline CachedPalette* get(CachedPalette* palette) { return palette->ref(); } static inline void release(CachedPalette* palette) { palette->unref(); } static const char* name() { return "palette";} }; typedef Cache PaletteCache; /* Lz decoder related classes */ class GlzDecodedSurface: public GlzDecodedImage { public: GlzDecodedSurface(uint64_t id, uint64_t win_head_id, uint8_t *data, int size, int bytes_per_pixel, cairo_surface_t *surface) : GlzDecodedImage(id, win_head_id, data, size, bytes_per_pixel) , _surface (surface) { cairo_surface_reference(_surface); } virtual ~GlzDecodedSurface() { cairo_surface_destroy(_surface); } private: cairo_surface_t *_surface; }; class GlzDecodeSurfaceHandler: public GlzDecodeHandler { public: virtual GlzDecodedImage *alloc_image(void *opaque_usr_info, uint64_t image_id, uint64_t image_win_head_id, LzImageType type, int width, int height, int gross_pixels, int n_bytes_per_pixel, bool top_down) { cairo_surface_t *surface = alloc_lz_image_surface((LzDecodeUsrData *)opaque_usr_info, type, width, height, gross_pixels, top_down); uint8_t *data = cairo_image_surface_get_data(surface); if (!top_down) { data = data - (gross_pixels / height) * n_bytes_per_pixel * (height - 1); } return (new GlzDecodedSurface(image_id, image_win_head_id, data, gross_pixels, n_bytes_per_pixel, surface)); } }; /* TODO: unite with the window debug callbacks? */ class GlzDecoderCanvasDebug: public GlzDecoderDebug { public: virtual void error(const std::string& str) { throw Exception(str); } virtual void warn(const std::string& str) { LOG_WARN("%s", str.c_str()); } virtual void info(const std::string& str) { LOG_INFO("%s", str.c_str()); } }; class Canvas { public: Canvas(PixmapCache& bits_cache, PaletteCache& palette_cache, GlzDecoderWindow &glz_decoder_window); virtual ~Canvas(); virtual void copy_pixels(const QRegion& region, RedDrawable* dc, const PixmapHeader* pixmap) = 0; virtual void copy_pixels(const QRegion& region, RedDrawable& dc) = 0; virtual void thread_touch() = 0; virtual void clear() = 0; void draw_fill(RedFill& fill, int size); void draw_text(RedText& text, int size); void draw_opaque(RedOpaque& opaque, int size); void draw_copy(RedCopy& copy, int size); void draw_transparent(RedTransparent& transparent, int size); void draw_alpha_blend(RedAlphaBlend& alpha_blend, int size); void copy_bits(RedCopyBits& copy_bits, int size); void draw_blend(RedBlend& blend, int size); void draw_blackness(RedBlackness& blackness, int size); void draw_whiteness(RedWhiteness& whiteness, int size); void draw_invers(RedInvers& invers, int size); void draw_rop3(RedRop3& rop3, int size); void draw_stroke(RedStroke& stroke, int size); #ifdef WIN32 virtual void put_image(HDC dc, const PixmapHeader& image, const Rect& dest, const QRegion* clip) = 0; #else virtual void put_image(const PixmapHeader& image, const Rect& dest, const QRegion* clip) = 0; #endif virtual CanvasType get_pixmap_type() { return CANVAS_TYPE_INVALID; } protected: virtual void set_access_params(ADDRESS delta, unsigned long base, unsigned long max) = 0; virtual void draw_fill(Rect *bbox, Clip *clip, Fill *fill) = 0; virtual void draw_copy(Rect *bbox, Clip *clip, Copy *copy) = 0; virtual void draw_opaque(Rect *bbox, Clip *clip, Opaque *opaque) = 0; virtual void copy_bits(Rect *bbox, Clip *clip, Point *src_pos) = 0; virtual void draw_text(Rect *bbox, Clip *clip, Text *text) = 0; virtual void draw_stroke(Rect *bbox, Clip *clip, Stroke *stroke) = 0; virtual void draw_rop3(Rect *bbox, Clip *clip, Rop3 *rop3) = 0; virtual void draw_blend(Rect *bbox, Clip *clip, Blend *blend) = 0; virtual void draw_blackness(Rect *bbox, Clip *clip, Blackness *blackness) = 0; virtual void draw_whiteness(Rect *bbox, Clip *clip, Whiteness *whiteness) = 0; virtual void draw_invers(Rect *bbox, Clip *clip, Invers *invers) = 0; virtual void draw_transparent(Rect *bbox, Clip *clip, Transparent* transparent) = 0; virtual void draw_alpha_blend(Rect *bbox, Clip *clip, AlphaBlnd* alpha_blend) = 0; PixmapCache& pixmap_cache() { return _pixmap_cache;} PaletteCache& palette_cache() { return _palette_cache;} static void bits_cache_put(void *opaque, uint64_t id, cairo_surface_t *surface); static cairo_surface_t* bits_cache_get(void *opaque, uint64_t id); static void palette_cache_put(void *opaque, Palette *palette); static Palette* palette_cache_get(void *opaque, uint64_t id); static void palette_cache_release(Palette* palette); GlzDecoder& glz_decoder() {return _glz_decoder;} static void glz_decode(void *opaque, uint8_t *data, Palette *plt, void *usr_data); private: void access_test(void* ptr, size_t size); void localalize_ptr(ADDRESS* data); void localalize_image(ADDRESS* in_bitmap); void localalize_brush(Brush& brush); void localalize_attr(LineAttr& attr); void localalize_mask(QMask& mask); void begin_draw(RedDrawBase& base, int size, size_t min_size); private: PixmapCache& _pixmap_cache; PaletteCache& _palette_cache; GlzDecodeSurfaceHandler _glz_handler; GlzDecoderCanvasDebug _glz_debug; GlzDecoder _glz_decoder; unsigned long _base; unsigned long _max; }; #endif