"Fossies" - the Fresh Open Source Software Archive

Member "reportlab-3.5.23/docs/userguide/ch2_graphics.py" (31 May 2019, 45548 Bytes) of package /linux/privat/reportlab-3.5.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "ch2_graphics.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.5.21_vs_3.5.23.

    1 #Copyright ReportLab Europe Ltd. 2000-2017
    2 #see license.txt for license details
    3 #history https://bitbucket.org/rptlab/reportlab/history-node/tip/src/reportlab/docs/userguide/ch2_graphics.py
    4 from tools.docco.rl_doc_utils import *
    5 from reportlab.lib.codecharts import SingleByteEncodingChart
    6 
    7 heading1("Graphics and Text with $pdfgen$")
    8 
    9 heading2("Basic Concepts")
   10 disc("""
   11 The $pdfgen$ package is the lowest level interface for
   12 generating PDF documents.  A $pdfgen$ program is essentially
   13 a sequence of instructions for "painting" a document onto
   14 a sequence of pages.  The interface object which provides the
   15 painting operations is the $pdfgen canvas$.
   16 """)
   17 
   18 disc("""
   19 The canvas should be thought of as a sheet of white paper
   20 with points on the sheet identified using Cartesian ^(X,Y)^ coordinates
   21 which by default have the ^(0,0)^ origin point at the lower
   22 left corner of the page.  Furthermore the first coordinate ^x^
   23 goes to the right and the second coordinate ^y^ goes up, by
   24 default.""")
   25 
   26 disc("""
   27 A simple example
   28 program that uses a canvas follows.
   29 """)
   30 
   31 eg("""
   32     from reportlab.pdfgen import canvas
   33     def hello(c):
   34         c.drawString(100,100,"Hello World")
   35     c = canvas.Canvas("hello.pdf")
   36     hello(c)
   37     c.showPage()
   38     c.save()
   39 """)
   40 
   41 disc("""
   42 The above code creates a $canvas$ object which will generate
   43 a PDF file named $hello.pdf$ in the current working directory.
   44 It then calls the $hello$ function passing the $canvas$ as an argument.
   45 Finally the $showPage$ method saves the current page of the canvas
   46 and the $save$ method stores the file and closes the canvas.""")
   47 
   48 disc("""
   49 The $showPage$ method causes the $canvas$ to stop drawing on the
   50 current page and any further operations will draw on a subsequent
   51 page (if there are any further operations -- if not no
   52 new page is created).  The $save$ method must be called after the
   53 construction of the document is complete -- it generates the PDF
   54 document, which is the whole purpose of the $canvas$ object.
   55 """)
   56 
   57 heading2("More about the Canvas")
   58 disc("""
   59 Before describing the drawing operations, we will digress to cover
   60 some of the things which can be done to configure a canvas.  There
   61 are many different settings available.  If you are new to Python
   62 or can't wait to produce some output, you can skip ahead, but
   63 come back later and read this!""")
   64 
   65 disc("""First of all, we will look at the constructor
   66 arguments for the canvas:""")
   67 
   68 eg("""    def __init__(self,filename,
   69                  pagesize=(595.27,841.89),
   70                  bottomup = 1,
   71                  pageCompression=0,
   72                  encoding=rl_config.defaultEncoding,
   73                  verbosity=0
   74                  encrypt=None):
   75                  """)
   76 
   77 disc("""The $filename$ argument controls the
   78 name of the final PDF file.  You
   79 may also pass in any open binary stream (such as $sys.stdout$, the python process standard output with a binary encoding)
   80 and the PDF document will be written to that.  Since PDF
   81 is a binary format, you should take care when writing other
   82 stuff before or after it; you can't deliver PDF documents
   83 inline in the middle of an HTML page!""")
   84 
   85 disc("""The $pagesize$ argument is a tuple of two numbers
   86 in points (1/72 of an inch). The canvas defaults to $A4$ (an international standard
   87 page size which differs from the American standard page size of $letter$),
   88 but it is better to explicitly specify it.  Most common page
   89 sizes are found in the library module $reportlab.lib.pagesizes$,
   90 so you can use expressions like""")
   91 
   92 eg("""from reportlab.lib.pagesizes import letter, A4
   93 myCanvas = Canvas('myfile.pdf', pagesize=letter)
   94 width, height = letter  #keep for later
   95 """)
   96 
   97 pencilnote()
   98 
   99 disc("""If you have problems printing your document make sure you
  100 are using the right page size (usually either $A4$ or $letter$).
  101 Some printers do not work well with pages that are too large or too small.""")
  102 
  103 disc("""Very often, you will want to calculate things based on
  104 the page size.  In the example above we extracted the width and
  105 height.  Later in the program we may use the $width$ variable to
  106 define a right margin as $width - inch$ rather than using
  107 a constant.  By using variables the margin will still make sense even
  108 if the page size changes.""")
  109 
  110 disc("""The $bottomup$ argument
  111 switches coordinate systems.  Some graphics systems (like PDF
  112 and PostScript) place (0,0) at the bottom left of the page
  113 others (like many graphical user interfaces [GUI's]) place the origin at the top left.  The
  114 $bottomup$ argument is deprecated and may be dropped in future""")
  115 
  116 todo("""Need to see if it really works for all tasks, and if not
  117      then get rid of it""")
  118 
  119 disc("""The $pageCompression$ option determines whether the stream
  120 of PDF operations for each page is compressed.  By default
  121 page streams are not compressed, because the compression slows the file generation process.
  122 If output size is important set $pageCompression=1$, but remember that, compressed documents will
  123 be smaller, but slower to generate.  Note that images are <i>always</i> compressed, and this option
  124 will only save space if you have a very large amount of text and vector graphics
  125 on each page.""")
  126 
  127 disc("""The $encoding$ argument is largely obsolete in version 2.0 and can
  128 probably be omitted by 99% of users.  Its default value is fine unless you
  129 very specifically need to use one of the 25 or so characters which are present
  130 in MacRoman and not in Winansi.  A useful reference to these is here:
  131 <font color="blue"><u><a href="http://www.alanwood.net/demos/charsetdiffs.html">http://www.alanwood.net/demos/charsetdiffs.html</a></u></font>.
  132 
  133 The parameter determines which font encoding is used for the
  134 standard Type 1 fonts; this should correspond to the encoding on your system.
  135 Note that this is the encoding used <i>internally by the font</i>; text you
  136 pass to the ReportLab toolkit for rendering should always either be a Python
  137 unicode string object or a UTF-8 encoded byte string (see the next chapter)!
  138 The font encoding has two values at present: $'WinAnsiEncoding'$ or
  139 $'MacRomanEncoding'$.  The variable $rl_config.defaultEncoding$ above points
  140 to the former, which is standard on Windows, Mac OS X and many Unices
  141 (including Linux). If you are Mac user and don't have OS X, you may want to
  142 make a global change: modify the line at the top of
  143 <i>reportlab/pdfbase/pdfdoc.py</i> to switch it over.  Otherwise, you can
  144 probably just ignore this argument completely and never pass it.  For all TTF
  145 and the commonly-used CID fonts, the encoding you pass in here is ignored,
  146 since the reportlab library itself knows the right encodings in those
  147 cases.""")
  148 
  149 disc("""The demo script $reportlab/demos/stdfonts.py$
  150 will print out two test documents showing all code points
  151 in all fonts, so you can look up characters.  Special
  152 characters can be inserted into string commands with
  153 the usual Python escape sequences; for example \\101 = 'A'.""")
  154 
  155 disc("""The $verbosity$ argument determines how much log
  156 information is printed.  By default, it is zero to assist
  157 applications which want to capture PDF from standard output.
  158 With a value of 1, you will get a confirmation message
  159 each time a document is generated.  Higher numbers may
  160 give more output in future.""")
  161 
  162 disc("""The $encrypt$ argument determines if and how the document is encrypted.
  163 By default, the document is not encrypted.
  164 If $encrypt$ is a string object, it is used as the user password for the pdf.
  165 If $encrypt$ is an instance of $reportlab.lib.pdfencrypt.StandardEncryption$, this object is
  166 used to encrypt the pdf. This allows more finegrained control over the encryption settings.
  167 Encryption is covered in more detail in Chapter 4.""")
  168 
  169 todo("to do - all the info functions and other non-drawing stuff")
  170 todo("""Cover all constructor arguments, and setAuthor etc.""")
  171 
  172 heading2("Drawing Operations")
  173 disc("""
  174 Suppose the $hello$ function referenced above is implemented as
  175 follows (we will not explain each of the operations in detail
  176 yet).
  177 """)
  178 
  179 eg(examples.testhello)
  180 
  181 disc("""
  182 Examining this code notice that there are essentially two types
  183 of operations performed using a canvas.  The first type draws something
  184 on the page such as a text string or a rectangle or a line.  The second
  185 type changes the state of the canvas such as
  186 changing the current fill or stroke color or changing the current font
  187 type and size.
  188 """)
  189 
  190 disc("""
  191 If we imagine the program as a painter working on
  192 the canvas the "draw" operations apply paint to the canvas using
  193 the current set of tools (colors, line styles, fonts, etcetera)
  194 and the "state change" operations change one of the current tools
  195 (changing the fill color from whatever it was to blue, or changing
  196 the current font to $Times-Roman$ in 15 points, for example).
  197 """)
  198 
  199 disc("""
  200 The document generated by the "hello world" program listed above would contain
  201 the following graphics.
  202 """)
  203 
  204 illust(examples.hello, '"Hello World" in pdfgen')
  205 
  206 heading3("About the demos in this document")
  207 
  208 disc("""
  209 This document contains demonstrations of the code discussed like the one shown
  210 in the rectangle above.  These demos are drawn on a "tiny page" embedded
  211 within the real pages of the guide.  The tiny pages are %s inches wide
  212 and %s inches tall. The demo displays show the actual output of the demo code.
  213 For convenience the size of the output has been reduced slightly.
  214 """ % (examplefunctionxinches, examplefunctionyinches))
  215 
  216 heading2('The tools: the "draw" operations')
  217 
  218 disc("""
  219 This section briefly lists the tools available to the program
  220 for painting information onto a page using the canvas interface.
  221 These will be discussed in detail in later sections.  They are listed
  222 here for easy reference and for summary purposes.
  223 """)
  224 
  225 heading3("Line methods")
  226 
  227 eg("""canvas.line(x1,y1,x2,y2)""")
  228 eg("""canvas.lines(linelist)""")
  229 
  230 disc("""
  231 The line methods draw straight line segments on the canvas.
  232 """)
  233 
  234 heading3("Shape methods")
  235 
  236 eg("""canvas.grid(xlist, ylist) """)
  237 eg("""canvas.bezier(x1, y1, x2, y2, x3, y3, x4, y4)""")
  238 eg("""canvas.arc(x1,y1,x2,y2) """)
  239 eg("""canvas.rect(x, y, width, height, stroke=1, fill=0) """)
  240 eg("""canvas.ellipse(x1,y1, x2,y2, stroke=1, fill=0)""")
  241 eg("""canvas.wedge(x1,y1, x2,y2, startAng, extent, stroke=1, fill=0) """)
  242 eg("""canvas.circle(x_cen, y_cen, r, stroke=1, fill=0)""")
  243 eg("""canvas.roundRect(x, y, width, height, radius, stroke=1, fill=0) """)
  244 
  245 disc("""
  246 The shape methods draw common complex shapes on the canvas.
  247 """)
  248 
  249 heading3("String drawing methods")
  250 
  251 eg("""canvas.drawString(x, y, text):""")
  252 eg("""canvas.drawRightString(x, y, text) """)
  253 eg("""canvas.drawCentredString(x, y, text)""")
  254 
  255 disc("""
  256 The draw string methods draw single lines of text on the canvas.
  257 """)
  258 
  259 heading3("The text object methods")
  260 eg("""textobject = canvas.beginText(x, y) """)
  261 eg("""canvas.drawText(textobject) """)
  262 
  263 disc("""
  264 Text objects are used to format text in ways that
  265 are not supported directly by the $canvas$ interface.
  266 A program creates a text object from the $canvas$ using $beginText$
  267 and then formats text by invoking $textobject$ methods.
  268 Finally the $textobject$ is drawn onto the canvas using
  269 $drawText$.
  270 """)
  271 
  272 heading3("The path object methods")
  273 
  274 eg("""path = canvas.beginPath() """)
  275 eg("""canvas.drawPath(path, stroke=1, fill=0, fillMode=None) """)
  276 eg("""canvas.clipPath(path, stroke=1, fill=0, fillMode=None) """)
  277 
  278 disc("""
  279 Path objects are similar to text objects: they provide dedicated control
  280 for performing complex graphical drawing not directly provided by the
  281 canvas interface.  A program creates a path object using $beginPath$
  282 populates the path with graphics using the methods of the path object
  283 and then draws the path on the canvas using $drawPath$.""")
  284 
  285 disc("""It is also possible
  286 to use a path as a "clipping region" using the $clipPath$ method -- for example a circular path
  287 can be used to clip away the outer parts of a rectangular image leaving
  288 only a circular part of the image visible on the page.
  289 """)
  290 
  291 disc("""If $fill=1$ is specified then the $fillMode$ argument may be used to set either 0=$even-odd$ or 1=$non-zero$ filling mode.
  292 which will alter the way that complex paths are filled. If the default $None$ values is used then the canvas
  293 $_fillMode$ attribute value is used (normally $0$ ie $even-odd$).""")
  294 
  295 heading3("Image methods")
  296 pencilnote()
  297 disc("""
  298 You need the Python Imaging Library (PIL) to use images with the ReportLab package.
  299 Examples of the techniques below can be found by running the script $test_pdfgen_general.py$
  300 in our $tests$ subdirectory and looking at page 7 of the output.
  301 """)
  302 
  303 disc("""
  304 There are two similar-sounding ways to draw images.  The preferred one is
  305 the $drawImage$ method.  This implements a caching system so you can
  306 define an image once and draw it many times; it will only be
  307 stored once in the PDF file.  $drawImage$ also exposes one advanced parameter,
  308 a transparency mask, and will expose more in future.  The older technique,
  309 $drawInlineImage$, stores bitmaps within the page stream and is thus very
  310 inefficient if you use the same image more than once in a document; but can result
  311 in PDFs which render faster if the images are very small and not repeated. We'll
  312 discuss the oldest one first:
  313 """)
  314 
  315 eg("""canvas.drawInlineImage(self, image, x,y, width=None,height=None) """)
  316 
  317 disc("""
  318 The $drawInlineImage$ method places an image on the canvas.  The $image$
  319 parameter may be either a PIL Image object or an image filename.  Many common
  320 file formats are accepted including GIF and JPEG.  It returns the size of the actual
  321 image in pixels as a (width, height) tuple.
  322 """)
  323 
  324 eg("""canvas.drawImage(self, image, x,y, width=None,height=None,mask=None) """)
  325 disc("""
  326 The arguments and return value work as for $drawInlineImage$.  However, we use a caching
  327 system; a given image will only be stored the first time it is used, and just referenced
  328 on subsequent use.  If you supply a filename, it assumes that the same filename
  329 means the same image.  If you supply a PIL image, it tests if the content
  330 has actually changed before re-embedding.""")
  331 
  332 disc("""
  333 The $mask$ parameter lets you create transparent images.  It takes 6 numbers
  334 and defines the range of RGB values which will be masked out or treated as
  335 transparent. For example with [0,2,40,42,136,139], it will mask out any pixels
  336 with a Red value from 0 or 1, Green from 40 or 41 and Blue of  136, 137 or 138
  337 (on a scale of 0-255). It's currently your job to know which color is the
  338 'transparent' or background one.""")
  339 
  340 disc("""PDF allows for many image features and we will expose more of the over
  341 time, probably with extra keyword arguments to $drawImage$.""")
  342 
  343 heading3("Ending a page")
  344 
  345 eg("""canvas.showPage()""")
  346 
  347 disc("""The $showPage$ method finishes the current page.  All additional drawing will
  348 be done on another page.""")
  349 
  350 pencilnote()
  351 
  352 disc("""Warning!  All state changes (font changes, color settings, geometry transforms, etcetera)
  353 are FORGOTTEN when you advance to a new page in $pdfgen$.  Any state settings you wish to preserve
  354 must be set up again before the program proceeds with drawing!""")
  355 
  356 heading2('The toolbox: the "state change" operations')
  357 
  358 disc("""
  359 This section briefly lists the ways to switch the tools used by the
  360 program
  361 for painting information onto a page using the $canvas$ interface.
  362 These too will be discussed in detail in later sections.
  363 """)
  364 
  365 heading3("Changing Colors")
  366 eg("""canvas.setFillColorCMYK(c, m, y, k) """)
  367 eg("""canvas.setStrikeColorCMYK(c, m, y, k) """)
  368 eg("""canvas.setFillColorRGB(r, g, b) """)
  369 eg("""canvas.setStrokeColorRGB(r, g, b) """)
  370 eg("""canvas.setFillColor(acolor) """)
  371 eg("""canvas.setStrokeColor(acolor) """)
  372 eg("""canvas.setFillGray(gray) """)
  373 eg("""canvas.setStrokeGray(gray) """)
  374 
  375 disc("""
  376 PDF supports three different color models: gray level, additive (red/green/blue or RGB), and
  377 subtractive with darkness parameter (cyan/magenta/yellow/darkness or CMYK).
  378 The ReportLab packages also provide named colors such as $lawngreen$.  There are two
  379 basic color parameters in the graphics state: the $Fill$ color for the interior of graphic
  380 figures and the $Stroke$ color for the boundary of graphic figures.  The above methods
  381 support setting the fill or stroke color using any of the four color specifications.
  382 """)
  383 
  384 heading3("Changing Fonts")
  385 eg("""canvas.setFont(psfontname, size, leading = None) """)
  386 
  387 disc("""
  388 The $setFont$ method changes the current text font to a given type and size.
  389 The $leading$ parameter specifies the distance down to move when advancing from
  390 one text line to the next.
  391 """)
  392 
  393 heading3("Changing Graphical Line Styles")
  394 
  395 eg("""canvas.setLineWidth(width) """)
  396 eg("""canvas.setLineCap(mode) """)
  397 eg("""canvas.setLineJoin(mode) """)
  398 eg("""canvas.setMiterLimit(limit) """)
  399 eg("""canvas.setDash(self, array=[], phase=0) """)
  400 
  401 disc("""
  402 Lines drawn in PDF can be presented in a number of graphical styles.
  403 Lines can have different widths, they can end in differing cap styles,
  404 they can meet in different join styles, and they can be continuous or
  405 they can be dotted or dashed.  The above methods adjust these various parameters.""")
  406 
  407 heading3("Changing Geometry")
  408 
  409 eg("""canvas.setPageSize(pair) """)
  410 eg("""canvas.transform(a,b,c,d,e,f): """)
  411 eg("""canvas.translate(dx, dy) """)
  412 eg("""canvas.scale(x, y) """)
  413 eg("""canvas.rotate(theta) """)
  414 eg("""canvas.skew(alpha, beta) """)
  415 
  416 disc("""
  417 All PDF drawings fit into a specified page size.  Elements drawn outside of the specified
  418 page size are not visible.  Furthermore all drawn elements are passed through an affine
  419 transformation which may adjust their location and/or distort their appearence.  The
  420 $setPageSize$ method adjusts the current page size.  The $transform$, $translate$, $scale$,
  421 $rotate$, and $skew$ methods add additional transformations to the current transformation.
  422 It is important to remember that these transformations are <i>incremental</i> -- a new
  423 transform modifies the current transform (but does not replace it).
  424 """)
  425 
  426 heading3("State control")
  427 
  428 eg("""canvas.saveState() """)
  429 eg("""canvas.restoreState() """)
  430 
  431 disc("""
  432 Very often it is important to save the current font, graphics transform, line styles and
  433 other graphics state in order to restore them later. The $saveState$ method marks the
  434 current graphics state for later restoration by a matching $restoreState$.  Note that
  435 the save and restore method invokation must match -- a restore call restores the state to
  436 the most recently saved state which hasn't been restored yet.
  437 You cannot save the state on one page and restore
  438 it on the next, however -- no state is preserved between pages.""")
  439 
  440 heading2("Other $canvas$ methods.")
  441 
  442 disc("""
  443 Not all methods of the $canvas$ object fit into the "tool" or "toolbox"
  444 categories.  Below are some of the misfits, included here for completeness.
  445 """)
  446 
  447 eg("""
  448  canvas.setAuthor()
  449  canvas.addOutlineEntry(title, key, level=0, closed=None)
  450  canvas.setTitle(title)
  451  canvas.setSubject(subj)
  452  canvas.pageHasData()
  453  canvas.showOutline()
  454  canvas.bookmarkPage(name)
  455  canvas.bookmarkHorizontalAbsolute(name, yhorizontal)
  456  canvas.doForm()
  457  canvas.beginForm(name, lowerx=0, lowery=0, upperx=None, uppery=None)
  458  canvas.endForm()
  459  canvas.linkAbsolute(contents, destinationname, Rect=None, addtopage=1, name=None, **kw)
  460  canvas.linkRect(contents, destinationname, Rect=None, addtopage=1, relative=1, name=None, **kw)
  461  canvas.getPageNumber()
  462  canvas.addLiteral()
  463  canvas.getAvailableFonts()
  464  canvas.stringWidth(self, text, fontName, fontSize, encoding=None)
  465  canvas.setPageCompression(onoff=1)
  466  canvas.setPageTransition(self, effectname=None, duration=1,
  467                         direction=0,dimension='H',motion='I')
  468 """)
  469 
  470 
  471 heading2('Coordinates (default user space)')
  472 
  473 disc("""
  474 By default locations on a page are identified by a pair of numbers.
  475 For example the pair $(4.5*inch, 1*inch)$ identifies the location
  476 found on the page by starting at the lower left corner and moving to
  477 the right 4.5 inches and up one inch.
  478 """)
  479 
  480 disc("""For example, the following function draws
  481 a number of elements on a $canvas$.""")
  482 
  483 eg(examples.testcoords)
  484 
  485 disc("""In the default user space the "origin" ^(0,0)^ point is at the lower
  486 left corner.  Executing the $coords$ function in the default user space
  487 (for the "demo minipage") we obtain the following.""")
  488 
  489 illust(examples.coords, 'The Coordinate System')
  490 
  491 heading3("Moving the origin: the $translate$ method")
  492 
  493 disc("""Often it is useful to "move the origin" to a new point off
  494 the lower left corner.  The $canvas.translate(^x,y^)$ method moves the origin
  495 for the current page to the point currently identified by ^(x,y)^.""")
  496 
  497 disc("""For example the following translate function first moves
  498 the origin before drawing the same objects as shown above.""")
  499 
  500 eg(examples.testtranslate)
  501 
  502 disc("""This produces the following.""")
  503 
  504 illust(examples.translate, "Moving the origin: the $translate$ method")
  505 
  506 
  507 #illust(NOP) # execute some code
  508 
  509 pencilnote()
  510 
  511 
  512 disc("""
  513 <i>Note:</i> As illustrated in the example it is perfectly possible to draw objects
  514 or parts of objects "off the page".
  515 In particular a common confusing bug is a translation operation that translates the
  516 entire drawing off the visible area of the page.  If a program produces a blank page
  517 it is possible that all the drawn objects are off the page.
  518 """)
  519 
  520 heading3("Shrinking and growing: the scale operation")
  521 
  522 disc("""Another important operation is scaling.  The scaling operation $canvas.scale(^dx,dy^)$
  523 stretches or shrinks the ^x^ and ^y^ dimensions by the ^dx^, ^dy^ factors respectively.  Often
  524 ^dx^ and ^dy^ are the same -- for example to reduce a drawing by half in all dimensions use
  525 $dx = dy = 0.5$.  However for the purposes of illustration we show an example where
  526 $dx$ and $dy$ are different.
  527 """)
  528 
  529 eg(examples.testscale)
  530 
  531 disc("""This produces a "short and fat" reduced version of the previously displayed operations.""")
  532 
  533 illust(examples.scale, "Scaling the coordinate system")
  534 
  535 
  536 #illust(NOP) # execute some code
  537 
  538 pencilnote()
  539 
  540 
  541 disc("""<i>Note:</i> scaling may also move objects or parts of objects off the page,
  542 or may cause objects to "shrink to nothing." """)
  543 
  544 disc("""Scaling and translation can be combined, but the order of the
  545 operations are important.""")
  546 
  547 eg(examples.testscaletranslate)
  548 
  549 disc("""This example function first saves the current $canvas$ state
  550 and then does a $scale$ followed by a $translate$.  Afterward the function
  551 restores the state (effectively removing the effects of the scaling and
  552 translation) and then does the <i>same</i> operations in a different order.
  553 Observe the effect below.""")
  554 
  555 illust(examples.scaletranslate, "Scaling and Translating")
  556 
  557 
  558 #illust(NOP) # execute some code
  559 
  560 pencilnote()
  561 
  562 
  563 disc("""<em>Note:</em> scaling shrinks or grows everything including line widths
  564 so using the canvas.scale method to render a microscopic drawing in
  565 scaled microscopic units
  566 may produce a blob (because all line widths will get expanded a huge amount).
  567 Also rendering an aircraft wing in meters scaled to centimeters may cause the lines
  568 to shrink to the point where they disappear.  For engineering or scientific purposes
  569 such as these scale and translate
  570 the units externally before rendering them using the canvas.""")
  571 
  572 heading3("Saving and restoring the $canvas$ state: $saveState$ and $restoreState$")
  573 
  574 disc("""
  575 The $scaletranslate$ function used an important feature of the $canvas$ object:
  576 the ability to save and restore the current parameters of the $canvas$.
  577 By enclosing a sequence of operations in a matching pair of $canvas.saveState()$
  578 an $canvas.restoreState()$ operations all changes of font, color, line style,
  579 scaling, translation, or other aspects of the $canvas$ graphics state can be
  580 restored to the state at the point of the $saveState()$.  Remember that the save/restore
  581 calls must match: a stray save or restore operation may cause unexpected
  582 and undesirable behavior.  Also, remember that <i>no</i> $canvas$ state is
  583 preserved across page breaks, and the save/restore mechanism does not work
  584 across page breaks.
  585 """)
  586 
  587 heading3("Mirror image")
  588 
  589 disc("""
  590 It is interesting although perhaps not terribly useful to note that
  591 scale factors can be negative.  For example the following function
  592 """)
  593 
  594 eg(examples.testmirror)
  595 
  596 disc("""
  597 creates a mirror image of the elements drawn by the $coord$ function.
  598 """)
  599 
  600 illust(examples.mirror, "Mirror Images")
  601 
  602 disc("""
  603 Notice that the text strings are painted backwards.
  604 """)
  605 
  606 heading2("Colors")
  607 disc("""
  608 There are generally two types of colors used in PDF depending on the media where
  609 the PDF will be used. The most commonly known screen colors model RGB can be used
  610 in PDF, however in professional printing another color model CMYK is mainly used 
  611 which gives more control over how inks are applied to paper. More on these color
  612 models below.
  613 """)
  614 
  615 heading3("RGB Colors")
  616 disc("""
  617 The $RGB$ or additive color representation follows the way a computer
  618 screen adds different levels of the red, green, and blue light to make
  619 any color in between, where white is formed by turning all three lights on full
  620 ($1,1,1$).
  621 """)
  622 
  623 disc("""
  624 There are three ways to specify RGB colors in $pdfgen$: by name (using the $color$
  625 module, by red/green/blue (additive, $RGB$) value, or by gray level.
  626 The $colors$ function below exercises each of the four methods.
  627 """)
  628 
  629 eg(examples.testRGBcolors)
  630 illust(examples.colorsRGB, "RGB Color Models")
  631 
  632 heading4("RGB Color Transparency")
  633 
  634 disc("""
  635 Objects may be painted over other objects to good effect in $pdfgen$.  Generally
  636 There are two modes of handling objects that overlap in space, the default objects 
  637 in the top layer will hide any part of other objects that falls underneath it. If you
  638 need transparency you got two choices:
  639 """)
  640 
  641 disc("""
  642 1. If your document is intended to be printed in a professional way and you are 
  643 working in CMYK color space then you can use overPrint. In overPrinting the colors
  644 physically mix in the printer and thus a new color is obtained. By default a 
  645 knockout will be applied and only top object appears. Read the CMYK section
  646 if this is what you intend to use.
  647 """)
  648 
  649 disc("""
  650 2. If your document is intended for screen output and you are using RGB colors 
  651 then you can set an alpha value, where alpha is the opacity value of the color.
  652 The default alpha value is $1$ (fully opaque) and you can use any real number
  653 value in the range 0-1.
  654 """)
  655 
  656 disc("""
  657 Alpha transparency ($alpha$) is similar to overprint but works in RGB color space
  658 this example below demonstrates the alpha funtionality. Refer to our website
  659 http://www.reportlab.com/snippets/ and look for snippets of overPrint and alpha
  660 to see the code that generates the graph below.
  661 """)
  662 
  663 eg(examples.testalpha)
  664 illust(examples.alpha, "Alpha example")
  665 
  666 heading3("CMYK Colors")
  667 disc("""
  668 The $CMYK$ or subtractive method follows the way a printer
  669 mixes three pigments (cyan, magenta, and yellow) to form colors.
  670 Because mixing chemicals is more difficult than combining light there
  671 is a fourth parameter for darkness.  For example a chemical
  672 combination of the $CMY$ pigments generally never makes a perfect
  673 black -- instead producing a muddy color -- so, to get black printers
  674 don not use the $CMY$ pigments but use a direct black ink.  Because
  675 $CMYK$ maps more directly to the way printer hardware works it may
  676 be the case that colors specified in $CMYK$ will provide better fidelity
  677 and better control when printed.
  678 """)
  679 
  680 disc("""
  681 There are two ways of representing CMYK Color: each color can be represented either
  682 by a real value between 0 and 1, or integer value between 0 and 100. Depending
  683 on your preference you can either use CMYKColor (for real values) or PCMYKColor ( for 
  684 integer values). 0 means 'no ink', so printing on white papers gives you white. 1 (or 100
  685 if you use PCMYKColor) means 'the maximum amount of ink'. e.g. CMYKColor(0,0,0,1) is black,
  686 CMYKColor(0,0,0,0) means 'no ink', and CMYKColor(0.5,0,0,0) means 50 percent cyan color.
  687 """)
  688 eg(examples.testCMYKcolors)
  689 illust(examples.colorsCMYK, "CMYK Color Models")
  690 
  691 heading2("Color space checking")
  692 disc("""The $enforceColorSpace$ argument of the canvas is used to enforce the consistency
  693 of the colour model used in a document. It accepts these values: CMYK, RGB, SEP, SEP_BLACK,
  694 SEP_CMYK. 'SEP' refers to named color separations such as Pantone spot colors - these can
  695 be mixed with CMYK or RGB according to the parameter used.  The default is 'MIXED' which
  696 allows you to use colors from any color space.  An exception is raised if any colors used
  697 are not convertible to the specified model, e.g. rgb and cmyk (more information in
  698 test_pdfgen_general). This approach doesn't check external images included in document.
  699 """)
  700 
  701 heading2("Color Overprinting")
  702 
  703 disc("""
  704 When two CMYK colored objects overlap in printing, then either the object 'on top'
  705 will knock out the color of the the one underneath it, or the colors of the two
  706 objects will mix in the overlapped area.
  707 This behaviour can be set using the property $overPrint$.
  708 """)
  709 
  710 disc("""
  711 The $overPrint$ function will cause ovelapping areas of color to mix. In the example
  712 below, the colors of the rectangles on the left should appear mixed where they overlap
  713 - If you can't see this effect then you may need to enable the 'overprint preview'
  714 option in your PDF viewing software.  Some PDF viewers such as $evince$ do not
  715 support overPrint; however Adobe Acrobat Reader does support it.
  716 """)
  717 illust(examples.overPrint, "overPrint example")
  718 
  719 heading3("Other Object Order of Printing Examples")
  720 
  721 disc("""
  722 The word "SPUMONI" is painted in white over the colored rectangles,
  723 with the apparent effect of "removing" the color inside the body of
  724 the word.
  725 """)
  726 
  727 eg(examples.testspumoni)
  728 illust(examples.spumoni, "Painting over colors")
  729 
  730 disc("""
  731 The last letters of the word are not visible because the default $canvas$
  732 background is white and painting white letters over a white background
  733 leaves no visible effect.
  734 """)
  735 
  736 disc("""
  737 This method of building up complex paintings in layers can be done
  738 in very many layers in $pdfgen$ -- there are fewer physical limitations
  739 than there are when dealing with physical paints.
  740 """)
  741 
  742 eg(examples.testspumoni2)
  743 
  744 disc("""
  745 The $spumoni2$ function layers an ice cream cone over the
  746 $spumoni$ drawing.  Note that different parts of the cone
  747 and scoops layer over eachother as well.
  748 """)
  749 illust(examples.spumoni2, "building up a drawing in layers")
  750 
  751 heading2('Standard fonts and text objects')
  752 
  753 disc("""
  754 Text may be drawn in many different colors, fonts, and sizes in $pdfgen$.
  755 The $textsize$ function demonstrates how to change the color and font and
  756 size of text and how to place text on the page.
  757 """)
  758 
  759 eg(examples.testtextsize)
  760 
  761 disc("""
  762 The $textsize$ function generates the following page.
  763 """)
  764 
  765 illust(examples.textsize, "text in different fonts and sizes")
  766 
  767 disc("""
  768 A number of different fonts are always available in $pdfgen$.
  769 """)
  770 
  771 eg(examples.testfonts)
  772 
  773 disc("""
  774 The $fonts$ function lists the fonts that are always available.
  775 These don't need to be stored in a PDF document, since they
  776 are guaranteed to be present in Acrobat Reader.
  777 """)
  778 
  779 illust(examples.fonts, "the 14 standard fonts")
  780 
  781 disc("""The Symbol and ZapfDingbats fonts cannot display properly because the required glyphs are not present in those fonts.""")
  782 
  783 disc("""
  784 For information on how to use arbitrary fonts, see the next chapter.
  785 """)
  786 
  787 
  788 heading2("Text object methods")
  789 
  790 disc("""
  791 For the dedicated presentation of text in a PDF document, use a text object.
  792 The text object interface provides detailed control of text layout parameters
  793 not available directly at the $canvas$ level.  In addition, it results in smaller
  794 PDF that will render faster than many separate calls to the $drawString$ methods.
  795 """)
  796 
  797 eg("""textobject.setTextOrigin(x,y)""")
  798 eg("""textobject.setTextTransform(a,b,c,d,e,f)""")
  799 eg("""textobject.moveCursor(dx, dy) # from start of current LINE""")
  800 eg("""(x,y) = textobject.getCursor()""")
  801 eg("""x = textobject.getX(); y = textobject.getY()""")
  802 eg("""textobject.setFont(psfontname, size, leading = None)""")
  803 eg("""textobject.textOut(text)""")
  804 eg("""textobject.textLine(text='')""")
  805 eg("""textobject.textLines(stuff, trim=1)""")
  806 
  807 disc("""
  808 The text object methods shown above relate to basic text geometry.
  809 """)
  810 
  811 disc("""
  812 A text object maintains a text cursor which moves about the page when
  813 text is drawn.  For example the $setTextOrigin$ places the cursor
  814 in a known position and the $textLine$ and $textLines$ methods move
  815 the text cursor down past the lines that have been missing.
  816 """)
  817 
  818 eg(examples.testcursormoves1)
  819 
  820 disc("""
  821 The $cursormoves$ function relies on the automatic
  822 movement of the text cursor for placing text after the origin
  823 has been set.
  824 """)
  825 
  826 illust(examples.cursormoves1, "How the text cursor moves")
  827 
  828 disc("""
  829 It is also possible to control the movement of the cursor
  830 more explicitly by using the $moveCursor$ method (which moves
  831 the cursor as an offset from the start of the current <i>line</i>
  832 NOT the current cursor, and which also has positive ^y^ offsets
  833 move <i>down</i> (in contrast to the normal geometry where
  834 positive ^y^ usually moves up.
  835 """)
  836 
  837 eg(examples.testcursormoves2)
  838 
  839 disc("""
  840 Here the $textOut$ does not move the down a line in contrast
  841 to the $textLine$ function which does move down.
  842 """)
  843 
  844 illust(examples.cursormoves2, "How the text cursor moves again")
  845 
  846 heading3("Character Spacing")
  847 
  848 eg("""textobject.setCharSpace(charSpace)""")
  849 
  850 disc("""The $setCharSpace$ method adjusts one of the parameters of text -- the inter-character
  851 spacing.""")
  852 
  853 eg(examples.testcharspace)
  854 
  855 disc("""The
  856 $charspace$ function exercises various spacing settings.
  857 It produces the following page.""")
  858 
  859 illust(examples.charspace, "Adjusting inter-character spacing")
  860 
  861 heading3("Word Spacing")
  862 
  863 eg("""textobject.setWordSpace(wordSpace)""")
  864 
  865 disc("The $setWordSpace$ method adjusts the space between words.")
  866 
  867 eg(examples.testwordspace)
  868 
  869 disc("""The $wordspace$ function shows what various word space settings
  870 look like below.""")
  871 
  872 illust(examples.wordspace, "Adjusting word spacing")
  873 
  874 heading3("Horizontal Scaling")
  875 
  876 eg("""textobject.setHorizScale(horizScale)""")
  877 
  878 disc("""Lines of text can be stretched or shrunken horizontally by the
  879 $setHorizScale$ method.""")
  880 
  881 eg(examples.testhorizontalscale)
  882 
  883 disc("""The horizontal scaling parameter ^horizScale^
  884 is given in percentages (with 100 as the default), so the 80 setting
  885 shown below looks skinny.
  886 """)
  887 illust(examples.horizontalscale, "adjusting horizontal text scaling")
  888 
  889 heading3("Interline spacing (Leading)")
  890 
  891 eg("""textobject.setLeading(leading)""")
  892 
  893 disc("""The vertical offset between the point at which one
  894 line starts and where the next starts is called the leading
  895 offset.  The $setLeading$ method adjusts the leading offset.
  896 """)
  897 
  898 eg(examples.testleading)
  899 
  900 disc("""As shown below if the leading offset is set too small
  901 characters of one line my write over the bottom parts of characters
  902 in the previous line.""")
  903 
  904 illust(examples.leading, "adjusting the leading")
  905 
  906 heading3("Other text object methods")
  907 
  908 eg("""textobject.setTextRenderMode(mode)""")
  909 
  910 disc("""The $setTextRenderMode$ method allows text to be used
  911 as a forground for clipping background drawings, for example.""")
  912 
  913 eg("""textobject.setRise(rise)""")
  914 
  915 disc("""
  916 The $setRise$ method <super>raises</super> or <sub>lowers</sub> text on the line
  917 (for creating superscripts or subscripts, for example).
  918 """)
  919 
  920 eg("""textobject.setFillColor(aColor);
  921 textobject.setStrokeColor(self, aColor)
  922 # and similar""")
  923 
  924 disc("""
  925 These color change operations change the <font color=darkviolet>color</font> of the text and are otherwise
  926 similar to the color methods for the $canvas$ object.""")
  927 
  928 heading2('Paths and Lines')
  929 
  930 disc("""Just as textobjects are designed for the dedicated presentation
  931 of text, path objects are designed for the dedicated construction of
  932 graphical figures.  When path objects are drawn onto a $canvas$ they
  933 are drawn as one figure (like a rectangle) and the mode of drawing
  934 for the entire figure can be adjusted: the lines of the figure can
  935 be drawn (stroked) or not; the interior of the figure can be filled or
  936 not; and so forth.""")
  937 
  938 disc("""
  939 For example the $star$ function uses a path object
  940 to draw a star
  941 """)
  942 
  943 eg(examples.teststar)
  944 
  945 disc("""
  946 The $star$ function has been designed to be useful in illustrating
  947 various line style parameters supported by $pdfgen$.
  948 """)
  949 
  950 illust(examples.star, "line style parameters")
  951 
  952 heading3("Line join settings")
  953 
  954 disc("""
  955 The $setLineJoin$ method can adjust whether line segments meet in a point
  956 a square or a rounded vertex.
  957 """)
  958 
  959 eg(examples.testjoins)
  960 
  961 disc("""
  962 The line join setting is only really of interest for thick lines because
  963 it cannot be seen clearly for thin lines.
  964 """)
  965 
  966 illust(examples.joins, "different line join styles")
  967 
  968 heading3("Line cap settings")
  969 
  970 disc("""The line cap setting, adjusted using the $setLineCap$ method,
  971 determines whether a terminating line
  972 ends in a square exactly at the vertex, a square over the vertex
  973 or a half circle over the vertex.
  974 """)
  975 
  976 eg(examples.testcaps)
  977 
  978 disc("""The line cap setting, like the line join setting, is only clearly
  979 visible when the lines are thick.""")
  980 
  981 illust(examples.caps, "line cap settings")
  982 
  983 heading3("Dashes and broken lines")
  984 
  985 disc("""
  986 The $setDash$ method allows lines to be broken into dots or dashes.
  987 """)
  988 
  989 eg(examples.testdashes)
  990 
  991 disc("""
  992 The patterns for the dashes or dots can be in a simple on/off repeating pattern
  993 or they can be specified in a complex repeating pattern.
  994 """)
  995 
  996 illust(examples.dashes, "some dash patterns")
  997 
  998 heading3("Creating complex figures with path objects")
  999 
 1000 disc("""
 1001 Combinations of lines, curves, arcs and other figures
 1002 can be combined into a single figure using path objects.
 1003 For example the function shown below constructs two path
 1004 objects using lines and curves.
 1005 This function will be used later on as part of a
 1006 pencil icon construction.
 1007 """)
 1008 
 1009 eg(examples.testpenciltip)
 1010 
 1011 disc("""
 1012 Note that the interior of the pencil tip is filled
 1013 as one object even though it is constructed from
 1014 several lines and curves.  The pencil lead is then
 1015 drawn over it using a new path object.
 1016 """)
 1017 
 1018 illust(examples.penciltip, "a pencil tip")
 1019 
 1020 heading2('Rectangles, circles, ellipses')
 1021 
 1022 disc("""
 1023 The $pdfgen$ module supports a number of generally useful shapes
 1024 such as rectangles, rounded rectangles, ellipses, and circles.
 1025 Each of these figures can be used in path objects or can be drawn
 1026 directly on a $canvas$.  For example the $pencil$ function below
 1027 draws a pencil icon using rectangles and rounded rectangles with
 1028 various fill colors and a few other annotations.
 1029 """)
 1030 
 1031 eg(examples.testpencil)
 1032 
 1033 pencilnote()
 1034 
 1035 disc("""
 1036 Note that this function is used to create the "margin pencil" to the left.
 1037 Also note that the order in which the elements are drawn are important
 1038 because, for example, the white rectangles "erase" parts of a black rectangle
 1039 and the "tip" paints over part of the yellow rectangle.
 1040 """)
 1041 
 1042 illust(examples.pencil, "a whole pencil")
 1043 
 1044 heading2('Bezier curves')
 1045 
 1046 disc("""
 1047 Programs that wish to construct figures with curving borders
 1048 generally use Bezier curves to form the borders.
 1049 """)
 1050 
 1051 eg(examples.testbezier)
 1052 
 1053 disc("""
 1054 A Bezier curve is specified by four control points
 1055 $(x1,y1)$, $(x2,y2)$, $(x3,y3)$, $(x4,y4)$.
 1056 The curve starts at $(x1,y1)$ and ends at $(x4,y4)$
 1057 and the line segment from $(x1,y1)$ to $(x2,y2)$
 1058 and the line segment from $(x3,y3)$ to $(x4,y4)$
 1059 both form tangents to the curve.  Furthermore the
 1060 curve is entirely contained in the convex figure with vertices
 1061 at the control points.
 1062 """)
 1063 
 1064 illust(examples.bezier, "basic bezier curves")
 1065 
 1066 disc("""
 1067 The drawing above (the output of $testbezier$) shows
 1068 a bezier curves, the tangent lines defined by the control points
 1069 and the convex figure with vertices at the control points.
 1070 """)
 1071 
 1072 heading3("Smoothly joining bezier curve sequences")
 1073 
 1074 disc("""
 1075 It is often useful to join several bezier curves to form a
 1076 single smooth curve.  To construct a larger smooth curve from
 1077 several bezier curves make sure that the tangent lines to adjacent
 1078 bezier curves that join at a control point lie on the same line.
 1079 """)
 1080 
 1081 eg(examples.testbezier2)
 1082 
 1083 disc("""
 1084 The figure created by $testbezier2$ describes a smooth
 1085 complex curve because adjacent tangent lines "line up" as
 1086 illustrated below.
 1087 """)
 1088 
 1089 illust(examples.bezier2, "bezier curves")
 1090 
 1091 heading2("Path object methods")
 1092 
 1093 disc("""
 1094 Path objects build complex graphical figures by setting
 1095 the "pen" or "brush" at a start point on the canvas and drawing
 1096 lines or curves to additional points on the canvas.  Most operations
 1097 apply paint on the canvas starting at the end point of the last
 1098 operation and leave the brush at a new end point.
 1099 """)
 1100 
 1101 eg("""pathobject.moveTo(x,y)""")
 1102 
 1103 disc("""
 1104 The $moveTo$ method lifts the brush (ending any current sequence
 1105 of lines or curves if there is one) and replaces the brush at the
 1106 new ^(x,y)^ location on the canvas to start a new path sequence.
 1107 """)
 1108 
 1109 eg("""pathobject.lineTo(x,y)""")
 1110 
 1111 disc("""
 1112 The $lineTo$ method paints straight line segment from the current brush
 1113 location to the new ^(x,y)^ location.
 1114 """)
 1115 
 1116 eg("""pathobject.curveTo(x1, y1, x2, y2, x3, y3) """)
 1117 
 1118 disc("""
 1119 The $curveTo$ method starts painting a Bezier curve beginning at
 1120 the current brush location, using ^(x1,y1)^, ^(x2,y2)^, and ^(x3,y3)^
 1121 as the other three control points, leaving the brush on ^(x3,y3)^.
 1122 """)
 1123 
 1124 eg("""pathobject.arc(x1,y1, x2,y2, startAng=0, extent=90) """)
 1125 
 1126 eg("""pathobject.arcTo(x1,y1, x2,y2, startAng=0, extent=90) """)
 1127 
 1128 disc("""
 1129 The $arc$ and $arcTo$ methods paint partial ellipses.  The $arc$ method first "lifts the brush"
 1130 and starts a new shape sequence.  The $arcTo$ method joins the start of
 1131 the partial ellipse to the current
 1132 shape sequence by line segment before drawing the partial ellipse.  The points
 1133 ^(x1,y1)^ and ^(x2,y2)^ define opposite corner points of a rectangle enclosing
 1134 the ellipse.  The $startAng$ is an angle (in degrees) specifying where to begin
 1135 the partial ellipse where the 0 angle is the midpoint of the right border of the enclosing
 1136 rectangle (when ^(x1,y1)^ is the lower left corner and ^(x2,y2)^ is the upper
 1137 right corner).  The $extent$ is the angle in degrees to traverse on the ellipse.
 1138 """)
 1139 
 1140 eg(examples.testarcs)
 1141 
 1142 disc("""The $arcs$ function above exercises the two partial ellipse methods.
 1143 It produces the following drawing.""")
 1144 
 1145 illust(examples.arcs, "arcs in path objects")
 1146 
 1147 eg("""pathobject.rect(x, y, width, height) """)
 1148 
 1149 disc("""The $rect$ method draws a rectangle with lower left corner
 1150 at ^(x,y)^ of the specified ^width^ and ^height^.""")
 1151 
 1152 eg("""pathobject.ellipse(x, y, width, height)""")
 1153 
 1154 disc("""The $ellipse$ method
 1155 draws an ellipse enclosed in the rectange with lower left corner
 1156 at ^(x,y)^ of the specified ^width^ and ^height^.
 1157 """)
 1158 
 1159 eg("""pathobject.circle(x_cen, y_cen, r) """)
 1160 
 1161 disc("""The $circle$ method
 1162 draws a circle centered at ^(x_cen, y_cen)^ with radius ^r^.
 1163 """)
 1164 
 1165 eg(examples.testvariousshapes)
 1166 
 1167 disc("""
 1168 The $variousshapes$ function above shows a rectangle, circle and ellipse
 1169 placed in a frame of reference grid.
 1170 """)
 1171 
 1172 illust(examples.variousshapes, "rectangles, circles, ellipses in path objects")
 1173 
 1174 eg("""pathobject.close() """)
 1175 
 1176 disc("""
 1177 The $close$ method closes the current graphical figure
 1178 by painting a line segment from the last point of the figure
 1179 to the starting point of the figure (the the most
 1180 recent point where the brush was placed on the paper by $moveTo$
 1181 or $arc$ or other placement operations).
 1182 """)
 1183 
 1184 eg(examples.testclosingfigures)
 1185 
 1186 disc("""
 1187 The $closingfigures$ function illustrates the
 1188 effect of closing or not closing figures including a line
 1189 segment and a partial ellipse.
 1190 """)
 1191 
 1192 illust(examples.closingfigures, "closing and not closing pathobject figures")
 1193 
 1194 disc("""
 1195 Closing or not closing graphical figures effects only the stroked outline
 1196 of a figure, not the filling of the figure as illustrated above.
 1197 """)
 1198 
 1199 
 1200 disc("""
 1201 For a more extensive example of drawing using a path object
 1202 examine the $hand$ function.
 1203 """)
 1204 
 1205 eg(examples.testhand)
 1206 
 1207 disc("""
 1208 In debug mode (the default) the $hand$ function shows the tangent line segments
 1209 to the bezier curves used to compose the figure.  Note that where the segments
 1210 line up the curves join smoothly, but where they do not line up the curves show
 1211 a "sharp edge".
 1212 """)
 1213 
 1214 illust(examples.hand, "an outline of a hand using bezier curves")
 1215 
 1216 disc("""
 1217 Used in non-debug mode the $hand$ function only shows the
 1218 Bezier curves.  With the $fill$ parameter set the figure is
 1219 filled using the current fill color.
 1220 """)
 1221 
 1222 eg(examples.testhand2)
 1223 
 1224 disc("""
 1225 Note that the "stroking" of the border draws over the interior fill where
 1226 they overlap.
 1227 """)
 1228 
 1229 illust(examples.hand2, "the finished hand, filled")
 1230 
 1231 
 1232 
 1233 heading2("Further Reading: The ReportLab Graphics Library")
 1234 
 1235 disc("""
 1236 So far the graphics we have seen were created on a fairly low level.
 1237 It should be noted, though, that there is another way of creating
 1238 much more sophisticated graphics using the dedicated
 1239 high-level <i>ReportLab Graphics Library</i>.
 1240 """)
 1241 
 1242 disc("""
 1243 It can be used to produce high-quality, platform-independant,
 1244 reusable graphics for different output formats (vector and bitmap)
 1245 like PDF, EPS, SVG, JPG and PNG.
 1246 """)
 1247 
 1248 disc("""
 1249 A more thorough description of its philsophy and features is
 1250 now covered in Chapter 11 of this document, <i>Graphics</i>, which 
 1251 contains information about the existing components and
 1252 how to create customized ones.
 1253 """)
 1254 
 1255 disc("""
 1256 Chapter 11 also contains details of the ReportLab 
 1257 charting package and its components (labels, axes, legends and
 1258 different types of charts like bar, line and pie charts) that
 1259 builds directly on the graphics library.
 1260 """)
 1261 
 1262 
 1263 ##### FILL THEM IN