#161552 - keldon - Wed Aug 06, 2008 7:31 am
I had initially created an image class (call it Mark I) that was a final class and worked directly with its pixel data (although the images were composed of PIXEL_BUFFER objects for each line). This allowed me to make one image refer to a subsection of another image with the same [fast] access speed and also join images together so that one image could represent both screens.
The image was overly bloated, doing far too much, such as filling (opaque and translucent), line drawing and text drawing:
I created a second class design using an abstract base class (call it Mark II). It makes no assumptions on whether the image is able to store graphics or not, allowing for some interesting compositions, such as an image that streams from file, containing [say] a section stored in VRAM (that waits for VBL when written to), while also holding a window view of another image. This image class has the following interface:
For further operations I created a GRAPHICS class for handling more complex drawing tasks. Functionally it couldn't be better (so to speak), but images that are composed of other images provides slow fill rates (due to the composition), although image blitting is fine. For example, I can load an image and copy it to screen quicker than I can paint a filled rectangle (with an image hidden behind 1-3 layers). In this system the GRAPHICS class is created independently of the IMAGE (taking the IMAGE as a parameter). The composition is necessary
Despite the lacking design of Mark I, it has proved useful for mapping both screens to a single image and creating window views of other images with fast draw speeds (due to its PIXEL_BUFFER approach, which allows the composed image to directly access the data).
For Mark III I would like to improve the performance for lower level operations (if possible) without sacrificing the freedom of the design. I could move rect-filling over to the IMAGE class (or at least as a method that only draws on one line). If anything, does anyone have any good experiences to add with these needs in mind.
p.s. purpose: bitmap mode GUI implementation (hence the benefit of being able to create IMAGE view ports).
The image was overly bloated, doing far too much, such as filling (opaque and translucent), line drawing and text drawing:
Code: |
class DS_BITMAP
{ public: enum DATA_MODE { RGB, ARGB, ARGB_SEMI }; DS_BITMAP (void); DS_BITMAP ( BITMAP_BUFFER_ALLOCATION<>& bitmap_allocation ); DS_BITMAP ( int _width, int _height, COLOUR *_bitmap_buffer = NULL ); DS_BITMAP ( DS_BITMAP& bitmap, int x, int y, int width, int height ); DS_BITMAP ( int _height, PIXEL_BUFFER* pixel_buffer_array ); ~DS_BITMAP (void); // methods void clear_bitmap ( COLOUR clear_colour = RGBA (0,0,0,0) ); const BOOL contains ( int x, int y ) const; void draw_bitmap ( int x, int y, const DS_BITMAP &ds_bitmap, BOOL is_only_drawing_updated_pixels = FALSE ); void draw_bitmap ( int dx, int dy, int sx1, int sy1, int sx2, int sy2, const DS_BITMAP &ds_bitmap, BOOL is_only_drawing_updated_pixels = FALSE ); void draw_line ( int x1, int y1, int x2, int y2, COLOUR colour, LINE_STYLE line_style ); void draw_line ( int x1, int y1, int x2, int y2, COLOUR colour ); void draw_text_background ( int x, int y, FONT_ID font_id, COLOUR bg_colour, const char* const text ); void draw_text ( int x, int y, FONT_ID font_id, COLOUR colour, const char* const text, int cursor_pos = -1 ); void draw_clip_text ( int x, int y, int width, FONT_ID font_id, COLOUR colour, const char* const text ); void draw_formatted_text ( int positioning, FONT_ID font_id, COLOUR text_colour, const char* const text, int cursor_pos = -1 ); void draw_formatted_text( int x1, int y1, int x2, int y2, int positioning, FONT_ID id, COLOUR text_colour, const char* const text, int cursor_pos = -1); void draw_rect ( int x, int y, int width, int height, COLOUR colour ); void fill_rect ( int x, int y, int width, int height, COLOUR colour ); void fill_semi_transparent_rect ( int x, int y, int width, int height, COLOUR colour ); void draw_border ( COLOUR colour, int size = 1 ); void clear_edited_region (void); void invalidate_pixel (int x, int y); void set_data_mode ( DATA_MODE mode ) { data_mode = mode; }; const DATA_MODE get_data_mode (void) const { return data_mode; }; const COLOUR get_pixel ( int x, int y ) const; void set_pixel ( int x, int y, COLOUR colour ); void set_pixel_without_invalidation ( int x, int y, COLOUR colour ); const int get_height (void) const { return height; }; const int get_width (void) const { return width; }; const DIMENSION get_dimension (void) const { return DIMENSION (get_width(), get_height()); }; const PIXEL_BUFFER& get_pixel_buffer ( int y ) const; PIXEL_BUFFER& get_pixel_buffer ( int y ); } |
I created a second class design using an abstract base class (call it Mark II). It makes no assumptions on whether the image is able to store graphics or not, allowing for some interesting compositions, such as an image that streams from file, containing [say] a section stored in VRAM (that waits for VBL when written to), while also holding a window view of another image. This image class has the following interface:
Code: |
class IMAGE
{ public: IMAGE (void); virtual ~IMAGE (void) {;}; virtual const DIMENSION2D get_size (void) const =0; const int get_width (void) const; const int get_height (void) const; virtual const COLOUR get_pixel (int x, int y) const =0; virtual void set_pixel (int x, int y, COLOUR colour) =0; virtual void draw_image (const IMAGE&, int dx, int dy, int sx, int sy, int width, int height) =0; void draw_image (const IMAGE&, int dx, int dy); virtual void blit_line (COLOUR *data, int x, int y, int width) const =0; virtual const bool contains (int x, int y) const; virtual const DRAW_MODE get_draw_mode (void) const; virtual void set_draw_mode (DRAW_MODE draw_mode); private: DRAW_MODE draw_mode_; }; // IMAGE |
For further operations I created a GRAPHICS class for handling more complex drawing tasks. Functionally it couldn't be better (so to speak), but images that are composed of other images provides slow fill rates (due to the composition), although image blitting is fine. For example, I can load an image and copy it to screen quicker than I can paint a filled rectangle (with an image hidden behind 1-3 layers). In this system the GRAPHICS class is created independently of the IMAGE (taking the IMAGE as a parameter). The composition is necessary
Despite the lacking design of Mark I, it has proved useful for mapping both screens to a single image and creating window views of other images with fast draw speeds (due to its PIXEL_BUFFER approach, which allows the composed image to directly access the data).
For Mark III I would like to improve the performance for lower level operations (if possible) without sacrificing the freedom of the design. I could move rect-filling over to the IMAGE class (or at least as a method that only draws on one line). If anything, does anyone have any good experiences to add with these needs in mind.
p.s. purpose: bitmap mode GUI implementation (hence the benefit of being able to create IMAGE view ports).