def update_preview(self, *args, **kwargs): try: imdata = self.preview_handler.queue.get(False) except queue.Empty: return # textures must be created in the main thread; # this is a limitation in pygame texture = Texture.create_from_data(imdata) if self.preview_widget is None: self.tilt = 90 tilt_max = pkConfig.getint('arduino', 'max-tilt') tilt_min = pkConfig.getint('arduino', 'min-tilt') def on_touch_move(widget, touch): if widget.collide_point(touch.x, touch.y): self.tilt += touch.dpos[1] / 5 if self.tilt < tilt_min: self.tilt = tilt_min if self.tilt > tilt_max: self.tilt = tilt_max value = int(round(self.tilt, 0)) self.arduino_handler.set_camera_tilt(value) self.preview_widget = Image(texture=texture, nocache=True) self.preview_widget.bind(on_touch_move=on_touch_move) self.preview_widget.allow_stretch = True self.preview_widget.x = 0 self.preview_widget.y = -2000 self.view.add_widget(self.preview_widget) else: self.preview_widget.texture = texture
def update_preview(self, *args, **kwargs): try: imdata = self.preview_handler.queue.get(False) except queue.Empty: return # textures must be created in the main thread; # this is a limitation in pygame texture = Texture.create_from_data(imdata) if self.preview_widget is None: tilt_max = pkConfig.getint('arduino', 'max-tilt') tilt_min = pkConfig.getint('arduino', 'min-tilt') def on_touch_move(widget, touch): if widget.collide_point(touch.x, touch.y): self.tilt += touch.dpos[1] / 5 if self.tilt < tilt_min: self.tilt = tilt_min if self.tilt > tilt_max: self.tilt = tilt_max value = int(round(self.tilt, 0)) self.arduino_handler.set_camera_tilt(value) self.preview_widget = Image(texture=texture, nocache=True) self.preview_widget.bind(on_touch_move=on_touch_move) self.preview_widget.allow_stretch = True self.preview_widget.size_hint = None, None self.preview_widget.size = (1280, 1024) self.preview_widget.x = (1280 / 2) - (self.preview_widget.width / 2) self.preview_widget.y = -self.preview_widget.height self.layout.add_widget(self.preview_widget) else: self.preview_widget.texture = texture
def TextureFromPyImage(pyImg): raw = pyImg.tostring() width, height = pyImg.size imdata = ImageData(width, height, 'rgb', raw) texture = Texture.create_from_data(imdata) texture.flip_vertical() return texture
def redisplay(self, root): if self.result.code == preview_thread.COMPLETE: root.cols = self.result.columnCount while len(root.children) > len(self.result.data): root.remove_widget(root.children[-1]) while len(root.children) < len(self.result.data): root.add_widget(Image()) for i in xrange(0, len(self.result.data)): current = root.children[i] if len(self.textures) <= i: self.textures.append( Texture.create_from_data(self.result.data[i])) self.textures[i].flip_vertical() else: self.textures[i].blit_data(self.result.data[i]) current.texture = None current.texture = self.textures[i] current.size_hint = (1.0 * self.result.sizes[i][0] / self.result.width, 1.0 * self.result.sizes[i][1] / self.result.height) root.width = root.height * self.result.width / self.result.height #root.height = root.width * self.result.height / self.result.width else: root.clear_widgets()
def plt_to_image(): buf = StringIO() plt.savefig(buf, format='png', dpi=400) buf.seek(0) imgdata = ImageLoaderPIL(buf)._data[0] t = Texture.create_from_data(imgdata) # for some reason image is loaded upside-down t.flip_vertical() return t
def create_preview_texture(self, initial_data): texture = Texture.create_from_data(initial_data) # add_reload_observer is required for loading texture info # after the openGL context is lost and images need to be reloaded # currently, losing opengl context is not tested texture.add_reload_observer(self.update_texture) texture.flip_vertical() texture.flip_horizontal() return texture
def textureFromPyImage(pyImg): # Suspect this has to be called in the OpenGL event loop which # is bound to slow us down. raw = pyImg.tostring() width, height = pyImg.size print width, height imdata = ImageData(width, height, 'rgb', raw) texture = Texture.create_from_data(imdata) texture.flip_vertical() return texture
def SetImageInWidget(self, image): if self.fbo is None: self._init_fbo() #show the image in kivy if image.get_bytesize() == 3: fmt = 'rgb' elif image.get_bytesize() == 4: fmt = 'rgba' data = pygame.image.tostring(image, fmt.upper(), True) k_im_data = ImageData(image.get_width(), image.get_height(), fmt, data) imageTexture = Texture.create_from_data(k_im_data) self.canvas.clear() #Modify size and offset to avoid image distortion orig_h = image.get_height() orig_w = image.get_width() wid_h = self.size[1] wid_w = self.size[0] print self.size s_size = (0,0) offset = (0,0) orig_ratio = float(orig_w)/orig_h wid_ratio = float(wid_w)/wid_h if wid_ratio > orig_ratio: #fix height s_size = (int(wid_h*orig_ratio), wid_h) offset = ((wid_w - s_size[0])/2, 0) self.fbo_scale = float(orig_h)/wid_h #scale factor to recover the original image size else: #fix width s_size = (wid_w, int(wid_w/orig_ratio)) offset = (0, (wid_h - s_size[1])/2) self.fbo_scale = float(orig_w)/wid_w #scale factor to recover the original image size self.fbo_pos = (self.pos[0] + offset[0], self.pos[1] + offset[1]) #self.fbo_pos = (self.pos[0] + offset[0]*self.fbo_scale, self.pos[1] + offset[1]*self.fbo_scale) self.fbo_size = s_size self.fbo_real_size = (orig_w, orig_h) #self.canvas.add(Rectangle(texture=imageTexture, pos = self.fbo_pos, # size=self.fbo_size)) self._init_fbo() #reload the fbo #here we are drawing the sketches directly over the background image #TODO: (tomas) I'm not sure why this happens, but scaling the widget does not keep the background with self.fbo: #Rectangle(texture=imageTexture, pos = (0,0) ,size=self.fbo_size) Rectangle(texture=imageTexture, pos = (0,0) ,size=self.fbo_real_size)
def redisplay(self, root): if self.result.code == preview_thread.COMPLETE: root.cols = self.result.columnCount while len(root.children) > len(self.result.data): root.remove_widget(root.children[-1]) while len(root.children) < len(self.result.data): root.add_widget(Image()) for i in xrange(0, len(self.result.data)): current = root.children[i] if len(self.textures) <= i: self.textures.append(Texture.create_from_data(self.result.data[i])) self.textures[i].flip_vertical() else: self.textures[i].blit_data(self.result.data[i]) current.texture = None current.texture = self.textures[i] current.size_hint = (1.0*self.result.sizes[i][0]/self.result.width, 1.0*self.result.sizes[i][1]/self.result.height) root.width = root.height * self.result.width / self.result.height #root.height = root.width * self.result.height / self.result.width else: root.clear_widgets()
def render(self): self.image_surface.fill(self.background_colour) for element in self.element_list: element.update_condition(self.weather_underground, self.sun_almanac, self.indoor_sensor) element.render() # Deal with any text alignments for element in self.element_list: if element.align_to_other is not None: for e in self.element_list: if e.element_name == element.align_to_other: element.pos = (e.surface.get_width() + element.align_base_pos, element.pos[1]) # Blit the new surfaces for element in self.element_list: element.blit(self.image_surface) # And import into kivy buffer = pygame.image.tostring(self.image_surface, 'RGB', True) imdata = ImageData(self.image_size[0], self.image_size[1], 'rgb', buffer) self.image.texture = Texture.create_from_data(imdata) self.update_birthdays()
def _real_render(self): # use the lines to do the rendering ! self._render_begin() r = self._render_text # convert halign/valign to int, faster comparaison av = {'top': 0, 'middle': 1, 'bottom': 2}[self.options['valign']] ah = {'left': 0, 'center': 1, 'right': 2}[self.options['halign']] y = 0 w, h = self._size refs = self._refs txt_height = sum(line[1] for line in self._lines) for line in self._lines: lh = line[1] lw = line[0] # horizontal alignement if ah == 0: x = 0 elif ah == 1: x = int((w - lw) / 2) else: x = w - lw # vertical alignement if y == 0: if av == 1: y = int((h - txt_height) / 2) elif av == 2: y = h - (txt_height) for pw, ph, part, options in line[2]: self.options = options r(part, x, y + (lh - ph) / 1.25) # should we record refs ? ref = options['_ref'] if ref is not None: if not ref in refs: refs[ref] = [] refs[ref].append((x, y, x + pw, y + ph)) #print 'render', repr(part), x, y, (lh, ph), options x += pw y += line[1] # get data from provider data = self._render_end() assert (data) # create texture is necessary texture = self.texture mipmap = self.options['mipmap'] if texture is None or \ self.width != texture.width or \ self.height != texture.height: texture = Texture.create_from_data(data, mipmap=mipmap) data = None texture.flip_vertical() texture.add_reload_observer(self._texture_refresh) self.texture = texture # update texture # If the text is 1px width, usually, the data is black. # Don't blit that kind of data, otherwise, you have a little black bar. if data is not None and data.width > 1: texture.blit_data(data)
def render(self, real=False): '''Return a tuple(width, height) to create the image with the user constraints. 2 differents methods are used: * if user don't set width, splitting line and calculate max width + height * if user set a width, blit per glyph ''' options = self.options uw, uh = self.text_size w, h = 0, 0 x, y = 0, 0 if real: self._render_begin() halign = options['halign'] valign = options['valign'] if valign == 'bottom': y = self.height - self._internal_height elif valign == 'middle': y = int((self.height - self._internal_height) / 2) else: self._internal_height = 0 # no width specified, faster method if uw is None: for line in self.text.split('\n'): lw, lh = self.get_extents(line) if real: x = 0 if halign == 'center': x = int((self.width - lw) / 2.) elif halign == 'right': x = int(self.width - lw) self._render_text(line, x, y) y += int(lh) else: w = max(w, int(lw)) self._internal_height += int(lh) h = self._internal_height if uh is None else uh # constraint else: # precalculate id/name if not self.fontid in self._cache_glyphs: self._cache_glyphs[self.fontid] = {} cache = self._cache_glyphs[self.fontid] if not real: # verify that each glyph have size glyphs = list(set(self.text)) + ['.'] for glyph in glyphs: if not glyph in cache: cache[glyph] = self.get_extents(glyph) # Shorten the text that we actually display text = self.text if options['shorten'] and self.get_extents(text)[0] > uw: text = self.shorten(text) # first, split lines glyphs = [] lines = [] lw = lh = 0 for word in re.split(r'( |\n)', text): # calculate the word width ww, wh = 0, 0 for glyph in word: gw, gh = cache[glyph] ww += gw wh = max(gh, wh) # is the word fit on the uw ? if ww > uw: lines.append(((ww, wh), word)) lw = lh = x = 0 continue # get the maximum height for this line lh = max(wh, lh) # is the word fit on the line ? if (word == '\n' or x + ww > uw) and lw != 0: # no, push actuals glyph lines.append(((lw, lh), glyphs)) glyphs = [] # reset size lw = lh = x = 0 # new line ? don't render if word == '\n' or word == ' ': continue # advance the width lw += ww x += ww lh = max(wh, lh) glyphs += list(word) # got some char left ? if lw != 0: lines.append(((lw, lh), glyphs)) if not real: self._internal_height = sum([size[1] for size, glyphs in lines]) h = self._internal_height if uh is None else uh w = uw else: # really render now. for size, glyphs in lines: x = 0 if halign == 'center': x = int((self.width - size[0]) / 2.) elif halign == 'right': x = int(self.width - size[0]) for glyph in glyphs: lw, lh = cache[glyph] if glyph != '\n': self._render_text(glyph, x, y) x += lw y += size[1] if not real: # was only the first pass # return with/height w = int(max(w, 1)) h = int(max(h, 1)) return w, h # get data from provider data = self._render_end() assert(data) # if data width is too tiny, just create texture, don't really render! if data.width <= 1: if self.texture: self.texture = None return # create texture is necessary texture = self.texture mipmap = options['mipmap'] if texture is None: if data is None: if platform() in ('android', 'ios'): colorfmt = 'rgba' else: colorfmt = 'luminance_alpha' texture = Texture.create( size=self.size, colorfmt=colorfmt, mipmap=mipmap) else: texture = Texture.create_from_data(data, mipmap=mipmap) texture.flip_vertical() elif self.width != texture.width or self.height != texture.height: if data is None: texture = Texture.create(size=self.size, mipmap=mipmap) else: texture = Texture.create_from_data(data, mipmap=mipmap) texture.flip_vertical() ''' # Avoid that for the moment. # The thing is, as soon as we got a region, the blitting is not going in # the right position cause of previous flip_vertical # In addition, as soon as we have a region, we are not testing from the # original texture. Mean we'll have region of region of region. # Take more time to implement a fix for it, if it's needed. else: print 'get region ??', self, self.width, self.height texture = texture.get_region( 0, 0, self.width, self.height) ''' self.texture = texture # update texture # If the text is 1px width, usually, the data is black. # Don't blit that kind of data, otherwise, you have a little black bar. if data is not None and data.width > 1: texture.blit_data(data)
def getKivyTexture(img): buffer = tostring(img.getPGSurface(),'RGB',True) # buffer = img.toString() imdata = ImageData(img.width, img.height, 'rgb', buffer) tex = Texture.create_from_data(imdata) return tex
def _real_render(self): # use the lines to do the rendering ! self._render_begin() r = self._render_text # convert halign/valign to int, faster comparison av = {'top': 0, 'middle': 1, 'bottom': 2}[self.options['valign']] ah = {'left': 0, 'center': 1, 'right': 2, 'justify': 3,}[self.options['halign']] y = 0 w, h = self._size refs = self._refs _lines = self._lines txt_height = sum(line[1] for line in _lines) for line in _lines: lh = line[1] lw = line[0] last_line = line[2] first_line = line[3] # horizontal alignement if ah in (0, 3): # left x = 0 elif ah == 1: # center x = int((w - lw) / 2) else: x = w - lw # vertical alignment if y == 0: if av == 1: # center y = int((h - txt_height) / 2) elif av == 2: # bottom y = h - (txt_height) # justification just_space = 0 first_space = 0 if ah > 2: # justified if line[4] and not last_line: last_word = line[4][-1][2] x = first_space = last_space = space_width = _spaces = 0 for pw, ph, word, options in line[4]: _spaces += 1 if word == ' ' else 0 if word == ' ': last_space = 1 space_width = pw if line[4][0][2][0] == ' ': first_space = 1 space_width += pw _spaces -= last_space + first_space # divide left over space between `spaces` if _spaces: just_space = (((w - lw + space_width) * 1.) /(_spaces*1.)) for pw, ph, part, options in line[4]: self.options = options if not first_line and first_space: first_line = 1 continue if part == ' ': x += just_space r(part, x, y + (lh - ph) / 1.25) # should we record refs ? ref = options['_ref'] if ref is not None: if not ref in refs: refs[ref] = [] refs[ref].append((x, y, x + pw, y + ph)) #print 'render', repr(part), x, y, (lh, ph), options x += pw y += line[1] # get data from provider data = self._render_end() assert(data) # create texture is necessary texture = self.texture mipmap = self.options['mipmap'] if texture is None or \ self.width != texture.width or \ self.height != texture.height: texture = Texture.create_from_data(data, mipmap=mipmap) data = None texture.flip_vertical() texture.add_reload_observer(self._texture_refresh) self.texture = texture # update texture # If the text is 1px width, usually, the data is black. # Don't blit that kind of data, otherwise, you have a little black bar. if data is not None and data.width > 1: texture.blit_data(data)
def getKivyTexture(img): buffer = tostring(img.getPGSurface(), 'RGB', True) # buffer = img.toString() imdata = ImageData(img.width, img.height, 'rgb', buffer) tex = Texture.create_from_data(imdata) return tex
def _real_render(self): # use the lines to do the rendering ! self._render_begin() r = self._render_text # convert halign/valign to int, faster comparaison av = {'top': 0, 'middle': 1, 'bottom': 2}[self.options['valign']] ah = {'left': 0, 'center': 1, 'right': 2}[self.options['halign']] y = 0 w, h = self._size refs = self._refs no_of_lines = len(self._lines) for line in self._lines: lh = line[1] lw = line[0] # horizontal alignement if ah == 0: x = 0 elif ah == 1: x = int((w - lw) / 2) else: x = w - lw # vertical alignement if y == 0: if av == 1: y = int((h - (lh*no_of_lines))/2) elif av == 2: y = h - (lh*(no_of_lines)) for pw, ph, part, options in line[2]: self.options = options r(part, x, y + (lh - ph) / 1.25) # should we record refs ? ref = options['_ref'] if ref is not None: if not ref in refs: refs[ref] = [] refs[ref].append((x, y, x + pw, y + ph)) #print 'render', repr(part), x, y, (lh, ph), options x += pw y += line[1] # get data from provider data = self._render_end() assert(data) # create texture is necessary texture = self.texture mipmap = self.options['mipmap'] if texture is None: if data is None: if platform() in ('android', 'ios'): colorfmt = 'rgba' else: colorfmt = 'luminance_alpha' texture = Texture.create( size=self.size, colorfmt=colorfmt, mipmap=mipmap) else: texture = Texture.create_from_data(data, mipmap=mipmap) texture.flip_vertical() elif self.width != texture.width or self.height != texture.height: if data is None: texture = Texture.create(size=self.size, mipmap=mipmap) else: texture = Texture.create_from_data(data, mipmap=mipmap) texture.flip_vertical() # update texture self.texture = texture self.texture.blit_data(data)
def render_page(self, index, zoom=1): w, h = map(int, self.get_page_size(index)) w, h = map(lambda x: x * zoom, (w, h)) print 'render1', index page = self.l_poppler.poppler_document_get_page(self._doc, index) print 'render2', page assert (page is not None) # use cairo ? if self.l_cairo is not None: # create a cairo surface # first argument 0 is ARGB32 surface = self.l_cairo.cairo_image_surface_create(0, w, h) assert (surface is not None) # create cairo context context = self.l_cairo.cairo_create(surface) assert (context is not None) # apply zoom print 'apply scale' self.l_cairo.cairo_scale(context, c_double(zoom), c_double(zoom)) # render to cairo print 'render page' self.l_poppler.poppler_page_render(page, context) # dump cairo to texture print 'render to texture' data = self.l_cairo.cairo_image_surface_get_data(surface) print 'got', type(data), data size = int(4 * w * h) print 'create string buffer', size buf = create_string_buffer(size) memmove(buf, data, size) # release cairo print 'destroy surface' self.l_cairo.cairo_surface_destroy(surface) print 'destroy context' self.l_cairo.cairo_destroy(context) print 'done!' # use gdk ? else: # 1: GDK_COLORSPACE_RGB (0) # 2: has_alpha (1) # 3: bit per samples print 'render3' self.l_gdk.gdk_pixbuf_new.restype = c_void_p surface = self.l_gdk.gdk_pixbuf_new(0, 1, 8, w, h) print 'render4' assert (surface is not None) # render to pixbuf (fix 6 arg) print 'render5' self.l_poppler.poppler_page_render_to_pixbuf.argtypes = [ c_void_p, c_int, c_int, c_int, c_int, c_double, c_int, c_void_p ] self.l_poppler.poppler_page_render_to_pixbuf( page, 0, 0, w, h, zoom, 0, surface) print 'render6' # get data class GdkPixdata(Structure): _fields_ = [('magic', c_int), ('length', c_int), ('pixdata_type', c_int), ('rowstride', c_int), ('width', c_int), ('height', c_int), ('pixel_data', c_void_p)] pixdata = (GdkPixdata)() # get a pixdata print 'render7' self.l_gdk.gdk_pixdata_from_pixbuf.argtypes = [ c_void_p, c_void_p, c_int ] self.l_gdk.gdk_pixdata_from_pixbuf(byref(pixdata), surface, 0) print 'render8' # convert to buffer size = int(4 * w * h) buf = create_string_buffer(size) memmove(buf, pixdata.pixel_data, size) print 'render9' # unref self.l_gobject.g_object_unref(surface) print 'render10' # picking only RGB print 'create texture' im = ImageData(w, h, 'bgra', buf.raw) texture = Texture.create_from_data(im, mipmap=True) print 'done !' texture.flip_vertical() return texture
def _real_render(self): # use the lines to do the rendering ! self._render_begin() r = self._render_text # convert halign/valign to int, faster comparison av = {"top": 0, "middle": 1, "bottom": 2}[self.options["valign"]] ah = {"left": 0, "center": 1, "right": 2, "justify": 3}[self.options["halign"]] y = 0 w, h = self._size refs = self._refs _lines = self._lines txt_height = sum(line[1] for line in _lines) for line in _lines: lh = line[1] lw = line[0] last_line = line[2] first_line = line[3] # horizontal alignement if ah in (0, 3): # left x = 0 elif ah == 1: # center x = int((w - lw) / 2) else: x = w - lw # vertical alignment if y == 0: if av == 1: # center y = int((h - txt_height) / 2) elif av == 2: # bottom y = h - (txt_height) # justification just_space = 0 first_space = 0 if ah > 2: # justified if line[4] and not last_line: last_word = line[4][-1][2] x = first_space = last_space = space_width = _spaces = 0 for pw, ph, word, options in line[4]: _spaces += 1 if word == " " else 0 if word == " ": last_space = 1 space_width = pw if line[4][0][2][0] == " ": first_space = 1 space_width += pw _spaces -= last_space + first_space # divide left over space between `spaces` if _spaces: just_space = ((w - lw + space_width) * 1.0) / (_spaces * 1.0) # previous part height/pos = 0 psp = pph = 0 for pw, ph, part, options in line[4]: self.options = options if not first_line and first_space: first_line = 1 continue if part == " ": x += just_space # calculate sub/super script pos if options["script"] == "superscript": script_pos = max(0, psp if psp else self.get_descent()) psp = script_pos pph = ph elif options["script"] == "subscript": script_pos = min(lh - ph, ((psp + pph) - ph) if pph else (lh - ph)) pph = ph psp = script_pos else: script_pos = (lh - ph) / 1.25 psp = pph = 0 r(part, x, y + script_pos) # should we record refs ? ref = options["_ref"] if ref is not None: if not ref in refs: refs[ref] = [] refs[ref].append((x, y, x + pw, y + ph)) x += pw y += line[1] # get data from provider data = self._render_end() assert data # create texture is necessary texture = self.texture mipmap = self.options["mipmap"] if texture is None or self.width != texture.width or self.height != texture.height: texture = Texture.create_from_data(data, mipmap=mipmap) data = None texture.flip_vertical() texture.add_reload_observer(self._texture_refresh) self.texture = texture # update texture # If the text is 1px width, usually, the data is black. # Don't blit that kind of data, otherwise, you have a little black bar. if data is not None and data.width > 1: texture.blit_data(data)
def generate_texture(self, data, size, mode, mipmap=False): idata = ImageData(size[0], size[1], mode, data) return Texture.create_from_data(idata, mipmap)
def render(self, real=False): '''Return a tuple(width, height) to create the image with the user constraints. 2 differents methods are used: * if user don't set width, splitting line and calculate max width + height * if user set a width, blit per glyph ''' options = self.options render_text = self._render_text get_extents = self.get_extents uw, uh = self.text_size w, h = 0, 0 x, y = 0, 0 if real: self._render_begin() halign = options['halign'] valign = options['valign'] if valign == 'bottom': y = self.height - self._internal_height elif valign == 'middle': y = int((self.height - self._internal_height) / 2) else: self._internal_height = 0 # no width specified, faster method if uw is None: for line in self.text.split('\n'): lw, lh = get_extents(line) lh = lh * options['line_height'] if real: x = 0 if halign == 'center': x = int((self.width - lw) / 2.) elif halign == 'right': x = int(self.width - lw) if len(line): render_text(line, x, y) y += int(lh) else: w = max(w, int(lw)) self._internal_height += int(lh) h = self._internal_height if uh is None else uh # constraint else: # precalculate id/name if not self.fontid in self._cache_glyphs: self._cache_glyphs[self.fontid] = {} cache = self._cache_glyphs[self.fontid] if not real: # verify that each glyph have size glyphs = list(set(self.text)) + ['.'] for glyph in glyphs: if not glyph in cache: cache[glyph] = get_extents(glyph) # Shorten the text that we actually display text = self.text last_word_width = get_extents(text[text.rstrip().rfind(' '):])[0] if (options['shorten'] and get_extents(text)[0] > uw - last_word_width): text = self.shorten(text) # first, split lines glyphs = [] lines = [] lw = lh = 0 for word in re.split(r'( |\n)', text): # calculate the word width ww, wh = 0, 0 if word == '': ww, wh = get_extents(' ') for glyph in word: gw, gh = cache[glyph] ww += gw wh = max(gh, wh) wh = wh * options['line_height'] # is the word fit on the uw ? if ww > uw: lines.append(((ww, wh), word)) lw = lh = x = 0 continue # get the maximum height for this line lh = max(wh, lh) # is the word fit on the line ? if (word == '\n' or x + ww > uw) and lw != 0: # no, push actuals glyph lines.append(((lw, lh), glyphs)) glyphs = [] # reset size lw = lh = x = 0 # new line ? don't render if word == '\n' or word == ' ': continue # advance the width lw += ww x += ww lh = max(wh, lh) glyphs += list(word) # got some char left ? if lw != 0: lines.append(((lw, lh), glyphs)) if not real: self._internal_height = sum([size[1] for size, glyphs in lines]) ll_h = lines[-1][0][1] lh_offset = ll_h - (ll_h / self.options['line_height']) self._internal_height = self._internal_height - lh_offset h = self._internal_height if uh is None else uh w = uw else: # really render now. for size, glyphs in lines: x = 0 if halign == 'center': x = int((self.width - size[0]) / 2.) elif halign == 'right': x = int(self.width - size[0]) for glyph in glyphs: lw, lh = cache[glyph] if glyph != ' ' and glyph != '\n': render_text(glyph, x, y) x += lw y += size[1] if not real: # was only the first pass # return with/height w = int(max(w, 1)) h = int(max(h, 1)) return w, h # get data from provider data = self._render_end() assert(data) # if data width is too tiny, just create texture, don't really render! if data.width <= 1: if self.texture: self.texture = None return # create texture is necessary texture = self.texture mipmap = options['mipmap'] if texture is None or \ self.width != texture.width or \ self.height != texture.height: texture = Texture.create_from_data(data, mipmap=mipmap) data = None texture.flip_vertical() texture.add_reload_observer(self._texture_refresh) self.texture = texture # update texture # If the text is 1px width, usually, the data is black. # Don't blit that kind of data, otherwise, you have a little black bar. if data is not None and data.width > 1: texture.blit_data(data)
def _real_render(self): # use the lines to do the rendering ! self._render_begin() r = self._render_text # convert halign/valign to int, faster comparaison #av = {'top': 0, 'middle': 1, 'bottom': 2}[self.options['valign']] ah = {'left': 0, 'center': 1, 'right': 2}[self.options['halign']] y = 0 w, h = self._size refs = self._refs for line in self._lines: lh = line[1] # horizontal alignement if ah == 0: x = 0 elif ah == 1: x = int((w - line[0]) / 2) else: x = w - line[0] for pw, ph, part, options in line[2]: self.options = options r(part, x, y + (lh - ph) / 1.25) # should we record refs ? ref = options['_ref'] if ref is not None: if not ref in refs: refs[ref] = [] refs[ref].append((x, y, x + pw, y + ph)) #print 'render', repr(part), x, y, (lh, ph), options x += pw y += line[1] # get data from provider data = self._render_end() assert(data) # create texture is necessary texture = self.texture mipmap = self.options['mipmap'] if texture is None: if data is None: if platform() in ('android', 'ios'): colorfmt = 'rgba' else: colorfmt = 'luminance_alpha' texture = Texture.create( size=self.size, colorfmt=colorfmt, mipmap=mipmap) else: texture = Texture.create_from_data(data, mipmap=mipmap) texture.flip_vertical() elif self.width != texture.width or self.height != texture.height: if data is None: texture = Texture.create(size=self.size, mipmap=mipmap) else: texture = Texture.create_from_data(data, mipmap=mipmap) texture.flip_vertical() # update texture self.texture = texture self.texture.blit_data(data)
def _update_preview(self, image): self.ui.preview_image.texture = Texture.create_from_data(ImageData(image.size[0], image.size[1], image.mode.lower(), image.tobytes()))
def _update_preview(self, image): self.ui.preview_image.texture = Texture.create_from_data( ImageData(image.size[0], image.size[1], image.mode.lower(), image.tobytes()))
def render_page(self, index, zoom=1): w, h = map(int, self.get_page_size(index)) w, h = map(lambda x: x * zoom, (w, h)) print 'render1', index page = self.l_poppler.poppler_document_get_page(self._doc, index) print 'render2', page assert( page is not None ) # use cairo ? if self.l_cairo is not None: # create a cairo surface # first argument 0 is ARGB32 surface = self.l_cairo.cairo_image_surface_create(0, w, h) assert( surface is not None ) # create cairo context context = self.l_cairo.cairo_create(surface) assert( context is not None ) # apply zoom print 'apply scale' self.l_cairo.cairo_scale(context, c_double(zoom), c_double(zoom)) # render to cairo print 'render page' self.l_poppler.poppler_page_render(page, context) # dump cairo to texture print 'render to texture' data = self.l_cairo.cairo_image_surface_get_data(surface) print 'got', type(data), data size = int(4 * w * h) print 'create string buffer', size buf = create_string_buffer(size) memmove(buf, data, size) # release cairo print 'destroy surface' self.l_cairo.cairo_surface_destroy(surface) print 'destroy context' self.l_cairo.cairo_destroy(context) print 'done!' # use gdk ? else: # 1: GDK_COLORSPACE_RGB (0) # 2: has_alpha (1) # 3: bit per samples print 'render3' self.l_gdk.gdk_pixbuf_new.restype = c_void_p surface = self.l_gdk.gdk_pixbuf_new(0, 1, 8, w, h) print 'render4' assert( surface is not None ) # render to pixbuf (fix 6 arg) print 'render5' self.l_poppler.poppler_page_render_to_pixbuf.argtypes = [ c_void_p, c_int, c_int, c_int, c_int, c_double, c_int, c_void_p] self.l_poppler.poppler_page_render_to_pixbuf(page, 0, 0, w, h, zoom, 0, surface) print 'render6' # get data class GdkPixdata(Structure): _fields_ = [('magic', c_int), ('length', c_int), ('pixdata_type', c_int), ('rowstride', c_int), ('width', c_int), ('height', c_int), ('pixel_data', c_void_p)] pixdata = (GdkPixdata)() # get a pixdata print 'render7' self.l_gdk.gdk_pixdata_from_pixbuf.argtypes = [ c_void_p, c_void_p, c_int] self.l_gdk.gdk_pixdata_from_pixbuf(byref(pixdata), surface, 0) print 'render8' # convert to buffer size = int(4 * w * h) buf = create_string_buffer(size) memmove(buf, pixdata.pixel_data, size) print 'render9' # unref self.l_gobject.g_object_unref(surface) print 'render10' # picking only RGB print 'create texture' im = ImageData(w, h, 'bgra', buf.raw) texture = Texture.create_from_data(im, mipmap=True) print 'done !' texture.flip_vertical() return texture
def render(self, real=False): '''Return a tuple(width, height) to create the image with the user constraints. 2 differents methods are used: * if user don't set width, splitting line and calculate max width + height * if user set a width, blit per glyph ''' options = self.options render_text = self._render_text get_extents = self.get_extents uw, uh = self.text_size w, h = 0, 0 x, y = 0, 0 if real: self._render_begin() halign = options['halign'] valign = options['valign'] if valign == 'bottom': y = self.height - self._internal_height elif valign == 'middle': y = int((self.height - self._internal_height) / 2) else: self._internal_height = 0 # no width specified, faster method if uw is None: for line in self.text.split('\n'): lw, lh = get_extents(line) if real: x = 0 if halign == 'center': x = int((self.width - lw) / 2.) elif halign == 'right': x = int(self.width - lw) if len(line): render_text(line, x, y) y += int(lh) else: w = max(w, int(lw)) self._internal_height += int(lh) h = self._internal_height if uh is None else uh # constraint else: # precalculate id/name if not self.fontid in self._cache_glyphs: self._cache_glyphs[self.fontid] = {} cache = self._cache_glyphs[self.fontid] if not real: # verify that each glyph have size glyphs = list(set(self.text)) + ['.'] for glyph in glyphs: if not glyph in cache: cache[glyph] = get_extents(glyph) # Shorten the text that we actually display text = self.text if options['shorten'] and get_extents(text)[0] > uw: text = self.shorten(text) # first, split lines glyphs = [] lines = [] lw = lh = 0 for word in re.split(r'( |\n)', text): # calculate the word width ww, wh = 0, 0 if word == '': ww, wh = get_extents(' ') for glyph in word: gw, gh = cache[glyph] ww += gw wh = max(gh, wh) # is the word fit on the uw ? if ww > uw: lines.append(((ww, wh), word)) lw = lh = x = 0 continue # get the maximum height for this line lh = max(wh, lh) # is the word fit on the line ? if (word == '\n' or x + ww > uw) and lw != 0: # no, push actuals glyph lines.append(((lw, lh), glyphs)) glyphs = [] # reset size lw = lh = x = 0 # new line ? don't render if word == '\n' or word == ' ': continue # advance the width lw += ww x += ww lh = max(wh, lh) glyphs += list(word) # got some char left ? if lw != 0: lines.append(((lw, lh), glyphs)) if not real: self._internal_height = sum([size[1] for size, glyphs in lines]) h = self._internal_height if uh is None else uh w = uw else: # really render now. for size, glyphs in lines: x = 0 if halign == 'center': x = int((self.width - size[0]) / 2.) elif halign == 'right': x = int(self.width - size[0]) for glyph in glyphs: lw, lh = cache[glyph] if glyph != ' ' and glyph != '\n': render_text(glyph, x, y) x += lw y += size[1] if not real: # was only the first pass # return with/height w = int(max(w, 1)) h = int(max(h, 1)) return w, h # get data from provider data = self._render_end() assert(data) # if data width is too tiny, just create texture, don't really render! if data.width <= 1: if self.texture: self.texture = None return # create texture is necessary texture = self.texture mipmap = options['mipmap'] if texture is None or \ self.width != texture.width or \ self.height != texture.height: texture = Texture.create_from_data(data, mipmap=mipmap) data = None texture.flip_vertical() texture.add_reload_observer(self._texture_refresh) self.texture = texture # update texture # If the text is 1px width, usually, the data is black. # Don't blit that kind of data, otherwise, you have a little black bar. if data is not None and data.width > 1: texture.blit_data(data)
def _real_render(self): # use the lines to do the rendering ! self._render_begin() r = self._render_text # convert halign/valign to int, faster comparaison # av = {'top': 0, 'middle': 1, 'bottom': 2}[self.options['valign']] ah = {"left": 0, "center": 1, "right": 2}[self.options["halign"]] y = 0 w, h = self._size refs = self._refs for line in self._lines: lh = line[1] # horizontal alignement if ah == 0: x = 0 elif ah == 1: x = int((w - line[0]) / 2) else: x = w - line[0] for pw, ph, part, options in line[2]: self.options = options r(part, x, y + (lh - ph) / 1.25) # should we record refs ? ref = options["_ref"] if ref is not None: if not ref in refs: refs[ref] = [] refs[ref].append((x, y, x + pw, y + ph)) # print 'render', repr(part), x, y, (lh, ph), options x += pw y += line[1] # get data from provider data = self._render_end() assert data # create texture is necessary texture = self.texture mipmap = self.options["mipmap"] if texture is None: if data is None: if platform() in ("android", "ios"): colorfmt = "rgba" else: colorfmt = "luminance_alpha" texture = Texture.create(size=self.size, colorfmt=colorfmt, mipmap=mipmap) else: texture = Texture.create_from_data(data, mipmap=mipmap) texture.flip_vertical() elif self.width != texture.width or self.height != texture.height: if data is None: texture = Texture.create(size=self.size, mipmap=mipmap) else: texture = Texture.create_from_data(data, mipmap=mipmap) texture.flip_vertical() # update texture self.texture = texture self.texture.blit_data(data)
def _real_render(self): # use the lines to do the rendering ! self._render_begin() r = self._render_text # convert halign/valign to int, faster comparaison av = {'top': 0, 'middle': 1, 'bottom': 2}[self.options['valign']] ah = {'left': 0, 'center': 1, 'right': 2}[self.options['halign']] y = 0 w, h = self._size refs = self._refs txt_height = sum(line[1] for line in self._lines) for line in self._lines: lh = line[1] lw = line[0] # horizontal alignement if ah == 0: x = 0 elif ah == 1: x = int((w - lw) / 2) else: x = w - lw # vertical alignement if y == 0: if av == 1: y = int((h - txt_height) / 2) elif av == 2: y = h - (txt_height) for pw, ph, part, options in line[2]: self.options = options r(part, x, y + (lh - ph) / 1.25) # should we record refs ? ref = options['_ref'] if ref is not None: if not ref in refs: refs[ref] = [] refs[ref].append((x, y, x + pw, y + ph)) #print 'render', repr(part), x, y, (lh, ph), options x += pw y += line[1] # get data from provider data = self._render_end() assert(data) # create texture is necessary texture = self.texture mipmap = self.options['mipmap'] if texture is None or \ self.width != texture.width or \ self.height != texture.height: texture = Texture.create_from_data(data, mipmap=mipmap) data = None texture.flip_vertical() texture.add_reload_observer(self._texture_refresh) self.texture = texture # update texture # If the text is 1px width, usually, the data is black. # Don't blit that kind of data, otherwise, you have a little black bar. if data is not None and data.width > 1: texture.blit_data(data)
def render(self, real=False): '''Return a tuple(width, height) to create the image with the user constraints. 2 differents methods are used: * if user don't set width, splitting line and calculate max width + height * if user set a width, blit per glyph ''' options = self.options uw, uh = self.text_size w, h = 0, 0 x, y = 0, 0 if real: self._render_begin() halign = options['halign'] valign = options['valign'] if valign == 'bottom': y = self.height - self._internal_height elif valign == 'middle': y = int((self.height - self._internal_height) / 2) else: self._internal_height = 0 # no width specified, faster method if uw is None: for line in self.text.split('\n'): lw, lh = self.get_extents(line) if real: x = 0 if halign == 'center': x = int((self.width - lw) / 2.) elif halign == 'right': x = int(self.width - lw) self._render_text(line, x, y) y += int(lh) else: w = max(w, int(lw)) self._internal_height += int(lh) h = self._internal_height if uh is None else uh # constraint else: # precalculate id/name if not self.fontid in self._cache_glyphs: self._cache_glyphs[self.fontid] = {} cache = self._cache_glyphs[self.fontid] if not real: # verify that each glyph have size glyphs = list(set(self.text)) + ['.'] for glyph in glyphs: if not glyph in cache: cache[glyph] = self.get_extents(glyph) # Shorten the text that we actually display text = self.text if options['shorten'] and self.get_extents(text)[0] > uw: text = self.shorten(text) # first, split lines glyphs = [] lines = [] lw = lh = 0 for word in re.split(r'( |\n)', text): # calculate the word width ww, wh = 0, 0 for glyph in word: gw, gh = cache[glyph] ww += gw wh = max(gh, wh) # is the word fit on the uw ? if ww > uw: lines.append(((ww, wh), word)) lw = lh = x = 0 continue # get the maximum height for this line lh = max(wh, lh) # is the word fit on the line ? if (word == '\n' or x + ww > uw) and lw != 0: # no, push actuals glyph lines.append(((lw, lh), glyphs)) glyphs = [] # reset size lw = lh = x = 0 # new line ? don't render if word == '\n' or word == ' ': continue # advance the width lw += ww x += ww lh = max(wh, lh) glyphs += list(word) # got some char left ? if lw != 0: lines.append(((lw, lh), glyphs)) if not real: self._internal_height = sum( [size[1] for size, glyphs in lines]) h = self._internal_height if uh is None else uh w = uw else: # really render now. for size, glyphs in lines: x = 0 if halign == 'center': x = int((self.width - size[0]) / 2.) elif halign == 'right': x = int(self.width - size[0]) for glyph in glyphs: lw, lh = cache[glyph] if glyph != '\n': self._render_text(glyph, x, y) x += lw y += size[1] if not real: # was only the first pass # return with/height w = int(max(w, 1)) h = int(max(h, 1)) return w, h # get data from provider data = self._render_end() assert (data) # if data width is too tiny, just create texture, don't really render! if data.width <= 1: if self.texture: self.texture = None return # create texture is necessary texture = self.texture mipmap = options['mipmap'] if texture is None: if data is None: texture = Texture.create(size=self.size, colorfmt='luminance_alpha', mipmap=mipmap) else: texture = Texture.create_from_data(data, mipmap=mipmap) texture.flip_vertical() elif self.width != texture.width or self.height != texture.height: if data is None: texture = Texture.create(size=self.size, mipmap=mipmap) else: texture = Texture.create_from_data(data, mipmap=mipmap) texture.flip_vertical() ''' # Avoid that for the moment. # The thing is, as soon as we got a region, the blitting is not going in # the right position cause of previous flip_vertical # In addition, as soon as we have a region, we are not testing from the # original texture. Mean we'll have region of region of region. # Take more time to implement a fix for it, if it's needed. else: print 'get region ??', self, self.width, self.height texture = texture.get_region( 0, 0, self.width, self.height) ''' self.texture = texture # update texture # If the text is 1px width, usually, the data is black. # Don't blit that kind of data, otherwise, you have a little black bar. if data is not None and data.width > 1: texture.blit_data(data)