From 8cc38ccbe8791d9939172084f46d10107a9b6cb9 Mon Sep 17 00:00:00 2001 From: Dan Lawrence Date: Sun, 2 Jun 2024 15:26:19 +0100 Subject: [PATCH 1/2] use premul_alpha everywhere --- docs/source/theme_reference/theme_button.rst | 4 ++++ docs/source/theme_reference/theme_panel.rst | 1 + pygame_gui/core/ui_appearance_theme.py | 10 +++++++-- pygame_gui/core/utility.py | 23 +++++--------------- pygame_gui/elements/ui_image.py | 3 +-- 5 files changed, 19 insertions(+), 22 deletions(-) diff --git a/docs/source/theme_reference/theme_button.rst b/docs/source/theme_reference/theme_button.rst index db2ec820..f0bf0625 100644 --- a/docs/source/theme_reference/theme_button.rst +++ b/docs/source/theme_reference/theme_button.rst @@ -93,6 +93,7 @@ Images - "**package** - The name of the python package containing this resource - e.g. 'data.images' - "**resource** - The file name of the resource in the python package - e.g. 'splat.png' - Use a 'package' and 'resource' or a 'path' not both. - "**sub_surface_rect**" - An optional rectangle (described like "x,y,width,height") that will be used to grab a smaller portion of the image specified. This allows us to create many image surfaces from one image file. + - "**premultiplied**" - Optional parameter to declare that a loaded image already contains premultiplied alpha and does not need premultiplying. Set to "1" to enable, "0" to disable (default). - "**hovered_image**" - The image displayed in the buttons hovered state. It has the following block of sub-parameters: @@ -100,6 +101,7 @@ Images - "**package** - The name of the python package containing this resource - e.g. 'data.images' - "**resource** - The file name of the resource in the python package - e.g. 'splat.png' - Use a 'package' and 'resource' or a 'path' not both. - "**sub_surface_rect**" - An optional rectangle (described like "x,y,width,height") that will be used to grab a smaller portion of the image specified. This allows us to create many image surfaces from one image file. + - "**premultiplied**" - Optional parameter to declare that a loaded image already contains premultiplied alpha and does not need premultiplying. Set to "1" to enable, "0" to disable (default). - "**selected_image**" - The image displayed in the buttons select focused state. It has the following block of sub-parameters: @@ -107,6 +109,7 @@ Images - "**package** - The name of the python package containing this resource - e.g. 'data.images' - "**resource** - The file name of the resource in the python package - e.g. 'splat.png' - Use a 'package' and 'resource' or a 'path' not both. - "**sub_surface_rect**" - An optional rectangle (described like "x,y,width,height") that will be used to grab a smaller portion of the image specified. This allows us to create many image surfaces from one image file. + - "**premultiplied**" - Optional parameter to declare that a loaded image already contains premultiplied alpha and does not need premultiplying. Set to "1" to enable, "0" to disable (default). - "**disabled_image**" - The image displayed in the buttons disabled state. It has the following block of sub-parameters: @@ -114,6 +117,7 @@ Images - "**package** - The name of the python package containing this resource - e.g. 'data.images' - "**resource** - The file name of the resource in the python package - e.g. 'splat.png' - Use a 'package' and 'resource' or a 'path' not both. - "**sub_surface_rect**" - An optional rectangle (described like "x,y,width,height") that will be used to grab a smaller portion of the image specified. This allows us to create many image surfaces from one image file. + - "**premultiplied**" - Optional parameter to declare that a loaded image already contains premultiplied alpha and does not need premultiplying. Set to "1" to enable, "0" to disable (default). Misc diff --git a/docs/source/theme_reference/theme_panel.rst b/docs/source/theme_reference/theme_panel.rst index d9d0ddd0..89b0cc69 100644 --- a/docs/source/theme_reference/theme_panel.rst +++ b/docs/source/theme_reference/theme_panel.rst @@ -30,6 +30,7 @@ Images - "**package** - The name of the python package containing this resource - e.g. 'data.images' - "**resource** - The file name of the resource in the python package - e.g. 'splat.png' - Use a 'package' and 'resource' or a 'path' not both. - "**sub_surface_rect**" - An optional rectangle (described like "x,y,width,height") that will be used to grab a smaller portion of the image specified. This allows us to create many image surfaces from one image file. + - "**premultiplied**" - Optional parameter to declare that a loaded image already contains premultiplied alpha and does not need premultiplying. Set to "1" to enable, "0" to disable (default). Misc ---- diff --git a/pygame_gui/core/ui_appearance_theme.py b/pygame_gui/core/ui_appearance_theme.py index 46738e5f..700e0bbc 100644 --- a/pygame_gui/core/ui_appearance_theme.py +++ b/pygame_gui/core/ui_appearance_theme.py @@ -288,11 +288,14 @@ def _load_images(self): self.ui_element_image_surfaces[element_key][image_id] = surf_resource def _load_image_from_path(self, res_data): + premultiplied = False + if 'premultiplied' in res_data: + premultiplied = bool(res_data['premultiplied']) resource_id = res_data['path'] if resource_id in self.image_resources: image_resource = self.image_resources[resource_id] else: - image_resource = ImageResource(resource_id, res_data['path']) + image_resource = ImageResource(resource_id, res_data['path'], premultiplied) if self._resource_loader.started(): error = image_resource.load() if error is not None: @@ -304,12 +307,15 @@ def _load_image_from_path(self, res_data): return image_resource def _load_image_resource(self, res_data): + premultiplied = False + if 'premultiplied' in res_data: + premultiplied = bool(res_data['premultiplied']) resource_id = (str(res_data['package']) + '/' + str(res_data['resource'])) if resource_id in self.image_resources: image_resource = self.image_resources[resource_id] else: package_resource = PackageResource(res_data['package'], res_data['resource']) - image_resource = ImageResource(resource_id, package_resource) + image_resource = ImageResource(resource_id, package_resource, premultiplied) if self._resource_loader.started(): error = image_resource.load() if error is not None: diff --git a/pygame_gui/core/utility.py b/pygame_gui/core/utility.py index 212f761d..249e5f3e 100644 --- a/pygame_gui/core/utility.py +++ b/pygame_gui/core/utility.py @@ -279,21 +279,6 @@ def restore_premul_col(premul_colour: pygame.Color) -> pygame.Color: premul_colour.a) -def premul_alpha_surface(surface: pygame.surface.Surface) -> pygame.surface.Surface: - """ - Perform a pre-multiply alpha operation on a pygame surface's colours. - """ - surf_copy = surface.copy() - surf_copy.fill(pygame.Color('#FFFFFF00'), special_flags=pygame.BLEND_RGB_MAX) - manipulate_surf = pygame.surface.Surface(surf_copy.get_size(), - flags=pygame.SRCALPHA, depth=32) - # Can't be exactly transparent black or we trigger SDL1 'bug' - manipulate_surf.fill(pygame.Color('#00000001')) - manipulate_surf.blit(surf_copy, (0, 0)) - surface.blit(manipulate_surf, (0, 0), special_flags=pygame.BLEND_RGB_MULT) - return surface - - def render_white_text_alpha_black_bg(font: IGUIFontInterface, text: str) -> pygame.surface.Surface: """ @@ -458,10 +443,12 @@ class ImageResource: """ def __init__(self, image_id: str, - location: Union[PackageResource, str]): + location: Union[PackageResource, str], + premultiplied: bool): self.image_id = image_id self.location = location self.loaded_surface: Optional[pygame.Surface] = None + self.is_file_premultiplied = premultiplied def load(self) -> Union[Exception, None]: """ @@ -488,8 +475,8 @@ def load(self) -> Union[Exception, None]: str(self.location)) # perform pre-multiply alpha operation - if error is None and self.loaded_surface is not None: - premul_alpha_surface(self.loaded_surface) + if error is None and self.loaded_surface is not None and not self.is_file_premultiplied: + self.loaded_surface.premul_alpha() return error diff --git a/pygame_gui/elements/ui_image.py b/pygame_gui/elements/ui_image.py index 19cfa046..232893e5 100644 --- a/pygame_gui/elements/ui_image.py +++ b/pygame_gui/elements/ui_image.py @@ -5,7 +5,6 @@ from pygame_gui.core import ObjectID from pygame_gui.core.interfaces import IContainerLikeInterface, IUIManagerInterface from pygame_gui.core import UIElement -from pygame_gui.core.utility import premul_alpha_surface from pygame_gui.core.gui_type_hints import Coordinate, RectLike @@ -94,7 +93,7 @@ def set_image(self, """ image_surface = new_image.convert_alpha() if not image_is_alpha_premultiplied: - image_surface = premul_alpha_surface(image_surface) + image_surface = image_surface.premul_alpha() if (image_surface.get_width() != self.rect.width or image_surface.get_height() != self.rect.height): self.original_image = image_surface From c163217e743fc1837972abb28e973936c161161d Mon Sep 17 00:00:00 2001 From: Dan Lawrence Date: Sun, 2 Jun 2024 17:12:58 +0100 Subject: [PATCH 2/2] use premul_alpha everywhere --- pygame_gui/core/utility.py | 2 +- pygame_gui/elements/ui_text_entry_line.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pygame_gui/core/utility.py b/pygame_gui/core/utility.py index 249e5f3e..f99fc07f 100644 --- a/pygame_gui/core/utility.py +++ b/pygame_gui/core/utility.py @@ -476,7 +476,7 @@ def load(self) -> Union[Exception, None]: # perform pre-multiply alpha operation if error is None and self.loaded_surface is not None and not self.is_file_premultiplied: - self.loaded_surface.premul_alpha() + self.loaded_surface = self.loaded_surface.premul_alpha() return error diff --git a/pygame_gui/elements/ui_text_entry_line.py b/pygame_gui/elements/ui_text_entry_line.py index 0458d384..2d4a8a2e 100644 --- a/pygame_gui/elements/ui_text_entry_line.py +++ b/pygame_gui/elements/ui_text_entry_line.py @@ -403,6 +403,8 @@ def focus(self): self.drawable_shape.set_text(self.text) self.drawable_shape.text_box_layout.set_cursor_position(self.edit_position) self.drawable_shape.apply_active_text_changes() + self.drawable_shape.text_box_layout.turn_on_cursor() + self.redraw() def process_event(self, event: pygame.event.Event) -> bool: """ @@ -568,6 +570,8 @@ def _process_action_key_event(self, event: pygame.event.Event) -> bool: self.drawable_shape.text_box_layout.backspace_at_cursor() self.drawable_shape.text_box_layout.set_cursor_position(self.edit_position) self.drawable_shape.apply_active_text_changes() + if len(self.text) == 0: + self.redraw() consumed_event = True elif event.key == pygame.K_DELETE: if abs(self.select_range[0] - self.select_range[1]) > 0: