def draw(self, cr): """ Draw the signal block with label and inputs/outputs. """ border_color = colors.HIGHLIGHT_COLOR if self.highlighted else self._border_color cr.translate(*self.coordinate) for port in self.active_ports(): # ports first cr.save() port.draw(cr) cr.restore() cr.rectangle(*self._area) cr.set_source_rgba(*self._bg_color) cr.fill_preserve() cr.set_source_rgba(*border_color) cr.stroke() # title and params label if self.is_vertical(): cr.rotate(-math.pi / 2) cr.translate(-self.width, 0) cr.set_source_rgba(*self._font_color) for layout, offset in zip(self._surface_layouts, self._surface_layouts_offsets): cr.save() cr.translate(*offset) PangoCairo.update_layout(cr, layout) PangoCairo.show_layout(cr, layout) cr.restore()
def draw_label(self, context, lod): layout, rect, cursor_rect, layout_pos = self._calc_layout_params() cursor_width = cursor_rect.h * 0.075 cursor_width = max(cursor_width, 1.0) label_rgba = self.get_label_color() context.save() context.rectangle(*rect) context.clip() # draw text context.set_source_rgba(*label_rgba) context.move_to(*layout_pos) PangoCairo.show_layout(context, layout) context.restore() # don't clip the caret # draw caret context.move_to(cursor_rect.x, cursor_rect.y) context.rel_line_to(0, cursor_rect.h) context.set_source_rgba(*label_rgba) context.set_line_width(cursor_width) context.stroke() # reset attributes; layout is reused by all keys due to memory leak layout.set_attributes(Pango.AttrList())
def render_paragraph(cr, unit_scale, y, text, font = "Serif 6.5", align_top = False): x = INSET + SIDE_TITLE_WIDTH + SIDE_GAP cr.save() cr.move_to(x, y) # Remove the mm scale cr.scale(1.0 / unit_scale, 1.0 / unit_scale) layout = PangoCairo.create_layout(cr) m = re.match(r'(.*?)([0-9]+(\.[0-9]*)?)$', font) font_size = float(m.group(2)) font_size *= unit_scale / POINTS_PER_MM font = m.group(1) + str(font_size) fd = Pango.FontDescription.from_string(font) layout.set_font_description(fd) layout.set_width((CARD_WIDTH - x - INSET) * unit_scale * Pango.SCALE) layout.set_text(text, -1) (ink_rect, logical_rect) = layout.get_pixel_extents() if align_top: cr.rel_move_to(0, -logical_rect.height) PangoCairo.show_layout(cr, layout) cr.restore() return logical_rect.height / unit_scale
def draw(self, canvas, cr): if self.sex == Person.MALE: label = '\u2642 ' + self.name bg_color = (0.72, 0.81, 0.90) elif self.sex == Person.FEMALE: label = '\u2640 ' + self.name bg_color = (1, 0.80, 0.94) else: label = '\u2650 ' + self.name bg_color = (0.95, 0.86, 0.71) layout = canvas.create_pango_layout(label) font = Pango.FontDescription('Sans') layout.set_font_description(font) width, height = layout.get_size() self.width = width / 1024 cr.set_source_rgb(*bg_color) cr.rectangle(self.x + 1, self.y + 1, self.width - 2, self.height - 2) cr.fill() cr.set_source_rgb(0.50, 0.50, 0.50) cr.move_to(self.x, self.y) cr.line_to(self.x + self.width, self.y) cr.stroke() cr.move_to(self.x, self.y + self.height) cr.line_to(self.x + self.width, self.y + self.height) cr.stroke() cr.set_source_rgb(0, 0, 0) cr.move_to(self.x, self.y) PangoCairo.show_layout(cr, layout)
def draw(self, cc): if self.text: cc.save() x_scale = cc.get_matrix()[0] x_trans = cc.get_matrix()[4] cc.identity_matrix() #layout = cc.create_layout() layout = PangoCairo.create_layout(cc) layout.set_markup(self.text) layout.set_font_description(Pango.FontDescription(self.font)) txw, txh = layout.get_size() if self.conf['text_position'] in [POSITION_SW, POSITION_NW]: x_trans = x_trans - txw / Pango.SCALE - x_scale * self.conf['border'] layout.set_alignment(Pango.Alignment.RIGHT) else: x_trans = x_trans + x_scale * (1 + self.conf['border']) layout.set_alignment(Pango.Alignment.LEFT) if self.conf['text_position'] in [POSITION_NE, POSITION_NW]: y_trans = x_scale * self.conf['border'] / 2 else: y_trans = x_scale * (1 - self.conf['border'] / 2) - txh / Pango.SCALE cc.translate(x_trans, y_trans) # Draw text shadow cc.translate(1,1) cc.set_source_rgba(self.conf['text_shadow_color_r'], self.conf['text_shadow_color_g'], self.conf['text_shadow_color_b'], self.conf['text_shadow_color_a']) PangoCairo.show_layout(cc, layout) # Draw text cc.translate(-1,-1) cc.set_source_rgba(self.conf['text_color_r'], self.conf['text_color_g'], self.conf['text_color_b'], self.conf['text_color_a']) PangoCairo.show_layout(cc, layout) cc.restore()
def draw(self,sender, c, data=None): c.set_source_rgb(0,0,0) self.drawBackground(c) pc = PangoCairo.create_context(c) #c.set_antialias( cairo.Antialias.SUBPIXEL ) l = Pango.Layout(pc) l.set_font_description( Pango.FontDescription(self.font)) l.set_text( self.text, -1) l.set_alignment( Pango.Alignment.CENTER ) l.set_wrap( Pango.WrapMode.WORD ) l.set_width( (self.width-5) * Pango.SCALE ) l.set_height( (self.height-5) * Pango.SCALE ) l.set_ellipsize( Pango.EllipsizeMode.END ) w = 0 h = 0 w,h = l.get_pixel_size() c.move_to( 0, (self.height/2) - (h/2) ) c.set_source_rgb(0, 0, 0) PangoCairo.update_layout(c, l) PangoCairo.show_layout(c, l) import storage if(storage.window.focusedItem == self): c.set_source_rgb(0,0,200) c.move_to(0,0) c.rectangle(0,0,self.width-1,self.height-1) c.stroke() return False
def draw(self, cr, layout_info, hide_if_empty=False): if not hide_if_empty or self.obj.text: layout = create_layout(cr, self.obj.id_str() + " " + self.obj.text, layout_info, 6) xpos, ypos = show_layout(cr, layout, layout_info) cr.move_to(self.obj.x, self.obj.y) cr.line_to(xpos, ypos) cr.set_line_width(LINE_WIDTH) set_rgb_from_color_cycle(cr) cr.stroke() cr.set_fill_rule(cairo.FILL_RULE_EVEN_ODD) cr.set_source_rgba(0.0, 0.0, 1.0, 0.5) cr.set_line_width(LINE_WIDTH) self.draw_box(cr) text = str(self.obj.id[-1]) layout = PangoCairo.create_layout(cr) layout.set_text(text, len(text)) # Dont recreate the description all the time? font = Pango.FontDescription(layout_info['boxfont']) layout.set_font_description(font) cr.move_to(self.obj.x + LINE_WIDTH, self.obj.y + LINE_WIDTH) PangoCairo.show_layout(cr, layout) cr.new_path()
def write_image(self, filename): # get text size tw, th = _get_text_size(self.ref) # create an image where the text fits w = int(tw + CONFIG.text_border_width + 2 * CONFIG.image_border_width) h = CONFIG.image_size[1] img = cairo.SVGSurface(filename, w, h) ctx = cairo.Context(img) # background fill ctx.rectangle(0, 0, w, h) ctx.set_source_rgb(*CONFIG.text_bgcolor) ctx.fill_preserve() # border ctx.set_line_width(CONFIG.text_border_width) levcol = CONFIG.level_colors[self.level] ctx.set_source_rgb(*levcol) ctx.stroke() # reference text ctx.set_source_rgb(*CONFIG.text_color) layout = PangoCairo.create_layout(ctx) layout.set_font_description(Pango.FontDescription(CONFIG.text_font)) layout.set_text(self.ref, -1) PangoCairo.update_layout(ctx, layout) ctx.move_to((w-tw)/2, (h-CONFIG.text_border_width-layout.get_iter().get_baseline()/Pango.SCALE)/2.0) PangoCairo.show_layout(ctx, layout) ctx.show_page()
def write_image(self, filename): w = 8 + len(self.ref)*7 h = CONFIG.image_size[1] # create an image where the text fits img = cairo.SVGSurface(filename, w, h) ctx = cairo.Context(img) # background fill ctx.rectangle(0, 0, w, h) ctx.set_source_rgb(*CONFIG.swiss_mobile_bgcolor) ctx.fill_preserve() # border ctx.set_line_width(CONFIG.image_border_width) levcol = CONFIG.level_colors[self.level] ctx.set_source_rgb(*levcol) ctx.stroke() # text ctx.set_source_rgb(*CONFIG.swiss_mobile_color) layout = PangoCairo.create_layout(ctx) layout.set_font_description(Pango.FontDescription(CONFIG.swiss_mobile_font)) layout.set_text(self.ref, -1) tw, th = layout.get_pixel_size() PangoCairo.update_layout(ctx, layout) ctx.move_to(w - tw - CONFIG.image_border_width/2, h - layout.get_iter().get_baseline()/Pango.SCALE - CONFIG.image_border_width/2) PangoCairo.show_layout(ctx, layout) ctx.show_page()
def draw_balloon(self, cr, b): x = int(b.x) y = int(b.y) # Draw the string. cr.set_source_rgb(0, 0, 0) cr.move_to(int(b.x), int(b.y + b.size / 2)) cr.line_to(int(b.x), int(b.y + b.size)) cr.stroke() # Draw the balloon. cr.save() cr.set_source_rgb(b.color[0], b.color[1], b.color[2]) cr.arc(b.x, b.y, b.size / 2, 0, 2 * math.pi) cr.fill() cr.restore() cr.set_source_rgb(0, 0, 0) pango_layout = PangoCairo.create_layout(cr) fd = Pango.FontDescription('Sans') fd.set_size(12 * Pango.SCALE) pango_layout.set_font_description(fd) pango_layout.set_text(b.word, len(b.word)) size = pango_layout.get_size() x = x - (size[0] / Pango.SCALE) / 2 y = y - (size[1] / Pango.SCALE) / 2 cr.move_to(x, y) PangoCairo.update_layout(cr, pango_layout) PangoCairo.show_layout(cr, pango_layout)
def draw_page(self, operation, context, page_number): """ Render the QSO details on the page. :arg Gtk.PrintOperation operation: The printing API. :arg Gtk.PrintContext context: Used to draw/render the pages to print. :arg int page_number: The current page number. """ cr = context.get_cairo_context() cr.set_source_rgb(0, 0, 0) layout = context.create_pango_layout() layout.set_font_description(Pango.FontDescription("monospace expanded 10")) layout.set_width(int(context.get_width()*Pango.SCALE)) current_line_number = 1 for line in self.text_to_print: layout.set_text(line, -1) cr.move_to(5, current_line_number*self.line_height) PangoCairo.update_layout(cr, layout) PangoCairo.show_layout(cr, layout) current_line_number += 1 if((current_line_number+1)*self.line_height >= context.get_height()): for j in range(0, current_line_number-1): self.text_to_print.pop(0) # Remove what has been printed already before draw_page is called again. break return
def draw_graph(): """Funkcja rysujaca wykres. Funkcja rysuje osie wykresu, slupki na osi OX dla zadanych wartosci a takze umieszcza jezyki na osi OY. """ ctx.set_source_rgba(0, 0, 0, 1) # ustawienie koloru ctx.set_line_width(2) # ustawienie grubosci linii ctx.move_to(130, 600) ctx.line_to(130, 250) ctx.move_to(130, 600) ctx.line_to(580, 600) # narysowanie osi wykresu ctx.stroke_preserve() count = 0 # ustawienie wartosci licznika na 0 k = 125 # przyjeta skala, sluzy do rysowania slupkow na podstawie danej ilosci ksiazek for length in get_values(): ctx.set_source_rgba(0, 0, 0, 1) # ustawienie koloru ctx.set_line_width(2) # ustawienie grubosci linii ctx.rectangle(132, 570 - 32 * count, length / k, 20) # rysowanie slupka dla zadanej dlugosci ctx.stroke_preserve() ctx.set_source_rgba(0, 128, 128, 1) # ustawienie koloru ctx.fill() # wypelnienie slupka kolorem count += 1 # inkrementacja licznika count = 0 # wyzerowanie licznika for name in get_names(): # dla kazdej nazwy kraju ctx.set_source_rgba(0, 0, 255, 1) # ustawienie koloru layout.set_text(name, -1) # umieszczenie nazwy kraju na osi OY ctx.move_to(0, 570 - 32 * count) PangoCairo.show_layout(ctx, layout) # wyswietlenie zmian count += 1
def do_draw(self, gpsmap, ctx): """ Draw all the messages """ ctx.save() font_size = "%s %d" % (self.font, self.size) font = Pango.FontDescription(font_size) descr = Pango.font_description_from_string(self.font) descr.set_size(self.size * Pango.SCALE) color = Gdk.color_parse(self.color) ctx.set_source_rgba(float(color.red / 65535.0), float(color.green / 65535.0), float(color.blue / 65535.0), 0.9) # transparency d_width = gpsmap.get_allocation().width d_width -= 100 ctx.restore() ctx.save() ctx.move_to(100, 5) layout = PangoCairo.create_layout(ctx) layout.set_font_description(descr) layout.set_indent(Pango.SCALE * 0) layout.set_alignment(Pango.Alignment.LEFT) layout.set_wrap(Pango.WrapMode.WORD_CHAR) layout.set_spacing(Pango.SCALE * 3) layout.set_width(d_width * Pango.SCALE) layout.set_text(self.message, -1) PangoCairo.show_layout(ctx, layout) ctx.restore() ctx.stroke()
def draw_cb(self, widget, cr): alloc = self.get_allocation() width = alloc.width height = alloc.height style = self.get_style() c = style.bg[gtk.STATE_NORMAL] c_rgb = [float(x)/65535 for x in (c.red, c.green, c.blue)] cr.set_source_rgb(*c_rgb) cr.rectangle(0, 0, width, height) cr.fill() c = style.text[gtk.STATE_NORMAL] c = [float(x)/65535 for x in (c.red, c.green, c.blue)] cr.set_source_rgb(*c_rgb) layout = self.lay_out_group_names(width) leading = style.font_desc.get_size() / 6 vmargin = leading // pango.SCALE layout.set_spacing(leading) cr.move_to(0, self.VERTICAL_MARGIN) if pygtkcompat.USE_GTK3: PangoCairo.show_layout(cr, layout) else: cr.show_layout(layout) # Catch reflows, which maybe result in more or fewer rows. self.set_size_request(-1, -1) # "ask again, give me my natural size" self.queue_resize_no_redraw() self.layout = layout
def _render(self, ctx=None): if not self._doRender: return ctx = ctx or self._get_context() if GI: ctx = _UNSAFE_cairocffi_context_to_pycairo(ctx) # we build a PangoCairo context linked to cairo context # then we create a pango layout # we update the context as we already used a null one on the pre-rendering # supposedly there should not be a big performance penalty self._pang_ctx = PangoCairo.create_context(ctx) if self._fillcolor is not None: # Go to initial point (CORNER or CENTER): transform = self._call_transform_mode(self._transform) if GI: transform = pycairo.Matrix(*transform.as_tuple()) ctx.set_matrix(transform) ctx.translate(self.x, self.y-self.baseline) if self._outline is False: ctx.set_source_rgba(*self._fillcolor) PangoCairo.show_layout(ctx, self.layout) PangoCairo.update_layout(ctx, self.layout)
def path(self): if not self._pang_ctx: self._pre_render() # here we create a new cairo.Context in order to hold the pathdata tempCairoContext = cairo.Context(cairo.RecordingSurface(cairo.CONTENT_ALPHA, None)) tempCairoContext = driver.ensure_pycairo_context(tempCairoContext) tempCairoContext.move_to(self.x, self.y - self.baseline) # in here we create a pangoCairoContext in order to display layout on it # supposedly showlayout should work, but it fills the path instead, # therefore we use layout_path instead to render the layout to pangoCairoContext # tempCairoContext.show_layout(self.layout) PangoCairo.layout_path(tempCairoContext, self.layout) # here we extract the path from the temporal cairo.Context we used to draw on the previous step pathdata = tempCairoContext.copy_path() # creates a BezierPath instance for storing new shoebot path p = BezierPath(self._bot) # parsing of cairo path to build a shoebot path for item in pathdata: cmd = item[0] args = item[1] if cmd == PATH_MOVE_TO: p.moveto(*args) elif cmd == PATH_LINE_TO: p.lineto(*args) elif cmd == PATH_CURVE_TO: p.curveto(*args) elif cmd == PATH_CLOSE_PATH: p.closepath() # cairo function for freeing path memory return p
def draw_string(self, label, x, y, offsets=None): '''Draw a string at the specified point. offsets is an optional tuple specifying where the string will be drawn relative to the coordinates passed in; for instance, if offsets are (-1, -1) the string will be drawn with the bottom right edge at the given x, y. ''' fontname = "Sans Italic 14" # fontname = "Sans Italic 14" layout = PangoCairo.create_layout(self.ctx) desc = Pango.font_description_from_string(fontname) layout.set_font_description( desc) layout.set_text(label, -1) if offsets: width, height = layout.get_pixel_size() # # pango draws text with the upper left corner at x, y. # # So that's an offset of (1, 1). Adjust if offsets are different. # # XXX Cairo may do things differently. # xbearing, ybearing, width, height, xadvance, yadvance = \ # self.ctx.text_extents(label) if offsets[0] == 0: x -= int(width/2) elif offsets[0] != 1: x += int(width * offsets[0]) if offsets[1] != 1: y += int(height * offsets[1] - height/2) self.ctx.move_to(x, y) PangoCairo.show_layout (self.ctx, layout)
def _pre_render(self): #we use a new CairoContext to pre render the text rs = cairo.RecordingSurface(cairo.CONTENT_ALPHA, None) cr = cairo.Context(rs) if GI: cr = _UNSAFE_cairocffi_context_to_pycairo(cr) self._pang_ctx = PangoCairo.create_context(cr) self.layout = PangoCairo.create_layout(cr) # layout line spacing # TODO: the behaviour is not the same as nodebox yet ## self.layout.set_spacing(int(((self._lineheight-1)*self._fontsize)*Pango.SCALE)) #pango requires an int casting # we pass pango font description and the text to the pango layout self.layout.set_font_description(self._fontface) self.layout.set_text(self.text, -1) # check if max text width is set and pass it to pango layout # text will wrap, meanwhile it checks if and indent has to be applied # indent is subordinated to width because it makes no sense on a single-line text block if self.width: self.layout.set_width(int(self.width)*Pango.SCALE) if self._indent: self.layout.set_indent(self._indent*Pango.SCALE) # set text alignment if self._align == "right": self.layout.set_alignment(Pango.Alignment.RIGHT) elif self._align == "center": self.layout.set_alignment(Pango.Alignment.CENTER) elif self._align == "justify": self.layout.set_alignment(Pango.Alignment.LEFT) self.layout.set_justify(True) else: self.layout.set_alignment(Pango.Alignment.LEFT)
def _print_text(self, context, x, y, text, font_size, max_width=0, alignment=None, color=None): if text is None: return context.save() context.translate(x, y) layout = self.create_pango_layout(text) if max_width > 0: layout.set_width(max_width * Pango.SCALE) layout.set_wrap(Pango.WrapMode.WORD_CHAR) if alignment is not None: layout.set_alignment(alignment) font_desc = Pango.FontDescription("Sans %s" % font_size) layout.set_font_description(font_desc) if color is None: context.set_source_rgb(0, 0, 0) else: context.set_source_rgba(*style.Color(color).get_rgba()) PangoCairo.update_layout(context, layout) PangoCairo.show_layout(context, layout) context.fill() context.restore()
def do_draw_cb(self, widget, cr): # The do_draw_cb is called when the widget is asked to draw itself # with the 'draw' as opposed to old function 'expose event' # Remember that this will be called a lot of times, so it's usually # a good idea to write this code as optimized as it can be, don't # Create any resources in here. cr.translate ( RADIUS, RADIUS) layout = PangoCairo.create_layout (cr) layout.set_text("శ్రీమదాంధ్రమహాభారతము", -1) desc = Pango.font_description_from_string (FONT) layout.set_font_description( desc) rangec = range(0, N_WORDS) for i in rangec: width, height = 0,0 angle = (360. * i) / N_WORDS; cr.save () red = (1 + math.cos ((angle - 60) * math.pi / 180.)) / 2 cr.set_source_rgb ( red, 0, 1.0 - red) cr.rotate ( angle * math.pi / 180.) #/* Inform Pango to re-layout the text with the new transformation */ PangoCairo.update_layout (cr, layout) width, height = layout.get_size() cr.move_to ( - (float(width) / 1024.) / 2, - RADIUS) PangoCairo.show_layout (cr, layout) cr.restore()
def draw_cb(self, widget, cr): alloc = self.get_allocation() width = alloc.width height = alloc.height fg, bg = self._text_colors["normal"] #cr.set_source_rgb(*bg.get_rgb()) #cr.paint() cr.set_source_rgb(*fg.get_rgb()) layout = self.lay_out_group_names(width) vmargin = self._leading // pango.SCALE layout.set_spacing(self._leading) cr.move_to(0, self.VERTICAL_MARGIN) if pygtkcompat.USE_GTK3: PangoCairo.show_layout(cr, layout) else: cr.show_layout(layout) # Catch reflows, which maybe result in more or fewer rows. self.set_size_request(-1, -1) # "ask again, give me my natural size" self.queue_resize_no_redraw() self.layout = layout
def __on_expose_event( self, widget, context ): """ Draws the text on the widget. This should be called indirectly by using self.queue_draw() """ #if self.__graphics_context is None: # self.__graphics_context = self.get_window().new_gc() #self.get_window().draw_layout(_context, # int(self.__x_offset), 0, self.__pango_layout, # self._fg) #context.show_text("test") if not self.__graphics_context: self.__graphics_context = context self.__graphics_context.set_source_rgb(1.0, 1.0, 1.0) #self.__graphics_context.set_source_rgb(self._fg) self.__pango_layout = PangoCairo.create_layout(self.__graphics_context) #self.__reset_widget() self.__pango_layout.set_markup(self.text, -1) PangoCairo.show_layout(self.__graphics_context, self.__pango_layout) lbl_x, lbl_y = self.__pango_layout.get_pixel_size() #self.set_size_request( -1, lbl_y ) print lbl_x, lbl_y self.__graphics_context.move_to(0, 0)
def do_draw(self, cairo_ctx): cairo_ctx.save() try: layout = PangoCairo.create_layout(cairo_ctx) if self.font: font = Pango.FontDescription() font.set_family(self.font) layout.set_font_description(font) layout.set_text(self.text, -1) txt_size = layout.get_size() if 0 in txt_size: return txt_factor = float(self.height) / txt_size[1] self.size = ( int(txt_size[0] * txt_factor), int(txt_size[1] * txt_factor) ) self.position = ( int(self.center_position[0] - (self.size[0] / 2)), int(self.center_position[1] - (self.size[1] / 2)) ) cairo_ctx.translate(self.position[0], self.position[1]) if txt_factor <= 0.0: return cairo_ctx.scale(txt_factor * Pango.SCALE, txt_factor * Pango.SCALE) cairo_ctx.set_source_rgb(0.0, 0.0, 0.0) PangoCairo.update_layout(cairo_ctx, layout) PangoCairo.show_layout(cairo_ctx, layout) finally: cairo_ctx.restore()
def _draw_text(cc, label, x, y, size, width, scale, heading, rgb, wrap=False): import textwrap final_scale = int(size * scale) * Pango.SCALE label = str(label) if wrap: label = '\n'.join(textwrap.wrap(label, int(width / scale))) pl = PangoCairo.create_layout(cc) fd = Pango.FontDescription(self._font) fd.set_size(final_scale) pl.set_font_description(fd) if isinstance(label, (str, unicode)): text = label.replace('\0', ' ') elif isinstance(label, (float, int)): text = str(label) else: text = label pl.set_text(str(label), len(str(label))) pl.set_width(int(width) * Pango.SCALE) cc.save() cc.translate(x, y) cc.rotate(heading * DEGTOR) cc.set_source_rgb(rgb[0] / 255., rgb[1] / 255., rgb[2] / 255.) PangoCairo.update_layout(cc, pl) PangoCairo.show_layout(cc, pl) cc.restore()
def _render_hits(self, surface): """Add the number of hits to a Cairo surface""" if not self.creature or not self.creature.hits: return ctx = cairo.Context(surface) ctx.set_antialias(cairo.ANTIALIAS_SUBPIXEL) layout = PangoCairo.create_layout(ctx) layout.set_alignment(Pango.Alignment.CENTER) # TODO Vary font size with scale desc = Pango.FontDescription("monospace 20") layout.set_font_description(desc) layout.set_text(str(self.creature.hits), -1) size = surface.get_width() layout.set_width(size) ctx.set_source_rgb(1, 0, 0) x = 0.5 * size y = 0.2 * size ctx.set_source_rgb(1, 1, 1) ctx.set_line_width(1) width, height = layout.get_pixel_size() ctx.rectangle(x - 0.5 * width, y, 0.9 * width, 0.8 * height) ctx.fill() ctx.set_source_rgb(1, 0, 0) ctx.move_to(x, y) PangoCairo.show_layout(ctx, layout)
def make_layout(self, ctx): layout = PangoCairo.create_layout(ctx) layout.set_text(self.text, -1) for k, v in self.attrs.items(): getattr(layout, "set_" + k)(v) PangoCairo.update_layout(ctx, layout) return layout
def _draw_time(self, cr): """Draw the time in colors (digital display). """ # TRANS: The format used to display the time for digital clock # You can add AM/PM indicator or use 12/24 format, for example # "%I:%M:%S %p". See # http://docs.python.org/lib/module-time.html for available # strftime formats If the display of the time is moving # horizontally, it means that the glyphs of the digits used in # the font don't have the same width. Try to use a Monospace # font. xgettext:no-python-format cr.save() markup = _('<markup>\ <span lang="en" font_desc="Sans,Monospace Bold 96">\ <span foreground="#005FE4">%I</span>:\ <span foreground="#00B20D">%M</span>:\ <span foreground="#E6000A">%S</span>%p</span></markup>') markup_time = self._time.strftime(markup) cr.set_source_rgba(*style.Color(self._COLOR_BLACK).get_rgba()) pango_layout = PangoCairo.create_layout(cr) d = int(self._center_y + 0.3 * self._radius) pango_layout.set_markup(markup_time) dx, dy = pango_layout.get_pixel_size() pango_layout.set_alignment(Pango.Alignment.CENTER) cr.translate(self._center_x - dx / 2.0, d - dy / 2.0) PangoCairo.update_layout(cr, pango_layout) PangoCairo.show_layout(cr, pango_layout) cr.restore()
def draw(self, cr): """ Draw the socket with a label. """ border_color = self._border_color cr.set_line_width(self._line_width_factor * cr.get_line_width()) cr.translate(*self.coordinate) cr.rectangle(*self._area) cr.set_source_rgba(*self._bg_color) cr.fill_preserve() cr.set_source_rgba(*border_color) cr.stroke() if not self._show_label: return # this port is folded (no label) if self.is_vertical(): cr.rotate(-math.pi / 2) cr.translate(-self.width, 0) cr.translate(*self._label_layout_offsets) cr.set_source_rgba(*self._font_color) PangoCairo.update_layout(cr, self.label_layout) PangoCairo.show_layout(cr, self.label_layout)
def draw_text_box_centered(ctx, widget, w_width, w_height, text, font_desc=None, add_progress=None): style_context = widget.get_style_context() text_color = style_context.get_color(Gtk.StateFlags.PRELIGHT) if font_desc is None: font_desc = style_context.get_font(Gtk.StateFlags.NORMAL) font_desc.set_size(14 * Pango.SCALE) pango_context = widget.create_pango_context() layout = Pango.Layout(pango_context) layout.set_font_description(font_desc) layout.set_text(text, -1) width, height = layout.get_pixel_size() ctx.move_to(w_width / 2 - width / 2, w_height / 2 - height / 2) ctx.set_source_rgba(text_color.red, text_color.green, text_color.blue, 0.5) PangoCairo.show_layout(ctx, layout) # Draw an optional progress bar below the text (same width) if add_progress is not None: bar_height = 10 ctx.set_source_rgba(*text_color) ctx.set_line_width(1.) rounded_rectangle(ctx, w_width / 2 - width / 2 - .5, w_height / 2 + height - .5, width + 1, bar_height + 1) ctx.stroke() rounded_rectangle(ctx, w_width / 2 - width / 2, w_height / 2 + height, int(width * add_progress) + .5, bar_height) ctx.fill()
def create_labels(self, cr=None): """Create the labels for the socket.""" self.label_layout = Gtk.DrawingArea().create_pango_layout('') self.label_layout.set_alignment(Pango.Alignment.CENTER) if cr: PangoCairo.update_layout(cr, self.label_layout) if self.domain in (Constants.GR_MESSAGE_DOMAIN, Constants.GR_STREAM_DOMAIN): self._line_width_factor = 1.0 else: self._line_width_factor = 2.0 self._update_colors() layout = self.label_layout layout.set_markup('<span font_desc="{font}">{name}</span>'.format( name=Utils.encode(self.name), font=Constants.PORT_FONT )) label_width, label_height = self.label_layout.get_size() self.width = 2 * Constants.PORT_LABEL_PADDING + label_width / Pango.SCALE self.height = 2 * Constants.PORT_LABEL_PADDING + label_height / Pango.SCALE self._label_layout_offsets = [0, Constants.PORT_LABEL_PADDING] # if self.dtype == 'bus': # self.height += Constants.PORT_EXTRA_BUS_HEIGHT # self._label_layout_offsets[1] += Constants.PORT_EXTRA_BUS_HEIGHT / 2 self.height += self.height % 2 # uneven height
def draw_text(self, gc, x, y, text, fg_col=None, bg_col=None): #print( "draw_text, ", self.xpos, x, y) if self.hex: text2 = "" for aa in text: tmp = "%02x " % ord(aa) text2 += tmp text2 = text2[self.xpos * 3:] elif self.stab: text2 = "" cnt = 0 for aa in text: if aa == " ": text2 += "_" elif aa == "\t": spaces = self.tabstop - (cnt % self.tabstop) cnt += spaces - 1 for bb in range(spaces): text2 += "o" else: text2 += aa cnt += 1 #text2 = text2[self.xpos:] #self.layout.set_text(ppp, len(ppp)) else: #text2 = text[self.xpos:].replace("\r", " ") text2 = text.replace("\r", "a ") #utf8_decoder = codecs.getincrementaldecoder('utf8')() try: if type(text2) != str: text2 = codecs.decode(text2) #print ("string is UTF-8, length %d bytes" % len(text2)) else: pass #print ("string is text, length %d bytes" % len(text2)) except UnicodeError: print("string is not UTF-8") #return xx, yy #text2 = kill_non_ascii(text2) '''bbb = is_ascii(text2) if bbb > 0: text2 = text2[:bbb-1] + " Non ASCII char " #return xx, yy ''' self.layout.set_text(text2, len(text2)) #xx, yy = self.layout.get_pixel_size() #xx, yy = self.layout.get_size() #xx /= Pango.SCALE; #yy /= Pango.SCALE; #(pr, lr) = self.layout.get_pixel_extents() (pr, lr) = self.layout.get_extents() xx = lr.width / Pango.SCALE yy = lr.height / Pango.SCALE #offs = self.xpos * self.cxx offs = 0 if bg_col: gc.set_source_rgba(bg_col[0], bg_col[1], bg_col[2]) # The hard way .... #rc = self.layout.get_extents().logical_rect #rc = self.layout.get_extents().ink_rect #print( "rc", rc.x, rc.y, rc.width / Pango.SCALE, \ # rc.height / Pango.SCALE ) #gc.rectangle(x, y, rc.width / Pango.SCALE, \ # rc.height / Pango.SCALE) gc.rectangle(x - offs, y, xx, yy) #print( self.xpos, x, y, xx, yy) gc.fill() if fg_col: gc.set_source_rgba(fg_col[0], fg_col[1], fg_col[2]) #gc.move_to(x - offs, y) gc.move_to(x, y) PangoCairo.show_layout(gc, self.layout) # Debug output, help on visuals #self.draw_line(gc, x+2, y+yy-5, x+xx-2, y+yy+5) if self.scol: gc.set_source_rgba(0, 0, 0) pos = BOUNDLINE - self.xpos self.draw_line(gc, pos * self.cxx, \ 0, pos * self.cxx, self.hhh, ) return xx, yy
def draw(self, context): style_ctxt = self.get_style_context() self.light = style_ctxt.lookup_color("p_light_color")[1] self.dark = style_ctxt.lookup_color("p_dark_color")[1] if not self.model: return # Draw graphical Clock. Should this be moved to preferences? drawClock = True rect = Gdk.Rectangle() clip_ext = context.clip_extents() rect.x, rect.y, rect.width, rect.height = clip_ext[0], clip_ext[1], \ clip_ext[2] - clip_ext[0], clip_ext[3] - clip_ext[1] context.rectangle(rect.width / 2. * self.model.movingColor, 0, rect.width / 2., rect.height) context.set_source_rgba(self.dark.red, self.dark.green, self.dark.blue, self.dark.alpha) context.fill_preserve() context.new_path() time0 = self.names[0], self.formatedCache[WHITE] layout0 = self.create_pango_layout(" %s: %s " % (time0)) layout0.set_font_description(Pango.FontDescription("Sans Serif 17")) time1 = self.names[1], self.formatedCache[BLACK] layout1 = self.create_pango_layout(" %s: %s " % (time1)) layout1.set_font_description(Pango.FontDescription("Sans Serif 17")) dbl_max = max(layout1.get_pixel_size()[0], layout0.get_pixel_size()[0]) * 2 self.set_size_request(dbl_max + rect.height + 7, -1) pangoScale = float(Pango.SCALE) # Analog clock code. def paintClock(player): clock_y = rect.height / 2. clock_x = clock_y + rect.width / 2. * player + 1 rec = rect.height / 2. - 3.5 context.arc(clock_x, clock_y, rec - 1, 0, 2 * pi) linear = cairo.LinearGradient(clock_x - rec * 2, clock_y - rec * 2, clock_x + rec * 2, clock_y + rec * 2) linear.add_color_stop_rgba(0, 1, 1, 1, 0.3) linear.add_color_stop_rgba(1, 0, 0, 0, 0.3) # context.set_source_rgba( 0, 0, 0, .3) context.set_source(linear) context.fill() linear = cairo.LinearGradient(clock_x - rec, clock_y - rec, clock_x + rec, clock_y + rec) linear.add_color_stop_rgba(0, 0, 0, 0, 0.5) linear.add_color_stop_rgba(1, 1, 1, 1, 0.5) context.arc(clock_x, clock_y, rec, 0, 2 * pi) context.set_source(linear) context.set_line_width(2.5) context.stroke() starttime = float(self.model.getInitialTime()) or 1 used = self.model.getPlayerTime(player) / starttime if used > 0: if used > 0: context.arc(clock_x, clock_y, rec - .8, -(used + 0.25) * 2 * pi, -0.5 * pi) context.line_to(clock_x, clock_y) context.close_path() elif used == 0: context.arc(clock_x, clock_y, rec - .8, -0.5 * pi, 1.5 * pi) context.line_to(clock_x, clock_y) radial = cairo.RadialGradient(clock_x, clock_y, 3, clock_x, clock_y, rec) if player == 0: # radial.add_color_stop_rgb(0, .73, .74, .71) radial.add_color_stop_rgb(0, .93, .93, .92) radial.add_color_stop_rgb(1, 1, 1, 1) else: # radial.add_color_stop_rgb(0, .53, .54, .52) radial.add_color_stop_rgb(0, .18, .20, .21) radial.add_color_stop_rgb(1, 0, 0, 0) context.set_source(radial) context.fill() x_loc = clock_x - cos((used - 0.25) * 2 * pi) * (rec - 1) y_loc = clock_y + sin((used - 0.25) * 2 * pi) * (rec - 1) context.move_to(clock_x, clock_y - rec + 1) context.line_to(clock_x, clock_y) context.line_to(x_loc, y_loc) context.set_line_width(0.2) if player == 0: context.set_source_rgb(0, 0, 0) else: context.set_source_rgb(1, 1, 1) context.stroke() if drawClock: paintClock(WHITE) if (self.model.movingColor or WHITE) == WHITE: context.set_source_rgba(self.light.red, self.light.green, self.light.blue, self.light.alpha) else: context.set_source_rgba(self.dark.red, self.dark.green, self.dark.blue, self.dark.alpha) y_loc = rect.height / 2. - layout0.get_extents()[0].height / pangoScale / 2 \ - layout0.get_extents()[0].y / pangoScale context.move_to(rect.height - 7, y_loc) PangoCairo.show_layout(context, layout0) if drawClock: paintClock(BLACK) if self.model.movingColor == BLACK: context.set_source_rgba(self.light.red, self.light.green, self.light.blue, self.light.alpha) else: context.set_source_rgba(self.dark.red, self.dark.green, self.dark.blue, self.dark.alpha) y_loc = rect.height / 2. - layout0.get_extents()[0].height / pangoScale / 2 \ - layout0.get_extents()[0].y / pangoScale context.move_to(rect.width / 2. + rect.height - 7, y_loc) PangoCairo.show_layout(context, layout1)
def text(ctx, obj, text, font, lang="en-US", debug=False): ctx.save() lyt = PangoCairo.create_layout(ctx) pg_ctx = lyt.get_context() pg_ctx.set_language(Pango.Language.from_string(lang)) fo = cairo.FontOptions() fo.set_antialias(cairo.ANTIALIAS_SUBPIXEL) PangoCairo.context_set_font_options(pg_ctx, fo) font_family = font.family if not font.replace else font.replace pg_font = Pango.FontDescription("{} {}px".format(font_family, font.size)) lyt.set_font_description(pg_font) lyt.set_text(text, -1) # force length calculation # lyt.set_height(obj["height"]) # lyt.set_width(obj["height"]) # PangoCairo.update_layout(ctx, lyt) pg_size = lyt.get_pixel_size() ink, logical = lyt.get_pixel_extents() if debug: print("pg: %s x %s" % pg_size) print("ink: %s %s %s %s" % (ink.x, ink.y, ink.width, ink.height)) print("logical: %s %s %s %s" % (logical.x, logical.y, logical.width, logical.height)) print("spacing: %s" % (lyt.get_spacing())) print("height: %s" % (lyt.get_height())) print("width: %s" % (lyt.get_width())) #x = obj["x"] - pext.x - pext.width / 2 #y = obj["y"] - pext.y - pext.height / 2 x = (obj.x + obj.width / 2) - ((ink.x + ink.width / 2)) y = (obj.y + obj.height / 2) - ((ink.y + ink.height / 2)) if debug: print("x,y: %s, %s" % (x, y)) ctx.translate(x, y) PangoCairo.update_layout(ctx, lyt) PangoCairo.layout_path(ctx, lyt) if font.outline: # set stroke outline stroke_width = font.size * 0.066 stroke_width = 5.0 if stroke_width < 5.0 else stroke_width ctx.set_line_width(stroke_width) ctx.set_line_cap(cairo.LINE_CAP_ROUND) ctx.set_line_join(cairo.LINE_JOIN_ROUND) ctx.set_source_rgb(*font.outline) ctx.stroke() ctx.set_source_rgb(*font.color) PangoCairo.show_layout(ctx, lyt) if debug: ctx.rectangle(ink.x, ink.y, ink.width, ink.height) ctx.set_line_width(2.0) ctx.set_line_join(cairo.LINE_JOIN_MITER) ctx.set_source_rgb(0, 0.8, 0) ctx.stroke() ctx.rectangle(logical.x, logical.y, logical.width, logical.height) ctx.set_line_width(2.0) ctx.set_line_join(cairo.LINE_JOIN_MITER) ctx.set_source_rgb(0, 0.2, 0.9) ctx.stroke() ctx.restore() if debug: #crosshair(ctx, obj["x"] + obj["width"] / 2, obj["y"] + obj["height"] / 2, 20, (1, 1, 1)) crosshair(ctx, obj.x, obj.y, 20, (1, 1, 1))
def render(self, dpi=UTILS.PT_PER_INCH): self.ctx.save() # Create a PangoCairo context for drawing to Cairo pc = PangoCairo.create_context(self.ctx) city_fd = Pango.FontDescription("DejaVu Sans Condensed Bold 18") header_fd = Pango.FontDescription("DejaVu Sans Condensed Bold 12") label_column_fd = Pango.FontDescription("DejaVu 6") city_layout, city_fascent, city_fheight, city_em = \ self._create_layout_with_font(self.ctx, pc, city_fd) header_layout, header_fascent, header_fheight, header_em = \ self._create_layout_with_font(self.ctx, pc, header_fd) label_layout, label_fascent, label_fheight, label_em = \ self._create_layout_with_font(self.ctx, pc, label_column_fd) column_layout, _, _, _ = \ self._create_layout_with_font(self.ctx, pc, label_column_fd) # By OCitysmap's convention, the default resolution is 72 dpi, # which maps to the default pangocairo resolution (96 dpi # according to pangocairo docs). If we want to render with # another resolution (different from 72), we have to scale the # pangocairo resolution accordingly: PangoCairo.context_set_resolution(city_layout.get_context(), 96. * dpi / UTILS.PT_PER_INCH) PangoCairo.context_set_resolution(column_layout.get_context(), 96. * dpi / UTILS.PT_PER_INCH) PangoCairo.context_set_resolution(label_layout.get_context(), 96. * dpi / UTILS.PT_PER_INCH) PangoCairo.context_set_resolution(header_layout.get_context(), 96. * dpi / UTILS.PT_PER_INCH) margin = label_em cityBlockHeight = city_fheight * 2 index_area_w_pt = self.rendering_area_w - 2 * self.print_bleed_pt - self.margin_inside_pt - self.margin_outside_pt city_layout.set_width( int(UTILS.convert_pt_to_dots((index_area_w_pt) * Pango.SCALE, dpi))) self._draw_page_stroke() self._draw_page_content_stroke() citiesWithEntries = { k: v for k, v in self.index_categories.items() if len(v) > 0 } # print only cities with entries cities = list(citiesWithEntries.keys()) cities.sort() margin_top = self.print_bleed_pt + self.margin_top_bottom_pt margin_top_page = margin_top offset_y = margin_top_page max_drawing_height = 0 city_index = -1 LOG.debug( "%f print_bleed_pt, %f print_safe_margin_pt, %f margin_top_bottom_pt, %f margin_top" % (self.print_bleed_pt, self.print_safe_margin_pt, self.margin_top_bottom_pt, margin_top)) page_full_available_h = self.rendering_area_h - 2 * self.print_bleed_pt - 2 * self.margin_top_bottom_pt content_width = self.rendering_area_w - 2 * Renderer.PRINT_BLEED_PT content_height = self.rendering_area_h - 2 * Renderer.PRINT_BLEED_PT margin_x = self.print_bleed_pt margin_y = self.print_bleed_pt if Renderer.DEBUG: # red stroke dash1: show area excluding bleed-difference self.ctx.save() self.ctx.set_source_rgba(1, 0.4, 0.4, .75) self.ctx.set_dash([1.0, 1.0], 1.0 / 2.0) self.ctx.rectangle(margin_x, margin_y, content_width, content_height) self.ctx.stroke() self.ctx.restore() content_width -= self.margin_inside_pt + self.margin_outside_pt content_height -= 2 * self.margin_top_bottom_pt margin_x += (self.margin_inside_pt if (self.index_page_num + self.page_offset) % 2 else self.margin_outside_pt) margin_y += self.margin_top_bottom_pt #LOG.debug(list(filter(lambda x: len(self.index_categories[cities[x]]) > 0, cities))) for city in cities: city_index = city_index + 1 margin_top_page += max_drawing_height # add max drawing height of previous city index_area_h_pt = self.rendering_area_h - self.print_bleed_pt - self.margin_top_bottom_pt - margin_top_page LOG.debug("============") LOG.debug( "printing index for city '%s'. available area: %f x %f, margin_top_page: %f" % (city, index_area_w_pt, index_area_h_pt, margin_top_page)) if (margin_top_page > (page_full_available_h * 4 / 5)): LOG.debug("NEW PAGE: margin_top_page (%f) > %f" % (margin_top_page, page_full_available_h * 4 / 5)) self._new_page() self._draw_page_stroke() self._draw_page_content_stroke() margin_top = self.print_bleed_pt + self.margin_top_bottom_pt margin_top_page = margin_top index_area_h_pt = self.rendering_area_h - self.print_bleed_pt - self.margin_top_bottom_pt - margin_top_page # full page height available now with this new page. city_header_height = 0 if len(cities) > 1: city_header_height = self._draw_page_header( self._i18n.isrtl(), self.ctx, pc, city_layout, UTILS.convert_pt_to_dots(city_fascent, dpi), UTILS.convert_pt_to_dots(cityBlockHeight, dpi), UTILS.convert_pt_to_dots( self.rendering_area_x + self.print_bleed_pt + (self.margin_inside_pt if (self.index_page_num + self.page_offset) % 2 else self.margin_outside_pt), dpi), UTILS.convert_pt_to_dots( margin_top_page + header_fascent / 2, dpi ), # baseline_y, original: self.rendering_area_y + header_fascent margin_top_page, #margin_top city) index_area_h_pt -= city_header_height margin_top_page += city_header_height # find largest label and location max_label_drawing_width = 0.0 max_location_drawing_width = 0.0 if False: self.index_categories[city].append( self.index_categories[city][0]) self.index_categories[city].append( self.index_categories[city][0]) self.index_categories[city].append( self.index_categories[city][0]) self.index_categories[city].append( self.index_categories[city][0]) self.index_categories[city].append( self.index_categories[city][0]) self.index_categories[city].append( self.index_categories[city][0]) self.index_categories[city].append( self.index_categories[city][0]) self.index_categories[city].append( self.index_categories[city][0]) self.index_categories[city].append( self.index_categories[city][0]) self.index_categories[city].append( self.index_categories[city][0]) self.index_categories[city].append( self.index_categories[city][0]) self.index_categories[city].append( self.index_categories[city][0]) self.index_categories[city].append( self.index_categories[city][0]) if False: # Alle Kategorien, bis auf 1 entfernen while len(self.index_categories[city]) > 1: self.index_categories[city].pop(1) # Alle Einträge, bis auf 1, dieser Kategorie entferne #while len(self.index_categories[city][0].items)>4: # self.index_categories[city][0].items.pop(1) # Bei dieser Kategorie weitere Einträge hinzufügen for i in range(40): self.index_categories[city][0].items.append( self.index_categories[city][0].items[3]) # calculate height of categories #LOG.debug("number of categories: %d" % len(self.index_categories[city])) #LOG.debug("number of entries in first category: %d" % len(self.index_categories[city][0].items)) sum_height = 0 for category in self.index_categories[city]: sum_height += category.label_drawing_height(header_layout) #LOG.debug("adding height %f for category %s" % (category.label_drawing_height(header_layout), category.name)) for street in category.items: #LOG.debug("label_drawing_height of %s: %f" % (street.label, street.label_drawing_height(label_layout))) sum_height += street.label_drawing_height(label_layout) w = street.label_drawing_width(label_layout) if w > max_label_drawing_width: max_label_drawing_width = w #LOG.debug("new max_label_drawing_width: %f (%s)" % (max_label_drawing_width, street.label)) w = street.location_drawing_width(label_layout) if w > max_location_drawing_width: max_location_drawing_width = w #LOG.debug("new max_location_drawing_width: %f (%s)" % (max_location_drawing_width, street.location_str)) col_max_height = math.ceil(float(sum_height) / 4) + 40 LOG.debug( "sum_height: %f, %f per column (4) => col_max_height: %d" % (sum_height, float(sum_height) / 4, col_max_height)) # No street to render, bail out if max_label_drawing_width == 0.0: return #LOG.debug("max_label_drawing_width: %f" % max_label_drawing_width) #LOG.debug("max_location_drawing_width: %f" % max_location_drawing_width) # Find best number of columns # max_drawing_width = max_label_drawing_width + max_location_drawing_width + 2 * margin max_drawing_height = col_max_height needed_drawing_height = max_drawing_height if (index_area_h_pt < max_drawing_height): LOG.debug( "more height neededed (max_drawing_height: %f), than there is available on this page left (index_area_h_pt: %f). Setting max_drawing_height to index_area_h_pt" % (max_drawing_height, index_area_h_pt)) max_drawing_height = index_area_h_pt if Renderer.DEBUG: # green stroke dash3: show printable page area (after header) LOG.debug("Index - printable area (after header): %f x %f" % (index_area_w_pt, max_drawing_height)) self.ctx.save() self.ctx.set_source_rgba(0, 1, 0, .75) self.ctx.set_dash([3.0, 3.0], 3.0 / 2.0) self.ctx.rectangle( self.print_bleed_pt + (self.margin_inside_pt if (self.index_page_num + self.page_offset) % 2 else self.margin_outside_pt), margin_top_page, index_area_w_pt, max_drawing_height) self.ctx.stroke() self.ctx.restore() #LOG.debug("max_drawing_width: %f" % max_drawing_width) #columns_count = int(math.ceil(index_area_w_pt / max_drawing_width)) # following test should not be needed. No time to prove it. ;-) #if columns_count == 0: # columns_count = 1 #LOG.debug("number of columns: %d" % columns_count) columns_count = 4 # Gerald: fixed to 4. # We have now have several columns column_width = index_area_w_pt / columns_count #LOG.debug("column_width: %d" % column_width) column_layout.set_width( int( UTILS.convert_pt_to_dots( (column_width - margin - 5) * Pango.SCALE, dpi))) label_layout.set_width( int( UTILS.convert_pt_to_dots( (column_width - margin - max_location_drawing_width - 2 * label_em) * Pango.SCALE, dpi))) header_layout.set_width( int( UTILS.convert_pt_to_dots( (column_width - margin) * Pango.SCALE, dpi))) if not self._i18n.isrtl(): orig_offset_x = offset_x = margin / 2. orig_delta_x = delta_x = column_width else: orig_offset_x = offset_x = index_area_w_pt - column_width + margin / 2. orig_delta_x = delta_x = -column_width actual_n_cols = 0 # page number of first page self._draw_page_number() if Renderer.DEBUG: # light pink stroke dash 4: full column # temp: show index-area (inside grayed margin) LOG.debug( "pink: %f w -> index_area_w_pt, %f h -> index_area_h_pt" % (index_area_w_pt, index_area_h_pt)) self.ctx.save() self.ctx.set_source_rgba(.85, .25, .85, .75) self.ctx.set_dash([4.0, 4.0], 4.0 / 2.0) self.ctx.rectangle( self.print_bleed_pt + (self.margin_inside_pt if (self.index_page_num + self.page_offset) % 2 else self.margin_outside_pt) + (city_index % 4) * column_width, margin_top_page, column_width, max_drawing_height) self.ctx.stroke() self.ctx.restore() offset_y = margin_top_page # each city/category starts on the corresponding margin for category in self.index_categories[city]: if (offset_y + header_fheight + label_fheight + margin / 2. > (max_drawing_height + margin_top_page)): offset_y = margin_top_page offset_x += delta_x actual_n_cols += 1 if actual_n_cols == columns_count: self._new_page() self._draw_page_stroke() self._draw_page_content_stroke() actual_n_cols = 0 city_header_height = 0 # no city-header on the additional city-pages margin_top_page = margin_top offset_y = margin_top_page offset_x = orig_offset_x delta_x = orig_delta_x max_drawing_height = needed_drawing_height - max_drawing_height + margin_top_page # OR index_area_h_pt => its a new page, full index_area_h_pt is available now # LOG.debug( "NEW PAGE (before category %s). actual_n_cols == columns_count (%d). needed_drawing_height %d, max_drawing_height %d" % (category.name, columns_count, needed_drawing_height, max_drawing_height)) if Renderer.DEBUG: self.ctx.save() self.ctx.set_source_rgba(1, 0, 0, .75) self.ctx.set_dash([8.0, 8.0], 8.0 / 2.0) self.ctx.rectangle( self.rendering_area_x + (self.margin_inside_pt if (self.index_page_num + self.page_offset) % 2 else self.margin_outside_pt) + offset_x, offset_y, column_width, max_drawing_height) self.ctx.stroke() self.ctx.restore() category_height = category.label_drawing_height(header_layout) #LOG.debug("category %s, height draw %d | %d | %d | %d" % (category.name, category_height, header_fascent, UTILS.convert_pt_to_dots(header_fascent, dpi), header_fheight)) category.draw( self._i18n.isrtl(), self.ctx, pc, header_layout, UTILS.convert_pt_to_dots(header_fascent, dpi), UTILS.convert_pt_to_dots(header_fheight, dpi), UTILS.convert_pt_to_dots( self.rendering_area_x + (self.margin_inside_pt if (self.index_page_num + self.page_offset) % 2 else self.margin_outside_pt) + offset_x, dpi), UTILS.convert_pt_to_dots( self.rendering_area_y + offset_y + header_fascent, dpi)) offset_y += category_height for street in category.items: label_height = street.label_drawing_height(label_layout) if (offset_y + label_height + margin / 2. > (max_drawing_height + margin_top_page)): offset_y = margin_top_page offset_x += delta_x actual_n_cols += 1 if actual_n_cols == columns_count: LOG.debug( "NEW PAGE (before street %s). actual_n_cols %d == columns_count %d" % (street.label, actual_n_cols, columns_count)) self._new_page() self._draw_page_stroke() self._draw_page_content_stroke() actual_n_cols = 0 city_header_height = 0 margin_top_page = margin_top offset_y = margin_top_page offset_x = orig_offset_x delta_x = orig_delta_x max_drawing_height = needed_drawing_height - max_drawing_height + margin_top_page if Renderer.DEBUG: self.ctx.save() self.ctx.set_source_rgba(1, 0, 0, .75) self.ctx.set_dash([8.0, 8.0], 8.0 / 2.0) self.ctx.rectangle( self.rendering_area_x + (self.margin_inside_pt if (self.index_page_num + self.page_offset) % 2 else self.margin_outside_pt) + offset_x, offset_y, column_width, max_drawing_height) self.ctx.stroke() self.ctx.restore() self.ctx.set_source_rgb(0, 0, 0) if (street.color is None): self.ctx.set_source_rgb(0, 0, 0) else: color = tuple( int(street.color.lstrip('#')[i:i + 2], 16) / 255. for i in (0, 2, 4)) # draw colorized rectangle next to street self.ctx.save() self.ctx.set_source_rgb(color[0], color[1], color[2]) self.ctx.rectangle( self.rendering_area_x + (self.margin_inside_pt if (self.index_page_num + self.page_offset) % 2 else self.margin_outside_pt) + offset_x, self.rendering_area_y + offset_y, 5, label_height) self.ctx.fill() self.ctx.restore() # alternative: colorize street-text: # self.ctx.set_source_rgb(color[0],color[1],color[2]) street.draw( self._i18n.isrtl(), self.ctx, pc, column_layout, UTILS.convert_pt_to_dots(label_fascent, dpi), UTILS.convert_pt_to_dots(label_fheight, dpi), UTILS.convert_pt_to_dots( self.rendering_area_x + 5 + (self.margin_inside_pt if (self.index_page_num + self.page_offset) % 2 else self.margin_outside_pt) + offset_x, dpi), UTILS.convert_pt_to_dots( self.rendering_area_y + offset_y + label_fascent, dpi), label_layout, UTILS.convert_pt_to_dots(label_height, dpi), UTILS.convert_pt_to_dots(max_location_drawing_width, dpi)) offset_y += label_height self.ctx.restore()
def do_render(self, cr, widget, background_area, cell_area, flags): vw_tags = self.__count_viewable_tags() count = 0 # Select source if self.tag_list is not None: tags = self.tag_list elif self.tag is not None: tags = [self.tag] else: return if self.config.get('dark_mode'): symbolic_color = Gdk.RGBA(0.9, 0.9, 0.9, 1) else: symbolic_color = Gdk.RGBA(0, 0, 0, 1) # Drawing context gdkcontext = cr scale_factor = widget.get_scale_factor() # Don't blur border on lodpi if scale_factor == 1: gdkcontext.set_antialias(cairo.ANTIALIAS_NONE) # Coordinates of the origin point x_align = self.get_property("xalign") y_align = self.get_property("yalign") padding = self.PADDING orig_x = cell_area.x + int( (cell_area.width - 16 * vw_tags - padding * 2 * (vw_tags - 1)) * x_align) orig_y = cell_area.y + int((cell_area.height - 16) * y_align) # We draw the icons & squares for my_tag in tags: my_tag_icon = my_tag.get_attribute("icon") my_tag_color = my_tag.get_attribute("color") rect_x = orig_x + self.PADDING * 2 * count + 16 * count rect_y = orig_y if my_tag_icon: if my_tag_icon in self.SYMBOLIC_ICONS: icon_theme = Gtk.IconTheme.get_default() info = icon_theme.lookup_icon_for_scale( my_tag_icon, 16, scale_factor, 0) pixbuf, was_symbolic = info.load_symbolic(symbolic_color) surface = Gdk.cairo_surface_create_from_pixbuf( pixbuf, scale_factor, widget.get_window()) Gtk.render_icon_surface(widget.get_style_context(), gdkcontext, surface, rect_x, rect_y) count += 1 else: layout = PangoCairo.create_layout(cr) layout.set_markup(my_tag_icon, -1) cr.move_to(rect_x - 2, rect_y - 1) PangoCairo.show_layout(cr, layout) count += 1 elif my_tag_color: # Draw rounded rectangle my_color = Gdk.RGBA() my_color.parse(my_tag_color) Gdk.cairo_set_source_rgba(gdkcontext, my_color) self.__roundedrec(gdkcontext, rect_x, rect_y, 16, 16, 8) gdkcontext.fill() count += 1 # Outer line Gdk.cairo_set_source_rgba(gdkcontext, Gdk.RGBA(0, 0, 0, 0.20)) gdkcontext.set_line_width(1.0) self.__roundedrec(gdkcontext, rect_x, rect_y, 16, 16, 8) gdkcontext.stroke() if self.tag and my_tag: my_tag_icon = my_tag.get_attribute("icon") my_tag_color = my_tag.get_attribute("color") if not my_tag_icon and not my_tag_color: # Draw rounded rectangle Gdk.cairo_set_source_rgba(gdkcontext, Gdk.RGBA(0.95, 0.95, 0.95, 1)) self.__roundedrec(gdkcontext, rect_x, rect_y, 16, 16, 8) gdkcontext.fill() # Outer line Gdk.cairo_set_source_rgba(gdkcontext, Gdk.RGBA(0, 0, 0, 0.20)) gdkcontext.set_line_width(1.0) self.__roundedrec(gdkcontext, rect_x, rect_y, 16, 16, 8) gdkcontext.stroke()
def draw(self, cr, layout, x_px, y_px, w_px, h_px): # Draw the background behind the text cr.rectangle(x_px, y_px, w_px, h_px) self.face.set_source_to_bg(cr) cr.fill() # Figure out the standard character width context = layout.get_context() font = context.load_font(layout.get_font_description()) metrics = font.get_metrics(None) char_w_px = (metrics.get_approximate_char_width()) / Pango.SCALE text = self.contents # In a proportional font, spaces are probably much less than char_w_px, # while visible characters are probably much wider. Thus, if we let # Pango layout an Atom with leading or trailing whitespace, the text # will wind up much wider than it should be. Therefore, we strip # leading and trailing whitespace from the text, and adjust x_px and # w_px to match. l_stripped_text = text.lstrip() stripped_chars = len(text) - len(l_stripped_text) if stripped_chars: text = l_stripped_text x_px += stripped_chars * char_w_px w_px -= stripped_chars * char_w_px r_stripped_text = text.rstrip() stripped_chars = len(text) - len(r_stripped_text) if stripped_chars: text = r_stripped_text w_px -= stripped_chars * char_w_px text = text.replace("&", "&") text = text.replace("<", "<") text = text.replace(">", ">") if "underline" in self.face.attributes: text = f"<u>{text}</u>" if "bold" in self.face.attributes: text = f"<b>{text}</b>" if "dim" in self.face.attributes: text = f"<span alpha='50%'>{text}</span>" if "italic" in self.face.attributes: text = f"<i>{text}</i>" if "blink" in self.face.attributes: # FIXME: support blink? print("Unsupported text attribute 'blink'") layout.set_markup(text, -1) # Measure the size of the text we need to draw. PangoCairo.update_layout(cr, layout) text_w_px, text_h_px = layout.get_pixel_size() if text_w_px == 0 or text_h_px == 0: # No text to actually draw return cr.save() cr.move_to(x_px, y_px) self.face.set_source_to_fg(cr) # Configure Cairo to scale the text to the space we have available cr.set_matrix( cairo.Matrix(xx=(w_px / text_w_px), yy=(h_px / text_h_px))) # Actually draw the text. PangoCairo.show_layout(cr, layout) cr.restore()
def _draw_copyright_notice(self, ctx, w_dots, h_dots, notice=None, osm_date=None): """ Draw a copyright notice at current location and within the given w_dots*h_dots rectangle. Args: ctx (cairo.Context): The Cairo context to use to draw. w_dots,h_dots (number): Rectangle dimension (ciaro units). font_face (str): Pango font specification. notice (str): Optional notice to replace the default. """ today = datetime.date.today() if notice is None: notice = _(u'Copyright © %(year)d MapOSMatic/OCitySMap developers.') notice+= ' ' notice+= _(u'Map data © %(year)d OpenStreetMap contributors (see http://osm.org/copyright)') notice+= '\n' annotations = [] if self.rc.stylesheet.annotation != '': annotations.append(self.rc.stylesheet.annotation) for overlay in self._overlays: if overlay.annotation != '': annotations.append(overlay.annotation) if len(annotations) > 0: notice+= _(u'Map styles:') notice+= ' ' + '; '.join(annotations) + '\n' datasources = set() if self.rc.stylesheet.datasource != '': datasources.add(self.rc.stylesheet.datasource) for overlay in self._overlays: if overlay.datasource != '': datasources.add(overlay.datasource) if len(datasources) > 0: notice+= _(u'Additional data sources:') notice+= ' ' + '; '.join(list(datasources)) + '\n' notice+= _(u'Map rendered on: %(date)s. OSM data updated on: %(osmdate)s.') notice+= ' ' notice+= _(u'The map may be incomplete or inaccurate.') # We need the correct locale to be set for strftime(). prev_locale = locale.getlocale(locale.LC_TIME) try: locale.setlocale(locale.LC_TIME, self.rc.i18n.language_code()) except Exception: LOG.warning('error while setting LC_COLLATE to "%s"' % self.rc.i18n.language_code()) try: if osm_date is None: osm_date_str = _(u'unknown') else: osm_date_str = osm_date.strftime("%d %B %Y %H:%M") notice = notice % {'year': today.year, 'date': today.strftime("%d %B %Y"), 'osmdate': osm_date_str} finally: locale.setlocale(locale.LC_TIME, prev_locale) ctx.save() pc = PangoCairo.create_context(ctx) fd = Pango.FontDescription('DejaVu') fd.set_size(Pango.SCALE) layout = PangoCairo.create_layout(ctx) layout.set_font_description(fd) layout.set_text(notice, -1) draw_utils.adjust_font_size(layout, fd, w_dots, h_dots) PangoCairo.update_layout(ctx, layout) PangoCairo.show_layout(ctx, layout) ctx.restore()
def _draw_title(self, ctx, w_dots, h_dots, font_face): """ Draw the title at the current position inside a w_dots*h_dots rectangle. Args: ctx (cairo.Context): The Cairo context to use to draw. w_dots,h_dots (number): Rectangle dimension (ciaro units) font_face (str): Pango font specification. """ # Title background ctx.save() ctx.set_source_rgb(0.8, 0.9, 0.96) # TODO: make title bar color configurable? ctx.rectangle(0, 0, w_dots, h_dots) ctx.fill() ctx.restore() # Retrieve and paint the OSM logo ctx.save() grp, logo_width = self._get_osm_logo(ctx, 0.8*h_dots) if grp: ctx.translate(w_dots - logo_width - 0.1*h_dots, 0.1*h_dots) ctx.set_source(grp) ctx.paint_with_alpha(0.5) else: LOG.warning("OSM Logo not available.") logo_width = 0 ctx.restore() # Retrieve and paint the extra logo # TODO: make configurable logo_width2 = 0 if self.rc.poi_file: ctx.save() grp, logo_width2 = self._get_extra_logo(ctx, 0.8*h_dots) if grp: ctx.translate(0.4*h_dots, 0.1*h_dots) ctx.set_source(grp) ctx.paint_with_alpha(0.5) logo_width2 += 0.4*h_dots else: LOG.warning("Extra Logo not available.") logo_width2 = 0 ctx.restore() # Prepare the title pc = PangoCairo.create_context(ctx) layout = PangoCairo.create_layout(ctx) layout.set_width(int((w_dots - 0.1*w_dots - logo_width - logo_width2) * Pango.SCALE)) if not self.rc.i18n.isrtl(): layout.set_alignment(Pango.Alignment.LEFT) else: layout.set_alignment(Pango.Alignment.RIGHT) fd = Pango.FontDescription(font_face) fd.set_size(Pango.SCALE) layout.set_font_description(fd) layout.set_text(self.rc.title, -1) draw_utils.adjust_font_size(layout, fd, layout.get_width(), 0.8*h_dots) # Draw the title ctx.save() ctx.set_line_width(1) ctx.rectangle(0, 0, w_dots, h_dots) ctx.stroke() ctx.translate(0.4*h_dots + logo_width2, (h_dots - (layout.get_size()[1] / Pango.SCALE)) / 2.0) PangoCairo.update_layout(ctx, layout) PangoCairo.show_layout(ctx, layout) ctx.restore()
def render_additional(self, ctx): ctx.move_to(280, 170) layout = PangoCairo.create_layout(ctx) layout.set_font_description(Pango.FontDescription(f"Source Sans Pro {52}")) layout.set_markup(self.get_title()) PangoCairo.show_layout(ctx, layout)
def generate(self, tracks, bg=(10, 10, 10), rows=3, columns=3, show_lables=True, font="Monospace 10", tile=False, cascade=False): # Main control variables border = 29 text_offset = -7 size = 170 spacing = 9 mode = 1 if cascade: mode = 2 if tile: border = 0 spacing = 0 size = 160 text_offset = 15 # Determine the final width and height of album grid h = round((border * 2) + (size * rows) + (spacing * (rows - 1))) w = round((border * 2) + (size * columns) + (spacing * (columns - 1))) if mode == 2: r1, r2, r3 = cascade[0] print(r1 * 2 + r2 * 2 + r3 * 2) sets = [] for q in range(100, 10000): a = q / r1 b = q / r2 c = q / r3 if a - int(a) == b - int(b) == c - int(c) == 0: sets.append((int(a), int(b), int(c))) if not sets: return False abc = None for s in sets: if s[(r1, r2, r3).index(min((r1, r2, r3)))] > 165: abc = s break else: return False d1, d2, d3 = cascade[1] w = round(border * 2) + (abc[0] * r1) h = round( border * 2) + (abc[0] * d1) + (abc[1] * d2) + (abc[2] * d3) ww = w i = -1 positions = [] # Grid mode if mode == 1: for r in range(rows): for c in range(columns): i += 1 # Break if we run out of albums if i > len(tracks) - 1: break # Determine coordinates for current album x = round(border + ((spacing + size) * c)) y = round(border + ((spacing + size) * r)) positions.append((tracks[i], x, y, size)) positions.append(False) # Cascade mode elif mode == 2: a, b, c = abc size = a spacing = 0 inv_space = 0 if not tile: inv_space = 8 x = border y = border for d in range(d1): for cl in range(r1): i += 1 x = border + (spacing + size) * cl if i > len(tracks) - 1: break positions.append((tracks[i], x + inv_space // 2, y + inv_space // 2, size - inv_space)) y += spacing + size size = b if not tile: inv_space = 6 positions.append(False) for d in range(d2): for cl in range(r2): i += 1 x = border + (spacing + size) * cl print(x) if i > len(tracks) - 1: break positions.append((tracks[i], x + inv_space // 2, y + inv_space // 2, size - inv_space)) y += spacing + size size = c if not tile: inv_space = 4 positions.append(False) for d in range(d3): for cl in range(r3): i += 1 x = border + (spacing + size) * cl if i > len(tracks) - 1: break positions.append((tracks[i], x + inv_space // 2, y + inv_space // 2, size - inv_space)) y += spacing + size # Parse font font_comp = font.split(" ") font_size = int(font_comp.pop()) col_w = 500 two_col = False font_comp = font.split(" ") font_size = int(font_comp.pop()) if len(positions) * (font_size + 4) > h - border * 2: two_col = True font_size += 1 col_w = 380 if show_lables: ww += col_w # Add extra area to final size for text if two_col: ww += col_w + 20 # Get lables text = "" b_text = "" f = False for item in positions: if item is False: if not f: text += " \n" # Insert extra line to form groups for each row else: b_text += " \n" if two_col: f ^= True continue track, x, y, size = item # Determine the text label line artist = track.artist if track.album_artist: artist = track.album_artist line = f"{artist} - {track.album}\n" if not f: text += line else: b_text += line # Prepare a blank Cairo surface surface = cairo.ImageSurface(cairo.FORMAT_RGB24, ww, h) context = cairo.Context(surface) bg = (bg[0] / 255, bg[1] / 255, bg[2] / 255 ) # Convert 8-bit rgb values to decimal context.set_source_rgb(bg[0], bg[1], bg[2]) context.paint() # Fill in the background colour for item in positions: if item is False: continue track, x, y, size = item # Export the album art to file object try: art_file = self.album_art_gen.save_thumb(track, (size, size), None, png=True, zoom=True) except: continue # Skip drawing this album if loading of artwork failed if not art_file: continue # Load image into Cairo and draw art = cairo.ImageSurface.create_from_png(art_file) context.set_source_surface(art, x, y) context.paint() if show_lables: # Setup font and prepare Pango layout options = context.get_font_options() options.set_antialias(cairo.ANTIALIAS_GRAY) context.set_font_options(options) layout = PangoCairo.create_layout(context) layout.set_ellipsize(Pango.EllipsizeMode.END) layout.set_width((col_w - text_offset - spacing) * 1000) # layout.set_height((h - spacing * 2) * 1000) #layout.set_spacing(3 * 1000) #layout.set_font_description(Pango.FontDescription(font)) # Here we make sure the font size is small enough to fit font = " ".join(font_comp) + " " + str(font_size) layout.set_font_description(Pango.FontDescription(font)) layout.set_text(text, -1) try: font_size = int(font_size) while font_size > 2: th = layout.get_pixel_size()[1] if th < h - border: break font_size -= 1 font = " ".join(font_comp) + " " + str(font_size) layout.set_font_description(Pango.FontDescription(font)) layout.set_text(text, -1) except: print("error adjusting font size") # All good to render now y_text_padding = 3 if tile: y_text_padding += 6 context.translate(w + text_offset, border + y_text_padding) context.set_source_rgb(0.9, 0.9, 0.9) PangoCairo.show_layout(context, layout) if b_text: # Setup font and prepare Pango layout options = context.get_font_options() options.set_antialias(cairo.ANTIALIAS_GRAY) context.set_font_options(options) layout = PangoCairo.create_layout(context) layout.set_ellipsize(Pango.EllipsizeMode.END) layout.set_width((col_w - text_offset - spacing) * 1000) layout.set_font_description(Pango.FontDescription(font)) layout.set_text(b_text, -1) # All good to render now y_text_padding = 3 if tile: y_text_padding += 6 context.translate(col_w + 10, 0) context.set_source_rgb(0.9, 0.9, 0.9) PangoCairo.show_layout(context, layout) # Finally export as PNG output_path = os.path.join(self.user_dir, "chart.png") surface.write_to_png(output_path) # Convert to JPEG for convenience output_path2 = os.path.join(self.user_dir, "chart.jpg") im = Image.open(output_path) im.save(output_path2, 'JPEG', quality=92) return output_path2
def draw_text_bubble(self, cr, pointx, pointy): corner_radius = 9.0 margin_top = 12.0 margin_bottom = 12.0 margin_left = 24.0 margin_right = 24.0 if len(self._bubble_text) <= 0: return alloc = self.get_allocation() layout = PangoCairo.create_layout(cr) font_description = Pango.font_description_from_string(BUBBLE_TEXT_FONT) layout.set_font_description(font_description) layout.set_alignment(Pango.Alignment.CENTER) layout.set_spacing(3) layout.set_markup(self._bubble_text) (ink_rect, logical_rect) = layout.get_pixel_extents() # Calculate the bubble size based on the text layout size width = logical_rect.width + margin_left + margin_right height = logical_rect.height + margin_top + margin_bottom if pointx < alloc.width / 2: x = pointx + 20 else: x = pointx - width - 20 y = pointy - height / 2 # Make sure it fits in the visible area x = self.clamp(x, 0, alloc.width - width) y = self.clamp(y, 0, alloc.height - height) cr.save() cr.translate(x, y) # Draw the bubble cr.new_sub_path() cr.arc(width - corner_radius, corner_radius, corner_radius, math.radians(-90), math.radians(0)) cr.arc(width - corner_radius, height - corner_radius, corner_radius, math.radians(0), math.radians(90)) cr.arc(corner_radius, height - corner_radius, corner_radius, math.radians(90), math.radians(180)) cr.arc(corner_radius, corner_radius, corner_radius, math.radians(180), math.radians(270)) cr.close_path() cr.set_source_rgba(0.2, 0.2, 0.2, 0.7) cr.fill() # And finally draw the text cr.set_source_rgb(1, 1, 1) cr.move_to(margin_left, margin_top) PangoCairo.show_layout(cr, layout) cr.restore()
def draw_title_info(self, cr): cr.save() do_shadow = (self.conf.shadow[0] != -1.0) do_outline = (self.conf.outline[0] != -1.0) self.set_name("osd_bubble") qltk.add_css( self, """ #osd_bubble { background-color:rgba(0,0,0,0); } """) cr.set_operator(cairo.OPERATOR_OVER) cr.set_source_rgba(*self.conf.fill) radius = min(25, self.corners_factor * min(*self.get_size())) self.draw_conf_rect(cr, 0, 0, self.get_size()[0], self.get_size()[1], radius) cr.fill() # draw border if do_outline: # Make border darker and more translucent than the fill f = self.conf.fill rgba = (f[0] / 1.25, f[1] / 1.25, f[2] / 1.25, f[3] / 2.0) cr.set_source_rgba(*rgba) self.draw_conf_rect(cr, 1, 1, self.get_size()[0] - 2, self.get_size()[1] - 2, radius) cr.set_line_width(2.0) cr.stroke() textx = self.BORDER if self.cover_surface is not None: rect = self.cover_rectangle textx += rect.width + self.BORDER surface = self.cover_surface transmat = cairo.Matrix() if do_shadow: cr.set_source_rgba(*self.conf.shadow) self.draw_conf_rect(cr, rect.x + 2, rect.y + 2, rect.width, rect.height, 0.6 * self.corners_factor * rect.width) cr.fill() if do_outline: cr.set_source_rgba(*self.conf.outline) self.draw_conf_rect(cr, rect.x, rect.y, rect.width, rect.height, 0.6 * self.corners_factor * rect.width) cr.stroke() cr.set_source_surface(surface, 0, 0) width, height = get_surface_extents(surface)[2:] transmat.scale(width / float(rect.width), height / float(rect.height)) transmat.translate(-rect.x, -rect.y) cr.get_source().set_matrix(transmat) self.draw_conf_rect(cr, rect.x, rect.y, rect.width, rect.height, 0.6 * self.corners_factor * rect.width) cr.fill() PangoCairo.update_layout(cr, self.title_layout) height = self.title_layout.get_pixel_size()[1] texty = (self.get_size()[1] - height) // 2 if do_shadow: cr.set_source_rgba(*self.conf.shadow) cr.move_to(textx + 2, texty + 2) PangoCairo.show_layout(cr, self.title_layout) if do_outline: cr.set_source_rgba(*self.conf.outline) cr.move_to(textx, texty) PangoCairo.layout_path(cr, self.title_layout) cr.stroke() cr.set_source_rgb(*self.conf.text[:3]) cr.move_to(textx, texty) PangoCairo.show_layout(cr, self.title_layout) cr.restore()
def _show(self, g): if self.color: g.set_color(self.color) pangocairo.show_layout(g.context, self.layout)
def get_gudgitters_image(rankings): """return PIL image for rankings""" SMOKE_WHITE = (250, 250, 250) BLACK = (0, 0, 0) DISCORD_GRAY = (.212, .244, .247) ROW_COLORS = ((0.95, 0.95, 0.95), (0.9, 0.9, 0.9)) WIDTH = 900 HEIGHT = 450 BORDER_MARGIN = 20 COLUMN_MARGIN = 10 HEADER_SPACING = 1.25 WIDTH_RANK = 0.08 * WIDTH WIDTH_NAME = 0.38 * WIDTH LINE_HEIGHT = (HEIGHT - 2 * BORDER_MARGIN) / (10 + HEADER_SPACING) # Cairo+Pango setup surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) context = cairo.Context(surface) context.set_line_width(1) context.set_source_rgb(*DISCORD_GRAY) context.rectangle(0, 0, WIDTH, HEIGHT) context.fill() layout = PangoCairo.create_layout(context) layout.set_font_description( Pango.font_description_from_string(','.join(FONTS) + ' 20')) layout.set_ellipsize(Pango.EllipsizeMode.END) def draw_bg(y, color_index): nxty = y + LINE_HEIGHT # Simple context.move_to(BORDER_MARGIN, y) context.line_to(WIDTH, y) context.line_to(WIDTH, nxty) context.line_to(0, nxty) context.set_source_rgb(*ROW_COLORS[color_index]) context.fill() def draw_row(pos, username, handle, rating, color, y, bold=False): context.set_source_rgb(*[x / 255.0 for x in color]) context.move_to(BORDER_MARGIN, y) def draw(text, width=-1): text = html.escape(text) if bold: text = f'<b>{text}</b>' layout.set_width( (width - COLUMN_MARGIN) * 1000) # pixel = 1000 pango units layout.set_markup(text, -1) PangoCairo.show_layout(context, layout) context.rel_move_to(width, 0) draw(pos, WIDTH_RANK) draw(username, WIDTH_NAME) draw(handle, WIDTH_NAME) draw(rating) # y = BORDER_MARGIN # draw header draw_row('#', 'Name', 'Handle', 'Points', SMOKE_WHITE, y, bold=True) y += LINE_HEIGHT * HEADER_SPACING for i, (pos, name, handle, rating, score) in enumerate(rankings): color = rating_to_color(rating) draw_bg(y, i % 2) draw_row(str(pos), f'{name} ({rating if rating else "N/A"})', handle, str(score), color, y) if rating and rating >= 3000: # nutella draw_row('', name[0], handle[0], '', BLACK, y) y += LINE_HEIGHT image_data = io.BytesIO() surface.write_to_png(image_data) image_data.seek(0) discord_file = discord.File(image_data, filename='gudgitters.png') return discord_file
def _draw(self, xrandr, context): # pylint: disable=too-many-locals cfg = xrandr.configuration state = xrandr.state context.set_source_rgb(0.25, 0.25, 0.25) context.rectangle(0, 0, *state.virtual.max) context.fill() context.set_source_rgb(0.5, 0.5, 0.5) context.rectangle(0, 0, *cfg.virtual) context.fill() for output_name in self.sequence: output = cfg.outputs[output_name] if not output.active: continue rect = (output.tentative_position if hasattr( output, 'tentative_position') else output.position) + tuple( output.size) center = rect[0] + rect[2] / 2, rect[1] + rect[3] / 2 # paint rectangle context.set_source_rgba(1, 1, 1, 0.7) context.rectangle(*rect) context.fill() context.set_source_rgb(0, 0, 0) context.rectangle(*rect) context.stroke() # set up for text context.save() textwidth = rect[3 if output.rotation.is_odd else 2] widthperchar = textwidth / len(output_name) # i think this looks nice and won't overflow even for wide fonts textheight = int(widthperchar * 0.8) newdescr = Pango.FontDescription("sans") newdescr.set_size(textheight * Pango.SCALE) # create text layout = PangoCairo.create_layout(context) layout.set_font_description(newdescr) if output.primary: underline_attrs = Pango.parse_markup("<u>test</u>", -1, "0")[1] # attrs = Pango.AttrList() # attr = Pango.Attribute() # attr_class = Pango.AttrClass() # attr_class.type = Pango.AttrType.UNDERLINE # attr.init(attr_class) # attrs.insert(attr) # attrs.insert(Pango.Underline.SINGLE) # layout.set_attributes(attrs) layout.set_attributes(underline_attrs) layout.set_text(output_name, -1) # position text layoutsize = layout.get_pixel_size() layoutoffset = -layoutsize[0] / 2, -layoutsize[1] / 2 context.move_to(*center) context.rotate(output.rotation.angle) context.rel_move_to(*layoutoffset) # paint text PangoCairo.show_layout(context, layout) context.restore()
def draw_cb(self, widget, event): #create a CAIRO context (to use with pango) self.context = widget.get_window().cairo_create() #Show the pango_layout in the Cairo context just created. PangoCairo.show_layout(self.context, self.pango_layout)
def draw_text(self, pos_y, text, icon): """ Draw a text message, returning the Y position of the next message """ icon_width = self.icon_size icon_pad = self.icon_pad if not self.show_icon: icon = None if not icon: icon_pad = 0 icon_width = 0 layout = self.create_pango_layout(text) layout.set_auto_dir(True) layout.set_markup(text, -1) attr = layout.get_attributes() width = self.limit_width if self.width > self.limit_width else self.width layout.set_width((Pango.SCALE * (width - (self.border_radius * 4 + icon_width + icon_pad)))) layout.set_spacing(Pango.SCALE * 3) if self.text_font: font = Pango.FontDescription(self.text_font) layout.set_font_description(font) text_width, text_height = layout.get_pixel_size() self.col(self.bg_col) top = 0 if self.align_vert == 2: # Bottom align top = pos_y - (text_height + self.border_radius * 4) else: # Top align top = pos_y if text_height < icon_width: text_height = icon_width shape_height = text_height + self.border_radius * 4 shape_width = text_width + self.border_radius*4 + icon_width + icon_pad left = 0 if self.align_right: left = self.width - shape_width self.context.save() # Draw Background self.context.translate(left, top) # self.context.rectangle(self.border_radius, 0, # shape_width - (self.border_radius*2), shape_height) # self.context.fill() # self.context.rectangle(0, self.border_radius, # shape_width, shape_height - (self.border_radius * 2)) #self.context.arc(0.7, 0.3, 0.035, 1.25 * math.pi, 2.25 * math.pi) #self.context.arc(0.3, 0.7, 0.035, .25 * math.pi, 1.25 * math.pi) if self.border_radius == 0: self.context.move_to(0.0, 0.0) self.context.line_to(shape_width, 0.0) self.context.line_to(shape_width, shape_height) self.context.line_to(0.0, shape_height) self.context.close_path() self.context.fill() else: # Edge top self.context.move_to(self.border_radius, 0.0) self.context.line_to(shape_width - self.border_radius, 0.0) # Arc topright self.context.arc(shape_width - self.border_radius, self.border_radius, self.border_radius, 1.5 * math.pi, 2 * math.pi) # Edge right self.context.line_to( shape_width, shape_height - self.border_radius) # Arc bottomright self.context.arc(shape_width - self.border_radius, shape_height - self.border_radius, self.border_radius, 0.0, 0.5 * math.pi) # Edge bottom self.context.line_to(self.border_radius, shape_height) # Arch bottomleft self.context.arc(self.border_radius, shape_height - self.border_radius, self.border_radius, 0.5 * math.pi, math.pi) # Edge left self.context.line_to(0.0, self.border_radius) # Arc topleft self.context.arc(self.border_radius, self.border_radius, self.border_radius, math.pi, 1.5 * math.pi) # End self.context.close_path() self.context.fill() self.context.set_operator(cairo.OPERATOR_OVER) # Draw Image if icon: self.context.save() if self.icon_left: self.context.translate( self.border_radius*2, self.border_radius*2) draw_img_to_rect(icon, self.context, 0, 0, icon_width, icon_width) else: self.context.translate( self.border_radius*2 + text_width + icon_pad, self.border_radius*2) draw_img_to_rect(icon, self.context, 0, 0, icon_width, icon_width) self.context.restore() self.col(self.fg_col) if self.icon_left: self.context.translate( self.border_radius*2 + icon_width + icon_pad, self.border_radius*2) PangoCairo.context_set_shape_renderer( self.get_pango_context(), self.render_custom, None) text = layout.get_text() count = 0 layout.set_attributes(attr) PangoCairo.show_layout(self.context, layout) else: self.context.translate(self.border_radius*2, self.border_radius*2) PangoCairo.context_set_shape_renderer( self.get_pango_context(), self.render_custom, None) text = layout.get_text() count = 0 layout.set_attributes(attr) PangoCairo.show_layout(self.context, layout) self.context.restore() next_y = 0 if self.align_vert == 2: next_y = pos_y - (shape_height + self.padding) else: next_y = pos_y + shape_height + self.padding return next_y
def run(self): """Create the output file. The derived class overrides EXT and create_cairo_surface """ # get paper dimensions paper_width = self.paper.get_size().get_width() * DPI / 2.54 paper_height = self.paper.get_size().get_height() * DPI / 2.54 page_width = round(self.paper.get_usable_width() * DPI / 2.54) page_height = round(self.paper.get_usable_height() * DPI / 2.54) left_margin = self.paper.get_left_margin() * DPI / 2.54 top_margin = self.paper.get_top_margin() * DPI / 2.54 # create cairo context and pango layout filename = self._backend.filename # Cairo can't reliably handle unicode filenames on Linux or # Windows, so open the file for it. with open(filename, 'wb') as fd: try: surface = self.create_cairo_surface(fd, paper_width, paper_height) surface.set_fallback_resolution(300, 300) cr = cairo.Context(surface) fontmap = PangoCairo.font_map_new() fontmap.set_resolution(DPI) pango_context = fontmap.create_context() options = cairo.FontOptions() options.set_hint_metrics(cairo.HINT_METRICS_OFF) PangoCairo.context_set_font_options(pango_context, options) layout = Pango.Layout(pango_context) PangoCairo.update_context(cr, pango_context) # paginate the document self.paginate_document(layout, page_width, page_height, DPI, DPI) body_pages = self._pages # build the table of contents and alphabetical index toc_page = None index_page = None toc = [] index = {} for page_nr, page in enumerate(body_pages): if page.has_toc(): toc_page = page_nr if page.has_index(): index_page = page_nr for mark in page.get_marks(): if mark.type == INDEX_TYPE_ALP: if mark.key in index: if page_nr + 1 not in index[mark.key]: index[mark.key].append(page_nr + 1) else: index[mark.key] = [page_nr + 1] elif mark.type == INDEX_TYPE_TOC: toc.append([mark, page_nr + 1]) # paginate the table of contents rebuild_required = False if toc_page is not None: toc_pages = self.__generate_toc(layout, page_width, page_height, toc) offset = len(toc_pages) - 1 if offset > 0: self.__increment_pages(toc, index, toc_page, offset) rebuild_required = True else: toc_pages = [] # paginate the index if index_page is not None: index_pages = self.__generate_index( layout, page_width, page_height, index) offset = len(index_pages) - 1 if offset > 0: self.__increment_pages(toc, index, index_page, offset) rebuild_required = True else: index_pages = [] # rebuild the table of contents and index if required if rebuild_required: if toc_page is not None: toc_pages = self.__generate_toc( layout, page_width, page_height, toc) if index_page is not None: index_pages = self.__generate_index( layout, page_width, page_height, index) # render the pages if toc_page is not None: body_pages = body_pages[:toc_page] + toc_pages + \ body_pages[toc_page+1:] if index_page is not None: body_pages = body_pages[:index_page] + index_pages + \ body_pages[index_page+1:] self._pages = body_pages for page_nr in range(len(self._pages)): cr.save() cr.translate(left_margin, top_margin) self.draw_page(page_nr, cr, layout, page_width, page_height, DPI, DPI) cr.show_page() cr.restore() # close the surface (file) surface.finish() except IOError as msg: errmsg = "%s\n%s" % (_("Could not create %s") % filename, msg) raise ReportError(errmsg) except Exception as err: errmsg = "%s\n%s" % (_("Could not create %s") % filename, err) raise ReportError(errmsg)
def draw_layout(self, cr, x, y, rotation, xscale, yscale): cr.save() layout = PangoCairo.create_layout(cr) layout.set_text(self.text, -1) layout.set_font_description(self.font_desc) layout.set_alignment(self.alignment) self.pixel_size = layout.get_pixel_size() # Shadow if self.shadow_on: cr.save() r, g, b = self.shadow_color_rgb a = self.shadow_opacity / 100.0 cr.set_source_rgba(r, g, b, a) cr.move_to(x + self.shadow_xoff, y + self.shadow_yoff) cr.scale(xscale, yscale) cr.rotate(rotation) PangoCairo.update_layout(cr, layout) PangoCairo.show_layout(cr, layout) cr.restore() # Text if self.fill_on: cr.set_source_rgba(*self.color_rgba) cr.move_to(x, y) cr.scale(xscale, yscale) cr.rotate(rotation) PangoCairo.update_layout(cr, layout) PangoCairo.show_layout(cr, layout) # Outline if self.outline_on: if self.fill_on == False: # case when user only wants outline we need to transform here cr.move_to(x, y) cr.scale(xscale, yscale) cr.rotate(rotation) PangoCairo.layout_path(cr, layout) cr.set_source_rgba(*self.outline_color_rgba) cr.set_line_width(self.outline_width) cr.stroke() cr.restore()
def do_render(self, cr, widget, background_area, cell_area, flags): x_offset = cell_area.x + 1 y_offset = cell_area.y + 1 # first paint the cover pixbuf = self.props.pixbuf.scale_simple(cell_area.width - 2, cell_area.height - 2, GdkPixbuf.InterpType.NEAREST) Gdk.cairo_set_source_pixbuf(cr, pixbuf, x_offset, y_offset) cr.paint() alpha = 0.40 if ((flags & Gtk.CellRendererState.PRELIT) == Gtk.CellRendererState.PRELIT): # if the cursor is over the cell then slightly dim alpha -= 0.15 if self.cell_area_source.hover_pixbuf: # if a hover pixbuf is given then paint this as well either just above the cover album info # of at the bottom of the cell area if album info is not within the cover area full, calc_x_offset, calc_y_offset = self.cell_area_source.calc_play_icon_offset(x_offset, y_offset) Gdk.cairo_set_source_pixbuf(cr, self.cell_area_source.hover_pixbuf, calc_x_offset, calc_y_offset - PLAY_SIZE_Y) cr.paint() if not (self.cell_area_source.display_text and self.cell_area_source.display_text_pos == False): return # the rest of the routine paints the contents of text within a cover if specified # PANGO LAYOUT layout_width = cell_area.width - 2 pango_layout = PangoCairo.create_layout(cr) pango_layout.set_markup(self.markup, -1) pango_layout.set_alignment(self.cell_area_source.text_alignment) pango_layout.set_font_description(self.font_description) pango_layout.set_width(int(layout_width * Pango.SCALE)) pango_layout.set_wrap(Pango.WrapMode.WORD_CHAR) wi, he = pango_layout.get_pixel_size() rect_offset = y_offset + (int((2.0 * self.cell_area_source.cover_size) / 3.0)) rect_height = int(self.cell_area_source.cover_size / 3.0) if he > rect_height: pango_layout.set_ellipsize(Pango.EllipsizeMode.END) pango_layout.set_height(int((self.cell_area_source.cover_size / 3.0) * Pango.SCALE)) wi, he = pango_layout.get_pixel_size() # RECTANGLE cr.set_source_rgba(0.0, 0.0, 0.0, alpha) cr.set_line_width(0) cr.rectangle(x_offset, rect_offset, cell_area.width - 1, rect_height - 1) cr.fill() # DRAW FONT cr.set_source_rgba(1.0, 1.0, 1.0, 1.0) cr.move_to(x_offset, y_offset + 2.0 * self.cell_area_source.cover_size / 3.0 + (((self.cell_area_source.cover_size / 3.0) - he) / 2.0) ) PangoCairo.show_layout(cr, pango_layout)
def main(args) -> int: # open output archive with tarfile.open(args.out, "w:xz") as tar: for lang in languages(args.podir): # these are the 1.6:1 of some common(ish) screen widths if lang == "en": label_translated: str = args.label else: potfile = PotFile( os.path.join(args.podir, "{}.po".format(lang))) try: label_translated = potfile.msgs[args.label] except KeyError as _: continue if label_translated == args.label: continue for width, height in ( (640, 480), (800, 600), (1024, 768), (1280, 720), (1280, 800), (1366, 768), (1536, 864), (1600, 900), (1920, 1080), (1920, 1200), (2160, 1350), (2560, 1440), (3840, 2160), (5120, 2880), (5688, 3200), (7680, 4320), ): # generate PangoLanguage font_desc = "Sans %.2fpx" % (height / 32, ) fd = Pango.FontDescription(font_desc) font_option = cairo.FontOptions() font_option.set_antialias(cairo.ANTIALIAS_SUBPIXEL) l = Pango.Language.from_string(lang) # create surface img = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1) cctx = cairo.Context(img) layout = PangoCairo.create_layout(cctx) pctx = layout.get_context() pctx.set_font_description(fd) pctx.set_language(l) fs = pctx.load_fontset(fd, l) PangoCairo.context_set_font_options(pctx, font_option) attrs = Pango.AttrList() length = len(bytes(label_translated, "utf8")) items = Pango.itemize(pctx, label_translated, 0, length, attrs, None) gs = Pango.GlyphString() Pango.shape(label_translated, length, items[0].analysis, gs) del img, cctx, pctx, layout def find_size(fs, f, data): """find our size, I hope...""" (ink, log) = gs.extents(f) if ink.height == 0 or ink.width == 0: return False data.update({"log": log, "ink": ink}) return True data: Dict[str, Any] = {} fs.foreach(find_size, data) if len(data) == 0: print("Missing sans fonts") return 2 log = data["log"] ink = data["ink"] surface_height = math.ceil( max(ink.height, log.height) / Pango.SCALE) surface_width = math.ceil( max(ink.width, log.width) / Pango.SCALE) x = -math.ceil(log.x / Pango.SCALE) y = -math.ceil(log.y / Pango.SCALE) img = cairo.ImageSurface(cairo.FORMAT_RGB24, surface_width, surface_height) cctx = cairo.Context(img) layout = PangoCairo.create_layout(cctx) pctx = layout.get_context() PangoCairo.context_set_font_options(pctx, font_option) cctx.set_source_rgb(1, 1, 1) cctx.move_to(x, y) def do_write(fs, f, data): """write out glyphs""" ink = gs.extents(f)[0] if ink.height == 0 or ink.width == 0: return False PangoCairo.show_glyph_string(cctx, f, gs) return True fs.foreach(do_write, None) img.flush() # convert to BMP and add to archive with io.BytesIO() as io_bmp: io_bmp.write(_cairo_surface_write_to_bmp(img)) filename = "fwupd-{}-{}-{}.bmp".format(lang, width, height) tarinfo = tarfile.TarInfo(filename) tarinfo.size = io_bmp.tell() io_bmp.seek(0) tar.addfile(tarinfo, fileobj=io_bmp) # success return 0
def __init__(self): GObject.GObject.__init__(self) self.set_title(_("Titler")) self.connect("delete-event", lambda w, e: close_titler()) if editorstate.screen_size_small_height() == True: global TEXT_LAYER_LIST_HEIGHT, TEXT_VIEW_HEIGHT, VIEW_EDITOR_HEIGHT TEXT_LAYER_LIST_HEIGHT = 150 TEXT_VIEW_HEIGHT = 180 VIEW_EDITOR_HEIGHT = 450 if editorstate.screen_size_small_height() == True: global VIEW_EDITOR_WIDTH VIEW_EDITOR_WIDTH = 680 self.block_updates = False self.view_editor = vieweditor.ViewEditor(PLAYER().profile, VIEW_EDITOR_WIDTH, VIEW_EDITOR_HEIGHT) self.view_editor.active_layer_changed_listener = self.active_layer_changed self.guides_toggle = vieweditor.GuidesViewToggle(self.view_editor) add_b = Gtk.Button(_("Add")) del_b = Gtk.Button(_("Delete")) add_b.connect("clicked", lambda w: self._add_layer_pressed()) del_b.connect("clicked", lambda w: self._del_layer_pressed()) add_del_box = Gtk.HBox() add_del_box = Gtk.HBox(True, 1) add_del_box.pack_start(add_b, True, True, 0) add_del_box.pack_start(del_b, True, True, 0) center_h_icon = Gtk.Image.new_from_file(respaths.IMAGE_PATH + "center_horizontal.png") center_v_icon = Gtk.Image.new_from_file(respaths.IMAGE_PATH + "center_vertical.png") center_h = Gtk.Button() center_h.set_image(center_h_icon) center_h.connect("clicked", lambda w: self._center_h_pressed()) center_v = Gtk.Button() center_v.set_image(center_v_icon) center_v.connect("clicked", lambda w: self._center_v_pressed()) self.layer_list = TextLayerListView(self._layer_selection_changed, self._layer_visibility_toggled) self.layer_list.set_size_request(TEXT_LAYER_LIST_WIDTH, TEXT_LAYER_LIST_HEIGHT) self.text_view = Gtk.TextView() self.text_view.set_pixels_above_lines(2) self.text_view.set_left_margin(2) self.text_view.get_buffer().connect("changed", self._text_changed) self.sw = Gtk.ScrolledWindow() self.sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.ALWAYS) self.sw.add(self.text_view) self.sw.set_size_request(TEXT_VIEW_WIDTH, TEXT_VIEW_HEIGHT) scroll_frame = Gtk.Frame() scroll_frame.add(self.sw) self.tc_display = guicomponents.MonitorTCDisplay() self.tc_display.use_internal_frame = True self.tc_display.widget.set_valign(Gtk.Align.CENTER) self.pos_bar = positionbar.PositionBar() self.pos_bar.set_listener(self.position_listener) self.pos_bar.update_display_from_producer(PLAYER().producer) self.pos_bar.mouse_release_listener = self.pos_bar_mouse_released pos_bar_frame = Gtk.Frame() pos_bar_frame.add(self.pos_bar.widget) pos_bar_frame.set_shadow_type(Gtk.ShadowType.ETCHED_IN) pos_bar_frame.set_valign(Gtk.Align.CENTER) font_map = PangoCairo.font_map_get_default() unsorted_families = font_map.list_families() if len(unsorted_families) == 0: print "No font families found in system! Titler will not work." self.font_families = sorted(unsorted_families, key=lambda family: family.get_name()) self.font_family_indexes_for_name = {} combo = Gtk.ComboBoxText() indx = 0 for family in self.font_families: combo.append_text(family.get_name()) self.font_family_indexes_for_name[family.get_name()] = indx indx += 1 combo.set_active(0) self.font_select = combo self.font_select.connect("changed", self._edit_value_changed) adj = Gtk.Adjustment(float(DEFAULT_FONT_SIZE), float(1), float(300), float(1)) self.size_spin = Gtk.SpinButton() self.size_spin.set_adjustment(adj) self.size_spin.connect("changed", self._edit_value_changed) self.size_spin.connect("key-press-event", self._key_pressed_on_widget) font_main_row = Gtk.HBox() font_main_row.pack_start(self.font_select, True, True, 0) font_main_row.pack_start(guiutils.pad_label(5, 5), False, False, 0) font_main_row.pack_start(self.size_spin, False, False, 0) self.bold_font = Gtk.ToggleButton() self.italic_font = Gtk.ToggleButton() bold_icon = Gtk.Image.new_from_stock(Gtk.STOCK_BOLD, Gtk.IconSize.BUTTON) italic_icon = Gtk.Image.new_from_stock(Gtk.STOCK_ITALIC, Gtk.IconSize.BUTTON) self.bold_font.set_image(bold_icon) self.italic_font.set_image(italic_icon) self.bold_font.connect("clicked", self._edit_value_changed) self.italic_font.connect("clicked", self._edit_value_changed) self.left_align = Gtk.RadioButton(None) self.center_align = Gtk.RadioButton.new_from_widget(self.left_align) self.right_align = Gtk.RadioButton.new_from_widget(self.left_align) left_icon = Gtk.Image.new_from_stock(Gtk.STOCK_JUSTIFY_LEFT, Gtk.IconSize.BUTTON) center_icon = Gtk.Image.new_from_stock(Gtk.STOCK_JUSTIFY_CENTER, Gtk.IconSize.BUTTON) right_icon = Gtk.Image.new_from_stock(Gtk.STOCK_JUSTIFY_RIGHT, Gtk.IconSize.BUTTON) self.left_align.set_image(left_icon) self.center_align.set_image(center_icon) self.right_align.set_image(right_icon) self.left_align.set_mode(False) self.center_align.set_mode(False) self.right_align.set_mode(False) self.left_align.connect("clicked", self._edit_value_changed) self.center_align.connect("clicked", self._edit_value_changed) self.right_align.connect("clicked", self._edit_value_changed) self.color_button = Gtk.ColorButton.new_with_rgba( Gdk.RGBA(red=1.0, green=1.0, blue=1.0, alpha=1.0)) self.color_button.connect("color-set", self._edit_value_changed) self.fill_on = Gtk.CheckButton() self.fill_on.set_active(True) self.fill_on.connect("toggled", self._edit_value_changed) buttons_box = Gtk.HBox() buttons_box.pack_start(Gtk.Label(), True, True, 0) buttons_box.pack_start(self.bold_font, False, False, 0) buttons_box.pack_start(self.italic_font, False, False, 0) buttons_box.pack_start(guiutils.pad_label(5, 5), False, False, 0) buttons_box.pack_start(self.left_align, False, False, 0) buttons_box.pack_start(self.center_align, False, False, 0) buttons_box.pack_start(self.right_align, False, False, 0) buttons_box.pack_start(guiutils.pad_label(15, 5), False, False, 0) buttons_box.pack_start(self.color_button, False, False, 0) buttons_box.pack_start(guiutils.pad_label(2, 1), False, False, 0) buttons_box.pack_start(self.fill_on, False, False, 0) buttons_box.pack_start(Gtk.Label(), True, True, 0) outline_label = Gtk.Label(_("Outline")) outline_size = Gtk.Label(_("Size")) self.out_line_color_button = Gtk.ColorButton.new_with_rgba( Gdk.RGBA(red=0.3, green=0.3, blue=0.3, alpha=1.0)) self.out_line_color_button.connect("color-set", self._edit_value_changed) adj2 = Gtk.Adjustment(float(3), float(1), float(50), float(1)) self.out_line_size_spin = Gtk.SpinButton() self.out_line_size_spin.set_adjustment(adj2) self.out_line_size_spin.connect("changed", self._edit_value_changed) self.out_line_size_spin.connect("key-press-event", self._key_pressed_on_widget) self.outline_on = Gtk.CheckButton() self.outline_on.set_active(False) self.outline_on.connect("toggled", self._edit_value_changed) outline_box = Gtk.HBox() outline_box.pack_start(outline_label, False, False, 0) outline_box.pack_start(guiutils.pad_label(15, 1), False, False, 0) outline_box.pack_start(outline_size, False, False, 0) outline_box.pack_start(guiutils.pad_label(2, 1), False, False, 0) outline_box.pack_start(self.out_line_size_spin, False, False, 0) outline_box.pack_start(guiutils.pad_label(15, 1), False, False, 0) outline_box.pack_start(self.out_line_color_button, False, False, 0) outline_box.pack_start(guiutils.pad_label(2, 1), False, False, 0) outline_box.pack_start(self.outline_on, False, False, 0) outline_box.pack_start(Gtk.Label(), True, True, 0) shadow_label = Gtk.Label(_("Shadow")) shadow_opacity_label = Gtk.Label(_("Opacity")) shadow_xoff = Gtk.Label(_("X Off")) shadow_yoff = Gtk.Label(_("Y Off")) self.shadow_opa_spin = Gtk.SpinButton() adj3 = Gtk.Adjustment(float(100), float(1), float(100), float(1)) self.shadow_opa_spin.set_adjustment(adj3) self.shadow_opa_spin.connect("changed", self._edit_value_changed) self.shadow_opa_spin.connect("key-press-event", self._key_pressed_on_widget) self.shadow_xoff_spin = Gtk.SpinButton() adj4 = Gtk.Adjustment(float(3), float(1), float(100), float(1)) self.shadow_xoff_spin.set_adjustment(adj4) self.shadow_xoff_spin.connect("changed", self._edit_value_changed) self.shadow_xoff_spin.connect("key-press-event", self._key_pressed_on_widget) self.shadow_yoff_spin = Gtk.SpinButton() adj5 = Gtk.Adjustment(float(3), float(1), float(100), float(1)) self.shadow_yoff_spin.set_adjustment(adj5) self.shadow_yoff_spin.connect("changed", self._edit_value_changed) self.shadow_yoff_spin.connect("key-press-event", self._key_pressed_on_widget) self.shadow_on = Gtk.CheckButton() self.shadow_on.set_active(False) self.shadow_on.connect("toggled", self._edit_value_changed) self.shadow_color_button = Gtk.ColorButton.new_with_rgba( Gdk.RGBA(red=0.3, green=0.3, blue=0.3, alpha=1.0)) self.shadow_color_button.connect("color-set", self._edit_value_changed) shadow_box_1 = Gtk.HBox() shadow_box_1.pack_start(shadow_label, False, False, 0) shadow_box_1.pack_start(guiutils.pad_label(15, 1), False, False, 0) shadow_box_1.pack_start(shadow_opacity_label, False, False, 0) shadow_box_1.pack_start(self.shadow_opa_spin, False, False, 0) shadow_box_1.pack_start(guiutils.pad_label(15, 1), False, False, 0) shadow_box_1.pack_start(self.shadow_color_button, False, False, 0) shadow_box_1.pack_start(guiutils.pad_label(2, 1), False, False, 0) shadow_box_1.pack_start(self.shadow_on, False, False, 0) shadow_box_1.pack_start(Gtk.Label(), True, True, 0) shadow_box_2 = Gtk.HBox() shadow_box_2.pack_start(shadow_xoff, False, False, 0) shadow_box_2.pack_start(self.shadow_xoff_spin, False, False, 0) shadow_box_2.pack_start(guiutils.pad_label(15, 1), False, False, 0) shadow_box_2.pack_start(shadow_yoff, False, False, 0) shadow_box_2.pack_start(self.shadow_yoff_spin, False, False, 0) shadow_box_2.pack_start(Gtk.Label(), True, True, 0) load_layers = Gtk.Button(_("Load Layers")) load_layers.connect("clicked", lambda w: self._load_layers_pressed()) save_layers = Gtk.Button(_("Save Layers")) save_layers.connect("clicked", lambda w: self._save_layers_pressed()) clear_layers = Gtk.Button(_("Clear All")) clear_layers.connect("clicked", lambda w: self._clear_layers_pressed()) layers_save_buttons_row = Gtk.HBox() layers_save_buttons_row.pack_start(save_layers, False, False, 0) layers_save_buttons_row.pack_start(load_layers, False, False, 0) layers_save_buttons_row.pack_start(Gtk.Label(), True, True, 0) adj = Gtk.Adjustment(float(0), float(0), float(3000), float(1)) self.x_pos_spin = Gtk.SpinButton() self.x_pos_spin.set_adjustment(adj) self.x_pos_spin.connect("changed", self._position_value_changed) self.x_pos_spin.connect("key-press-event", self._key_pressed_on_widget) adj = Gtk.Adjustment(float(0), float(0), float(3000), float(1)) self.y_pos_spin = Gtk.SpinButton() self.y_pos_spin.set_adjustment(adj) self.y_pos_spin.connect("changed", self._position_value_changed) self.y_pos_spin.connect("key-press-event", self._key_pressed_on_widget) adj = Gtk.Adjustment(float(0), float(0), float(3000), float(1)) self.rotation_spin = Gtk.SpinButton() self.rotation_spin.set_adjustment(adj) self.rotation_spin.connect("changed", self._position_value_changed) self.rotation_spin.connect("key-press-event", self._key_pressed_on_widget) undo_pos = Gtk.Button() undo_icon = Gtk.Image.new_from_stock(Gtk.STOCK_UNDO, Gtk.IconSize.BUTTON) undo_pos.set_image(undo_icon) next_icon = Gtk.Image.new_from_file(respaths.IMAGE_PATH + "next_frame_s.png") prev_icon = Gtk.Image.new_from_file(respaths.IMAGE_PATH + "prev_frame_s.png") prev_frame = Gtk.Button() prev_frame.set_image(prev_icon) prev_frame.connect("clicked", lambda w: self._prev_frame_pressed()) next_frame = Gtk.Button() next_frame.set_image(next_icon) next_frame.connect("clicked", lambda w: self._next_frame_pressed()) self.scale_selector = vieweditor.ScaleSelector(self) timeline_box = Gtk.HBox() timeline_box.pack_start(self.tc_display.widget, False, False, 0) timeline_box.pack_start(guiutils.pad_label(12, 12), False, False, 0) timeline_box.pack_start(pos_bar_frame, True, True, 0) timeline_box.pack_start(guiutils.pad_label(12, 12), False, False, 0) timeline_box.pack_start(prev_frame, False, False, 0) timeline_box.pack_start(next_frame, False, False, 0) timeline_box.pack_start(self.guides_toggle, False, False, 0) timeline_box.pack_start(self.scale_selector, False, False, 0) timeline_box.set_margin_top(6) timeline_box.set_margin_bottom(6) positions_box = Gtk.HBox() positions_box.pack_start(Gtk.Label(), True, True, 0) positions_box.pack_start(Gtk.Label(label="X:"), False, False, 0) positions_box.pack_start(self.x_pos_spin, False, False, 0) positions_box.pack_start(guiutils.pad_label(40, 5), False, False, 0) positions_box.pack_start(Gtk.Label(label="Y:"), False, False, 0) positions_box.pack_start(self.y_pos_spin, False, False, 0) #positions_box.pack_start(Gtk.Label(label=_("Angle")), False, False, 0) #positions_box.pack_start(self.rotation_spin, False, False, 0) positions_box.pack_start(guiutils.pad_label(40, 5), False, False, 0) positions_box.pack_start(center_h, False, False, 0) positions_box.pack_start(center_v, False, False, 0) positions_box.pack_start(Gtk.Label(), True, True, 0) controls_panel_1 = Gtk.VBox() controls_panel_1.pack_start(add_del_box, False, False, 0) controls_panel_1.pack_start(self.layer_list, False, False, 0) controls_panel_1.pack_start(layers_save_buttons_row, False, False, 0) controls_panel_2 = Gtk.VBox() controls_panel_2.pack_start(scroll_frame, True, True, 0) controls_panel_2.pack_start(font_main_row, False, False, 0) controls_panel_2.pack_start(buttons_box, False, False, 0) controls_panel_2.pack_start(guiutils.pad_label(40, 1), False, False, 0) controls_panel_2.pack_start(outline_box, False, False, 0) controls_panel_2.pack_start(guiutils.pad_label(40, 1), False, False, 0) controls_panel_2.pack_start(shadow_box_1, False, False, 0) controls_panel_2.pack_start(shadow_box_2, False, False, 0) controls_panel = Gtk.VBox() controls_panel.pack_start( guiutils.get_named_frame(_("Active Layer"), controls_panel_2), True, True, 0) controls_panel.pack_start( guiutils.get_named_frame(_("Layers"), controls_panel_1), False, False, 0) view_editor_editor_buttons_row = Gtk.HBox() view_editor_editor_buttons_row.pack_start(positions_box, False, False, 0) view_editor_editor_buttons_row.pack_start(Gtk.Label(), True, True, 0) keep_label = Gtk.Label(label=_("Keep Layers When Closed")) self.keep_layers_check = Gtk.CheckButton() self.keep_layers_check.set_active(_keep_titler_data) self.keep_layers_check.connect("toggled", self._keep_layers_toggled) open_label = Gtk.Label(label=_("Open Saved Title In Bin")) self.open_in_current_check = Gtk.CheckButton() self.open_in_current_check.set_active(_open_saved_in_bin) self.open_in_current_check.connect("toggled", self._open_saved_in_bin) exit_b = guiutils.get_sized_button(_("Close"), 150, 32) exit_b.connect("clicked", lambda w: close_titler()) save_titles_b = guiutils.get_sized_button(_("Save Title Graphic"), 150, 32) save_titles_b.connect("clicked", lambda w: self._save_title_pressed()) editor_buttons_row = Gtk.HBox() editor_buttons_row.pack_start(Gtk.Label(), True, True, 0) editor_buttons_row.pack_start(keep_label, False, False, 0) editor_buttons_row.pack_start(self.keep_layers_check, False, False, 0) editor_buttons_row.pack_start(guiutils.pad_label(24, 2), False, False, 0) editor_buttons_row.pack_start(open_label, False, False, 0) editor_buttons_row.pack_start(self.open_in_current_check, False, False, 0) editor_buttons_row.pack_start(guiutils.pad_label(24, 2), False, False, 0) editor_buttons_row.pack_start(exit_b, False, False, 0) editor_buttons_row.pack_start(save_titles_b, False, False, 0) editor_panel = Gtk.VBox() editor_panel.pack_start(self.view_editor, True, True, 0) editor_panel.pack_start(timeline_box, False, False, 0) editor_panel.pack_start( guiutils.get_in_centering_alignment( view_editor_editor_buttons_row), False, False, 0) editor_panel.pack_start(guiutils.pad_label(2, 24), True, True, 0) editor_panel.pack_start(editor_buttons_row, False, False, 0) editor_row = Gtk.HBox() editor_row.pack_start(controls_panel, False, False, 0) editor_row.pack_start(editor_panel, True, True, 0) alignment = guiutils.set_margins(editor_row, 8, 8, 8, 8) self.add(alignment) self.layer_list.fill_data_model() self._update_gui_with_active_layer_data() self.show_all() self.connect("size-allocate", lambda w, e: self.window_resized()) self.connect("window-state-event", lambda w, e: self.window_resized())
def expose(self, widget, context): #context = widget.bin_window.cairo_create() context.set_antialias(cairo.ANTIALIAS_NONE) width, height = widget.get_size() size = width if self.orientation == HORIZONTAL else height context.set_dash([]) def draw_lines(context, position, margin, size, unit, zoom): while position <= size: if self.orientation == HORIZONTAL: context.move_to(position * zoom, margin) context.line_to(position * zoom, size) elif self.orientation == VERTICAL: context.move_to(margin, position * zoom) context.line_to(size, position * zoom) position += unit context.set_line_width(1) draw_lines(context, 25, 18, size, 10, self.zoom) draw_lines(context, 25, 10, size, 50, self.zoom) context.stroke() context.set_line_width(2) draw_lines(context, 25, 8, size, 100, self.zoom) context.stroke() context.set_line_width(3) for tag in self.tags: tag.draw_tag(context) context.stroke() if self.show_position: context.set_line_width(1) context.set_source_rgb(0.0, 0.0, 0.75) border = 2 if self.orientation == HORIZONTAL and self.x: context.move_to(self.x, border) context.line_to(self.x, size) elif self.orientation == VERTICAL and self.y: context.move_to(border, self.y) context.line_to(size - border, self.y) context.stroke() #_context = PangoCairo.create_context(context) #layout = PangoCairo.create_layout(_context) layout = PangoCairo.create_layout(context) fontname = 'Sans' if platform.system() == 'Windows' else 'Ubuntu' size = 8 description = '%s %d' % (fontname, size) font = Pango.FontDescription(description) layout.set_justify(True) layout.set_font_description(font) text = None if self.orientation == HORIZONTAL: context.move_to(self.x + 2, 0) text = str(int(self.x)) elif self.orientation == VERTICAL: context.move_to(2, self.y) text = str(int(self.y)) layout.set_text(text, len(text)) context.set_antialias(cairo.ANTIALIAS_DEFAULT) context.set_source_rgb(0.0, 0.0, 0.0) PangoCairo.show_layout(context, layout) return True
def on_enter_frame(self, scene, context): g = graphics.Graphics(context) self.plot_area.height = self.height - 30 vertical = min(self.plot_area.height / 5, 7) minute_pixel = (self.scope_hours * 60.0 - 15) / self.width g.set_line_style(width=1) g.translate(0.5, 0.5) colors = { "normal": self._style.get_color(gtk.StateFlags.NORMAL), "normal_bg": self._style.get_background_color(gtk.StateFlags.NORMAL), "selected": self._style.get_color(gtk.StateFlags.SELECTED), "selected_bg": self._style.get_background_color(gtk.StateFlags.SELECTED), } bottom = self.plot_area.y + self.plot_area.height for bar in self.fact_bars: bar.y = vertical * bar.category + 5 bar.height = vertical bar_start_time = bar.fact.start_time - self.view_time minutes = bar_start_time.seconds / 60 + bar_start_time.days * self.scope_hours * 60 bar.x = round(minutes / minute_pixel) + 0.5 bar.width = round((bar.fact.delta).seconds / 60 / minute_pixel) if self.chosen_selection.start_time and self.chosen_selection.width is None: # we have time but no pixels minutes = round( (self.chosen_selection.start_time - self.view_time).seconds / 60 / minute_pixel) + 0.5 self.chosen_selection.x = minutes if self.chosen_selection.end_time: self.chosen_selection.width = round( (self.chosen_selection.end_time - self.chosen_selection.start_time).seconds / 60 / minute_pixel) else: self.chosen_selection.width = 0 self.chosen_selection.height = self.chosen_selection.parent.height # use the oportunity to set proper colors too self.chosen_selection.fill = colors['selected_bg'] self.chosen_selection.duration_label.color = colors['selected'] #time scale g.set_color("#000") background = colors["normal_bg"] text = colors["normal"] tick_color = g.colors.contrast(background, 80) layout = g.create_layout(size=10) for i in range(self.scope_hours * 60): time = (self.view_time + dt.timedelta(minutes=i)) g.set_color(tick_color) if time.minute == 0: g.move_to(round(i / minute_pixel), bottom - 15) g.line_to(round(i / minute_pixel), bottom) g.stroke() elif time.minute % 15 == 0: g.move_to(round(i / minute_pixel), bottom - 5) g.line_to(round(i / minute_pixel), bottom) g.stroke() if time.minute == 0 and time.hour % 4 == 0: if time.hour == 0: g.move_to(round(i / minute_pixel), self.plot_area.y) g.line_to(round(i / minute_pixel), bottom) label_minutes = time.strftime("%b %d") else: label_minutes = time.strftime( "%-I<small><sup>%M %p</sup></small>") g.set_color(text) layout.set_markup(label_minutes) g.move_to(round(i / minute_pixel) + 2, 0) pangocairo.show_layout(context, layout) #current time if self.view_time < dt.datetime.now() < self.view_time + dt.timedelta( hours=self.scope_hours): minutes = round((dt.datetime.now() - self.view_time).seconds / 60 / minute_pixel) g.rectangle(minutes, 0, self.width, self.height) g.fill(colors['normal_bg'], 0.7) g.move_to(minutes, self.plot_area.y) g.line_to(minutes, bottom) g.stroke("#f00", 0.4)
def draw(self, context): alloc = self.get_allocation() width = alloc.width height = alloc.height #------------------------------------------------------ Paint side ruler context.move_to(alloc.x + line, alloc.y + line) context.rel_line_to(0, height - line * 2 - curve) context.rel_curve_to(0, curve, 0, curve, curve, curve) context.rel_line_to(width - line * 2 - curve, 0) style_ctxt = self.get_style_context() dark_prelight = style_ctxt.lookup_color("p_dark_prelight")[1] fg_prelight = style_ctxt.lookup_color("p_fg_prelight")[1] bg_prelight = style_ctxt.lookup_color("p_bg_prelight")[1] context.set_line_width(line) context.set_line_cap(cairo.LINE_CAP_ROUND) state = self.state == Gtk.StateType.NORMAL and Gtk.StateType.PRELIGHT or self.state context.set_source_rgba(dark_prelight.red, dark_prelight.green, dark_prelight.blue, dark_prelight.alpha) context.stroke() #------------------------------------------------ Paint horizontal marks for x_loc, title in self.xmarks: context.set_source_rgba(fg_prelight.red, fg_prelight.green, fg_prelight.blue, fg_prelight.alpha) context.set_font_size(12) x_loc, y_loc = self.prcToPix(x_loc, 1) context.move_to(x_loc + line / 2., y_loc - line / 2.) context.rotate(-math.pi / 2) context.show_text(title) context.rotate(math.pi / 2) context.set_source_rgba(bg_prelight.red, bg_prelight.green, bg_prelight.blue, bg_prelight.alpha) context.move_to(x_loc - line / 2., y_loc) context.rel_curve_to(6, 0, 6, line, 6, line) context.rel_curve_to(0, -line, 6, -line, 6, -line) context.close_path() context.fill() #-------------------------------------------------- Paint vertical marks for y_loc, title in self.ymarks: context.set_source_rgba(fg_prelight.red, fg_prelight.green, fg_prelight.blue, fg_prelight.alpha) context.set_font_size(12) x_loc, y_loc = self.prcToPix(0, y_loc) context.move_to(x_loc + line / 2., y_loc + line / 2.) context.show_text(title) context.set_source_rgba(bg_prelight.red, bg_prelight.green, bg_prelight.blue, bg_prelight.alpha) context.move_to(x_loc, y_loc - line / 2.) context.rel_curve_to(0, 6, -line, 6, -line, 6) context.rel_curve_to(line, 0, line, 6, line, 6) context.close_path() context.fill() #----------------------------------------------------------- Paint spots context.set_line_width(dotSmall * lineprc) for x_loc, y_loc, col_type, name, text in self.spots.values(): context.set_source_rgb(*self.typeColors[col_type][0]) if self.hovered and name == self.hovered[3]: continue x_loc, y_loc = self.prcToPix(x_loc, y_loc) context.arc(x_loc, y_loc, dotSmall / (1 + lineprc) / 2., 0, 2 * math.pi) context.fill_preserve() context.set_source_rgb(*self.typeColors[col_type][1]) context.stroke() #--------------------------------------------------- Paint hovered spots context.set_line_width(dotLarge * lineprc) if self.hovered: x_loc, y_loc, col_type, name, text = self.hovered x_loc, y_loc = self.prcToPix(x_loc, y_loc) if not self.pressed: context.set_source_rgb(*self.typeColors[col_type][0]) else: context.set_source_rgb(*self.typeColors[col_type][1]) context.arc(x_loc, y_loc, dotLarge / (1 + lineprc) / 2., 0, 2 * math.pi) context.fill_preserve() context.set_source_rgb(*self.typeColors[col_type][1]) context.stroke() x_loc, y_loc, width, height = self.getTextBounds(self.hovered) style_ctxt = self.get_style_context() style_ctxt.save() style_ctxt.add_class(Gtk.STYLE_CLASS_NOTEBOOK) Gtk.render_background(style_ctxt, context, int(x_loc - hpadding), int(y_loc - vpadding), ceil(width + hpadding * 2), ceil(height + vpadding * 2)) Gtk.render_frame(style_ctxt, context, int(x_loc - hpadding), int(y_loc - vpadding), ceil(width + hpadding * 2), ceil(height + vpadding * 2)) style_ctxt.restore() context.move_to(x_loc, y_loc) context.set_source_rgba(fg_prelight.red, fg_prelight.green, fg_prelight.blue, fg_prelight.alpha) PangoCairo.show_layout(context, self.create_pango_layout(text))
def do_draw(self, cr): """Handler for the 'draw' signal. :type cr: cairo.Context :rtype: bool """ alloc = self.get_allocation() width, height = alloc.width, alloc.height if self.surf: # Mood cr.save() cr.scale(width / self.surf.get_width(), height) cr.set_source_surface(self.surf, 0, 0) cr.paint() cr.restore() # Text text = self.text if text: cr.save() # TODO: Do we need PangoCairo.update_layout anywhere? ext = self.text_extents scale = Pango.SCALE tx = int((width - ext.width / scale) / 2 - ext.x / scale) ty = int((height - ext.height / scale) / 2 - ext.y / scale) cr.move_to(tx, ty) cr.set_line_width(4) PangoCairo.layout_path(cr, self.pango_layout) cr.set_source_rgba(1, 1, 1, 0.8) cr.stroke_preserve() cr.set_source_rgb(0, 0, 0) cr.fill() cr.restore() # Seek position pos = self._seek_position if pos is not None: cr.save() x = pos * width y = height * self.pos_size xd = y linesize = self.pos_linesize top = linesize / 2 - 0.5 # Triangle cr.move_to(x, y) cr.line_to(x - xd, top) cr.line_to(x + xd, top) cr.close_path() # White fill cr.set_source_rgb(1, 1, 1) cr.fill_preserve() # Black stroke cr.set_source_rgb(0, 0, 0) cr.set_line_width(linesize) cr.stroke() cr.restore() # Border cr.save() cr.rectangle(0, 0, width, height) if self.surf or pos is not None: cr.set_source_rgb(0, 0, 0) else: cr.set_source_rgb(0.63, 0.63, 0.63) cr.stroke() cr.restore() # Tint tint = self.tint if tint is not None: cr.save() cr.set_source_rgba(tint.red, tint.green, tint.blue, tint.alpha) cr.paint() cr.restore() return False
def draw_text_pill(left_text, right_text, x=0, y=0, border=2, radius=14, font_desc=None): # Use GTK+ style of a normal Button widget = Gtk.Label() style_context = widget.get_style_context() # Padding (in px) at the right edge of the image (for Ubuntu; bug 1533) padding_right = 7 x_border = border * 2 if font_desc is None: font_desc = style_context.get_font(Gtk.StateFlags.NORMAL) font_desc.set_weight(Pango.Weight.BOLD) pango_context = widget.create_pango_context() layout_left = Pango.Layout(pango_context) layout_left.set_font_description(font_desc) layout_left.set_text(left_text, -1) layout_right = Pango.Layout(pango_context) layout_right.set_font_description(font_desc) layout_right.set_text(right_text, -1) width_left, height_left = layout_left.get_pixel_size() width_right, height_right = layout_right.get_pixel_size() text_height = max(height_left, height_right) image_height = int(y + text_height + border * 2) image_width = int(x + width_left + width_right + x_border * 4 + padding_right) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, image_width, image_height) ctx = cairo.Context(surface) # Clip so as to not draw on the right padding (for Ubuntu; bug 1533) ctx.rectangle(0, 0, image_width - padding_right, image_height) ctx.clip() if left_text == '0': left_text = None if right_text == '0': right_text = None left_side_width = width_left + x_border * 2 right_side_width = width_right + x_border * 2 rect_width = left_side_width + right_side_width rect_height = text_height + border * 2 if left_text is not None: draw_rounded_rectangle(ctx, x, y, rect_width, rect_height, radius, left_side_width, RRECT_LEFT_SIDE, right_text is None) linear = cairo.LinearGradient(x, y, x + left_side_width / 2, y + rect_height / 2) linear.add_color_stop_rgba(0, .8, .8, .8, .5) linear.add_color_stop_rgba(.4, .8, .8, .8, .7) linear.add_color_stop_rgba(.6, .8, .8, .8, .6) linear.add_color_stop_rgba(.9, .8, .8, .8, .8) linear.add_color_stop_rgba(1, .8, .8, .8, .9) ctx.set_source(linear) ctx.fill() xpos, ypos, width_left, height = x + 1, y + 1, left_side_width, rect_height - 2 if right_text is None: width_left -= 2 draw_rounded_rectangle(ctx, xpos, ypos, rect_width, height, radius, width_left, RRECT_LEFT_SIDE, right_text is None) ctx.set_source_rgba(1., 1., 1., .3) ctx.set_line_width(1) ctx.stroke() draw_rounded_rectangle(ctx, x, y, rect_width, rect_height, radius, left_side_width, RRECT_LEFT_SIDE, right_text is None) ctx.set_source_rgba(.2, .2, .2, .6) ctx.set_line_width(1) ctx.stroke() ctx.move_to(x + x_border, y + 1 + border) ctx.set_source_rgba(0, 0, 0, 1) PangoCairo.show_layout(ctx, layout_left) ctx.move_to(x - 1 + x_border, y + border) ctx.set_source_rgba(1, 1, 1, 1) PangoCairo.show_layout(ctx, layout_left) if right_text is not None: draw_rounded_rectangle(ctx, x, y, rect_width, rect_height, radius, left_side_width, RRECT_RIGHT_SIDE, left_text is None) linear = cairo.LinearGradient( x + left_side_width, y, x + left_side_width + right_side_width / 2, y + rect_height) linear.add_color_stop_rgba(0, .2, .2, .2, .9) linear.add_color_stop_rgba(.4, .2, .2, .2, .8) linear.add_color_stop_rgba(.6, .2, .2, .2, .6) linear.add_color_stop_rgba(.9, .2, .2, .2, .7) linear.add_color_stop_rgba(1, .2, .2, .2, .5) ctx.set_source(linear) ctx.fill() xpos, ypos, width, height = x, y + 1, rect_width - 1, rect_height - 2 if left_text is None: xpos, width = x + 1, rect_width - 2 draw_rounded_rectangle(ctx, xpos, ypos, width, height, radius, left_side_width, RRECT_RIGHT_SIDE, left_text is None) ctx.set_source_rgba(1., 1., 1., .3) ctx.set_line_width(1) ctx.stroke() draw_rounded_rectangle(ctx, x, y, rect_width, rect_height, radius, left_side_width, RRECT_RIGHT_SIDE, left_text is None) ctx.set_source_rgba(.1, .1, .1, .6) ctx.set_line_width(1) ctx.stroke() ctx.move_to(x + left_side_width + x_border, y + 1 + border) ctx.set_source_rgba(0, 0, 0, 1) PangoCairo.show_layout(ctx, layout_right) ctx.move_to(x - 1 + left_side_width + x_border, y + border) ctx.set_source_rgba(1, 1, 1, 1) PangoCairo.show_layout(ctx, layout_right) return surface
def use_pango_font(font, start, count, will_call_prepost=False): import gi gi.require_version('Pango', '1.0') gi.require_version('PangoCairo', '1.0') from gi.repository import Pango from gi.repository import PangoCairo #from gi.repository import Cairo as cairo import cairo fontDesc = Pango.FontDescription(font) a = array.array('b', itertools.repeat(0, 256 * 256)) surface = cairo.ImageSurface.create_for_data(a, cairo.FORMAT_A8, 256, 256) context = cairo.Context(surface) pango_context = PangoCairo.create_context(context) layout = PangoCairo.create_layout(context) fontmap = PangoCairo.font_map_get_default() font = fontmap.load_font(fontmap.create_context(), fontDesc) layout.set_font_description(fontDesc) metrics = font.get_metrics() descent = metrics.get_descent() d = descent / Pango.SCALE linespace = metrics.get_ascent() + metrics.get_descent() width = metrics.get_approximate_char_width() GL.glPushClientAttrib(GL.GL_CLIENT_PIXEL_STORE_BIT) GL.glPixelStorei(GL.GL_UNPACK_SWAP_BYTES, 0) GL.glPixelStorei(GL.GL_UNPACK_LSB_FIRST, 1) GL.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, 256) GL.glPixelStorei(GL.GL_UNPACK_IMAGE_HEIGHT, 256) GL.glPixelStorei(GL.GL_UNPACK_SKIP_PIXELS, 0) GL.glPixelStorei(GL.GL_UNPACK_SKIP_ROWS, 0) GL.glPixelStorei(GL.GL_UNPACK_SKIP_IMAGES, 0) GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1) GL.glPixelZoom(1, -1) base = GL.glGenLists(count) for i in range(count): ch = chr(start + i) layout.set_text(ch, -1) w, h = layout.get_size() context.save() context.new_path() context.rectangle(0, 0, 256, 256) context.set_source_rgba(0., 0., 0., 0.) context.set_operator(cairo.OPERATOR_SOURCE) context.paint() context.restore() context.save() context.set_source_rgba(1., 1., 1., 1.) context.set_operator(cairo.OPERATOR_SOURCE) context.move_to(0, 0) PangoCairo.update_context(context, pango_context) PangoCairo.show_layout(context, layout) context.restore() w, h = int(w / Pango.SCALE), int(h / Pango.SCALE) GL.glNewList(base + i, GL.GL_COMPILE) GL.glBitmap(0, 0, 0, 0, 0, h - d, ''.encode()) #glDrawPixels(0, 0, 0, 0, 0, h-d, ''); if not will_call_prepost: pango_font_pre() if w and h: try: pass GL.glDrawPixels(w, h, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE, a.tobytes()) except Exception as e: print("glnav Exception ", e) GL.glBitmap(0, 0, 0, 0, w, -h + d, ''.encode()) if not will_call_prepost: pango_font_post() GL.glEndList() GL.glPopClientAttrib() return base, int(width / Pango.SCALE), int(linespace / Pango.SCALE)
def create_labels(self, cr=None): """Create the labels for the signal block.""" # (Re-)creating layouts here, because layout.context_changed() doesn't seems to work (after zoom) title_layout, params_layout = self._surface_layouts = [ Gtk.DrawingArea().create_pango_layout(''), # title Gtk.DrawingArea().create_pango_layout(''), # params ] if cr: # to fix up extents after zooming PangoCairo.update_layout(cr, title_layout) PangoCairo.update_layout(cr, params_layout) title_layout.set_markup( '<span {foreground} font_desc="{font}"><b>{label}</b></span>'. format( foreground='foreground="red"' if not self.is_valid() else '', font=BLOCK_FONT, label=Utils.encode(self.label))) title_width, title_height = title_layout.get_size() force_show_id = Actions.TOGGLE_SHOW_BLOCK_IDS.get_active() # update the params layout if not self.is_dummy_block: markups = [ param.format_block_surface_markup() for param in self.params.values() if (param.hide not in ( 'all', 'part') or (param.dtype == 'id' and force_show_id)) ] else: markups = [ '<span font_desc="{font}"><b>key: </b>{key}</span>'.format( font=PARAM_FONT, key=self.key) ] params_layout.set_spacing(LABEL_SEPARATION * Pango.SCALE) params_layout.set_markup('\n'.join(markups)) params_width, params_height = params_layout.get_size( ) if markups else (0, 0) label_width = max(title_width, params_width) / Pango.SCALE label_height = title_height / Pango.SCALE if markups: label_height += LABEL_SEPARATION + params_height / Pango.SCALE # calculate width and height needed width = label_width + 2 * BLOCK_LABEL_PADDING height = label_height + 2 * BLOCK_LABEL_PADDING self._update_colors() self.create_port_labels() def get_min_height_for_ports(ports): min_height = 2 * PORT_BORDER_SEPARATION + len( ports) * PORT_SEPARATION # If any of the ports are bus ports - make the min height larger if any([p.dtype == 'bus' for p in ports]): min_height = 2 * PORT_BORDER_SEPARATION + sum( port.height + PORT_SPACING for port in ports if port.dtype == 'bus') - PORT_SPACING else: if ports: min_height -= ports[-1].height return min_height height = max(height, get_min_height_for_ports(self.active_sinks), get_min_height_for_ports(self.active_sources)) self.width, self.height = width, height = Utils.align_to_grid( (width, height)) self._surface_layouts_offsets = [ (0, (height - label_height) / 2.0), (0, (height - label_height) / 2.0 + LABEL_SEPARATION + title_height / Pango.SCALE) ] title_layout.set_width(width * Pango.SCALE) title_layout.set_alignment(Pango.Alignment.CENTER) params_layout.set_indent((width - label_width) / 2.0 * Pango.SCALE) self.create_comment_layout()
def write_quote_on_surface(surface, quote, author=None, options=None, margin=30): qcontext = cairo.Context(surface) # pylint: disable=no-member acontext = cairo.Context(surface) # pylint: disable=no-member iw = surface.get_width() ih = surface.get_height() sw = Gdk.Screen.get_default().get_width() sh = Gdk.Screen.get_default().get_height() trimw, trimh = Util.compute_trimmed_offsets((iw, ih), (sw, sh)) width = max(200, sw * options.quotes_width // 100) # use quotes_width percent of the visible width qlayout = PangoCairo.create_layout(qcontext) qlayout.set_width((width - 4 * margin) * Pango.SCALE) qlayout.set_alignment(Pango.Alignment.LEFT) qlayout.set_wrap(Pango.WrapMode.WORD) font = options.quotes_font if options else "Bitstream Charter 30" qlayout.set_font_description(Pango.FontDescription(font)) qlayout.set_text(quote, -1) qheight = qlayout.get_pixel_size()[1] qwidth = qlayout.get_pixel_size()[0] if options.quotes_width < 98: width = qwidth + 4 * margin else: width = sw alayout = PangoCairo.create_layout(acontext) aheight = 0 if author: alayout.set_width(qwidth * Pango.SCALE) alayout.set_alignment(Pango.Alignment.RIGHT) alayout.set_wrap(Pango.WrapMode.WORD) alayout.set_font_description(Pango.FontDescription(font)) alayout.set_text(author, -1) aheight = alayout.get_pixel_size()[1] height = qheight + aheight + 2.5 * margin bgc = options.quotes_bg_color qcontext.set_source_rgba(bgc[0] / 255.0, bgc[1] / 255.0, bgc[2] / 255.0, options.quotes_bg_opacity / 100.0) # gray semi-transparent background hpos = trimw + (sw - width) * options.quotes_hpos // 100 vpos = trimh + (sh - height) * options.quotes_vpos // 100 qcontext.rectangle(hpos, vpos, width, height) qcontext.fill() qcontext.translate(hpos + (width - qwidth) / 2, vpos + margin) if options.quotes_text_shadow: qcontext.set_source_rgba(0, 0, 0, 0.2) PangoCairo.update_layout(qcontext, qlayout) PangoCairo.show_layout(qcontext, qlayout) qcontext.translate(-2, -2) tc = options.quotes_text_color qcontext.set_source_rgb(tc[0] / 255.0, tc[1] / 255.0, tc[2] / 255.0) PangoCairo.update_layout(qcontext, qlayout) PangoCairo.show_layout(qcontext, qlayout) acontext.translate(hpos + (width - qwidth) / 2, vpos + margin + qheight + margin / 2) if options.quotes_text_shadow: acontext.set_source_rgba(0, 0, 0, 0.2) PangoCairo.update_layout(acontext, alayout) PangoCairo.show_layout(acontext, alayout) acontext.translate(-2, -2) acontext.set_source_rgb(tc[0] / 255.0, tc[1] / 255.0, tc[2] / 255.0) PangoCairo.update_layout(acontext, alayout) PangoCairo.show_layout(acontext, alayout) qcontext.show_page() acontext.show_page()