def render_text(self, text, lang_text, base_font_size, bold_font, pos_x, pos_y): # Use language variant if desired if self.lang is not None and lang_text is not None: text = lang_text if "English" in text: text = text.replace("English", self.lang.name) # Format text text = text % self.params cjk = is_cjk(text) offset = 0 for line in text.splitlines(): # Iterate until text fits into widget for font_size in range(base_font_size, 3, -1): font = get_font(font_size, bold_font, cjk) layout_size = font.getsize(line) layout_width = layout_size[0] if layout_width + pos_x < self.width: break # Render text self.draw.text((pos_x, pos_y + offset), line, font=font, fill=COLOR_DATA[self.color]["text"]) offset += layout_size[1]
def render_activity(activity): ''' Helper for rendering activity charts. ''' # Preprocess data for chart maximum = max([l[1] for l in activity] + [1]) step = 780.0 / len(activity) width = step / 2 # Prepare image image = Image.new('RGB', (800, 100), 'white') draw = ImageDraw.Draw(image) # Render axises draw.line(((15, 5), (15, 85), (795, 85)), fill='black') # Load font font = get_font(11) # Create Y axis label y_label = str(maximum) text = Image.new('L', font.getsize(y_label), 'white') draw_txt = ImageDraw.Draw(text) draw_txt.text((0, 0), y_label, font=font, fill='black') text = text.transpose(Image.ROTATE_90) image.paste(text, (2, 5)) # Counter for rendering ticks last = -40 # Render activity itself for offset, value in enumerate(activity): # Calculate position current = offset * step # Render bar draw.rectangle( ( 20 + current, 84, 20 + current + width, 84 - value[1] * 78.0 / maximum ), fill=(0, 67, 118) ) # Skip axis labels if they are too frequent if current < last + 40: continue last = current # X-Axis ticks draw.text( (15 + current, 86), value[0].strftime('%m/%d'), font=font, fill='black' ) # Render surface to PNG out = StringIO() image.convert('P', palette=Image.ADAPTIVE).save(out, 'PNG') # Return response return HttpResponse(content_type='image/png', content=out.getvalue())