Python制作PDF的一個庫,效率非常高,比pypdf不知道快了多少。 文檔下載地址:https://www.reportlab.com/docs/reportlab-userguide.pdf
Chapter 1 環境篇
編程語言:Python3.8
1.1 安裝
pip install reportlab
如果有缺失的依賴包(比如之前沒有安裝pillow),pip會自動進行安裝
Chapter 2 Graphics and Text with pdfgen - 有pdfgen的圖形和文本
2.1 Basic Concepts - 基本概念
from reportlab.pdfgen import canvas
def hello(c):
c.drawString(0, 0, "Hello World")
c = canvas.Canvas("hello.pdf")
hello(c)
c.showPage() # 保存當前畫布頁面
c.save() # 保存文件並關閉畫布
結果如下圖: pdfgen軟件包是用於生成PDF文檔的最低級別的接口,其本質相當於在一個畫布上進行繪畫的工具。 畫布應被視為一張白紙,並且在紙上使用笛卡爾坐標確定點(X,Y)坐標,默認情況下在頁面的左下角具有(0,0)起點。 此外默認情況下,第一個坐標x朝右,第二個坐標y朝上。
2.2 More about the Canvas - 關於畫布
一張畫布有很多屬性可以進行配置。 首先這個是畫布對象的初始屬性:
def __init__(
self, filename, pagesize=(595.27, 841.89), bottomup=1,
pageCompression=0, encoding=rl_config.defaultEncoding,
verbosity=0, encrypt=None):
- filename - 控制最終PDF文件的名稱。 也可以傳入任何打開的二進制流(例如sys.stdout,帶有二進制編碼的python處理標准輸出),然后將PDF文檔寫入其中。 注意:不能在HTML頁面中間內聯傳遞PDF文檔!
- pagesize 以點(1/72英寸)為單位的兩個數字的元組。畫布默認為A4(國際標准頁面大小與美國標准字母大小不同),但最好明確指定它。在reportlab.lib.pagesizes中可以找到最常見的頁面大小,因此可以使用如下表達式:
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter, A4
myCanvas = canvas.Canvas('myfile.pdf', pagesize=A4)
如果打印文檔時遇到問題,請確保使用正確的頁面尺寸(通常為A4或Letter)。某些打印機無法處理太大或太小的頁面。 可以使用width變量將右邊距定義為width-inch,而不是使用常量。通過使用變量,即使頁面大小發生變化,頁邊距仍然有意義。
bottomup已被棄用,將來可能會被刪除- pageCompression - 是否壓縮每個頁面 默認情況下,不壓縮頁面流,因為壓縮會減慢文件生成過程。 如果輸出大小很重要,請設置pageCompression=1。但是請記住,壓縮后的文檔會變小,但生成起來會更慢。請注意,圖像始終是壓縮的,並且只有在每頁上都有大量文本和矢量圖形時,此選項才會節省空間。
- encoding 在2.0版中已過時,99%的用戶可能會忽略它。所有TTF和常用的CID字體,此處傳遞的編碼將被忽略,因為在這些情況下reportlab庫本身知道正確的編碼。
- encrypt 默認情況下,文檔未加密。如果encrypt是字符串對象,則將其用作pdf的用戶密碼。如果encrypt是reportlab.lib.pdfencrypt.StandardEncryption的實例,則此對象用於加密pdf。
2.3 Drawing Operations - 繪圖操作
先看示例:
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
def hello(c):
# 將原點坐標都移動1英寸
c.translate(inch, inch) # 不寫這行的話,原點會是0,0
c.setFont("Helvetica", 14) # 定義字體
# 設置一些顏色
c.setStrokeColorRGB(0.2, 0.5, 0.3)
c.setFillColorRGB(1, 0, 1)
# 畫幾條線
c.line(0, 0, 0, 1.7 * inch)
c.line(0, 0, 1 * inch, 0)
c.rect(0.2 * inch, 0.2 * inch, 1 * inch, 1.5 * inch, fill=1) # 畫一個長方形
c.rotate(90) # 將文字旋轉90度
c.setFillColorRGB(0, 0, 0.77)
# 注意:旋轉后,y坐標必須為負數
c.drawString(0.3 * inch, -inch, "Hello World")
c = canvas.Canvas("hello.pdf")
hello(c)
c.showPage() # 保存當前畫布頁面
c.save() # 保存文件並關閉畫布
觀察上述代碼可以發現,使用畫布執行的操作基本上有兩種: 第一種在頁面上繪制內容,例如文本字符串,矩形或線條。 第二種類型更改畫布的狀態,例如更改當前的填充或筆觸顏色或更改當前的字體類型和大小。 想象成正在使用Windows自帶的畫圖工具,"繪制"操作使用當前的一組工具(顏色,線條樣式,字體等)將顏料施加到畫布上,而"狀態更改"操作將更改當前的其中一個工具(例如,將填充顏色從原來的顏色更改為藍色,或者將當前字體更改為15點的Times-Roman)。
2.4 The tools: the "draw" operations - 工具:"繪制"操作
- Line methods 在畫布上繪制直線段 有如下幾種方法:
canvas.line(x1,y1,x2,y2)
canvas.lines(linelist)
- Shape methods 繪制常見的復雜形狀 有如下幾種方法:
canvas.grid(xlist, ylist)
canvas.bezier(x1, y1, x2, y2, x3, y3, x4, y4)
canvas.arc(x1,y1,x2,y2)
canvas.rect(x, y, width, height, stroke=1, fill=0)
canvas.ellipse(x1,y1, x2,y2, stroke=1, fill=0)
canvas.wedge(x1,y1, x2,y2, startAng, extent, stroke=1, fill=0)
canvas.circle(x_cen, y_cen, r, stroke=1, fill=0)
canvas.roundRect(x, y, width, height, radius, stroke=1, fill=0)
- String drawing methods 繪制單行文本 有如下幾種方法:
canvas.drawString(x, y, text):
canvas.drawRightString(x, y, text)
canvas.drawCentredString(x, y, text)
- The text object methods 文本對象用於格式化畫布不直接支持的文本。 使用beginText()方法在畫布上創建一個文本對象,然后把這個文本對象傳遞給canvas.drawText(textobject)方法,去設置文本格式。 reportlab使用drawText()方法將textobject繪制到畫布上。 有如下幾種方法:
textobject = canvas.beginText(x, y)
canvas.drawText(textobject)
- The path object methods 路徑對象類似於文本對象:它們提供專用控件來執行復雜的圖形繪圖,而畫布界面並未直接提供該圖形。 程序使用beginPath創建路徑對象,並使用該路徑對象的方法使用圖形填充該路徑,然后使用drawPath在畫布上繪制該路徑。 也可以使用clipPath方法將路徑用作“剪切區域”。例如,圓形路徑可用於剪切掉矩形圖像的外部,而僅在頁面上可見圖像的圓形部分。 如果指定fill=1,則fillMode參數可用於設置0、1、奇數或非零填充模式。這將改變復雜路徑的填充方式。如果使用默認的None值,則使用canvas_fillMode屬性值(通常為0,即奇數)。 有如下幾種方法:
path = canvas.beginPath()
canvas.drawPath(path, stroke=1, fill=0, fillMode=None)
canvas.clipPath(path, stroke=1, fill=0, fillMode=None)
- Image methods 該功能需要依賴python的pillow庫 有如下幾種方法:
canvas.drawInlineImage(self, image, x,y, width=None,height=None)
canvas.drawImage(self, image, x,y, width=None,height=None,mask=None)
1). 推薦使用drawImage()方法!該方法實現了一個緩存系統,定義一次圖像並繪制多次,它僅在PDF文件中存儲一次。drawImage還公開了一個高級參數,即透明蒙版,將來還會有更多的介紹。 2). 較舊的drawInlineImage()方法將圖像放置在畫布上、存儲在頁面流中,如果文檔中多次使用同一圖像,效率將非常低下。但是如果圖像非常小且不重復,PDF會渲染得更快。image參數可以是PIL Image對象或圖像文件名。接受常見的文件格式,包括GIF和JPEG。以(寬度,高度)元組的形式返回實際圖像的大小(以像素為單位)。 3). drawImage()方法的參數和返回值與drawInlineImage相同。但是,drawImage()使用了緩存系統,給定的圖像只會在第一次使用時存儲,並且在以后的使用中會被引用。如果提供文件名,則假定相同的文件名表示相同的圖像。如果提供了PIL圖像,它將在重新嵌入之前測試內容是否已實際更改。 4). mask參數可以創建透明圖像。它有6個數字,並定義了將被掩蓋或視為透明的RGB值范圍。 例如,使用[0,2,40,42,136,139],它將掩蓋任何具有0或1的紅色值,綠色40或41的顏色以及136、137或138的藍色的像素(在0-255的范圍內) 。目前,需要知道哪種顏色是"透明"或背景顏色。
- Ending a page 完成當前頁面,所有其他繪圖將在另一頁上完成。 有如下幾種方法:
canvas.showPage()
警告!當使用新的pdfgen頁面時,所有狀態(字體更改,顏色設置,幾何變換等)都會被拋棄。任何狀態設置都必須在程序進行繪圖之前重新設置!
2.5 The toolbox: the "state change" operations - 工具箱:"狀態更改"操作
- Changing Colors 有如下幾種方法:
canvas.setFillColorCMYK(c, m, y, k)
canvas.setStrikeColorCMYK(c, m, y, k)
canvas.setFillColorRGB(r, g, b)
canvas.setStrokeColorRGB(r, g, b)
canvas.setFillColor(acolor)
canvas.setStrokeColor(acolor)
canvas.setFillGray(gray)
canvas.setStrokeGray(gray)
PDF支持三種不同的顏色模型:灰度,加性(紅色/綠色/藍色或RGB)和帶有暗度降解的參數(青色/品紅色/黃色/暗度或CMYK)。ReportLab庫還提供了諸如草坪綠之類的命名顏色。 圖形狀態中有兩個基本顏色參數:圖形內部的填充顏色和圖形邊界的描邊顏色。上述方法支持使用四種顏色規范中的任何一種來設置填充或描邊顏色。
- Changing Fonts 有如下幾種方法:
canvas.setFont(psfontname, size, leading = None)
根據給定的psfontname和size,改變當前的文本字體。leading參數指定從一個文本行前進到下一個文本行時,向下移動的距離。
- Changing Graphical Line Styles 有如下幾種方法:
canvas.setLineWidth(width)
canvas.setLineCap(mode)
canvas.setLineJoin(mode)
canvas.setMiterLimit(limit)
canvas.setDash(self, array=[], phase=0)
PDF中繪制的線條可以多種圖形樣式顯示。線可以具有不同的寬度,可以以不同的端點風格樣式結束,可以以不同的連接樣式相遇,並且可以連續,也可以點划線。以上方法調整了這些各種參數。
- Changing Geometry 改變幾何形狀 有如下幾種方法:
canvas.setPageSize(pair)
canvas.transform(a,b,c,d,e,f):
canvas.translate(dx, dy)
canvas.scale(x, y)
canvas.rotate(theta)
canvas.skew(alpha, beta)
所有PDF圖紙都適合指定的頁面尺寸。在指定頁面尺寸之外繪制的元素不可見。此外,所有繪制的元素都要經過仿射變換,仿射變換可以調整其位置和/或扭曲其外觀。 setPageSize()方法調整當前頁面大小。變換,平移,縮放,旋轉和傾斜方法將其他變換添加到當前變換中。重要的是要記住,這些轉換是漸進式的-新的轉換會修改當前的轉換(但不能替代它)。
- State control 有如下幾種方法:
canvas.saveState()
canvas.restoreState()
保存當前字體、圖形轉換、線條樣式和其他圖形狀態非常重要,以便以后恢復它們。 saveState()方法將當前圖形狀態標記為以后通過匹配的restoreState恢復。請注意,保存和還原方法的調用必須匹配-還原調用會將狀態還原為尚未還原的最新保存狀態。不能在一個頁面上保存狀態,而不能在下一頁上恢復狀態,但是頁面之間不會保留任何狀態。
2.6 Other canvas methods
並非所有的畫布對象方法都適合"工具"或"工具箱"類別。以下是一些不適當的地方,出於完整性考慮,此處包含了一些不適當的地方。
canvas.setAuthor()
canvas.addOutlineEntry(title, key, level=0, closed=None)
canvas.setTitle(title)
canvas.setSubject(subj)
canvas.pageHasData()
canvas.showOutline()
canvas.bookmarkPage(name)
canvas.bookmarkHorizontalAbsolute(name, yhorizontal)
canvas.doForm()
canvas.beginForm(name, lowerx=0, lowery=0, upperx=None, uppery=None)
canvas.endForm()
canvas.linkAbsolute(contents, destinationname, Rect=None, addtopage=1, name=None, **kw)
canvas.linkRect(contents, destinationname, Rect=None, addtopage=1, relative=1, name=None, **kw)
canvas.getPageNumber()
canvas.addLiteral()
canvas.getAvailableFonts()
canvas.stringWidth(self, text, fontName, fontSize, encoding=None)
canvas.setPageCompression(onoff=1)
canvas.setPageTransition(self, effectname=None, duration=1, direction=0,dimension='H',motion='I')
2.7 Coordinates (default user space) - 坐標(默認用戶空間)
默認情況下,頁面上的位置由一對數字標識。例如,(4.5 * inch,1 * inch)就是從左下角開始向右移動4.5英寸並向上移動一英寸來標識頁面上找到的位置。 示例代碼:
from reportlab.pdfgen import canvas
canvas = canvas.Canvas("hello.pdf")
def coords(canvas):
from reportlab.lib.units import inch
from reportlab.lib.colors import pink, black, red, blue, green
c = canvas
c.setStrokeColor(pink)
c.grid([inch, 2 * inch, 3 * inch, 4 * inch], [0.5 * inch, inch, 1.5 * inch, 2 * inch, 2.5 * inch])
c.setStrokeColor(black)
c.setFont("Times-Roman", 20)
c.drawString(0, 0, "(0,0) the Origin")
c.drawString(2.5 * inch, inch, "(2.5,1) in inches")
c.drawString(4 * inch, 2.5 * inch, "(4, 2.5)")
c.setFillColor(red)
c.rect(0, 2 * inch, 0.2 * inch, 0.3 * inch, fill=1)
c.setFillColor(green)
c.circle(4.5 * inch, 0.4 * inch, 0.2 * inch, fill=1)
c.showPage()
c.save()
coords(canvas=canvas)
最終效果如下圖: 在默認用戶空間中,原點(0,0)點位於左下角。
- Moving the origin: the translate method canvas.translate(x,y)方法將當前頁面的原點移動到指定的(x,y)坐標位置。 本示例代碼直接使用了上面的那個示例,只是加了2行新的代碼(新代碼已在行末注釋說明了):
from reportlab.pdfgen import canvas
canvas = canvas.Canvas("hello.pdf")
def coords(canvas):
from reportlab.lib.units import inch
from reportlab.lib.units import cm # 厘米單位
from reportlab.lib.colors import pink, black, red, blue, green
c = canvas
c.translate(2.3 * cm, 0.3 * cm) # 移動原點坐標
c.setStrokeColor(pink)
c.grid([inch, 2 * inch, 3 * inch, 4 * inch], [0.5 * inch, inch, 1.5 * inch, 2 * inch, 2.5 * inch])
c.setStrokeColor(black)
c.setFont("Times-Roman", 20)
c.drawString(0, 0, "(0,0) the Origin")
c.drawString(2.5 * inch, inch, "(2.5,1) in inches")
c.drawString(4 * inch, 2.5 * inch, "(4, 2.5)")
c.setFillColor(red)
c.rect(0, 2 * inch, 0.2 * inch, 0.3 * inch, fill=1)
c.setFillColor(green)
c.circle(4.5 * inch, 0.4 * inch, 0.2 * inch, fill=1)
c.showPage()
c.save()
coords(canvas=canvas)
最終效果如下,可看到與上面那張效果圖相比,下圖有了明顯的位移變化: 注意:移動原點坐標可能會導致"脫離頁面"的情況。簡而言之,就是錯誤地將整個圖形移到頁面的可見區域之外。如果程序產生空白頁,則所有繪制的對象都可能不在該頁面上。
- Shrinking and growing: the scale operation - 縮小和放大,比例操作 通過使用canvas.scale(dx,dy)方法,來伸展或收縮尺寸。dx和dy通常相同,例如要在所有尺寸上將圖形縮小一半,可指定dx=dy=0.5 演示一個收縮比例的示例:
from reportlab.pdfgen import canvas
canvas = canvas.Canvas("hello.pdf")
def coords(canvas):
from reportlab.lib.units import inch
from reportlab.lib.units import cm # 厘米單位
from reportlab.lib.colors import pink, black, red, blue, green
c = canvas
c.translate(2.3 * cm, 0.3 * cm) # 移動原點坐標,在繪畫開始前就必須設定好
c.scale(0.75, 0.5) # 指定收縮的比例
c.setStrokeColor(pink)
c.grid([inch, 2 * inch, 3 * inch, 4 * inch], [0.5 * inch, inch, 1.5 * inch, 2 * inch, 2.5 * inch])
c.setStrokeColor(black)
c.setFont("Times-Roman", 20)
c.drawString(0, 0, "(0,0) the Origin")
c.drawString(2.5 * inch, inch, "(2.5,1) in inches")
c.drawString(4 * inch, 2.5 * inch, "(4, 2.5)")
c.setFillColor(red)
c.rect(0, 2 * inch, 0.2 * inch, 0.3 * inch, fill=1)
c.setFillColor(green)
c.circle(4.5 * inch, 0.4 * inch, 0.2 * inch, fill=1)
c.showPage()
c.save()
coords(canvas=canvas)
最終效果如下: 注意:縮放比例還可能使對象或對象的一部分移出頁面,或者可能導致對象縮小到看不見。 scale()方法和translate()方法可以聯合使用,但前后出現的順序很重要! 先看如下代碼:
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
from reportlab.lib.units import cm # 厘米單位
from reportlab.lib.colors import pink, black, red, blue, green
canvas = canvas.Canvas("hello.pdf")
def coords(canvas):
canvas.setStrokeColor(pink)
canvas.grid([inch, 2 * inch, 3 * inch, 4 * inch], [0.5 * inch, inch, 1.5 * inch, 2 * inch, 2.5 * inch])
canvas.setStrokeColor(black)
canvas.setFont("Times-Roman", 20)
canvas.drawString(0, 0, "(0,0) the Origin")
canvas.drawString(2.5 * inch, inch, "(2.5,1) in inches")
canvas.drawString(4 * inch, 2.5 * inch, "(4, 2.5)")
canvas.setFillColor(red)
canvas.rect(0, 2 * inch, 0.2 * inch, 0.3 * inch, fill=1)
canvas.setFillColor(green)
canvas.circle(4.5 * inch, 0.4 * inch, 0.2 * inch, fill=1)
def scaletranslate(canvas):
canvas.setFont("Courier-BoldOblique", 12)
canvas.saveState() # 保存當前狀態
# 先縮放然后再調整原點
canvas.scale(0.3, 0.5)
canvas.translate(2.4 * inch, 1.5 * inch)
canvas.drawString(0, 2.7 * inch, "Scale then translate")
coords(canvas)
canvas.restoreState() # 重置所有的狀態
# 先調整原點再縮放
canvas.translate(2.4 * inch, 1.5 * inch)
canvas.scale(0.3, 0.5)
canvas.drawString(0, 2.7 * inch, "Translate then scale")
coords(canvas)
scaletranslate(canvas=canvas)
canvas.showPage()
canvas.save()
最終效果如下: 注意:縮放會縮小或增長包括線寬在內的所有內容,因此使用canvas.scale()縮放的微觀單位渲染微觀圖形可能會產生斑點(因為所有線寬都會大量擴展)。以米為單位縮放比例的飛機機翼可能會導致線條縮小到消失的程度。出於工程或科學目的,在使用畫布進行渲染之前,應先將其進行縮放且移動原點。
- Saving and restoring the canvas state: saveState and restoreState - 保存、重置畫布狀態:saveState()、restoreState() 保存和恢復畫布當前狀態。通過將一系列操作,包含在一對匹配的canvas.saveState()和canvas.restoreState()操作中,可以將字體圖形的所有更改(顏色,線條樣式,縮放,旋轉或其他畫布圖像狀態)恢復到saveState()所標記的位置。請記住,保存/恢復調用必須匹配:孤立的保存或恢復操作可能導致無法預期的意外發生。另外,分頁符之間不會保留任何畫布狀態,並且跨分頁符無法使用保存/恢復機制。
- Mirror image - 鏡像 相當於PS中的水平翻轉畫布,將canvas.scale(dx,dy)方法中的第一個參數dx設置為-1.0即可
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
from reportlab.lib.units import cm # 厘米單位
from reportlab.lib.colors import pink, black, red, blue, green
canvas = canvas.Canvas("hello.pdf")
def coords(canvas):
canvas.setStrokeColor(pink)
canvas.grid([inch, 2 * inch, 3 * inch, 4 * inch], [0.5 * inch, inch, 1.5 * inch, 2 * inch, 2.5 * inch])
canvas.setStrokeColor(black)
canvas.setFont("Times-Roman", 20)
canvas.drawString(0, 0, "(0,0) the Origin")
canvas.drawString(2.5 * inch, inch, "(2.5,1) in inches")
canvas.drawString(4 * inch, 2.5 * inch, "(4, 2.5)")
canvas.setFillColor(red)
canvas.rect(0, 2 * inch, 0.2 * inch, 0.3 * inch, fill=1)
canvas.setFillColor(green)
canvas.circle(4.5 * inch, 0.4 * inch, 0.2 * inch, fill=1)
def mirror(canvas):
# 把原點的x坐標增加一定距離,不然的話就是在原點的位置上進行水平翻轉
# 一翻就翻出了畫布,導致看不到任何內容
canvas.translate(5.5 * inch, 0)
canvas.scale(-1.0, 1.0) # 將第一個參數設置為-1.0即可實現水平翻轉
coords(canvas)
mirror(canvas)
canvas.showPage()
canvas.save()
注意:文本對象是向后繪制的。 最終效果如下: PS中的效果,圖像->變換->水平翻轉畫布
2.8 Colors
PDF中通常使用兩種顏色,具體取決於使用PDF的媒介。最常見的屏幕顏色模型RGB可以在PDF中使用。但是在專業印刷中,主要使用另一種顏色模型CMYK,它可以更好地控制將墨水應用於紙張的方式。
- RGB Colors pdfgen中有三種指定RGB色彩的方式:使用color模塊的名稱、指定紅/綠/藍(RGB)值、灰階度 下例中,演示了這三種方式:
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
from reportlab.lib.units import cm # 厘米單位
from reportlab.lib.colors import pink, black, red, blue, green
from reportlab.lib import colors
canvas = canvas.Canvas("hello.pdf")
def colorsRGB(canvas):
black = colors.black
y = x = 0
dy = inch * 3 / 4.0
dx = inch * 5.5 / 5
w = h = dy / 2
rdx = (dx - w) / 2
rdy = h / 5.0
texty = h + 2 * rdy
canvas.setFont("Helvetica", 10)
# 指定color模塊的名稱
for [namedcolor, name] in (
[colors.lavenderblush, "lavenderblush"], [colors.lawngreen, "lawngreen"],
[colors.lemonchiffon, "lemonchiffon"], [colors.lightblue, "lightblue"],
[colors.lightcoral, "lightcoral"]):
canvas.setFillColor(namedcolor)
canvas.rect(x + rdx, y + rdy, w, h, fill=1)
canvas.setFillColor(black)
canvas.drawCentredString(x + dx / 2, y + texty, name)
x = x + dx
y = y + dy
x = 0
# 指定RGB數值
for rgb in [(1, 0, 0), (0, 1, 0), (0, 0, 1), (0.5, 0.3, 0.1), (0.4, 0.5, 0.3)]:
r, g, b = rgb
canvas.setFillColorRGB(r, g, b)
canvas.rect(x + rdx, y + rdy, w, h, fill=1)
canvas.setFillColor(black)
canvas.drawCentredString(x + dx / 2, y + texty, "r%s g%s b%s" % rgb)
x = x + dx
y = y + dy
x = 0
# 灰階度
for gray in (0.0, 0.25, 0.50, 0.75, 1.0):
canvas.setFillGray(gray)
canvas.rect(x + rdx, y + rdy, w, h, fill=1)
canvas.setFillColor(black)
canvas.drawCentredString(x + dx / 2, y + texty, "gray: %s" % gray)
x = x + dx
colorsRGB(canvas)
canvas.showPage()
canvas.save()
最終效果如下:
- RGB Color Transparency - RGB透明色 在pdfgen中可以將對象塗在其他對象上。有兩種處理空間重疊物體的模式,頂層中的默認對象將隱藏位於其下方的其他對象的任何部分。如果需要透明度,則有兩種選擇: 1). 如果要以專業方式打印文檔,並且正在使用CMYK色彩空間,則可以使用overPrint()。在套印中,顏色會在打印機中物理混合,從而獲得新的顏色。默認情況下,將應用剔除,並且僅出現頂部對象。 2). 如果文檔用於屏幕輸出,並且使用的是RGB顏色,則可以設置一個alpha值。其中alpha是顏色的不透明度值,默認的Alpha值為1(完全不透明),使用0-1范圍內的實數值進行設置。
Alpha透明度(alpha)與套印類似,但只在RGB顏色空間中有效。訪問網站http://www.reportlab.com/snippets/,查找overPrint和alpha的摘要,以獲得詳情。 以下演示RGB模式下的透明方式:
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
from reportlab.lib.units import cm # 厘米單位
from reportlab.lib.colors import pink, black, red, blue, green
from reportlab.lib import colors
from reportlab.lib.colors import Color
canvas = canvas.Canvas("hello.pdf")
def alpha(canvas):
red50transparent = Color(100, 0, 0, alpha=0.5)
canvas.setFillColor(black)
canvas.setFont('Helvetica', 10)
canvas.drawString(25, 180, 'solid')
canvas.setFillColor(blue)
canvas.rect(25, 25, 100, 100, fill=True, stroke=False)
canvas.setFillColor(red)
canvas.rect(100, 75, 100, 100, fill=True, stroke=False)
canvas.setFillColor(black)
canvas.drawString(225, 180, 'transparent')
canvas.setFillColor(blue)
canvas.rect(225, 25, 100, 100, fill=True, stroke=False)
canvas.setFillColor(red50transparent)
canvas.rect(300, 75, 100, 100, fill=True, stroke=False)
alpha(canvas)
canvas.showPage()
canvas.save()
- CMYK Colors CMYK或減法方法是遵循將打印機的三種顏料(青色,品紅色和黃色)混合形成顏色的方式。因為混合化學物質比混合光更困難,所以存在第四個參數:暗色。 例如,CMY顏料的化學組合通常不能產生完美的黑色,而是產生渾濁的顏色。因此,使用黑色打印機,請勿使用CMYK顏料,而應使用直接黑色墨水。由於CMYK的工作方式是更直接地映射到打印機硬件,因此在CMYK中指定的顏色可能會在打印時提供更好的保真度和更好的控制。 表示CMYK顏色的方式有兩種:每種顏色都可以用0到1之間的實數值,或0到100之間的整數值表示。根據自己的喜好,可以使用0-1之間實值的CMYKColor()或0-100之間整數的PCMYKColor()。0表示"無墨水",因此在白紙上打印可得到白色。1(如果使用PCMYKColor,則為100)表示"最大墨水量"。 例如 CMYKColor(0,0,0,1)為黑色,CMYKColor(0,0,0,0)表示"無墨水",而CMYKColor(0.5,0,0,0)表示50%的青色。 示例:
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
from reportlab.lib.colors import pink, black, red, blue, green
from reportlab.lib.colors import CMYKColor, PCMYKColor
canvas = canvas.Canvas("hello.pdf")
def colorsCMYK(canvas):
# create a black CMYK, CMYKColor use real values
black = CMYKColor(0, 0, 0, 1)
# create a cyan CMYK, PCMYKColor use integer values
cyan = PCMYKColor(100, 0, 0, 0)
y = x = 0
dy = inch * 3 / 4.0
dx = inch * 5.5 / 5
w = h = dy / 2
rdx = (dx - w) / 2
rdy = h / 5.0
texty = h + 2 * rdy
canvas.setFont("Helvetica", 10)
y = y + dy
x = 0
for cmyk in [(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1), (0, 0, 0, 0)]:
c, m, y1, k = cmyk
canvas.setFillColorCMYK(c, m, y1, k)
canvas.rect(x + rdx, y + rdy, w, h, fill=1)
canvas.setFillColor(black)
canvas.drawCentredString(x + dx / 2, y + texty, "c%s m%s y%s k%s" % cmyk)
x = x + dx
colorsCMYK(canvas)
canvas.showPage()
canvas.save()
最終效果如下:
2.9 Color space checking - 色彩空間檢查
canvas對象的executeColorSpace屬性,用於增強文檔中使用的顏色模型的一致性。它接受以下值:CMYK,RGB,SEP,SEP_BLACK,SEP_CMYK。"SEP"是指命名的顏色分離,例如Pantone專色-可以根據使用的參數將它們與CMYK或RGB混合。默認值為"MIXED",它允許使用任何顏色空間中的顏色。如果使用的任何顏色都無法轉換為指定的模型,將引發異常。(例如rgb和cmyk更多信息,請參見test_pdfgen_general)。這種方法不檢查文檔中包含的外部圖像。
2.10 Color Overprinting - 色彩疊印
當兩個CMYK彩色對象在打印中重疊時,則"頂部"對象將剔除其下一個對象的顏色,或者兩個對象的顏色在重疊區域混合。可以使用屬性overPrint設置此行為。套印功能將導致顏色的重疊區域混合。 用法:
canvas.setFillOverprint(bool)
示例代碼:
from reportlab.pdfgen import canvas
from reportlab.lib.colors import PCMYKColorSep
canvas = canvas.Canvas("hello.pdf")
def overprinting(canvas):
# 好像必須使用PCMYKColorSep。其他CMYKColor和PCMYKColor,沒有任何效果
blue = PCMYKColorSep(91.0, 43.0, 0.0, 0.0, density=100, spotName="blue") # spotName必須指定
red = PCMYKColorSep(0.0, 100.0, 91.0, 0.0, density=100, spotName="red")
canvas.setFillOverprint(True) # 使用疊印模式
canvas.setFillColor(blue)
canvas.rect(25, 25, 100, 100, fill=True, stroke=False)
canvas.setFillColor(red)
canvas.rect(100, 75, 100, 100, fill=True, stroke=False)
canvas.setFillOverprint(False) # 不使用疊印模式。這行代碼沒有的話,連同接下來的繪圖,都一直使用疊印模式
canvas.setFillColor(blue)
canvas.rect(225, 25, 100, 100, fill=True, stroke=False)
canvas.setFillColor(red)
canvas.rect(300, 75, 100, 100, fill=True, stroke=False)
overprinting(canvas)
canvas.showPage()
canvas.save()
左側矩形的顏色在重疊的位置處呈現混合顯示,最終效果如下: 如果看不到這種效果,則可能需要在PDF查看軟件中啟用"套印預覽"選項。某些PDF查看器(例如evince)不支持套印。Adobe Acrobat Reader是支持套印的。 Adobe Acrobat Reader開啟疊印的方式:
- Other Object Order of Printing Examples - 打印示例的其他對象順序
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
from reportlab.lib.colors import pink, black, red, white, green, brown
canvas = canvas.Canvas("hello.pdf")
def spumoni(canvas):
x = 0
dx = 0.4 * inch
for i in range(4):
for color in (pink, green, brown):
canvas.setFillColor(color)
canvas.rect(x, 0, dx, 3 * inch, stroke=0, fill=1)
x = x + dx
canvas.setFillColor(white)
canvas.setStrokeColor(white)
canvas.setFont("Helvetica-Bold", 85)
canvas.drawCentredString(2.75 * inch, 1.3 * inch, "SPUMONI")
spumoni(canvas)
canvas.showPage()
canvas.save()
最終效果如下: 該單詞的最后一個字母不可見,是因為默認的畫布背景為白色,並且在白色背景上繪制白色字母,造成視覺上的不可見效果。 這種在層上面構建復雜繪畫的方法可以在pdfgen的很多層中完成,物理限制比處理物理繪畫要少。 在上圖的基礎上,畫一個冰淇淋:
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
from reportlab.lib.colors import pink, black, red, white, green, blue, brown
canvas = canvas.Canvas("hello.pdf")
def spumoni(canvas):
x = 0
dx = 0.4 * inch
for i in range(4):
for color in (pink, green, brown):
canvas.setFillColor(color)
canvas.rect(x, 0, dx, 3 * inch, stroke=0, fill=1)
x = x + dx
canvas.setFillColor(white)
canvas.setStrokeColor(white)
canvas.setFont("Helvetica-Bold", 85)
canvas.drawCentredString(2.75 * inch, 1.3 * inch, "SPUMONI")
def spumoni2(canvas):
# 在spumoni的基礎上,畫一個冰淇淋
# 復用spumoni的代碼
spumoni(canvas)
# 首先畫一個冰淇淋的圓錐體(空心的圓錐體)
p = canvas.beginPath()
xcenter = 2.75 * inch # 198.0
radius = 0.45 * inch # 32.4
p.moveTo(xcenter - radius, 1.5 * inch) # 線條路徑移動至(x,y)
p.lineTo(xcenter + radius, 1.5 * inch) # 線條滑動,從x到y
p.lineTo(xcenter, 0) # 線條從xcenter開始(相當於x的點),滑動到0(相當於y的點)
p.lineTo(xcenter - radius, 1.5 * inch)
canvas.setFillColor(brown)
canvas.setStrokeColor(black)
canvas.drawPath(p, fill=1)
# 畫冰淇淋上面的圓球(從下往上畫)
y = 1.5 * inch
for color in (pink, green, brown):
canvas.setFillColor(color)
canvas.circle(xcenter, y, radius, fill=1)
y = y + radius
spumoni2(canvas)
canvas.showPage()
canvas.save()
冰淇淋最終效果:(注意:圓錐體和圓球的不同部分是彼此重疊的)
2.11 Standard fonts and text objects - 標准字體及文本對象
在pdfgen中,可以用許多不同的顏色、字體和大小來繪制文本。 示例1:
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
from reportlab.lib.colors import magenta, red
canvas = canvas.Canvas("hello.pdf")
lyrics = [
"well she hit Net Solutions", "and she registered her own .com site now",
"and filled it up with yahoo profile pics", "she snarfed in one night now",
"and she made 50 million when Hugh Hefner", "bought up the rights now",
"and she'll have fun fun fun", "til her Daddy takes the keyboard away"
]
def textsize(canvas):
canvas.setFont("Times-Roman", 20)
canvas.setFillColor(red)
canvas.drawCentredString(2.75 * inch, 2.5 * inch, "Font size examples")
canvas.setFillColor(magenta)
size = 7
y = 2.3 * inch
x = 1.3 * inch
for line in lyrics:
canvas.setFont("Helvetica", size)
canvas.drawRightString(x, y, f"{size} points:") # RightString相當於:x = x - textLen
canvas.drawString(x, y, line)
y = y - size * 1.2
size = size + 1.5
textsize(canvas)
canvas.showPage()
canvas.save()
示例1的最終效果: pdfgen中始終提供許多不同的字體。這些字體不需要存儲在PDF文檔中,就可以保證它們會出現在Acrobat Reader中。 示例2
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
canvas = canvas.Canvas("hello.pdf")
def fonts(canvas):
text = "Now is the time for all good men to..."
x = 1.8 * inch
y = 2.7 * inch
for font in canvas.getAvailableFonts(): # 獲取所有的自帶的可用字體
canvas.setFont(font, 10)
canvas.drawString(x, y, text)
canvas.setFont("Helvetica", 10)
canvas.drawRightString(x - 10, y, font + ":")
y -= 13
fonts(canvas)
canvas.showPage()
canvas.save()
示例2的最終效果: Symbol和ZapfDingbats字體無法顯示,是因為這些字體中不存在所需要的字形。(估計是因為字體的呈現需要字形依賴)
2.12 Text object methods - 文本對象的方法
對於PDF文檔中的文本專用顯示,請使用文本對象。文本對象接口提供了對文本布局參數的詳細控制,這些參數在畫布級別上不直接可用。另外,它產生的PDF較小,比對drawString()的許多單獨調用而言,文本對象的渲染速度更快。 以下一些文本對象的方法與基本文字幾何有關:
textobject.setTextOrigin(x,y)
textobject.setTextTransform(a,b,c,d,e,f)
textobject.moveCursor(dx, dy) # from start of current LINE
(x,y) = textobject.getCursor()
x = textobject.getX()
y = textobject.getY()
textobject.setFont(psfontname, size, leading = None)
textobject.textOut(text)
textobject.textLine(text='')
textobject.textLines(stuff, trim=1)
文本對象維護一個文本光標,該光標在繪制文本時在頁面上移動。例如,setTextOrigin將光標放置在已知位置,textLine和textLines方法將文本光標向下移動到缺少的行上方。 下例中,演示了:當文本對象的原點設置后,文本對象將依賴於文本光標的自動移動來放置文本
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
canvas = canvas.Canvas("hello.pdf")
lyrics = [
"well she hit Net Solutions", "and she registered her own .com site now",
"and filled it up with yahoo profile pics", "she snarfed in one night now",
"and she made 50 million when Hugh Hefner", "bought up the rights now",
"and she'll have fun fun fun", "til her Daddy takes the keyboard away",
]
def cursormoves1(canvas):
textobject = canvas.beginText()
textobject.setTextOrigin(inch, 2.5 * inch)
textobject.setFont("Helvetica-Oblique", 14)
for line in lyrics:
textobject.textLine(line)
textobject.setFillGray(0.4)
# 下面這個方法,如果少一個"s"變成了textLine,那么換行符會被渲染成一個黑色的實心框框
textobject.textLines("""With many apologies to the Beach Boys
and anyone else who finds this objectionable""")
canvas.drawText(textobject)
cursormoves1(canvas)
canvas.showPage()
canvas.save()
最終效果如下: 也可以通過使用moveCursor()方法來更明確地控制光標的移動。 例:
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
canvas = canvas.Canvas("hello.pdf")
lyrics = [
"well she hit Net Solutions", "and she registered her own .com site now",
"and filled it up with yahoo profile pics", "she snarfed in one night now",
"and she made 50 million when Hugh Hefner", "bought up the rights now",
"and she'll have fun fun fun", "til her Daddy takes the keyboard away",
]
def cursormoves2(canvas):
textobject = canvas.beginText()
textobject.setTextOrigin(2, 2.5 * inch)
textobject.setFont("Helvetica-Oblique", 14)
for line in lyrics:
textobject.textOut(line)
textobject.moveCursor(14, 14) # 根據給定的值進行移動
textobject.setFillColorRGB(0.4, 0, 1)
textobject.textLines("""With many apologies to the Beach Boys
and anyone else who finds this objectionable""")
canvas.drawText(textobject)
cursormoves2(canvas)
canvas.showPage()
canvas.save()
與textLine()函數向下移動相比,此處的textOut()不會向下移動一行,是通過moveCursor()方法進行移動。 moveCursor()方法的作用:從當前行的起始處偏移(dx,dy)開始新行。這不會相對於當前位置移動光標,它會更改以后繪制的每條線的當前偏移量(例如,下次調用textLine()方法,它將光標移動到比此調用中指定的位置低一行的位置) 最終效果如下:
- Character Spacing - 字符間距(字間距) 注意:該方法是控制每個字符的間距,而不是單詞之間的間距! 用法:
textobject.setCharSpace(int)
示例:
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
canvas = canvas.Canvas("hello.pdf")
lyrics = [
"well she hit Net Solutions", "and she registered her own .com site now",
"and filled it up with yahoo profile pics", "she snarfed in one night now",
"and she made 50 million when Hugh Hefner", "bought up the rights now",
"and she'll have fun fun fun", "til her Daddy takes the keyboard away",
]
def charspace(canvas):
textobject = canvas.beginText()
textobject.setTextOrigin(3, 2 * inch)
textobject.setFont("Helvetica-Oblique", 10)
charspace = 0
for line in lyrics:
textobject.setCharSpace(charspace)
textobject.textLine(f"{charspace}: {line}")
charspace += 0.5
textobject.setFillGray(0.4)
textobject.textLines("""With many apologies to the Beach Boys
and anyone else who finds this objectionable""")
canvas.drawText(textobject)
charspace(canvas)
canvas.showPage()
canvas.save()
最終效果如下:
- Word Spacing - 單詞間距 注意:該方法是控制單詞之間的間距(詞間距)! 用法:
textobject.setWordSpace(int)
示例:
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
canvas = canvas.Canvas("hello.pdf")
lyrics = [
"well she hit Net Solutions", "and she registered her own .com site now",
"and filled it up with yahoo profile pics", "she snarfed in one night now",
"and she made 50 million when Hugh Hefner", "bought up the rights now",
"and she'll have fun fun fun", "til her Daddy takes the keyboard away",
]
def wordspace(canvas):
textobject = canvas.beginText()
textobject.setTextOrigin(3, 2 * inch)
textobject.setFont("Helvetica-Oblique", 12)
wordspace = 0
for line in lyrics:
textobject.setWordSpace(wordspace)
textobject.textLine(f"{wordspace}: {line}")
wordspace += 2.5
textobject.setFillColorCMYK(0.4, 0, 0.4, 0.2)
textobject.textLines('''With many apologies to the Beach Boys
and anyone else who finds this objectionable''')
canvas.drawText(textobject)
wordspace(canvas)
canvas.showPage()
canvas.save()
最終效果如下:
- Horizontal Scaling - 水平縮放 可以使用setHorizScale()方法水平拉伸或縮小文本行。實際上就是拉伸或壓縮文本。 用法:
textobject.setHorizScale(horizScale)
setHorizScale()方法的參數,實際上是一個百分比,默認為100 示例:
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
canvas = canvas.Canvas("hello.pdf")
lyrics = [
"well she hit Net Solutions", "and she registered her own .com site now",
"and filled it up with yahoo profile pics", "she snarfed in one night now",
"and she made 50 million when Hugh Hefner", "bought up the rights now",
"and she'll have fun fun fun", "til her Daddy takes the keyboard away",
]
def horizontalscale(canvas):
textobject = canvas.beginText()
textobject.setTextOrigin(3, 2 * inch)
textobject.setFont("Helvetica-Oblique", 12)
horizontalscale = 80
for line in lyrics:
textobject.setHorizScale(horizontalscale) # setHorizScale()方法的參數,實際上是一個百分比值,默認是100
textobject.textLine(f"{horizontalscale}: {line}")
horizontalscale += 10
textobject.setFillColorCMYK(0.0, 0.4, 0.4, 0.2)
textobject.textLines('''With many apologies to the Beach Boys
and anyone else who finds this objectionable''')
canvas.drawText(textobject)
horizontalscale(canvas)
canvas.showPage()
canvas.save()
最終效果如下:
- Interline spacing(Leading) - 行間間距(行距) 一條線的起點與下一條線的起點之間的垂直偏移稱為行距。setLeading()方法調整行距偏移。 用法:
textobject.setLeading(leading)
示例:
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
canvas = canvas.Canvas("hello.pdf")
lyrics = [
"well she hit Net Solutions", "and she registered her own .com site now",
"and filled it up with yahoo profile pics", "she snarfed in one night now",
"and she made 50 million when Hugh Hefner", "bought up the rights now",
"and she'll have fun fun fun", "til her Daddy takes the keyboard away",
]
def leading(canvas):
textobject = canvas.beginText()
textobject.setTextOrigin(3, 2 * inch)
textobject.setFont("Helvetica-Oblique", 14)
leading = 5
for line in lyrics:
textobject.setLeading(leading)
textobject.textLine(f"{leading}: {line}")
leading += 2
textobject.setFillColorCMYK(0.8, 0, 0, 0.3)
textobject.textLines('''With many apologies to the Beach Boys
and anyone else who finds this objectionable''')
canvas.drawText(textobject)
leading(canvas)
canvas.showPage()
canvas.save()
最終效果如下:
- Other text object methods - 其他的文本對象方法 a).``` textobject.setTextRenderMode(mode)
b).```
textobject.setRise(float)
```將文本設置為上標或者下標
如果不再需要上標或者下標,必須要復原:setRise(0),不然下一次輸出文本內容時,還是在老位子顯示文本內容。
setRise()示例:
```python
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
canvas = canvas.Canvas("hello.pdf")
lyrics = [
"well she hit Net Solutions", "and she registered her own .com site now",
"and filled it up with yahoo profile pics", "she snarfed in one night now",
"and she made 50 million when Hugh Hefner", "bought up the rights now",
"and she'll have fun fun fun", "til her Daddy takes the keyboard away",
]
def leading(canvas):
textobject = canvas.beginText()
textobject.setTextOrigin(10, 50)
textobject.setFont("Helvetica-Oblique", 12)
# textOut()在當前位置輸出文本內容,文本游標橫向移動
# textLine()在當前位置輸出文本內容,文本游標移動到下一行
textobject.textOut("O")
textobject.setRise(5)
textobject.textLine("2")
# 不再需要使用上標或者下標時,就必須進行復原
# 文本對象會記憶它當前的所有狀態,否則下一次輸出的文本內容還是會出現在老地方
textobject.setRise(0)
textobject.textLine() # 空一行而已
textobject.textOut("H")
textobject.setRise(-5)
textobject.textOut("2")
textobject.setRise(0) # 復原
textobject.textOut("O")
canvas.drawText(textobject)
leading(canvas)
canvas.showPage()
canvas.save()
最終效果如下:
2.13 Paths and Lines - 路徑和線
路徑對象是為圖形的專用構造而設計的。將路徑對象繪制到畫布上時,它們將被繪制為一個圖形(如矩形),並且可以調整整個圖形的繪制方式:圖形的線條是否可以繪制(描邊);圖的內部是否可以填充等等。 示例,畫一顆星型:
from math import pi, cos, sin
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
canvas = canvas.Canvas("hello.pdf")
def star(canvas, title="Title Here", aka="Comment here.", xcenter=None, ycenter=None, nvertices=5):
radius = inch / 3
if xcenter is None:
xcenter = 1.2 * inch
if ycenter is None:
ycenter = 1 * inch
canvas.drawCentredString(xcenter, ycenter + 1.3 * radius, title)
canvas.drawCentredString(xcenter, ycenter - 1.4 * radius, aka)
p = canvas.beginPath()
p.moveTo(xcenter, ycenter + radius)
angle = (2 * pi) * 2 / 5.0
startangle = pi / 2.0
for vertex in range(nvertices - 1):
nextangle = angle * (vertex + 1) + startangle
x = xcenter + radius * cos(nextangle)
y = ycenter + radius * sin(nextangle)
p.lineTo(x, y)
if nvertices == 5:
p.close()
canvas.drawPath(p)
star(canvas)
canvas.showPage()
canvas.save()
最終效果如下:
- Line join settings - 線連接設置 setLineJoin()方法可以調整線段連接頂點的樣式(圓形、棱角……)。 線連接設置僅對粗線有用,對於細的線無法清晰地看到。
from math import pi, cos, sin
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
canvas = canvas.Canvas("hello.pdf")
def star(canvas, title="Title Here", aka="Comment here.", xcenter=None, ycenter=None, nvertices=5):
radius = inch / 3
if xcenter is None:
xcenter = 2.7 * inch
if ycenter is None:
ycenter = 1 * inch
canvas.drawCentredString(xcenter, ycenter + 1.3 * radius, title)
canvas.drawCentredString(xcenter, ycenter - 1.4 * radius, aka)
p = canvas.beginPath()
p.moveTo(xcenter, ycenter + radius)
angle = (2 * pi) * 2 / 5.0
startangle = pi / 2.0
for vertex in range(nvertices - 1):
nextangle = angle * (vertex + 1) + startangle
x = xcenter + radius * cos(nextangle)
y = ycenter + radius * sin(nextangle)
p.lineTo(x, y)
if nvertices == 5:
p.close()
canvas.drawPath(p)
def joins(canvas):
canvas.setLineWidth(5) # 將線條加粗
# setLineJoin()所提供的參數 -> {0:'miter', 1:'round', 2:'bevel'}
# miter:尖頭的(默認)、round:圓形的、bevel:方角的
star(canvas, "Default: mitered join", "0: pointed", xcenter=1 * inch)
canvas.setLineJoin(1)
star(canvas, "Round join", "1: rounded")
canvas.setLineJoin(2)
star(canvas, "Bevelled join", "2: square", xcenter=4.5 * inch)
joins(canvas)
canvas.showPage()
canvas.save()
最終效果如下:
- Line cap settings - 線帽設置