#!/usr/bin/python # -*- mode: python; coding: utf-8; -*- # ============================================================================= # Copyright (C) 2017-2023 LB # # 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 3 of the License, or # (at your option) any later version. # # ============================================================================= import math # import inspect from kivy.graphics import Color from kivy.graphics import Rectangle from kivy.properties import ObjectProperty from kivy.properties import StringProperty from kivy.uix.image import Image as KivyImage from kivy.uix.widget import Widget from pysollib.kivy.LBase import LBase # ============================================================================= class LImage(Widget, LBase): CONTAIN = 0 FILL = 1 COVER = 2 SCALE_DOWN = 3 TILING = 4 fit_mode = StringProperty("fill") texture = ObjectProperty(None, allownone=True) def make_scale_down(self, s, p): r = self.rect t = self.texture.size if (t[0] > s[0]) or (t[1] > s[1]): self.make_contain(s, p) else: r.size = t r.pos = (p[0]+(s[0]-t[0])/2.0, p[1]+(s[1]-t[1])/2.0) def make_fill(self, s, p): self.rect.size = s self.rect.pos = p def make_contain(self, s, p): taspect = self.texture.size[0]/self.texture.size[1] waspect = s[0]/s[1] r = self.rect if waspect < taspect: s1 = s[1]*waspect/taspect r.size = (s[0], s1) r.pos = (p[0], p[1]+(s[1]-s1)/2.0) else: s0 = s[0]/waspect*taspect r.size = (s0, s[1]) r.pos = (p[0]+(s[0]-s0)/2.0, p[1]) def make_cover(self, s, p): aspect = self.texture.size[0]/self.texture.size[1] waspect = self.size[0]/self.size[1] print ('aspect: ', aspect) # noqa print ('waspect: ', waspect) # noqa # 'clamp_to_edge','repeat','mirrored_repeat' self.texture.wrap = 'repeat' print ('wrap: ',self.texture.wrap) # noqa # set rect size/pos to window self.rect.size = s self.rect.pos = p # evaluate original texture coords ? u = uu = self.tex_u # noqa v = vv = self.tex_v # noqa w = ww = self.tex_w h = hh = self.tex_h # in order to center the image in the window # modify texture coords if waspect < aspect: w = ww/aspect*waspect # noqa u = 0.5 - w/2.0 # noqa else: h = hh*aspect/waspect # noqa v = 0.5 - h/2.0 # noqa # and update them. tc = ( u, v, u + w, v, u + w, v + h, u, v + h ) # noqa self.rect.tex_coords = tc def make_tiling(self, s, p): # set rect size/pos to window self.rect.size = s self.rect.pos = p # number of repetitions t = self.texture t.wrap = 'repeat' stepsy = self.size[1] / t.size[1] stepsx = self.size[0] / t.size[0] # set coord parameters. w = self.tex_w * stepsx h = self.tex_h * stepsy u = self.tex_u v = stepsy - math.floor(stepsy) self.rect.tex_coords = ( u, v, u + w, v, u + w, v + h, u, v + h ) # noqa def make_format(self, size, pos): if hasattr(self, "rect"): if self.texture is None: self.rect.size = size self.rect.pos = pos elif self.fit_num == self.CONTAIN: self.make_contain(size, pos) elif self.fit_num == self.FILL: self.make_fill(size, pos) elif self.fit_num == self.COVER: self.make_cover(size, pos) elif self.fit_num == self.SCALE_DOWN: self.make_scale_down(size, pos) elif self.fit_num == self.TILING: self.make_tiling(size, pos) def __init__(self, **kwargs): super(LImage, self).__init__(**kwargs) # NOTE: # properties self.texture and self.fit_mode are # already set here from the super call either to its # default value or set from evaluaion of a matching kwargs # entry. ''' print('LImage __init__: ',self) print('stack[1] = ',inspect.stack()[1].frame) print('stack[2] = ',inspect.stack()[2].frame) print('texture=',self.texture) print('fit_mode=',self.fit_mode) ''' self.corePos = None self.coreSize = None self.source = None if "source" in kwargs: self.source = kwargs["source"] image = KivyImage(source=self.source) self.texture = image.texture # update fit_num from fit_mode (needs self.fit_num defined) self.fit_num = self.FILL self.fit_num_update(self.fit_mode) # setup canvas. self.background = False if "background" in kwargs: self.background = kwargs["background"] if self.background: with self.canvas.before: self.color = Color(1.0,1.0,1.0,1.0) # noqa self.rect = Rectangle(texture=self.texture) else: with self.canvas: self.color = Color(1.0,1.0,1.0,1.0) # noqa self.rect = Rectangle(texture=self.texture) # save original tex_coords (needs self.rect defined) self.tex_coord_update(self.texture) # initial size is the natural size of the image. self.size = self.texture.size def tex_coord_update(self, texture): if hasattr(self, "rect"): self.rect.texture = texture self.tex_u = self.rect.tex_coords[0] self.tex_v = self.rect.tex_coords[1] self.tex_w = self.rect.tex_coords[2] - self.tex_u self.tex_h = self.rect.tex_coords[5] - self.tex_v def fit_num_update(self, fit_mode): if hasattr(self, "fit_num"): if fit_mode == "contain": self.fit_num = self.CONTAIN if fit_mode == "fill": self.fit_num = self.FILL if fit_mode == "cover": self.fit_num = self.COVER if fit_mode == "scale_down": self.fit_num = self.SCALE_DOWN if fit_mode == "tiling": self.fit_num = self.TILING def on_size(self, a, s): self.make_format(s, self.pos) def on_pos(self, a, p): self.make_format(self.size, p) def on_fit_mode(self, a, m): self.fit_num_update(self.fit_mode) self.make_format(self.size, self.pos) def on_texture(self, a, texture): self.tex_coord_update(self.texture) self.make_format(self.size, self.pos) def setColor(self, color): self.color.rgba = color def getHeight(self): return self.size[1] def getWidth(self): return self.size[0] def subsample(self, r): return LImage(texture=self.texture) def on_touch_down(self, touch): # print('LImage: touch_down on %s' % str(touch.pos)) if self.collide_point(*touch.pos): if (self.source is not None): print('LImage match %s' % self.source) else: print('LImage match with texture') return True return False def on_touch_up(self, touch): # print('LImage: touch_up on %s' % str(touch.pos)) if self.collide_point(*touch.pos): if (self.source is not None): print('LImage match %s' % self.source) else: print('LImage match with texture') return True return False # =============================================================================