<s> from django import template <EOL> register = template . Library ( ) <EOL> from django . template import Node , TemplateSyntaxError , Variable <EOL> from django . core . mail import mail_admins <EOL> try : <EOL> from hashlib import md5 <EOL> except ImportError : <EOL> from md5 import md5 <EOL> import struct <EOL> from urlparse import urljoin <EOL> from os import remove , rename <EOL> from os . path import join , abspath , exists , split <EOL> from pprint import pformat <EOL> from subprocess import Popen , PIPE <EOL> import cairo <EOL> from django . conf import settings <EOL> PARAM_KEYWORDS = set ( <EOL> [ '<STR_LIT>' , '<STR_LIT:size>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> _colors = { <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' } <EOL> def convert_color ( s ) : <EOL> if not isinstance ( s , basestring ) : <EOL> return s <EOL> if not s . startswith ( '<STR_LIT:#>' ) : <EOL> s = _colors [ s ] <EOL> l = len ( s ) <EOL> if l in ( <NUM_LIT:4> , <NUM_LIT:5> ) : <EOL> c = [ int ( x * <NUM_LIT:2> , <NUM_LIT:16> ) / <NUM_LIT> for x in s [ <NUM_LIT:1> : ] ] <EOL> elif l in ( <NUM_LIT:7> , <NUM_LIT:9> ) : <EOL> c = [ int ( s [ i : i + <NUM_LIT:2> ] , <NUM_LIT:16> ) / <NUM_LIT> for i in range ( <NUM_LIT:1> , l , <NUM_LIT:2> ) ] <EOL> else : <EOL> raise ValueError ( '<STR_LIT>' % s ) <EOL> if len ( c ) < <NUM_LIT:4> : <EOL> c . append ( <NUM_LIT:1> ) <EOL> return tuple ( c ) <EOL> def read_png_chunk ( pngfile ) : <EOL> "<STR_LIT>" <EOL> data_bytes , tag = struct . unpack ( '<STR_LIT>' , pngfile . read ( <NUM_LIT:8> ) ) <EOL> data = pngfile . read ( data_bytes ) <EOL> return tag , data <EOL> def get_png_size ( filepath ) : <EOL> pngfile = file ( filepath , '<STR_LIT:rb>' ) <EOL> signature = pngfile . read ( <NUM_LIT:8> ) <EOL> if ( signature != struct . pack ( "<STR_LIT>" , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT:10> , <NUM_LIT> , <NUM_LIT:10> ) ) : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> while True : <EOL> try : <EOL> tag , data = read_png_chunk ( pngfile ) <EOL> except ValueError , e : <EOL> raise ValueError ( '<STR_LIT>' + e . args [ <NUM_LIT:0> ] ) <EOL> if tag == '<STR_LIT>' : <EOL> return struct . unpack ( "<STR_LIT>" , data ) [ : <NUM_LIT:2> ] <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> def render_text ( text , filepath , params ) : <EOL> size = params . get ( '<STR_LIT:size>' , <NUM_LIT> ) <EOL> weight = cairo . FONT_WEIGHT_NORMAL <EOL> style = cairo . FONT_SLANT_NORMAL <EOL> font = params . get ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> surface = cairo . ImageSurface ( cairo . FORMAT_ARGB32 , <NUM_LIT:1> , <NUM_LIT:1> ) <EOL> context = cairo . Context ( surface ) <EOL> context . select_font_face ( font , style , weight ) <EOL> context . set_font_size ( size ) <EOL> extents = context . text_extents ( text ) <EOL> x = - extents [ <NUM_LIT:0> ] <EOL> baseline = params . get ( '<STR_LIT>' , - extents [ <NUM_LIT:1> ] ) <EOL> width = max ( <NUM_LIT:1> , extents [ <NUM_LIT:2> ] ) <EOL> height = max ( <NUM_LIT:1> , params . get ( '<STR_LIT>' , extents [ <NUM_LIT:3> ] ) ) <EOL> surface = cairo . ImageSurface ( cairo . FORMAT_ARGB32 , int ( width ) , int ( height ) ) <EOL> font_options = surface . get_font_options ( ) <EOL> font_options . set_antialias ( cairo . ANTIALIAS_GRAY ) <EOL> context = cairo . Context ( surface ) <EOL> background = convert_color ( params . get ( '<STR_LIT>' , ( <NUM_LIT:1> , <NUM_LIT:1> , <NUM_LIT:1> , <NUM_LIT:1> ) ) ) <EOL> context . set_source_rgba ( * background ) <EOL> context . paint ( ) <EOL> color = convert_color ( params . get ( '<STR_LIT>' , ( <NUM_LIT:0> , <NUM_LIT:0> , <NUM_LIT:0> , <NUM_LIT:1> ) ) ) <EOL> context . set_source_rgba ( * color ) <EOL> context . select_font_face ( font , style , weight ) <EOL> context . set_font_size ( size ) <EOL> context . move_to ( x , baseline ) <EOL> context . text_path ( text ) <EOL> context . fill ( ) <EOL> filepath = abspath ( filepath ) <EOL> try : <EOL> surface . write_to_png ( filepath ) <EOL> except IOError , e : <EOL> raise IOError ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" % ( filepath , e , text , params ) ) <EOL> optimizer = Optimizer ( ) <EOL> if optimizer . is_enabled ( ) : <EOL> optimizer . optimize ( filepath ) <EOL> surface . finish ( ) <EOL> return int ( width ) , int ( height ) <EOL> class OptimizerError ( Exception ) : pass <EOL> class Optimizer ( object ) : <EOL> def __init__ ( self ) : <EOL> self . cmdline_template = getattr ( <EOL> settings , '<STR_LIT>' , None ) <EOL> self . dest_path_template = getattr ( <EOL> settings , '<STR_LIT>' , None ) <EOL> def is_enabled ( self ) : <EOL> return self . cmdline_template and self . dest_path_template <EOL> def optimize ( self , filepath ) : <EOL> self . filepath = filepath <EOL> params = self . get_params_for ( filepath ) <EOL> self . cmdline = self . cmdline_template % params <EOL> self . dest_path = self . dest_path_template % params <EOL> process = Popen ( self . cmdline , shell = True , stdout = PIPE , stderr = PIPE ) <EOL> self . stdout , self . stderr = process . stdout . read ( ) , process . stderr . read ( ) <EOL> self . retval = process . wait ( ) <EOL> if self . retval : <EOL> self . error ( '<STR_LIT>' ) <EOL> elif not exists ( self . dest_path ) : <EOL> self . error ( '<STR_LIT>' ) <EOL> elif self . stdout or self . stderr : <EOL> if not self . stderr . startswith ( '<STR_LIT>' ) : <EOL> self . error ( '<STR_LIT>' ) <EOL> if exists ( self . dest_path ) : <EOL> rename ( self . dest_path , filepath ) <EOL> def get_params_for ( self , filepath ) : <EOL> directory , filename = split ( filepath ) <EOL> name , ext = filename . rsplit ( '<STR_LIT:.>' , <NUM_LIT:1> ) <EOL> return { '<STR_LIT:path>' : filepath , <EOL> '<STR_LIT>' : directory , <EOL> '<STR_LIT:name>' : name , <EOL> '<STR_LIT>' : ext } <EOL> def error ( self , subject ) : <EOL> message = ( <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' % ( <EOL> self . filepath , self . dest_path , self . cmdline , <EOL> self . retval , self . stdout , self . stderr ) ) <EOL> if settings . DEBUG : <EOL> raise OptimizerError ( message ) <EOL> else : <EOL> mail_admins ( subject , message , fail_silently = True ) <EOL> class TextImage ( object ) : <EOL> def __init__ ( self , url , path , size ) : <EOL> self . url = url <EOL> self . path = path <EOL> self . width , self . height = size <EOL> def _embed ( self ) : <EOL> if not hasattr ( self , '<STR_LIT>' ) : <EOL> self . _base64 = ( '<STR_LIT>' % <EOL> file ( self . path ) . read ( ) . encode ( '<STR_LIT>' ) [ : - <NUM_LIT:1> ] ) <EOL> return self . _base64 <EOL> embed = property ( _embed ) <EOL> class GetTextImageNode ( Node ) : <EOL> def __init__ ( self , base_params , text , overrides , varname ) : <EOL> self . base_params = base_params <EOL> self . text = text <EOL> self . overrides = overrides <EOL> self . varname = varname <EOL> def render ( self , context ) : <EOL> params = { } <EOL> if self . base_params is not None : <EOL> params = self . base_params . resolve ( context ) <EOL> if isinstance ( params , basestring ) : <EOL> try : <EOL> presets = settings . CAIROTEXT_PRESETS <EOL> params = dict ( presets [ params ] ) <EOL> except ( AttributeError , KeyError ) : <EOL> raise KeyError ( '<STR_LIT>' <EOL> '<STR_LIT>' % params ) <EOL> params . update ( dict ( ( key , val . resolve ( context ) ) <EOL> for key , val in self . overrides . items ( ) ) ) <EOL> text = self . text . resolve ( context ) <EOL> name = md5 ( text . encode ( '<STR_LIT>' ) + pformat ( params ) ) . hexdigest ( ) <EOL> render_dir = getattr ( settings , '<STR_LIT>' , '<STR_LIT>' ) <EOL> filename = '<STR_LIT>' % name <EOL> fileurl = urljoin ( settings . MEDIA_URL , join ( render_dir , filename ) ) <EOL> filepath = join ( settings . MEDIA_ROOT , render_dir , filename ) <EOL> size = None <EOL> if not exists ( filepath ) : <EOL> size = render_text ( text , filepath , params ) <EOL> pngsize = get_png_size ( filepath ) <EOL> assert size is None or size == pngsize , '<STR_LIT>' % ( size + pngsize ) <EOL> context [ self . varname ] = TextImage ( fileurl , filepath , pngsize ) <EOL> return '<STR_LIT>' <EOL> def compile ( parser , value ) : <EOL> if value [ <NUM_LIT:0> ] in '<STR_LIT>' : <EOL> return Variable ( value ) <EOL> return parser . compile_filter ( value ) <EOL> def do_get_text_image ( parser , token ) : <EOL> """<STR_LIT>""" <EOL> bits = token . split_contents ( ) <EOL> count = len ( bits ) <EOL> if count < <NUM_LIT:4> : <EOL> raise TemplateSyntaxError ( '<STR_LIT>' ) <EOL> if bits [ - <NUM_LIT:2> ] != '<STR_LIT>' : <EOL> raise TemplateSyntaxError ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> text = parser . compile_filter ( bits [ <NUM_LIT:1> ] ) <EOL> base_params = None <EOL> if count % <NUM_LIT:2> : <EOL> base_params = parser . compile_filter ( bits [ <NUM_LIT:2> ] ) <EOL> overrides = dict ( ( keyword , compile ( parser , value ) ) <EOL> for keyword , value in zip ( bits [ <NUM_LIT:2> + count % <NUM_LIT:2> : - <NUM_LIT:2> : <NUM_LIT:2> ] , bits [ <NUM_LIT:3> + count % <NUM_LIT:2> : - <NUM_LIT:2> : <NUM_LIT:2> ] ) ) <EOL> varname = bits [ - <NUM_LIT:1> ] <EOL> unknown_keywords = set ( overrides . keys ( ) ) . difference ( PARAM_KEYWORDS ) <EOL> if unknown_keywords : <EOL> raise TemplateSyntaxError ( '<STR_LIT>' % ( <EOL> bits [ <NUM_LIT:0> ] , <EOL> '<STR_LIT:U+002CU+0020>' . join ( unknown_keywords ) ) ) <EOL> return GetTextImageNode ( base_params , text , overrides , varname ) <EOL> do_get_text_image = register . tag ( '<STR_LIT>' , do_get_text_image ) </s>
