#!/usr/bin/python from __future__ import division import gtk import cairo import math VSTRIP = 0 HSTRIP = 1 SQUARE = 2 HEIGHTS = [ 1, 8, 16, 23, 32 ] WIDTHS = [ 4, 8, 16, 23, 32 ] RENDER_TYPES = [VSTRIP, HSTRIP, SQUARE] DO_OFFSETS = [False, True] SIZE = 80 PAD = 10 set_width = None set_height = None sizes_showing = False outline_showing = False use_paths = True rotate_source = False alpha_source = False do_repeat = True width= None height = None render_type = None do_offset = None def draw_size(cr, x, y, w, h): text = "%s x %s" % (w, h) _, y_bearing, text_width, text_height, _, _ = cr.text_extents(text) cr.move_to(x + (SIZE - text_width) / 2, y + (SIZE - text_height) / 2 - y_bearing) cr.set_source_rgb(1, 1, 1) cr.show_text(text) def compute_offset(length): if length == 1: return 0 elif length == 2: return 1 else: return length // 3 def offset_surface(surface, x_offset, y_offset): new_surface = cairo.ImageSurface(cairo.FORMAT_RGB24, surface.get_width(), surface.get_height()) cr = cairo.Context(new_surface) pat = cairo.SurfacePattern(surface) pat.set_extend(cairo.EXTEND_REPEAT) m = cairo.Matrix() m.translate(x_offset, y_offset) pat.set_matrix(m) cr.set_source(pat) cr.paint() return new_surface def outline_surface(surface): cr = cairo.Context(surface) cr.set_source_rgb(1,1,1) cr.rectangle(0.5, 0.5, surface.get_width() - 1, surface.get_height() - 1) cr.set_line_width(1) cr.stroke() def draw_set(cr, start_x, start_y, type, offset): if width == None: widths = WIDTHS else: widths = [width] if height == None: heights = HEIGHTS else: heights = [height] y = start_y + PAD for h in heights: x = start_x + PAD for w in widths: image_surface = cairo.ImageSurface(cairo.FORMAT_RGB24, w, h) cr2 = cairo.Context(image_surface) if offset: x_offset = compute_offset(w) y_offset = compute_offset(h) else: x_offset = y_offset = 0 pat = cairo.LinearGradient(0, 0, w, h) pat.add_color_stop_rgb(0, 1, 0, 0) pat.add_color_stop_rgb(1, 0, 0, 1) cr2.set_source(pat) cr2.paint() if offset: image_surface = offset_surface(image_surface, x_offset, y_offset) if outline_showing: outline_surface(image_surface) surface = cr.get_target().create_similar(cairo.CONTENT_COLOR_ALPHA if alpha_source else cairo.CONTENT_COLOR, w, h) cr3 = cairo.Context(surface) cr3.set_source_surface(image_surface, 0, 0) cr3.paint() if type == VSTRIP: tw = w th = SIZE elif type == HSTRIP: tw = SIZE th = h else: tw = SIZE th = SIZE tx = x + (SIZE - tw) // 2 ty = y + (SIZE - th) // 2 pat = cairo.SurfacePattern(surface) if do_repeat: pat.set_extend(cairo.EXTEND_REPEAT) m = cairo.Matrix() if rotate_source: m.rotate(math.pi / 4) m.translate(- (tx + x_offset), - (ty + y_offset)) pat.set_matrix(m) cr.set_source(pat) if use_paths: cr.move_to(tx, ty) cr.line_to(tx + tw / 2, ty + 2.5) cr.line_to(tx + tw, ty) cr.line_to(tx + tw, ty) cr.line_to(tx + tw - 2.5, ty + th / 2) cr.line_to(tx + tw, ty + th) cr.line_to(tx + tw / 2, ty + th - 2.5) cr.line_to(tx, ty + th) cr.line_to(tx + 2.5, ty + th / 2) cr.close_path() else: cr.rectangle (tx, ty, tw, th) cr.fill() if sizes_showing: draw_size(cr, x, y, w, h) x += SIZE + PAD y += SIZE + PAD def draw(cr): cr.set_source_rgb(0, 1, 0) cr.paint() if render_type == None: render_types = RENDER_TYPES else: render_types = [render_type] if do_offset == None: do_offsets = DO_OFFSETS else: do_offsets = [do_offset] y = 0 for d_o in do_offsets: x = 0 for r_t in render_types: draw_set(cr, x, y, r_t, offset=d_o) x += set_width y += set_height def on_expose(widget, event): cr = widget.window.cairo_create() draw(cr) def dump(): width, height = w.size_request() surface = cairo.ImageSurface(cairo.FORMAT_RGB24, width, height) cr = cairo.Context(surface) draw(cr) surface.write_to_png("repeats.png") def reset(): if width == None: n_widths = len(WIDTHS) else: n_widths = 1 if height == None: n_heights = len(HEIGHTS) else: n_heights = 1 if render_type == None: n_render_types = len(RENDER_TYPES) else: n_render_types = 1 if do_offset == None: n_do_offsets = len(DO_OFFSETS) else: n_do_offsets = 1 global set_width, set_height set_width = (PAD + n_widths * (SIZE + PAD)) set_height = (PAD + n_heights * (SIZE + PAD)) w.queue_draw() w.set_size_request(n_render_types * set_width, n_do_offsets * set_height) def cycle(value, a): if value == None: return a[0] for i, v in enumerate(a): if v == value: break if i + 1 < len(a): return a[i + 1] else: return None def on_key_press(widget, event): if event.keyval in (gtk.keysyms.q, gtk.keysyms.Q): gtk.main_quit() elif event.keyval in (gtk.keysyms.d, gtk.keysyms.D): dump() elif event.keyval in (gtk.keysyms.f, gtk.keysyms.F): global alpha_source alpha_source = not alpha_source reset() elif event.keyval in (gtk.keysyms.h, gtk.keysyms.H): global height height = cycle(height, HEIGHTS) reset() elif event.keyval in (gtk.keysyms.l, gtk.keysyms.L): global outline_showing outline_showing = not outline_showing reset() elif event.keyval in (gtk.keysyms.o, gtk.keysyms.O): global do_offset do_offset = cycle(do_offset, DO_OFFSETS) reset() elif event.keyval in (gtk.keysyms.p, gtk.keysyms.p): global use_paths use_paths = not use_paths reset() elif event.keyval in (gtk.keysyms.r, gtk.keysyms.R): reset() elif event.keyval in (gtk.keysyms.t, gtk.keysyms.T): global render_type render_type = cycle(render_type, RENDER_TYPES) reset() elif event.keyval in (gtk.keysyms.w, gtk.keysyms.W): global width width = cycle(width, WIDTHS) reset() elif event.keyval in (gtk.keysyms.x, gtk.keysyms.X): global rotate_source rotate_source = not rotate_source reset() elif event.keyval in (ord('1'), gtk.keysyms.KP_1): global do_repeat do_repeat = not do_repeat reset() elif event.keyval == gtk.keysyms.space: global sizes_showing sizes_showing = not sizes_showing reset() w = gtk.Window() w.set_app_paintable(True) w.set_resizable(False) reset() w.connect('expose-event', on_expose) w.connect('key-press-event', on_key_press) w.show() gtk.main()