src/reportlab/pdfgen/textobject.py
branchpy33
changeset 3723 99aa837b6703
parent 3721 0c93dd8ff567
child 3731 b233dd0577ff
equal deleted inserted replaced
3722:29c11b905751 3723:99aa837b6703
     7 instantiate directly, obtain one from the Canvas instead.
     7 instantiate directly, obtain one from the Canvas instead.
     8 
     8 
     9 Progress Reports:
     9 Progress Reports:
    10 8.83, 2000-01-13, gmcm: created from pdfgen.py
    10 8.83, 2000-01-13, gmcm: created from pdfgen.py
    11 """
    11 """
       
    12 import sys
    12 import string
    13 import string
    13 from types import *
    14 from types import *
    14 from reportlab.lib.colors import Color, CMYKColor, CMYKColorSep, toColor, black, white, _CMYK_black, _CMYK_white
    15 from reportlab.lib.colors import Color, CMYKColor, CMYKColorSep, toColor, black, white, _CMYK_black, _CMYK_white
    15 from reportlab.lib.utils import fp_str
    16 from reportlab.lib.utils import fp_str, isStrType, isPython3
    16 from reportlab.pdfbase import pdfmetrics
    17 from reportlab.pdfbase import pdfmetrics
    17 
    18 
    18 class _PDFColorSetter:
    19 class _PDFColorSetter:
    19     '''Abstracts the color setting operations; used in Canvas and Textobject
    20     '''Abstracts the color setting operations; used in Canvas and Textobject
    20     asseumes we have a _code object'''
    21     asseumes we have a _code object'''
    76             elif l==4:
    77             elif l==4:
    77                 self._fillColorObj = aColor
    78                 self._fillColorObj = aColor
    78                 self._code.append('%s k' % fp_str(aColor))
    79                 self._code.append('%s k' % fp_str(aColor))
    79             else:
    80             else:
    80                 raise ValueError('Unknown color %r' % aColor)
    81                 raise ValueError('Unknown color %r' % aColor)
    81         elif isinstance(aColor,str):
    82         elif isStrType(aColor):
    82             self.setFillColor(toColor(aColor))
    83             self.setFillColor(toColor(aColor))
    83         else:
    84         else:
    84             raise ValueError('Unknown color %r' % aColor)
    85             raise ValueError('Unknown color %r' % aColor)
    85         if alpha is not None:
    86         if alpha is not None:
    86             self.setFillAlpha(alpha)
    87             self.setFillAlpha(alpha)
   112             elif l==4:
   113             elif l==4:
   113                 self._fillColorObj = aColor
   114                 self._fillColorObj = aColor
   114                 self._code.append('%s K' % fp_str(aColor))
   115                 self._code.append('%s K' % fp_str(aColor))
   115             else:
   116             else:
   116                 raise ValueError('Unknown color %r' % aColor)
   117                 raise ValueError('Unknown color %r' % aColor)
   117         elif isinstance(aColor,str):
   118         elif isStrType(aColor):
   118             self.setStrokeColor(toColor(aColor))
   119             self.setStrokeColor(toColor(aColor))
   119         else:
   120         else:
   120             raise ValueError('Unknown color %r' % aColor)
   121             raise ValueError('Unknown color %r' % aColor)
   121         if alpha is not None:
   122         if alpha is not None:
   122             self.setStrokeAlpha(alpha)
   123             self.setStrokeAlpha(alpha)
   185     def getCode(self):
   186     def getCode(self):
   186         "pack onto one line; used internally"
   187         "pack onto one line; used internally"
   187         self._code.append('ET')
   188         self._code.append('ET')
   188         if self._clipping:
   189         if self._clipping:
   189             self._code.append('%d Tr' % (self._textRenderMode^4))
   190             self._code.append('%d Tr' % (self._textRenderMode^4))
   190         return string.join(self._code, ' ')
   191         return ' '.join(self._code)
   191 
   192 
   192     def setTextOrigin(self, x, y):
   193     def setTextOrigin(self, x, y):
   193         if self._canvas.bottomup:
   194         if self._canvas.bottomup:
   194             self._code.append('1 0 0 1 %s Tm' % fp_str(x, y)) #bottom up
   195             self._code.append('1 0 0 1 %s Tm' % fp_str(x, y)) #bottom up
   195         else:
   196         else:
   222         position specificied in this call.  """
   223         position specificied in this call.  """
   223 
   224 
   224         # Check if we have a previous move cursor call, and combine
   225         # Check if we have a previous move cursor call, and combine
   225         # them if possible.
   226         # them if possible.
   226         if self._code and self._code[-1][-3:]==' Td':
   227         if self._code and self._code[-1][-3:]==' Td':
   227             L = string.split(self._code[-1])
   228             L = self._code[-1].split()
   228             if len(L)==3:
   229             if len(L)==3:
   229                 del self._code[-1]
   230                 del self._code[-1]
   230             else:
   231             else:
   231                 self._code[-1] = string.join(L[:-4])
   232                 self._code[-1] = ''.join(L[:-4])
   232 
   233 
   233             # Work out the last movement
   234             # Work out the last movement
   234             lastDx = float(L[-3])
   235             lastDx = float(L[-3])
   235             lastDy = float(L[-2])
   236             lastDy = float(L[-2])
   236 
   237 
   381                 ))
   382                 ))
   382             R.append("(%s) Tj" % font.formatForPdf(text))
   383             R.append("(%s) Tj" % font.formatForPdf(text))
   383         else:
   384         else:
   384             #convert to T1  coding
   385             #convert to T1  coding
   385             fc = font
   386             fc = font
   386             if not isinstance(text,str):
   387             if not isPython3 and not isinstance(text,unicode):
   387                 try:
   388                 try:
   388                     text = text.decode('utf8')
   389                     text = text.decode('utf8')
   389                 except UnicodeDecodeError as e:
   390                 except UnicodeDecodeError as e:
   390                     i,j = e.args[2:4]
   391                     i,j = e.args[2:4]
   391                     raise UnicodeDecodeError(*(e.args[:4]+('%s\n%s-->%s<--%s' % (e.args[4],text[max(i-10,0):i],text[i:j],text[j:j+10]),)))
   392                     raise UnicodeDecodeError(*(e.args[:4]+('%s\n%s-->%s<--%s' % (e.args[4],text[max(i-10,0):i],text[i:j],text[j:j+10]),)))
   429         """prints multi-line or newlined strings, moving down.  One
   430         """prints multi-line or newlined strings, moving down.  One
   430         comon use is to quote a multi-line block in your Python code;
   431         comon use is to quote a multi-line block in your Python code;
   431         since this may be indented, by default it trims whitespace
   432         since this may be indented, by default it trims whitespace
   432         off each line and from the beginning; set trim=0 to preserve
   433         off each line and from the beginning; set trim=0 to preserve
   433         whitespace."""
   434         whitespace."""
   434         if isinstance(stuff,str):
   435         if isStrType(stuff):
   435             lines = string.split(string.strip(stuff), '\n')
   436             lines = '\n'.split(stuff.strip())
   436             if trim==1:
   437             if trim==1:
   437                 lines = list(map(string.strip,lines))
   438                 lines = [s.strip() for s in lines]
   438         elif isinstance(stuff,(tuple,list)):
   439         elif isinstance(stuff,(tuple,list)):
   439             lines = stuff
   440             lines = stuff
   440         else:
   441         else:
   441             assert 1==0, "argument to textlines must be string,, list or tuple"
   442             assert 1==0, "argument to textlines must be string,, list or tuple"
   442 
   443 
   443         # Output each line one at a time. This used to be a long-hand
   444         # Output each line one at a time. This used to be a long-hand
   444         # copy of the textLine code, now called as a method.
   445         # copy of the textLine code, now called as a method.
   445         for line in lines:
   446         for line in lines:
   446             self.textLine(line)
   447             self.textLine(line)
   447 
   448 
   448     def __bool__(self):
   449     def __nonzero__(self):
   449         'PDFTextObject is true if it has something done after the init'
   450         'PDFTextObject is true if it has something done after the init'
   450         return self._code != ['BT']
   451         return self._code != ['BT']