summaryrefslogtreecommitdiff
path: root/bin/reportlab/docs/graphguide/ch3_shapes.py
diff options
context:
space:
mode:
authorpinky <>2007-01-07 21:41:39 +0000
committerpinky <>2007-01-07 21:41:39 +0000
commit05bb5d58295cd959c34f1fbcd5b605cd6dafaacc (patch)
tree3b3651037037c1617a54ef3d216e8c11ea8cdddf /bin/reportlab/docs/graphguide/ch3_shapes.py
parent62524af2f41454a2302efb21f15a95318d257a76 (diff)
Repotrlab 2.0
bzr revid: pinky-b8333ccaab5dad8ff965b6c380fadadf30d5212a
Diffstat (limited to 'bin/reportlab/docs/graphguide/ch3_shapes.py')
-rw-r--r--bin/reportlab/docs/graphguide/ch3_shapes.py416
1 files changed, 416 insertions, 0 deletions
diff --git a/bin/reportlab/docs/graphguide/ch3_shapes.py b/bin/reportlab/docs/graphguide/ch3_shapes.py
new file mode 100644
index 00000000000..375513a037e
--- /dev/null
+++ b/bin/reportlab/docs/graphguide/ch3_shapes.py
@@ -0,0 +1,416 @@
+#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/ch3_shapes.py
+
+from reportlab.tools.docco.rl_doc_utils import *
+from reportlab.graphics.shapes import *
+
+heading1("Shapes")
+
+disc("""
+This chapter describes the concept of shapes and their importance
+as building blocks for all output generated by the graphics library.
+Some properties of existing shapes and their relationship to
+diagrams are presented and the notion of having different renderers
+for different output formats is briefly introduced.
+""")
+
+heading2("Available Shapes")
+
+disc("""
+Drawings are made up of Shapes.
+Absolutely anything can be built up by combining the same set of
+primitive shapes.
+The module $shapes.py$ supplies a number of primitive shapes and
+constructs which can be added to a drawing.
+They are:
+""")
+
+bullet("Rect")
+bullet("Circle")
+bullet("Ellipse")
+bullet("Wedge (a pie slice)")
+bullet("Polygon")
+bullet("Line")
+bullet("PolyLine")
+bullet("String")
+bullet("Group")
+bullet("Path (<i>not implemented yet, but will be added in the future</i>)")
+
+disc("""
+The following drawing, taken from our test suite, shows most of the
+basic shapes (except for groups).
+Those with a filled green surface are also called <i>solid shapes</i>
+(these are $Rect$, $Circle$, $Ellipse$, $Wedge$ and $Polygon$).
+""")
+
+from reportlab.graphics import testshapes
+
+t = testshapes.getDrawing06()
+draw(t, "Basic shapes")
+
+
+heading2("Shape Properties")
+
+disc("""
+Shapes have two kinds of properties - some to define their geometry
+and some to define their style.
+Let's create a red rectangle with 3-point thick green borders:
+""")
+
+eg("""
+>>> from reportlab.graphics.shapes import Rect
+>>> from reportlab.lib.colors import red, green
+>>> r = Rect(5, 5, 200, 100)
+>>> r.fillColor = red
+>>> r.strokeColor = green
+>>> r.strokeWidth = 3
+>>>
+""")
+
+from reportlab.graphics.shapes import Rect
+from reportlab.lib.colors import red, green
+d = Drawing(220, 120)
+r = Rect(5, 5, 200, 100)
+r.fillColor = red
+r.strokeColor = green
+r.strokeWidth = 3
+d.add(r)
+draw(d, "red rectangle with green border")
+
+disc("""
+<i>Note: In future examples we will omit the import statements.</i>
+""")
+
+disc("""
+All shapes have a number of properties which can be set.
+At an interactive prompt, we can use their <i>dumpProperties()</i>
+method to list these.
+Here's what you can use to configure a Rect:
+""")
+
+eg("""
+>>> r.dumpProperties()
+fillColor = Color(1.00,0.00,0.00)
+height = 100
+rx = 0
+ry = 0
+strokeColor = Color(0.00,0.50,0.00)
+strokeDashArray = None
+strokeLineCap = 0
+strokeLineJoin = 0
+strokeMiterLimit = 0
+strokeWidth = 3
+width = 200
+x = 5
+y = 5
+>>>
+""")
+
+disc("""
+Shapes generally have <i>style properties</i> and <i>geometry
+properties</i>.
+$x$, $y$, $width$ and $height$ are part of the geometry and must
+be provided when creating the rectangle, since it does not make
+much sense without those properties.
+The others are optional and come with sensible defaults.
+""")
+
+disc("""
+You may set other properties on subsequent lines, or by passing them
+as optional arguments to the constructor.
+We could also have created our rectangle this way:
+""")
+
+eg("""
+>>> r = Rect(5, 5, 200, 100,
+ fillColor=red,
+ strokeColor=green,
+ strokeWidth=3)
+""")
+
+disc("""
+Let's run through the style properties. $fillColor$ is obvious.
+$stroke$ is publishing terminology for the edge of a shape;
+the stroke has a color, width, possibly a dash pattern, and
+some (rarely used) features for what happens when a line turns
+a corner.
+$rx$ and $ry$ are optional geometric properties and are used to
+define the corner radius for a rounded rectangle.
+""")
+
+disc("All the other solid shapes share the same style properties.")
+
+
+heading2("Lines")
+
+disc("""
+We provide single straight lines, PolyLines and curves.
+Lines have all the $stroke*$ properties, but no $fillColor$.
+Here are a few Line and PolyLine examples and the corresponding
+graphics output:
+""")
+
+eg("""
+ Line(50,50, 300,100,
+ strokeColor=colors.blue, strokeWidth=5)
+ Line(50,100, 300,50,
+ strokeColor=colors.red,
+ strokeWidth=10,
+ strokeDashArray=[10, 20])
+ PolyLine([120,110, 130,150, 140,110, 150,150, 160,110,
+ 170,150, 180,110, 190,150, 200,110],
+ strokeWidth=2,
+ strokeColor=colors.purple)
+""")
+
+d = Drawing(400, 200)
+d.add(Line(50,50, 300,100,strokeColor=colors.blue, strokeWidth=5))
+d.add(Line(50,100, 300,50,
+ strokeColor=colors.red,
+ strokeWidth=10,
+ strokeDashArray=[10, 20]))
+d.add(PolyLine([120,110, 130,150, 140,110, 150,150, 160,110,
+ 170,150, 180,110, 190,150, 200,110],
+ strokeWidth=2,
+ strokeColor=colors.purple))
+draw(d, "Line and PolyLine examples")
+
+
+heading2("Strings")
+
+disc("""
+The ReportLab Graphics package is not designed for fancy text
+layout, but it can place strings at desired locations and with
+left/right/center alignment.
+Let's specify a $String$ object and look at its properties:
+""")
+
+eg("""
+>>> s = String(10, 50, 'Hello World')
+>>> s.dumpProperties()
+fillColor = Color(0.00,0.00,0.00)
+fontName = Times-Roman
+fontSize = 10
+text = Hello World
+textAnchor = start
+x = 10
+y = 50
+>>>
+""")
+
+disc("""
+Strings have a textAnchor property, which may have one of the
+values 'start', 'middle', 'end'.
+If this is set to 'start', x and y relate to the start of the
+string, and so on.
+This provides an easy way to align text.
+""")
+
+disc("""
+Strings use a common font standard: the Type 1 Postscript fonts
+present in Acrobat Reader.
+We can thus use the basic 14 fonts in ReportLab and get accurate
+metrics for them.
+We have recently also added support for extra Type 1 fonts
+and the renderers all know how to render Type 1 fonts.
+""")
+
+##Until now we have worked with bitmap renderers which have to use
+##TrueType fonts and which make some substitutions; this could lead
+##to differences in text wrapping or even the number of labels on
+##a chart between renderers.
+
+disc("""
+Here is a more fancy example using the code snippet below.
+Please consult the ReportLab User Guide to see how non-standard
+like 'LettErrorRobot-Chrome' fonts are being registered!
+""")
+
+eg("""
+ d = Drawing(400, 200)
+ for size in range(12, 36, 4):
+ d.add(String(10+size*2, 10+size*2, 'Hello World',
+ fontName='Times-Roman',
+ fontSize=size))
+
+ d.add(String(130, 120, 'Hello World',
+ fontName='Courier',
+ fontSize=36))
+
+ d.add(String(150, 160, 'Hello World',
+ fontName='LettErrorRobot-Chrome',
+ fontSize=36))
+""")
+
+from reportlab.pdfbase import pdfmetrics
+from reportlab import rl_config
+rl_config.warnOnMissingFontGlyphs = 0
+afmFile, pfbFile = getJustFontPaths()
+T1face = pdfmetrics.EmbeddedType1Face(afmFile, pfbFile)
+T1faceName = 'LettErrorRobot-Chrome'
+pdfmetrics.registerTypeFace(T1face)
+T1font = pdfmetrics.Font(T1faceName, T1faceName, 'WinAnsiEncoding')
+pdfmetrics.registerFont(T1font)
+
+d = Drawing(400, 200)
+for size in range(12, 36, 4):
+ d.add(String(10+size*2, 10+size*2, 'Hello World',
+ fontName='Times-Roman',
+ fontSize=size))
+
+d.add(String(130, 120, 'Hello World',
+ fontName='Courier',
+ fontSize=36))
+
+d.add(String(150, 160, 'Hello World',
+ fontName='LettErrorRobot-Chrome',
+ fontSize=36))
+
+draw(d, 'fancy font example')
+
+
+heading2("""Paths""")
+
+disc("""
+Postscript paths are a widely understood concept in graphics.
+They are not implemented in $reportlab/graphics$ as yet, but they
+will be, soon.
+""")
+
+# NB This commented out section is for 'future compatibility' - paths haven't
+# been implemented yet, but when they are we can uncomment this back in.
+
+ ##disc("""Postscript paths are a widely understood concept in graphics. A Path
+ ## is a way of defining a region in space. You put an imaginary pen down,
+ ## draw straight and curved segments, and even pick the pen up and move
+ ## it. At the end of this you have described a region, which may consist
+ ## of several distinct close shapes or unclosed lines. At the end, this
+ ## 'path' is 'stroked and filled' according to its properties. A Path has
+ ## the same style properties as a solid shape. It can be used to create
+ ## any irregular shape.""")
+ ##
+ ##disc("""In Postscript-based imaging models such as PDF, Postscript and SVG,
+ ## everything is done with paths. All the specific shapes covered above
+ ## are instances of paths; even text strings (which are shapes in which
+ ## each character is an outline to be filled). Here we begin creating a
+ ## path with a straight line and a bezier curve:""")
+ ##
+ ##eg("""
+ ##>>> P = Path(0,0, strokeWidth=3, strokeColor=red)
+ ##>>> P.lineTo(0, 50)
+ ##>>> P.curveTo(10,50,80,80,100,30)
+ ##>>>
+ ##""")
+
+ ##disc("""As well as being the only way to draw complex shapes, paths offer some
+ ## performance advantages in renderers which support them. If you want to
+ ## create a scatter plot with 5000 blue circles of different sizes, you
+ ## can create 5000 circles, or one path object. With the latter, you only
+ ## need to set the color and line width once. PINGO just remembers the
+ ## drawing sequence, and writes it out into the file. In renderers which
+ ## do not support paths, the renderer will still have to decompose it
+ ## into 5000 circles so you won't save anything.""")
+ ##
+ ##disc("""<b>Note that our current path implementation is an approximation; it
+ ## should be finished off accurately for PDF and PS.</b>""")
+
+
+heading2("Groups")
+
+disc("""
+Finally, we have Group objects.
+A group has a list of contents, which are other nodes.
+It can also apply a transformation - its contents can be rotated,
+scaled or shifted.
+If you know the math, you can set the transform directly.
+Otherwise it provides methods to rotate, scale and so on.
+Here we make a group which is rotated and translated:
+""")
+
+eg("""
+>>> g =Group(shape1, shape2, shape3)
+>>> g.rotate(30)
+>>> g.translate(50, 200)
+""")
+
+disc("""
+Groups provide a tool for reuse.
+You can make a bunch of shapes to represent some component - say,
+a coordinate system - and put them in one group called "Axis".
+You can then put that group into other groups, each with a different
+translation and rotation, and you get a bunch of axis.
+It is still the same group, being drawn in different places.
+""")
+
+disc("""Let's do this with some only slightly more code:""")
+
+eg("""
+ d = Drawing(400, 200)
+
+ Axis = Group(
+ Line(0,0,100,0), # x axis
+ Line(0,0,0,50), # y axis
+ Line(0,10,10,10), # ticks on y axis
+ Line(0,20,10,20),
+ Line(0,30,10,30),
+ Line(0,40,10,40),
+ Line(10,0,10,10), # ticks on x axis
+ Line(20,0,20,10),
+ Line(30,0,30,10),
+ Line(40,0,40,10),
+ Line(50,0,50,10),
+ Line(60,0,60,10),
+ Line(70,0,70,10),
+ Line(80,0,80,10),
+ Line(90,0,90,10),
+ String(20, 35, 'Axes', fill=colors.black)
+ )
+
+ firstAxisGroup = Group(Axis)
+ firstAxisGroup.translate(10,10)
+ d.add(firstAxisGroup)
+
+ secondAxisGroup = Group(Axis)
+ secondAxisGroup.translate(150,10)
+ secondAxisGroup.rotate(15)
+
+ d.add(secondAxisGroup)
+
+ thirdAxisGroup = Group(Axis,
+ transform=mmult(translate(300,10),
+ rotate(30)))
+ d.add(thirdAxisGroup)
+""")
+
+d = Drawing(400, 200)
+Axis = Group(
+ Line(0,0,100,0), # x axis
+ Line(0,0,0,50), # y axis
+ Line(0,10,10,10), # ticks on y axis
+ Line(0,20,10,20),
+ Line(0,30,10,30),
+ Line(0,40,10,40),
+ Line(10,0,10,10), # ticks on x axis
+ Line(20,0,20,10),
+ Line(30,0,30,10),
+ Line(40,0,40,10),
+ Line(50,0,50,10),
+ Line(60,0,60,10),
+ Line(70,0,70,10),
+ Line(80,0,80,10),
+ Line(90,0,90,10),
+ String(20, 35, 'Axes', fill=colors.black)
+ )
+firstAxisGroup = Group(Axis)
+firstAxisGroup.translate(10,10)
+d.add(firstAxisGroup)
+secondAxisGroup = Group(Axis)
+secondAxisGroup.translate(150,10)
+secondAxisGroup.rotate(15)
+d.add(secondAxisGroup)
+thirdAxisGroup = Group(Axis,
+ transform=mmult(translate(300,10),
+ rotate(30)))
+d.add(thirdAxisGroup)
+draw(d, "Groups examples") \ No newline at end of file