From bed8281b2209f502da355fdf46df015744861a89 Mon Sep 17 00:00:00 2001 From: Joey Payne Date: Mon, 10 Feb 2014 13:43:15 -0700 Subject: [PATCH] Fixed some issues with image aspect ratio. Added preliminary gradient features for rounded rectangles. --- img/bluebanner.png | Bin 0 -> 33046 bytes img/test.png | Bin 0 -> 3155 bytes jgui/surface/structures.py | 43 +++++++++++- jgui/surface/surface.py | 140 ++++++++++++++++++++++++++++--------- testclasses.py | 37 +++++++++- 5 files changed, 184 insertions(+), 36 deletions(-) create mode 100644 img/bluebanner.png create mode 100644 img/test.png diff --git a/img/bluebanner.png b/img/bluebanner.png new file mode 100644 index 0000000000000000000000000000000000000000..3cf3050f0b54828d89ba798cea7345c4988cff0b GIT binary patch literal 33046 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 1.0 or offset < 0: + raise Exception('Offset must be between 0 and 1.') + self.offset = offset + self.color = Color.from_value(color) + + +class Gradient(StructureBase): + def __init__(self, start_position=(0,0), end_position=(0,1), stops=()): + self._type = 'linear' + self.stops = self.get_stops(stops) + self.start_position = Position.from_value(start_position) + self.end_position = Position.from_value(end_position) + + def get_stops(self, stops): + gstops = [] + for g_stop in stops: + gstops.append(GradientStop.from_value(g_stop)) + return gstops + + def add_stop(self, offset_pos, color): + self.stops.append(GradientStop.from_value((offset_pos, color))) + + +class RadialGradient(Gradient): + def __init__(self, inner_radius=0, outer_radius=1, *args, **kwargs): + super(RadialGradient, self).__init__(*args, **kwargs) + self._type = 'radial' + self.inner_radius = inner_radius + self.outer_radius = outer_radius + + class Rectangle(StructureBase): def __init__(self, position=None, size=None): """ A rectangle object with coordinates and size. diff --git a/jgui/surface/surface.py b/jgui/surface/surface.py index 0613478..3b24772 100644 --- a/jgui/surface/surface.py +++ b/jgui/surface/surface.py @@ -3,7 +3,7 @@ import pango import pangocairo as pc import gtk import math -from .structures import Size, Position, Rectangle, Color, BorderRadius, Padding +from .structures import Size, Position, Rectangle, Color, BorderRadius, Padding, Gradient, RadialGradient from ..events.events import WindowEventSource from ..logger import log @@ -135,14 +135,17 @@ class WindowSurface(object): context.arc(0, 0, 1, start_angle, end_angle * math.pi/180.0) context.restore() - context.set_source_rgba(*color) + context.set_source_rgba(color.r, color.g, color.b, color.a) context.fill_preserve() - context.set_source_rgba(*line_color) + context.set_source_rgba(line_color.r, line_color.g, line_color.b, line_color.a) context.stroke() def draw_image(self, image, position, size, - filter='none', stretch=True, - keep_aspect=True, center_horizontal=True, + filter='none', + stretch_horizontal=False, + stretch_vertical=False, + keep_ratio=False, + center_horizontal=True, center_vertical=True, image_offset=(0, 0)): context = self.context @@ -167,12 +170,18 @@ class WindowSurface(object): new_height = height new_width = width - if keep_aspect: - aspect_ratio = min(im_width, im_height)/float(max(im_width, im_height)) + if keep_ratio: + aspect_ratio = im_width/float(im_height) if width >= height: - new_width = aspect_ratio * new_height + if im_height < im_width: + new_height = width/aspect_ratio + else: + new_width = aspect_ratio * height else: - new_height = aspect_ratio * new_width + if im_height > im_width: + new_width = aspect_ratio * height + else: + new_height = width/aspect_ratio if center_horizontal: x += width/2.0 - new_width/2.0 @@ -192,8 +201,15 @@ class WindowSurface(object): ct3 = gtk.gdk.CairoContext(ct2) - if stretch: - ct3.scale(new_width/float(im_width), new_height/float(im_height)) + new_scale_x = 1 + new_scale_y = 1 + + if stretch_horizontal or keep_ratio: + new_scale_x = new_width/float(im_width) + if stretch_vertical or keep_ratio: + new_scale_y = new_height/float(im_height) + + ct3.scale(new_scale_x, new_scale_y) ct3.set_source_pixbuf(image, -offset.x, -offset.y) ct3.get_source().set_filter(self.filters[filter]) @@ -232,9 +248,7 @@ class WindowSurface(object): layout.set_alignment(alignment) context.set_line_width(line_width) - context.set_source_rgba(*font_color) - #context.select_font_face("Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) - #context.set_font_size(size.height) + context.set_source_rgba(font_color.r, font_color.g, font_color.b, font_color.a) extents = context.text_extents(text) @@ -244,7 +258,6 @@ class WindowSurface(object): context.move_to(x, y) pc_context.update_layout(layout) pc_context.show_layout(layout) - #context.show_text(text) def draw_lines(self, lines, line_color=(0,0,0,1), background_color=(1,1,1,1), line_width=1, line_join='miter', line_cap='butt'): @@ -267,18 +280,56 @@ class WindowSurface(object): context.set_line_join(self.line_caps[line_cap]) except KeyError: pass - context.set_source_rgba(*background_color) + context.set_source_rgba(background_color.r, background_color.g, background_color.b, background_color.a) context.fill_preserve() - context.set_source_rgba(*line_color) + context.set_source_rgba(line_color.r, line_color.g, line_color.b, line_color.a) context.stroke() + def render_radial_gradient(self, gradient, inner_radius=None, outer_radius=None): + context = self.context + position = self.position + size = self.size + gradient = RadialGradient.from_value(gradient) + rp = cairo.RadialGradient(gradient.start_position.x*float(size.width) + position.x, + gradient.start_position.y*float(size.height) + position.y, + inner_radius or gradient.inner_radius, + gradient.end_position.x*float(size.width) + position.x, + gradient.end_position.y*float(size.height) + position.y, + outer_radius or gradient.outer_radius) + for gstop in gradient.stops: + rp.add_color_stop_rgba(gstop.offset, gstop.color.r, gstop.color.g, + gstop.color.b, gstop.color.a) + if gradient.stops: + context.save() + context.set_source(rp) + context.fill_preserve() + context.restore() - def draw_rounded_rect(self, position, size, background_color=(1,1,1), line_width=1, line_color=(0,0,0), corner_radius=0, line_dashed=False, clip=False): + def render_linear_gradient(self, gradient): + context = self.context + position = self.position + size = self.size + gradient = Gradient.from_value(gradient) + lp = cairo.LinearGradient(gradient.start_position.x*float(size.width) + position.x, + gradient.start_position.y*float(size.height) + position.y, + gradient.end_position.x*float(size.width) + position.x, + gradient.end_position.y*float(size.height) + position.y) + for gstop in gradient.stops: + lp.add_color_stop_rgba(gstop.offset, gstop.color.r, gstop.color.g, + gstop.color.b, gstop.color.a) + if gradient.stops: + context.save() + context.set_source(lp) + context.fill_preserve() + context.restore() + + def draw_rounded_rect(self, position, size, background_color=(1,1,1), line_width=1, line_color=(0,0,0), corner_radius=0, line_dashed=False, clip=False, gradient=()): position = Position.from_value(position) size = Size.from_value(size) background_color = Color.from_value(background_color) line_color = Color.from_value(line_color) corner_radius = BorderRadius.from_value(corner_radius) + gradient = Gradient.from_value(gradient) context = self.context radius = corner_radius @@ -287,7 +338,9 @@ class WindowSurface(object): y = position.y + self.position.y width = size.width height = size.height + if clip: #clips the entire region so any child windows will be confined to the parent + context.new_path() context.arc(x + width - radius.topright - line_width/2.0, y + radius.topright + line_width/2.0, radius.topright+self.border_width/2.0, -90 * degrees, 0 * degrees) @@ -318,9 +371,18 @@ class WindowSurface(object): radius.topleft, 180 * degrees, 270 * degrees) context.close_path() - context.set_source_rgba(*background_color) + if gradient.stops: + if gradient._type == 'linear': + self.render_linear_gradient(gradient) + elif gradient._type == 'radial': + self.render_radial_gradient(gradient) + else: + context.set_source_rgba(background_color.r, background_color.g, background_color.b, background_color.a) + else: + context.set_source_rgba(background_color.r, background_color.g, background_color.b, background_color.a) + context.fill_preserve() - context.set_source_rgba(*line_color) + context.set_source_rgba(line_color.r, line_color.g, line_color.b, line_color.a) context.set_line_width(line_width) context.save() if line_dashed: @@ -329,6 +391,7 @@ class WindowSurface(object): context.restore() if clip: #clips the entire region so any child windows will be confined to the parent + context.new_path() context.arc(x + width - radius.topright - line_width/2.0, y + radius.topright + line_width/2.0, radius.topright-self.border_width/2.0, -90 * degrees, 0 * degrees) @@ -380,12 +443,15 @@ class Window(WindowEventSource, WindowSurface): self.background_color = Color.from_value(kwargs.pop('background_color', (0,0,0,0))) self.background_image = self.load_image(kwargs.pop('background_image', None)) self.background_image_filter = kwargs.pop('background_image_filter','none') - self.background_image_stretch = kwargs.pop('background_image_stretch', True) - self.background_image_keep_ratio = kwargs.pop('background_image_keep_ratio', True) + self.background_image_stretch_horizontal = kwargs.pop('background_image_stretch_horizontal', False) + self.background_image_stretch_vertical = kwargs.pop('background_image_stretch_vertical', False) + self.background_image_keep_ratio = kwargs.pop('background_image_keep_ratio', False) self.background_image_center_horizontal = kwargs.pop('background_image_center_horizontal', True) self.background_image_center_vertical = kwargs.pop('background_image_center_vertical', True) self.background_image_offset = Position.from_value(kwargs.pop('background_image_offset', (0, 0))) + self.gradient = Gradient.from_value(kwargs.pop('gradient', ())) + self.border_radius = BorderRadius.from_value(kwargs.pop('border_radius', 1)) self.padding = Padding.from_value(kwargs.pop('padding', 0)) self.dashed_border = kwargs.pop('dashed_border', False) @@ -421,13 +487,14 @@ class Window(WindowEventSource, WindowSurface): line_width=self.border_width, corner_radius=self.border_radius, line_dashed=self.dashed_border, - clip=self.clip_children) + clip=self.clip_children, gradient=self.gradient) if self.background_image is not None: self.draw_image(self.background_image, [0, 0], self.size, filter=self.background_image_filter, - stretch=self.background_image_stretch, - keep_aspect=self.background_image_keep_ratio, + stretch_horizontal=self.background_image_stretch_horizontal, + stretch_vertical=self.background_image_stretch_vertical, + keep_ratio=self.background_image_keep_ratio, center_horizontal=self.background_image_center_horizontal, center_vertical=self.background_image_center_vertical, image_offset=self.background_image_offset) @@ -463,25 +530,34 @@ class Window(WindowEventSource, WindowSurface): self.reject('mouse-left', self.click) self.reject('mouse-left-up', self.click_up) - def _restrict_pos_size(self, new_pos, new_size): + def _restrict_pos_size_height(self, new_pos, new_size): if new_size.height <= self.min_size.height: new_pos.y = self.position.y + self.size.height - self.min_size.height new_size.height = self.min_size.height - if new_size.width <= self.min_size.width: - new_pos.x = self.position.x + self.size.width - self.min_size.width - new_size.width = self.min_size.width - if self.max_size.height > -1 and new_size.height >= self.max_size.height: new_pos.y = self.position.y + self.size.height - self.max_size.height new_size.height = self.max_size.height + return new_pos, new_size + + def _restrict_pos_size_width(self, new_pos, new_size): + + if new_size.width <= self.min_size.width: + new_pos.x = self.position.x + self.size.width - self.min_size.width + new_size.width = self.min_size.width + if self.max_size.width > -1 and new_size.width >= self.max_size.width: new_pos.x = self.position.x + self.size.width - self.max_size.width new_size.width = self.max_size.width return new_pos, new_size + def _restrict_pos_size(self, new_pos, new_size): + self._restrict_pos_size_height(new_pos, new_size) + self._restrict_pos_size_width(new_pos, new_size) + return new_pos, new_size + def drag_bottomright_handle(self, obj, mouse_pos): diff = mouse_pos - self.mouse_diff old_size = Size.from_value(self.size) @@ -495,7 +571,7 @@ class Window(WindowEventSource, WindowSurface): new_pos = Position(self.position.x + diff.x, self.position.y) new_size = Size(self.size.width - diff.x, self.size.height + diff.y) - new_pos, new_size = self._restrict_pos_size(new_pos, new_size) + new_pos, new_size = self._restrict_pos_size_width(new_pos, new_size) if self.draggable: self.position = new_pos @@ -512,7 +588,7 @@ class Window(WindowEventSource, WindowSurface): new_pos = Position(self.position.x, self.position.y + diff.y) new_size = Size(self.size.width + diff.x, self.size.height - diff.y) - new_pos, new_size = self._restrict_pos_size(new_pos, new_size) + new_pos, new_size = self._restrict_pos_size_height(new_pos, new_size) if self.draggable: self.position = new_pos diff --git a/testclasses.py b/testclasses.py index 62a6d43..59bc459 100644 --- a/testclasses.py +++ b/testclasses.py @@ -1,4 +1,4 @@ -from jgui.surface import Surface, Window, Position, Size, Color, TextWindow, ImageWindow +from jgui.surface import Surface, Window, Position, Size, Color, TextWindow, ImageWindow, Gradient, RadialGradient import math, os from jgui.settings import IMG_DIR @@ -19,7 +19,13 @@ class TestSurface(Surface): clip_children=True, ignore_debug=True, background_image=os.path.join(IMG_DIR, 'wrench.png'), - background_image_filter='bilinear') + background_image_filter='bilinear', + background_image_keep_ratio=True, + background_image_center_vertical=True, + background_image_center_horizontal=True, + background_image_stretch_horizontal=True, + background_image_stretch_vertical=True, + gradient=RadialGradient(start_position=[0.5, 0], end_position=[0.5, 0.5], inner_radius=30, outer_radius=500, stops=[(0, Color(1,1,1)), (1, Color(0.3,0.3,0.3))])) my_win.add_child(TextWindow('text','Micro Bean is the best bean ever.', position=[20,20], size=[100, 50], @@ -28,6 +34,33 @@ class TestSurface(Surface): draggable=True)) self.root_window.add_child(my_win) + + my_win2 = Window('linear_gradient', + position=[400, 400], + size=[500,500], + draggable=True, + resizable=True, + min_size=Size(40,40), + border_width=5, + border_radius=[40,20], + border_color=(0,0,0), + background_color=(1,1,1), + clip_children=True, + ignore_debug=True, + background_image=os.path.join(IMG_DIR, 'bluebanner.png'), + background_image_filter='bilinear', + background_image_keep_ratio=True, + background_image_center_vertical=False, + background_image_center_horizontal=False, + gradient=Gradient(stops=[(0, Color(1,1,1)), (0.8, Color(0.5,0.5,0.5)), (1, Color(0.7,0.7,0.7))])) + + my_win2.add_child(TextWindow('text2',"I haven't had a bean in forever.", + position=[20,20], size=[200, 100], + resizable=False, clip_children=True, + font_color=(0,0,0), padding=20, + draggable=False)) + + self.root_window.add_child(my_win2) #self.root_window.add_child(TestWindow('child2', position=[200,200], # size=[200,200], draggable=True))