Flat / OOP

First document

# If flat is not installed, run
!pip install flat
from flat import document, shape, rgb

# create a new document
d = document(210, 297, 'mm')

# add a page to the document
p = d.addpage()

# create a line
line = shape().stroke(rgb(0, 0, 0)).line(0, 0, 210, 297)

# put that line on the page
p.place(line)

# export the document as a pdf
d.pdf('data/line.pdf')
b'%PDF-1.3\n1 0 obj\n<< /Type /Catalog /Pages 3 0 R >>\nendobj\n2 0 obj\n<< /Title (Untitled) /Producer (Flat) >>\nendobj\n3 0 obj\n<< /Type /Pages /Kids [4 0 R] /Count 1 >>\nendobj\n4 0 obj\n<< /Type /Page /Parent 3 0 R /MediaBox [0 0 595.2756 841.8898] /BleedBox [0 0 595.2756 841.8898] /TrimBox [0 0 595.2756 841.8898] /Resources << /ProcSet [/PDF] >> /Contents 5 0 R >>\nendobj\n5 0 obj\n<< /Length 36 >>\nstream\n0 0 0 RG\n0 841.8898 m 595.2756 0 l S\nendstream\nendobj\nxref\n0 6\n0000000000 65535 f \n0000000009 00000 n \n0000000058 00000 n \n0000000114 00000 n \n0000000171 00000 n \n0000000368 00000 n \ntrailer << /ID [<9723a4d664560adfcdec6ffe4e8cbe18> <9723a4d664560adfcdec6ffe4e8cbe18>] /Root 1 0 R /Info 2 0 R /Size 6 >>\nstartxref\n454\n%%EOF'

Function to display the result inside this Jupyter Notebook

The code above exports the resulting document as a pdf and the code of the pdf is output here. The function below displays the result in here.

from IPython.display import SVG, display

def show(page):
    display(SVG(page.svg()))
# create a new document
d = document(210, 297, 'mm')

# add a page to the document
p = d.addpage()

# create a line
line = shape().stroke(rgb(0, 0, 0)).line(0, 0, 210, 297)

# put that line on the page
p.place(line)

# display the page
show(p)
_images/flat_oop_6_0.svg

Object-oriented programming

Python is like many other languages capable of object-oriented programming. Furthermore, the language itself is constructed through objects.

Objects combine data (properties) with actions (instructions, functions, methods). We can compare this concept and the example above with other ways of creating artefacts.

Let’s say we work with pen and paper:

pen_and_paper

The first object will hold all our papers together. It has the property

  • size: 210 x 297 mm

d = document(210, 297, 'mm')

The second object is one piece of paper with the dimensions of the document that we add to the document.

p = d.addpage()

The third object is a pen with the following properties:

In addition to the properties, the pen has a functionality:

  • line: draw a line from one point to another

Chained together:

line = shape().stroke(rgb(0, 0, 0)).line(0, 0, 210, 297)

The page has the functionality to place an object on itself, in this case the line.

p.place(line)
<flat.shape.placedshape at 0x7f66800a52c0>

The document has the functionality to export itself:

d.pdf('data/line.pdf')
b'%PDF-1.3\n1 0 obj\n<< /Type /Catalog /Pages 3 0 R >>\nendobj\n2 0 obj\n<< /Title (Untitled) /Producer (Flat) >>\nendobj\n3 0 obj\n<< /Type /Pages /Kids [4 0 R] /Count 1 >>\nendobj\n4 0 obj\n<< /Type /Page /Parent 3 0 R /MediaBox [0 0 595.2756 841.8898] /BleedBox [0 0 595.2756 841.8898] /TrimBox [0 0 595.2756 841.8898] /Resources << /ProcSet [/PDF] >> /Contents 5 0 R >>\nendobj\n5 0 obj\n<< /Length 36 >>\nstream\n0 0 0 RG\n0 841.8898 m 595.2756 0 l S\nendstream\nendobj\nxref\n0 6\n0000000000 65535 f \n0000000009 00000 n \n0000000058 00000 n \n0000000114 00000 n \n0000000171 00000 n \n0000000368 00000 n \ntrailer << /ID [<916a572f1af954f09c459544e6762d32> <916a572f1af954f09c459544e6762d32>] /Root 1 0 R /Info 2 0 R /Size 6 >>\nstartxref\n454\n%%EOF'


We can imagine the same for a DTP software.

First we create a document with a specific

  • size

Then we add a page, pick a pen, set

  • width

  • color

and draw a line from one point to another.

Classes

The words behind the import keyword in the code above refer to classes. Every object in object-oriented programming (like a page) is based on a blueprint, which is called a class. Inside this class all the properties and functions of the object are defined.

When we write

d = document(210, 297, 'mm')

we create one specific instance of the class document and store it in a variable called d. This specific instance of the class document is independent of the class itself. This means we can create more instances of the same class, but they are independent objects with their own data.

doc = document(125, 125, 'mm')
doc.width
354.33070866141736
d.width
595.2755905511812

Variables

Why use variables?

We can store data in variables and reuse the data multiple times in our code.

For example we can store the width and height of the document inside variables and reuse them through the document:

# Define variables for width, height and the color black
width = 210
height = 297
black = rgb(0, 0, 0)

d = document(width, height, 'mm') # insert the variables into the document creation
p = d.addpage()
line = shape().stroke(black).line(0, 0, width, height) # insert the variables to draw the line
p.place(line)
line = shape().stroke(black).line(0, height, width, 0) # insert the variables to draw the line
p.place(line)
show(p)
_images/flat_oop_26_0.svg

Now if we want to change the size of our document, we have to change it only once and the code still works:

Using variables instead of fixed values (hard-coded values) makes our programs flexible. For e.g. it’s easy to change the document size and the color just for the variables and it’s applied to the whole program:

# Define variables for width, height and the color black
width = 75
height = 85
black = rgb(0, 0, 0)

d = document(width, height, 'mm') # insert the variables into the document creation
p = d.addpage()
line = shape().stroke(black).line(0, 0, width, height) # insert the variables to draw the line
p.place(line)
line = shape().stroke(black).line(0, height, width, 0) # insert the variables to draw the line
p.place(line)
show(p)
_images/flat_oop_29_0.svg