indexing description: "[ Singleton factory that creates objects of type EM_BITMAP. Use EM_SHARED_BITMAP_FACTORY to access this singleton. ]" date: "$Date$" revision: "$Revision$" class EM_BITMAP_FACTORY inherit EM_SHARED_SUBSYSTEMS export {NONE} all {ANY} Video_subsystem end EM_SHARED_ERROR_HANDLER export {NONE} all end SDL_IMAGE_FUNCTIONS_EXTERNAL export {NONE} all end SDL_VIDEO_FUNCTIONS_EXTERNAL export {NONE} all end SDL_ROTOZOOM_FUNCTIONS_EXTERNAL export {NONE} all end SDL_RWOPS_FUNCTIONS_EXTERNAL export {NONE} all end KL_SHARED_FILE_SYSTEM export {NONE} all end PLATFORM export {NONE} all end create {EM_SHARED_BITMAP_FACTORY} make feature {NONE} -- Initialization make is -- Create new bitmap factory. do end feature -- Access last_bitmap: EM_BITMAP -- Last bitmap created last_surface: EM_SURFACE -- Last surface created feature -- Bitmap creation create_empty_bitmap (a_width: INTEGER; a_height: INTEGER) is -- Create empty surface with the width `a_width' and the height -- `a_height' in the same format as -- `video_subsystem.video_surface'. Make resulting surface -- available via `last_bitmap'. -- If the bitmap could not be created an exception is raised. require a_width_positive: a_width >= 0 a_height_positive: a_height >= 0 video_subsystem_is_enabled: video_subsystem.is_enabled local temp_surface_pointer: POINTER surface_pointer: POINTER do last_bitmap := Void temp_surface_pointer := sdl_create_rgbsurface_external (0, a_width, a_height, 32, 0, 0, 0, 0) if temp_surface_pointer /= default_pointer then -- Convert `temp_surface_pointer' to `surface_pointer' in same format as display, if successful. surface_pointer := sdl_display_format_external (temp_surface_pointer) sdl_free_surface_external (temp_surface_pointer) if surface_pointer /= default_pointer then create last_bitmap.make_from_pointer (surface_pointer) end end if last_bitmap = Void then Error_handler.raise_error (Error_handler.Em_error_create_empty_bitmap, [a_width, a_height]) else last_bitmap.set_visible (True) end ensure bitmap_created: last_bitmap /= Void height_set: last_bitmap.height = a_height width_set: last_bitmap.width = a_width bitmap_is_visible: last_bitmap.is_visible end create_empty_alpha_bitmap (a_width, a_height: INTEGER) is -- Create empty surface with the width `a_width' and the height -- `a_height' and in the same format as -- `video_subsystem.video_surface'. Make resulting surface -- available via `last_bitmap'. -- If the bitmap could not be created an exception is raised. -- Note: The created surface has per pixel alpha transparency enabled. --- As a result of that neither per surface alpha transparency nor a --- transparent colorkey is enabled. require a_width_positive: a_width >= 0 a_height_positive: a_height >= 0 video_subsystem_is_enabled: video_subsystem.is_enabled local temp_surface_pointer: POINTER surface_pointer: POINTER do last_bitmap := Void temp_surface_pointer := sdl_create_rgbsurface_external (0, a_width, a_height, 32, 0, 0, 0, 0) if temp_surface_pointer /= default_pointer then -- Convert `temp_surface_pointer' to `surface_pointer' in same format as display, if successful. surface_pointer := sdl_display_format_alpha_external (temp_surface_pointer) sdl_free_surface_external (temp_surface_pointer) if surface_pointer /= default_pointer then create last_bitmap.make_from_pointer (surface_pointer) end end if last_bitmap = Void then Error_handler.raise_error (Error_handler.Em_error_create_empty_alpha_bitmap, [a_width, a_height]) else last_bitmap.set_visible (True) end ensure bitmap_created: last_bitmap /= Void height_set: last_bitmap.height = a_height width_set: last_bitmap.width = a_width per_pixel_alpha_enabled: last_bitmap.is_per_pixel_alpha_enabled bitmap_is_visible: last_bitmap.is_visible end create_empty_open_gl_bitmap (a_width:INTEGER; a_height:INTEGER) is -- Create empty OpenGL accelerated surface with the width -- `a_width' and height `a_height'. Make resulting surface -- available via `last_bitmap'. -- If the bitmap could not be created an exception is raised. local p: POINTER endian_test: MANAGED_POINTER do last_bitmap := Void -- TODO: Move endian test into a class of its own -- Check for big/little-endian and change masks create endian_test.make (integer_32_bytes) endian_test.put_integer_32 (5, 0) if endian_test.read_integer_32_le (0) = 5 -- Little-endian then p := sdl_create_rgbsurface_external (0,a_width, a_height,32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 ) -- Big-endian else p := sdl_create_rgbsurface_external (0,a_width, a_height,32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF ) end if p /= Default_pointer then create last_bitmap.make_from_pointer (p) end if last_bitmap = Void then Error_handler.raise_error (Error_handler.Em_error_create_empty_opengl_bitmap, [a_width, a_height]) else last_bitmap.set_visible (True) end ensure bitmap_created: last_bitmap /= Void height_set: last_bitmap.height = a_height width_set: last_bitmap.width = a_width bitmap_is_visible: last_bitmap.is_visible end create_bitmap_from_image (a_filename: STRING) is -- Create bitmap surface and initialize it using the image -- from the file named `a_filename'. Make resulting bitmap -- available via `last_bitmap'. -- If the image could not be loaded an exception is raised. require a_filename_not_void: a_filename /= Void local c_string: EWG_ZERO_TERMINATED_STRING temp_image_pointer: POINTER image_pointer: POINTER do last_bitmap := Void create c_string.make_unshared_from_string (a_filename) temp_image_pointer := img_load_external (c_string.item) if temp_image_pointer /= Default_pointer then image_pointer := sdl_display_format_alpha_external (temp_image_pointer) sdl_free_surface_external (temp_image_pointer) if image_pointer /= default_pointer then create last_bitmap.make_from_pointer (image_pointer) end end if last_bitmap = Void then if File_system.file_exists (a_filename) then Error_handler.raise_error (Error_handler.Em_error_loading_image_format_not_supported, [a_filename]) else Error_handler.raise_error (Error_handler.Em_error_loading_image_does_not_exist, [a_filename]) end else last_bitmap.set_visible (True) end ensure image_loaded: last_bitmap /= Void bitmap_is_visible: last_bitmap.is_visible end create_bitmap_from_surface_part (a_surface: EM_SURFACE; an_x, a_y, a_width, a_height: INTEGER) is -- Create bitmap with the width `a_width' and the height -- `a_height'. Initialize bitmap with the content of surface -- `a_surface' at the frame starting at position (`an_x', -- `a_y_pos'. Make new bitmap available via `last_bimap'. -- If the bitmap could not be created an exception is raised. require a_surface_not_void: a_surface /= Void an_x: an_x >= 0 a_y: a_y >= 0 a_width_positive: a_width > 0 a_height_positive: a_height > 0 local colkey: INTEGER has_colkey: BOOLEAN do last_bitmap := Void has_colkey := a_surface.has_transparent_colorkey colkey := a_surface.transparent_colorkey if has_colkey then a_surface.disable_transparent_colorkey end create_empty_bitmap (a_width, a_height) if last_bitmap /= Void then last_bitmap.blit_surface_part (a_surface, an_x, a_y, a_width, a_height, 0, 0) if has_colkey then a_surface.set_transparent_colorkey (colkey) last_bitmap.set_transparent_colorkey (colkey) end last_bitmap.set_anti_aliasing_enabled (a_surface.is_anti_aliasing_enabled) end if last_bitmap = Void then Error_handler.raise_error (Error_handler.Em_error_create_bitmap_from_surface_part, [an_x, a_y, a_width, a_height]) else last_bitmap.set_visible (True) end ensure bitmap_created: last_bitmap /= Void transparent_colorkey_transfered: a_surface.has_transparent_colorkey implies last_bitmap.transparent_colorkey = a_surface.transparent_colorkey anti_aliasing_as_in_source: a_surface.is_anti_aliasing_enabled = last_bitmap.is_anti_aliasing_enabled bitmap_is_visible: last_bitmap.is_visible end create_zoomed_bitmap (a_surface: EM_SURFACE; a_zoom_factor: DOUBLE) is -- Create zoomed (by the factor `a_zoom_factor') bitmap from -- surface `a_surface'. Make new bitmap available via `last_bimap'. -- If the bitmap could not be created an exception is raised. require a_surface_not_void: a_surface /= Void positive_zoom_factor: a_zoom_factor > 0 local p: POINTER do p := zoom_surface_external (a_surface.item, a_zoom_factor, a_zoom_factor, a_surface.is_anti_aliasing_enabled.to_integer) if p /= default_pointer then create last_bitmap.make_from_pointer (p) if a_surface.has_transparent_colorkey then last_bitmap.set_transparent_colorkey (a_surface.transparent_colorkey) end last_bitmap.set_anti_aliasing_enabled (a_surface.is_anti_aliasing_enabled) end if last_bitmap = Void then Error_handler.raise_error (Error_handler.Em_error_create_zoomed_bitmap, [a_zoom_factor]) else last_bitmap.set_visible (True) end ensure bitmap_created: last_bitmap /= Void transparent_colorkey_transfered: a_surface.has_transparent_colorkey implies last_bitmap.transparent_colorkey = a_surface.transparent_colorkey anti_aliasing_as_in_source: a_surface.is_anti_aliasing_enabled = last_bitmap.is_anti_aliasing_enabled bitmap_is_visible: last_bitmap.is_visible -- TODO: ensure height and width end create_stretched_bitmap (a_surface: EM_SURFACE; an_x_factor, a_y_factor: DOUBLE) is -- Create stretched (horizontally by `an_x_factor', vertically -- by `a_y_factor') bitmap from `a_surface'. Make new bitmap -- available via `last_bimap'. -- If the bitmap could not be created an exception is raised. require a_surface_not_void: a_surface /= Void an_x_factor_is_positive: an_x_factor > 0 a_y_factor_is_positive: a_y_factor > 0 local p: POINTER do p := zoom_surface_external (a_surface.item, an_x_factor, a_y_factor, a_surface.is_anti_aliasing_enabled.to_integer) if p /= default_pointer then create last_bitmap.make_from_pointer (p) if a_surface.has_transparent_colorkey then last_bitmap.set_transparent_colorkey (a_surface.transparent_colorkey) end last_bitmap.set_anti_aliasing_enabled (a_surface.is_anti_aliasing_enabled) end if last_bitmap = Void then Error_handler.raise_error (Error_handler.Em_error_create_stretched_bitmap, [an_x_factor, a_y_factor]) else last_bitmap.set_visible (True) end ensure bitmap_created: last_bitmap /= Void transparent_colorkey_transfered: a_surface.has_transparent_colorkey implies last_bitmap.transparent_colorkey = a_surface.transparent_colorkey anti_aliasing_as_in_source: a_surface.is_anti_aliasing_enabled = last_bitmap.is_anti_aliasing_enabled bitmap_is_visible: last_bitmap.is_visible -- TODO: ensure height and width end create_rotated_bitmap (a_surface: EM_SURFACE; an_angle: DOUBLE) is -- Create rotated (by angle `an_angle') bitmap from -- `a_surface'. Make new bitmap available via `last_bimap'. -- If the bitmap could not be created an exception is raised. require a_surface_not_void: a_surface /= Void local p: POINTER do p := rotozoom_surface_external (a_surface.item, an_angle, 1.0, a_surface.is_anti_aliasing_enabled.to_integer) if p /= default_pointer then create last_bitmap.make_from_pointer (p) if a_surface.has_transparent_colorkey then last_bitmap.set_transparent_colorkey (a_surface.transparent_colorkey) end last_bitmap.set_anti_aliasing_enabled (a_surface.is_anti_aliasing_enabled) end if last_bitmap = Void then Error_handler.raise_error (Error_handler.Em_error_create_rotated_bitmap, [an_angle]) else last_bitmap.set_visible (True) end ensure transparent_colorkey_transfered: last_bitmap /= Void implies a_surface.has_transparent_colorkey implies last_bitmap.transparent_colorkey = a_surface.transparent_colorkey anti_aliasing_as_in_source: last_bitmap /= Void implies a_surface.is_anti_aliasing_enabled = last_bitmap.is_anti_aliasing_enabled bitmap_is_visible: last_bitmap.is_visible end create_transformed_bitmap (a_surface: EM_SURFACE; an_x_factor, a_y_factor, an_angle: DOUBLE) is -- Create stretched (horizontally by `an_x_factor', vertically -- by `a_y_factor') and rotated (by angle `an_angle') bitmap -- from `a_surface'. Make new bitmap available via `last_bimap' -- If the bitmap could not be created an exception is raised. require a_surface_not_void: a_surface /= Void local p, q: POINTER do last_bitmap := Void last_surface := Void -- TODO: `rotozoom_surface_xy' requires SDL_gfx 2.0.13, for which there is no deb yet. Reenable as soon as deb is there. -- p := rotozoom_surface_xy_external (a_surface.item, an_angle, an_x_factor, a_y_factor, a_surface.is_anti_aliasing_enabled.to_integer) q := zoom_surface_external (a_surface.item, an_x_factor, a_y_factor, a_surface.is_anti_aliasing_enabled.to_integer) p := rotozoom_surface_external (q, an_angle, 1, a_surface.is_anti_aliasing_enabled.to_integer) sdl_free_surface_external (q) if p /= default_pointer then create last_bitmap.make_from_pointer (p) if a_surface.has_transparent_colorkey then last_bitmap.set_transparent_colorkey (a_surface.transparent_colorkey) end last_bitmap.set_anti_aliasing_enabled (a_surface.is_anti_aliasing_enabled) end if last_bitmap = Void then Error_handler.raise_error (Error_handler.Em_error_create_transformed_bitmap, [an_x_factor, a_y_factor, an_angle]) else last_bitmap.set_visible (True) end ensure bitmap_created: last_bitmap /= Void transparent_colorkey_transfered: a_surface.has_transparent_colorkey implies last_bitmap.transparent_colorkey = a_surface.transparent_colorkey anti_aliasing_as_in_source: a_surface.is_anti_aliasing_enabled = last_bitmap.is_anti_aliasing_enabled bitmap_is_visible: last_bitmap.is_visible -- TODO: ensure height and width end create_bitmap_from_c_array (an_array: POINTER; size: INTEGER) is -- create bitmap using a c array as source. -- Make new bitmap available via `last_bimap'. -- If creation fails set `last_bitmap' to `Void'. local rwops_pointer, surface_pointer, temp_surface_pointer: POINTER do last_bitmap := Void rwops_pointer := sdl_rwfrom_mem_external (an_array, size) temp_surface_pointer := img_load_rw_external (rwops_pointer, 1) if temp_surface_pointer /= default_pointer then surface_pointer := sdl_display_format_external (temp_surface_pointer) sdl_free_surface_external (temp_surface_pointer) if surface_pointer /= default_pointer then create last_bitmap.make_from_pointer (surface_pointer) end end if last_bitmap /= Void then last_bitmap.set_visible (True) end ensure bitmap_is_visible: (last_bitmap /= Void) implies (last_bitmap.is_visible) end feature -- Surface creation create_empty_surface (a_width: INTEGER; a_height: INTEGER) is -- Create empty surface with dimension `a_width' `a_height'. -- The format is the same as`video_subsystem.video_surface'. -- Make resulting surface available via `last_surface'. -- If the surface could not be created an exception is raised. require a_width_positive: a_width >= 0 a_height_positive: a_height >= 0 video_subsystem_is_enabled: video_subsystem.is_enabled local temp_surface_pointer: POINTER surface_pointer: POINTER do last_bitmap := Void last_surface := Void temp_surface_pointer := sdl_create_rgbsurface_external (0, a_width, a_height, 32, 0, 0, 0, 0) if temp_surface_pointer /= default_pointer then -- Convert `temp_surface_pointer' to `surface_pointer' in same format as display, if successful. surface_pointer := sdl_display_format_external (temp_surface_pointer) sdl_free_surface_external (temp_surface_pointer) if surface_pointer /= default_pointer then create last_surface.make_from_pointer (surface_pointer) end end if last_surface = Void then Error_handler.raise_error (Error_handler.em_error_create_empty_surface, [a_width, a_height]) end ensure surface_created: last_surface /= Void height_set: last_surface.height = a_height width_set: last_surface.width = a_width end create_empty_alpha_surface (a_width, a_height: INTEGER) is -- Create empty surface with dimension `a_width' `a_height'. -- The format is the same as`video_subsystem.video_surface'. -- Make resulting surface available via `last_surface'. -- If the surface could not be created an exception is raised. -- Note: The created surface has per pixel alpha transparency enabled. --- As a result of that neither per surface alpha transparency nor a --- transparent colorkey is enabled. require a_width_positive: a_width >= 0 a_height_positive: a_height >= 0 video_subsystem_is_enabled: video_subsystem.is_enabled local temp_surface_pointer: POINTER surface_pointer: POINTER do last_bitmap := Void last_surface := Void temp_surface_pointer := sdl_create_rgbsurface_external (0, a_width, a_height, 32, 0, 0, 0, 0) if temp_surface_pointer /= default_pointer then -- Convert `temp_surface_pointer' to `surface_pointer' in same format as display, if successful. surface_pointer := sdl_display_format_alpha_external (temp_surface_pointer) sdl_free_surface_external (temp_surface_pointer) if surface_pointer /= default_pointer then create last_surface.make_from_pointer (surface_pointer) end end if last_surface = Void then Error_handler.raise_error (Error_handler.em_error_create_empty_alpha_surface, [a_width, a_height]) end ensure surface_created: last_surface /= Void height_set: last_surface.height = a_height width_set: last_surface.width = a_width per_pixel_alpha_enabled: last_surface.is_per_pixel_alpha_enabled end end