diff options
Diffstat (limited to 'ep_layer_letterpress.py')
-rw-r--r-- | ep_layer_letterpress.py | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/ep_layer_letterpress.py b/ep_layer_letterpress.py new file mode 100644 index 0000000..7ce19d9 --- /dev/null +++ b/ep_layer_letterpress.py @@ -0,0 +1,216 @@ +# coding: UTF8 +# Copyright 2009 Thomas Jourdan +# +# 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. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import math +import random +import pango +import pangocairo +import model_layer +import ka_random +import model_constraintpool +import exon_color +import exon_position +import exon_direction +import exon_buzzword + +class LetterPress(model_layer.Layer): + """LetterPress + inv: len(self.direction_steps) > 0 + """ + + cdef = [{'bind' : 'family', + 'name' : 'Font family', + 'domain': model_constraintpool.STRING_1_OF_N, + 'enum' : ['Sans', + 'Nimbus Sans L', + 'Monospace',]}, + {'bind' : 'style', + 'name' : 'Font style', + 'domain': model_constraintpool.INT_1_OF_N, + 'enum' : [('Normal', pango.STYLE_NORMAL), + ('Oblique', pango.STYLE_OBLIQUE), + ('Italic', pango.STYLE_ITALIC),]}, + {'bind' : 'size', + 'name' : 'Font size', + 'domain': model_constraintpool.INT_RANGE, + 'min' : 4, 'max': 64}, + ] + + font_style = {pango.STYLE_NORMAL: 'Normal', + pango.STYLE_OBLIQUE: 'Oblique', + pango.STYLE_ITALIC: 'Italic', + } + + def __init__(self, trunk): + """LetterPress diagram layer constructor""" + super(LetterPress, self).__init__(trunk) + cpool = model_constraintpool.ConstraintPool.get_pool() + self.textcolor = exon_color.Color(self.path, 0, 0, 0, 1) + self.family = cpool.get(self, 'family')[0] + self.style = cpool.get(self, 'style')[0] + self.size = cpool.get(self, 'size')[0] + self.center = exon_position.Position(self.path, 0.0, 0.0) + self.direction_steps = [exon_direction.Direction(self.path, 0.0, 0.0)] + self.buzzwords = exon_buzzword.Buzzword(self.path, ['']) + + def __eq__(self, other): + """Equality based on the objects components.""" + equal = isinstance(other, LetterPress) \ + and super(LetterPress, self).__eq__(other) \ + and self.textcolor == other.textcolor \ + and self.family == other.family \ + and self.style == other.style \ + and self.size == other.size \ + and self.center == other.center \ + and len(self.direction_steps) == len(other.direction_steps) \ + and self.buzzwords == other.buzzwords + if equal: + for index, direction in enumerate(self.direction_steps): + equal = equal and direction == other.direction_steps[index] + return equal + + def randomize(self): + """Randomize the layers components.""" + super(LetterPress, self).randomize() + cpool = model_constraintpool.ConstraintPool.get_pool() + family_constraint = cpool.get(self, 'family') + style_constraint = cpool.get(self, 'style') + size_constraint = cpool.get(self, 'size') + self.textcolor.randomize() + self.family = random.choice(family_constraint) + self.style = random.choice(style_constraint) + self.size = random.randint(size_constraint[0], size_constraint[1]) + self.center.randomize() + self.buzzwords.randomize() + self.direction_steps = [] + for i in range(random.randint(1, 6)): + direction = exon_direction.Direction(self.path, 0.0, 0.0) + direction.randomize() + self.direction_steps.append(direction) + + def mutate(self): + """Make small random changes to the layers components.""" + super(LetterPress, self).mutate() + cpool = model_constraintpool.ConstraintPool.get_pool() + family_constraint = cpool.get(self, 'family') + style_constraint = cpool.get(self, 'style') + size_constraint = cpool.get(self, 'size') + self.textcolor.mutate() + if ka_random.is_mutating(): + self.family = random.choice(family_constraint) + if ka_random.is_mutating(): + self.style = random.choice(style_constraint) + if ka_random.is_mutating(): + self.size += random.randint(-12, 12) + self.size = ka_random.limitate_range(self.size, \ + size_constraint[0], \ + size_constraint[1]) + self.center.mutate() + self.buzzwords.mutate() + for direction in self.direction_steps: + direction.mutate() + + def shuffle(self): + """Shuffle similar componets.""" + super(LetterPress, self).shuffle() + self.buzzwords.shuffle() +# self.direction_steps.shuffle() + + def crossingover(self, other): + """ + pre: isinstance(other, LetterPress) + pre: isinstance(self, LetterPress) + # check for distinct references, needs to copy content, not references + post: __return__ is not self + post: __return__ is not other + """ + new_one = LetterPress(self.get_trunk()) + crossing = self.crossingover_base(new_one, other, 5) + new_one.textcolor = self.textcolor.crossingover(other.textcolor) + new_one.center = self.center if crossing[0] else other.center + new_one.buzzwords = self.buzzwords if crossing[1] else other.buzzwords + new_one.family = self.family if crossing[2] else other.family + new_one.style = self.style if crossing[3] else other.style + new_one.size = self.size if crossing[4] else other.size + new_one.direction_steps = ka_random.crossingover(self.direction_steps, \ + other.direction_steps) + return new_one + + def draw(self, ctx, width, height): + """ + pre: ctx is not None + pre: width > 0 + pre: height > 0 + pre: width == height + """ +# self.operator = cairo.OPERATOR_OVER + self.begin_draw(ctx, width, height) + + ctx.scale(1.0/width, 1.0/height) + pango_ctx = pangocairo.CairoContext(ctx) + px, py = self.center.x_pos, self.center.y_pos + fi = di = -1 + for word in self.buzzwords.wordlist: + di = (di+1) % len(self.direction_steps) + step = self.direction_steps[di] + px += step.offset * math.cos(step.radian) + py += step.offset * math.sin(step.radian) + + layout = pango_ctx.create_layout() + fi = (fi+1) % len(self.family) + desc = pango.FontDescription(self.family[fi]) + desc.set_size(self.size * pango.SCALE) + desc.set_style(self.style) + # desc.set_weight(self.font["weight"]) + layout.set_text(word.encode('utf-8')) + layout.set_font_description(desc) + layout.set_alignment(pango.ALIGN_CENTER) + rgba = self.textcolor.rgba + pango_ctx.set_source_rgba(rgba[0], rgba[1], rgba[2], rgba[3]) + pango_ctx.update_layout(layout) + pixel_extents = layout.get_pixel_extents() +# extents = layout.get_extents() + dx = pixel_extents[1][2] / 2 + dy = pixel_extents[1][3] / 2 + pango_ctx.move_to((width * px) - dx, (height * py) - dy) + pango_ctx.show_layout(layout) + + def explain(self, formater): +# super(LetterPress, self).explain(formater) + formater.text_list('buzzwords: ', self.buzzwords.wordlist) + formater.color_item(self.textcolor, 'text color:') + formater.text_item(self.family \ + + ', ' + LetterPress.font_style[self.style] \ + + ', ' + str(self.size)) + formater.position_item(self.center, 'center:') + formater.direction_array(self.direction_steps, 'direction:') + + def copy(self): + """The LetterPress diagram layers copy constructor. + # check for distinct references, needs to copy content, not references + post: __return__ is not self + """ + new_one = LetterPress(self.get_trunk()) + self.copy_base(new_one) + new_one.textcolor = self.textcolor.copy() + new_one.family = self.family + new_one.style = self.style + new_one.size = self.size + new_one.center = self.center.copy() + new_one.buzzwords = self.buzzwords.copy() + new_one.direction_steps = ka_random.copy_list(self.direction_steps) + return new_one |