diff options
| author | pinky <> | 2007-01-07 21:41:39 +0000 |
|---|---|---|
| committer | pinky <> | 2007-01-07 21:41:39 +0000 |
| commit | 05bb5d58295cd959c34f1fbcd5b605cd6dafaacc (patch) | |
| tree | 3b3651037037c1617a54ef3d216e8c11ea8cdddf /bin/reportlab/docs/graphguide/ch2_concepts.py | |
| parent | 62524af2f41454a2302efb21f15a95318d257a76 (diff) | |
Repotrlab 2.0
bzr revid: pinky-b8333ccaab5dad8ff965b6c380fadadf30d5212a
Diffstat (limited to 'bin/reportlab/docs/graphguide/ch2_concepts.py')
| -rw-r--r-- | bin/reportlab/docs/graphguide/ch2_concepts.py | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/bin/reportlab/docs/graphguide/ch2_concepts.py b/bin/reportlab/docs/graphguide/ch2_concepts.py new file mode 100644 index 00000000000..28dab45fece --- /dev/null +++ b/bin/reportlab/docs/graphguide/ch2_concepts.py @@ -0,0 +1,376 @@ +#Copyright ReportLab Europe Ltd. 2000-2004 +#see license.txt for license details +#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/docs/graphguide/ch2_concepts.py +from reportlab.tools.docco.rl_doc_utils import * + +heading1("General Concepts") + +disc(""" +In this chapter we will present some of the more fundamental principles of +the graphics library, which will show-up later in various places. +""") + + +heading2("Drawings and Renderers") + +disc(""" +A <i>Drawing</i> is a platform-independent description of a collection of +shapes. +It is not directly associated with PDF, Postscript or any other output +format. +Fortunately, most vector graphics systems have followed the Postscript +model and it is possible to describe shapes unambiguously. +""") + +disc(""" +A drawing contains a number of primitive <i>Shapes</i>. +Normal shapes are those widely known as rectangles, circles, lines, +etc. +One special (logic) shape is a <i>Group</i>, which can hold other +shapes and apply a transformation to them. +Groups represent composites of shapes and allow to treat the +composite as if it were a single shape. +Just about anything can be built up from a small number of basic +shapes. +""") + +disc(""" +The package provides several <i>Renderers</i> which know how to draw a +drawing into different formats. +These include PDF (of course), Postscript, and bitmap output. +The bitmap renderer uses Raph Levien's <i>libart</i> rasterizer +and Fredrik Lundh's <i>Python Imaging Library</i> (PIL). +Very recently, an experimental SVG renderer was also added. +It makes use of Python's standard library XML modules, so you don't +need to install the XML-SIG's additional package named PyXML. +If you have the right extensions installed, you can generate drawings +in bitmap form for the web as well as vector form for PDF documents, +and get "identical output". +""") + +disc(""" +The PDF renderer has special "privileges" - a Drawing object is also +a <i>Flowable</i> and, hence, can be placed directly in the story +of any Platypus document, or drawn directly on a <i>Canvas</i> with +one line of code. +In addition, the PDF renderer has a utility function to make +a one-page PDF document quickly. +""") + +disc(""" +The SVG renderer is special as it is still pretty experimental. +The SVG code it generates is not really optimised in any way and +maps only the features available in ReportLab Graphics (RLG) to +SVG. This means there is no support for SVG animation, interactivity, +scripting or more sophisticated clipping, masking or graduation +shapes. +So, be careful, and please report any bugs you find! +""") + +disc(""" +We expect to add both input and output filters for many vector +graphics formats in future. +SVG was the most prominent first one to start with for which there +is now an output filter in the graphics package. +An SVG input filter will probably become available in Summer 2002 +as an additional module. +GUIs will be able to obtain screen images from the bitmap output +filter working with PIL, so a chart could appear in a Tkinter +GUI window. +""") + + +heading2("Coordinate System") + +disc(""" +The Y-direction in our X-Y coordinate system points from the +bottom <i>up</i>. +This is consistent with PDF, Postscript and mathematical notation. +It also appears to be more natural for people, especially when +working with charts. +Note that in other graphics models (such as SVG) the Y-coordinate +points <i>down</i>. +For the SVG renderer this is actually no problem as it will take +your drawings and flip things as needed, so your SVG output looks +just as expected. +""") + +disc(""" +The X-coordinate points, as usual, from left to right. +So far there doesn't seem to be any model advocating the opposite +direction - at least not yet (with interesting exceptions, as it +seems, for Arabs looking at time series charts...). +""") + + +heading2("Getting Started") + +disc(""" +Let's create a simple drawing containing the string "Hello World", +displayed on top of a coloured rectangle. +After creating it we will save the drawing to a standalone PDF file. +""") + +eg(""" + from reportlab.lib import colors + from reportlab.graphics.shapes import * + + d = Drawing(400, 200) + d.add(Rect(50, 50, 300, 100, fillColor=colors.yellow)) + d.add(String(150,100, 'Hello World', + fontSize=18, fillColor=colors.red)) + + from reportlab.graphics import renderPDF + renderPDF.drawToFile(d, 'example1.pdf', 'My First Drawing') +""") + +disc("This will produce a PDF file containing the following graphic:") + +from reportlab.graphics.shapes import * +from reportlab.graphics import testshapes +t = testshapes.getDrawing01() +draw(t, "'Hello World'") + +disc(""" +Each renderer is allowed to do whatever is appropriate for its format, +and may have whatever API is needed. +If it refers to a file format, it usually has a $drawToFile$ function, +and that's all you need to know about the renderer. +Let's save the same drawing in Encapsulated Postscript format: +""") + +##eg(""" +## from reportlab.graphics import renderPS +## renderPS.drawToFile(D, 'example1.eps', 'My First Drawing') +##""") +eg(""" + from reportlab.graphics import renderPS + renderPS.drawToFile(d, 'example1.eps') +""") + +disc(""" +This will produce an EPS file with the identical drawing, which +may be imported into publishing tools such as Quark Express. +If we wanted to generate the same drawing as a bitmap file for +a website, say, all we need to do is write code like this: +""") + +eg(""" + from reportlab.graphics import renderPM + renderPM.saveToFile(d, 'example1.png', 'PNG') +""") + +disc(""" +Many other bitmap formats, like GIF, JPG, TIFF, BMP and PPN are +genuinely available, making it unlikely you'll need to add external +postprocessing steps to convert to the final format you need. +""") + +disc(""" +To produce an SVG file containing the identical drawing, which +may be imported into graphical editing tools such as Illustrator +all we need to do is write code like this: +""") + +eg(""" + from reportlab.graphics import renderSVG + renderSVG.drawToFile(d, 'example1.svg') +""") + + +heading2("Attribute Verification") + +disc(""" +Python is very dynamic and lets us execute statements at run time that +can easily be the source for unexpected behaviour. +One subtle 'error' is when assigning to an attribute that the framework +doesn't know about because the used attribute's name contains a typo. +Python lets you get away with it (adding a new attribute to an object, +say), but the graphics framework will not detect this 'typo' without +taking special counter-measures. +""") + +disc(""" +There are two verification techniques to avoid this situation. +The default is for every object to check every assignment at run +time, such that you can only assign to 'legal' attributes. +This is what happens by default. +As this imposes a small performance penalty, this behaviour can +be turned off when you need it to be. +""") + +eg(""" +>>> r = Rect(10,10,200,100, fillColor=colors.red) +>>> +>>> r.fullColor = colors.green # note the typo +>>> r.x = 'not a number' # illegal argument type +>>> del r.width # that should confuse it +""") + +disc(""" +These statements would be caught by the compiler in a statically +typed language, but Python lets you get away with it. +The first error could leave you staring at the picture trying to +figure out why the colors were wrong. +The second error would probably become clear only later, when +some back-end tries to draw the rectangle. +The third, though less likely, results in an invalid object that +would not know how to draw itself. +""") + +eg(""" +>>> r = shapes.Rect(10,10,200,80) +>>> r.fullColor = colors.green +Traceback (most recent call last): + File "<interactive input>", line 1, in ? + File "C:\code\users\andy\graphics\shapes.py", line 254, in __setattr__ + validateSetattr(self,attr,value) #from reportlab.lib.attrmap + File "C:\code\users\andy\lib\attrmap.py", line 74, in validateSetattr + raise AttributeError, "Illegal attribute '%s' in class %s" % (name, obj.__class__.__name__) +AttributeError: Illegal attribute 'fullColor' in class Rect +>>> +""") + +disc(""" +This imposes a performance penalty, so this behaviour can be turned +off when you need it to be. +To do this, you should use the following lines of code before you +first import reportlab.graphics.shapes: +""") + +eg(""" +>>> import reportlab.rl_config +>>> reportlab.rl_config.shapeChecking = 0 +>>> from reportlab.graphics import shapes +>>> +""") + +disc(""" +Once you turn off $shapeChecking$, the classes are actually built +without the verification hook; code should get faster, then. +Currently the penalty seems to be about 25% on batches of charts, +so it is hardly worth disabling. +However, if we move the renderers to C in future (which is eminently +possible), the remaining 75% would shrink to almost nothing and +the saving from verification would be significant. +""") + +disc(""" +Each object, including the drawing itself, has a $verify()$ method. +This either succeeds, or raises an exception. +If you turn off automatic verification, then you should explicitly +call $verify()$ in testing when developing the code, or perhaps +once in a batch process. +""") + + +heading2("Property Editing") + +disc(""" +A cornerstone of the reportlab/graphics which we will cover below is +that you can automatically document widgets. +This means getting hold of all of their editable properties, +including those of their subcomponents. +""") + +disc(""" +Another goal is to be able to create GUIs and config files for +drawings. +A generic GUI can be built to show all editable properties +of a drawing, and let you modify them and see the results. +The Visual Basic or Delphi development environment are good +examples of this kind of thing. +In a batch charting application, a file could list all the +properties of all the components in a chart, and be merged +with a database query to make a batch of charts. +""") + +disc(""" +To support these applications we have two interfaces, $getProperties$ +and $setProperties$, as well as a convenience method $dumpProperties$. +The first returns a dictionary of the editable properties of an +object; the second sets them en masse. +If an object has publicly exposed 'children' then one can recursively +set and get their properties too. +This will make much more sense when we look at <i>Widgets</i> later on, +but we need to put the support into the base of the framework. +""") + +eg(""" +>>> r = shapes.Rect(0,0,200,100) +>>> import pprint +>>> pprint.pprint(r.getProperties()) +{'fillColor': Color(0.00,0.00,0.00), + 'height': 100, + 'rx': 0, + 'ry': 0, + 'strokeColor': Color(0.00,0.00,0.00), + 'strokeDashArray': None, + 'strokeLineCap': 0, + 'strokeLineJoin': 0, + 'strokeMiterLimit': 0, + 'strokeWidth': 1, + 'width': 200, + 'x': 0, + 'y': 0} +>>> r.setProperties({'x':20, 'y':30, 'strokeColor': colors.red}) +>>> r.dumpProperties() +fillColor = Color(0.00,0.00,0.00) +height = 100 +rx = 0 +ry = 0 +strokeColor = Color(1.00,0.00,0.00) +strokeDashArray = None +strokeLineCap = 0 +strokeLineJoin = 0 +strokeMiterLimit = 0 +strokeWidth = 1 +width = 200 +x = 20 +y = 30 +>>> """) + +disc(""" +<i>Note: $pprint$ is the standard Python library module that allows +you to 'pretty print' output over multiple lines rather than having +one very long line.</i> +""") + +disc(""" +These three methods don't seem to do much here, but as we will see +they make our widgets framework much more powerful when dealing with +non-primitive objects. +""") + + +heading2("Naming Children") + +disc(""" +You can add objects to the $Drawing$ and $Group$ objects. +These normally go into a list of contents. +However, you may also give objects a name when adding them. +This allows you to refer to and possibly change any element +of a drawing after constructing it. +""") + +eg(""" +>>> d = shapes.Drawing(400, 200) +>>> s = shapes.String(10, 10, 'Hello World') +>>> d.add(s, 'caption') +>>> s.caption.text +'Hello World' +>>> +""") + +disc(""" +Note that you can use the same shape instance in several contexts +in a drawing; if you choose to use the same $Circle$ object in many +locations (e.g. a scatter plot) and use different names to access +it, it will still be a shared object and the changes will be +global. +""") + +disc(""" +This provides one paradigm for creating and modifying interactive +drawings. +""")
\ No newline at end of file |
