text: # -*- coding: iso-8859-1 -*-
  
  "PDF Template Helper for FPDF.py"
  
  from __future__ import with_statement
  
  __author__ = "Mariano Reingart <reingart@gmail.com>"
  __copyright__ = "Copyright (C) 2010 Mariano Reingart"
  __license__ = "LGPL 3.0"
  
  import sys,os,csv
  from .fpdf import FPDF
  from .py3k import PY3K, basestring, unicode
  
  def rgb(col):
      return (col // 65536), (col // 256 % 256), (col% 256)
  
  class Template:
      def __init__(self, infile=None, elements=None, format='A4', orientation='portrait',
                   title='', author='', subject='', creator='', keywords=''):
          if elements:
              self.load_elements(elements)
          self.handlers = {'T': self.text, 'L': self.line, 'I': self.image, 
                           'B': self.rect, 'BC': self.barcode, 'W': self.write, }
          self.texts = {}
          pdf = self.pdf = FPDF(format=format,orientation=orientation, unit="mm")
          pdf.set_title(title)
          pdf.set_author(author)
          pdf.set_creator(creator)
          pdf.set_subject(subject)
          pdf.set_keywords(keywords)
  
      def load_elements(self, elements):
          "Initialize the internal element structures"
          self.pg_no = 0
          self.elements = elements
          self.keys = [v['name'].lower() for v in self.elements]
      
      def parse_csv(self, infile, delimiter=",", decimal_sep="."):
          "Parse template format csv file and create elements dict"
          keys = ('name','type','x1','y1','x2','y2','font','size',
              'bold','italic','underline','foreground','background',
              'align','text','priority', 'multiline')
          self.elements = []
          self.pg_no = 0
          if not PY3K:
              f = open(infile, 'rb')
          else:
              f = open(infile)
          with f:
              for row in csv.reader(f, delimiter=delimiter):
                  kargs = {}
                  for i,v in enumerate(row):
                      if not v.startswith("'") and decimal_sep!=".": 
                          v = v.replace(decimal_sep,".")
                      else:
                          v = v
                      if v=='':
                          v = None
                      else:
                          v = eval(v.strip())
                      kargs[keys[i]] = v
                  self.elements.append(kargs)
          self.keys = [v['name'].lower() for v in self.elements]
  
      def add_page(self):
          self.pg_no += 1
          self.texts[self.pg_no] = {}
          
      def __setitem__(self, name, value):
          if name.lower() in self.keys:
              if not PY3K and isinstance(value, unicode):
                  value = value.encode("latin1","ignore")
              elif value is None:
                  value = ""
              else:
                  value = str(value)
              self.texts[self.pg_no][name.lower()] = value
  
      # setitem shortcut (may be further extended)
      set = __setitem__
  
      def has_key(self, name):
          return name.lower() in self.keys
          
      def __contains__(self, name):
          return self.has_key(name)
  
      def __getitem__(self, name):
          if name in self.keys:
              key = name.lower()
              if key in self.texts:
                  # text for this page:
                  return self.texts[self.pg_no][key]
              else:
                  # find first element for default text:
                  elements = [element for element in self.elements
                      if element['name'].lower() == key]
                  if elements:
                      return elements[0]['text']
  
      def split_multicell(self, text, element_name):
          "Divide (\n) a string using a given element width"
          pdf = self.pdf
          element = [element for element in self.elements
              if element['name'].lower() == element_name.lower()][0]
          style = ""
          if element['bold']: style += "B"
          if element['italic']: style += "I"
          if element['underline']: style += "U"
          pdf.set_font(element['font'],style,element['size'])
          align = {'L':'L','R':'R','I':'L','D':'R','C':'C','':''}.get(element['align']) # D/I in spanish
          if isinstance(text, unicode) and not PY3K:
              text = text.encode("latin1","ignore")
          else:
              text = str(text)
          return pdf.multi_cell(w=element['x2']-element['x1'],
                               h=element['y2']-element['y1'],
                               txt=text,align=align,split_only=True)
          
      def render(self, outfile, dest="F"):
          pdf = self.pdf
          for pg in range(1, self.pg_no+1):
              pdf.add_page()
              pdf.set_font('Arial','B',16)
              pdf.set_auto_page_break(False,margin=0)
  
              for element in sorted(self.elements,key=lambda x: x['priority']):
                  #print "dib",element['type'], element['name'], element['x1'], element['y1'], element['x2'], element['y2']
                  element = element.copy()
                  element['text'] = self.texts[pg].get(element['name'].lower(), element['text'])
                  if 'rotate' in element:
                      pdf.rotate(element['rotate'], element['x1'], element['y1'])
                  self.handlers[element['type'].upper()](pdf, **element)
                  if 'rotate' in element:
                      pdf.rotate(0)
          
          if dest:
              return pdf.output(outfile, dest)
          
      def text(self, pdf, x1=0, y1=0, x2=0, y2=0, text='', font="arial", size=10, 
               bold=False, italic=False, underline=False, align="", 
               foreground=0, backgroud=65535, multiline=None,
               *args, **kwargs):
          if text:
              if pdf.text_color!=rgb(foreground):
                  pdf.set_text_color(*rgb(foreground))
              if pdf.fill_color!=rgb(backgroud):
                  pdf.set_fill_color(*rgb(backgroud))
  
              font = font.strip().lower()
              if font == 'arial black':
                  font = 'arial'
              style = ""
              for tag in 'B', 'I', 'U':
                  if (text.startswith("<%s>" % tag) and text.endswith("</%s>" %tag)):
                      text = text[3:-4]
                      style += tag
              if bold: style += "B"
              if italic: style += "I"
              if underline: style += "U"
              align = {'L':'L','R':'R','I':'L','D':'R','C':'C','':''}.get(align) # D/I in spanish
              pdf.set_font(font,style,size)
              ##m_k = 72 / 2.54
              ##h = (size/m_k)
              pdf.set_xy(x1,y1)
              if multiline is None:
                  # multiline==None: write without wrapping/trimming (default)
                  pdf.cell(w=x2-x1,h=y2-y1,txt=text,border=0,ln=0,align=align)
              elif multiline:
                  # multiline==True: automatic word - warp
                  pdf.multi_cell(w=x2-x1,h=y2-y1,txt=text,border=0,align=align)
              else:
                  # multiline==False: trim to fit exactly the space defined
                  text = pdf.multi_cell(w=x2-x1, h=y2-y1,
                               txt=text, align=align, split_only=True)[0]
                  print("trimming: *%s*" % text)
                  pdf.cell(w=x2-x1,h=y2-y1,txt=text,border=0,ln=0,align=align)
  
              #pdf.Text(x=x1,y=y1,txt=text)
  
      def line(self, pdf, x1=0, y1=0, x2=0, y2=0, size=0, foreground=0, *args, **kwargs):
          if pdf.draw_color!=rgb(foreground):
              #print "SetDrawColor", hex(foreground)
              pdf.set_draw_color(*rgb(foreground))
          #print "SetLineWidth", size
          pdf.set_line_width(size)
          pdf.line(x1, y1, x2, y2)
  
      def rect(self, pdf, x1=0, y1=0, x2=0, y2=0, size=0, foreground=0, backgroud=65535, *args, **kwargs):
          if pdf.draw_color!=rgb(foreground):
              pdf.set_draw_color(*rgb(foreground))
          if pdf.fill_color!=rgb(backgroud):
              pdf.set_fill_color(*rgb(backgroud))
          pdf.set_line_width(size)
          pdf.rect(x1, y1, x2-x1, y2-y1)
  
      def image(self, pdf, x1=0, y1=0, x2=0, y2=0, text='', *args,**kwargs):
          if text:
              pdf.image(text,x1,y1,w=x2-x1,h=y2-y1,type='',link='')
  
      def barcode(self, pdf, x1=0, y1=0, x2=0, y2=0, text='', font="arial", size=1,
               foreground=0, *args, **kwargs):
          if pdf.draw_color!=rgb(foreground):
              pdf.set_draw_color(*rgb(foreground))
          font = font.lower().strip()
          if font == 'interleaved 2of5 nt':
              pdf.interleaved2of5(text,x1,y1,w=size,h=y2-y1)
  
      # Added by Derek Schwalenberg Schwalenberg1013@gmail.com to allow (url) links in templates (using write method) 2014-02-22
      def write(self, pdf, x1=0, y1=0, x2=0, y2=0, text='', font="arial", size=1,
                bold=False, italic=False, underline=False, align="", link='http://example.com',
               foreground=0, *args, **kwargs):
          if pdf.text_color!=rgb(foreground):
              pdf.set_text_color(*rgb(foreground))
          font = font.strip().lower()
          if font == 'arial black':
              font = 'arial'
          style = ""
          for tag in 'B', 'I', 'U':
              if (text.startswith("<%s>" % tag) and text.endswith("</%s>" %tag)):
                  text = text[3:-4]
                  style += tag
          if bold: style += "B"
          if italic: style += "I"
          if underline: style += "U"
          align = {'L':'L','R':'R','I':'L','D':'R','C':'C','':''}.get(align) # D/I in spanish
          pdf.set_font(font,style,size)
          ##m_k = 72 / 2.54
          ##h = (size/m_k)
          pdf.set_xy(x1,y1)
          pdf.write(5,text,link)
  