ren1244/pdfwriter

此包最新版本(v1.0.0-alpha)无可用许可证信息。

可扩展的PHP PDF库

v1.0.0-alpha 2020-11-10 09:30 UTC

This package is auto-updated.

Last update: 2024-09-06 12:48:05 UTC


README

这是一个于2020年底新开发的PHP PDF库

*注意:这是一个预览版本,非正式发布,有些东西可能还会变动*

项目方向

  • 支持全范围Unicode(现在很多PHP PDF函数库只支持到基本多文种平面
  • 至少支持TTF与OTF字体,或是更多种。
  • 当字体缺字时,自动切换为候选字体。这可以达到英数与中文字采用不同字型的效果。
  • 提供扩展的接口,让其他开发者根据需求扩展自己需要的模块。

安装

composer require ren1244/pdfwriter:dev-main

使用

以下是最简单的代码,只生成一个空白页面

$pdf = new PDFWriter; //建立 PDFWriter 物件
$pdf->addPage('A4'); //添加空白頁面
$pdf->output();

通过调用addPage方法可以不断地增加新的页面

※以下均以 $pdf 代表建立好的PDFWriter对象

新增页面

指定新增的页面大小,可以直接给予长宽

//新增寬 20 cm 高 15 cm 的頁面
$pdf->addPage(200, 150);

或是输入预先设定的纸张种类,目前可设定的值有:

  • A 系列: "A0""A10"
  • B 系列: "B0""B10"
  • C 系列: "C0""C10"
  • JIS-B 系列: "JIS-B0""JIS-B10"
//新增一張 A4 大小的頁面,預設是直向
$pdf->addPage('A4');

如果希望纸张是横向的,可以在预定的纸张种类后面加上 "L""H",意思分别是Landscape 与 Horizontal

//新增一張 A4 大小的頁面,橫向
$pdf->addPage('A4H');

输出PDF

默认是把pdf直接返回给用户,如果想先存储在服务器内的文件,可以在输出时指定一个file pointer resource

$fp = fopen('output.pdf', 'wb');
$pdf->output($fp);
fclose($fp);

单位

当涉及到长度的参数时,若没有特别提及,都是指「目前选用的单位」(后面以「目前单位」简称)

默认状态下,「目前单位」被设置为 "mm",可以设置 PageMetrics::$unit 来改变它

允许设定的值有 "cm", "mm", "pt",设置其他值的的话都会视为 "pt"

// 把「目前單位」設定為 "cm"
PageMetrics::$unit = "cm";

如果临时要把 pt 转换为「目前单位」

// 把 0.5 pt 轉換為「目前單位」
PageMetrics::getUnit(0.5);

如果临时要把「目前单位」转换为 pt

// 把 0.25 「目前單位」轉換 pt
PageMetrics::getPt(0.25);

文字

$pdf = new PDFWriter;
$pdf->addPage('A4');

// 添加字型(此時會自動設定目前字型為 Times-Roman 12pt)
$pdf->font->addFont('Times-Roman');
// 設定字型(Times-Roman 14pt)
$pdf->font->setFont('Times-Roman', 14);
// 設定要寫入的矩形區域: left, top, width, height (單位是「目前單位」,此時是 mm)
$pdf->text->setRect(10, 10, 100, 100);
//寫入文字
$pdf->text->addText('Hello');

$pdf->output();

内置字体

上面的示例中的 $pdf->font->addFont('Times-Roman'); 就是使用内置字体。

目前内置的字型有,包含一般的英数字元

  • Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic
  • Helvetica, Helvetica-Bold, Helvetica-Oblique, Helvetica-BoldOblique
  • Courier, Courier-Bold, Courier-Oblique, Courier-BoldOblique

自定义字体

通过script/addFont.php添加字体(产生的结果放在font文件夹)

php script/addFont.php {filename} [{outname}]
  • filename: 字体文件
  • outname: 提供 addFontsetFont 使用的名称,若省略会自动根据字体文件产生

字体替代

这个功能是在字体缺字的情况下,允许自动切换替代的字型。

通过这个功能,可以让我们在英数字自动使用 Times-Roman,而遇到中文自动使用 Noto-Sans

示例如下

$pdf->font->setFont([
    'Times-Roman' => 12, // 優先使用 Times-Roman 12pt
    'Noto-Sans' => 14,   // 如果缺字,用 Noto-Sans 14pt 替代
]);

文字的排版

  • 文字必须在由 setRect 指定的文字框内,如果空间不够会截断
  • 目前不支持跨页,也就是每页的状态是独立的

addText 的第二个参数是一个可选参数,为一个关联数组,可以有以下选项

直书

此功能开发中,目前处理英文、数字与中文,其他语言会当作中文处理。

addTextV 写入直书文字

$pdf = new PDFWriter;
$pdf->addPage('A4');

// 這邊用到自訂字型,請參考前面的說明
// 第二個參數設為 true 開啟直書功能
$pdf->font->addFont('SourceHanSansTC-Regular', true);
// 設定字型(Times-Roman 14pt)
$pdf->font->setFont('SourceHanSansTC-Regular', 14);
// 設定要寫入的矩形區域: left, top, width, height (單位是「目前單位」,此時是 mm)
$pdf->text->setRect(10, 10, 100, 100);
// 用 addTextV 寫入直書文字
$pdf->text->addTextV("關關雎鳩,在河之洲。\n窈窕淑女,君子好逑。");

$pdf->output();

addTextV 的第二个参数是一个可选参数,为一个关联数组,可以有以下选项

图形

向量图(线条)

目前只能用postScript语言来画线条(跟svg有点像)

/**
 * 畫一條從 (10, 10) 到 (20, 30) 的直線,線寬是 1 pt
 * 這邊單位都是「目前單位」,所以指定線寬時使用 PageMetrics::getUnit
 */
$pdf->postscriptGragh->addPath('10 10 m 20 30 l S', PageMetrics::getUnit(1));

点阵图

目前支持的格式有 pngjpeg,其他格式要先转换一下

// 把 jpg 圖片畫在 ($x, $y) 的位置,長寬依照原本的尺寸
$pdf->image->addImage("example.jpg", $x, $y);

// 把 png 圖片畫在 ($x, $y) 的位置,並指定長寬
$pdf->image->addImage("example.png", $x, $y, $width, $height);

/** 
 * 把 png 圖片畫在 ($x, $y) 的位置
 * 當長寬只指定一個的時候,另一個請設定為 false,此時會等比例縮放
 */
$pdf->image->addImage("example.png", $x, $y, false, $height);

若是已经取得图文件内容,可以使用 addImageRaw 方法,使用方法与 addImage 相同。

$imageContent = file_get_contents("example.png");
$pdf->image->addImageRaw($imageContent, $x, $y, $width, $height);

书签

简易书签

// 建立一個書籤,當點擊時會跳到第 2 頁,從頂部往下算 10 unit 的位置
$pdf->addOutline("第一章", 2, 10);

/**
 * 建立一個書籤,當點擊時會跳到第 3 頁,從頂部往下算 10 unit 的位置
 * 樣式被設定為「斜體 + 粗體」,顏色為紅色(#FF0000)
 */
$pdf->addOutline("第二章", 3, 10, Outline::ITALIC | Outline::BOLD, "FF0000");

多层级书签

// 紀錄 addOutline 回傳的值,這是一個 Outline 物件
$chapter1 = $pdf->addOutline("第一章", 2, 10);

// Outline 物件本身也可以建立書籤,參數最多可以有 5 個,說明參考「簡易書籤」的部分
$chapter1->addOutline("第一節", 2, 15);

// 若不指定第幾頁,則點擊後無任何效果,可以單純作為資料夾
$other = $pdf->addOutline("其他");
$other->addOutline("參考文件", 10, 10);

加密

目前支持 Aes256、Aes128、Rc4_128 三种加密,可参考 examples/ex3_encryption.php

扩展功能

在架构上,PDFWriter 分为三层:

  1. PDFWriter 核心:管理字体、页面等,并把字体和页面提供给 Cntent Module 开发使用。
  2. Cntent Module:通过 PDFWriter 提供的对象,负责产生页面的内容。
  3. 一般使用者:使用 PDFWriter + Cntent Module(s) 产生 PDF

关于如何建立 Cntent Module 可以参考:如何加入新的模块

这边的只介绍自带的基本功能:字体、文字、线条、内嵌点阵图 如果只是产生报表应该还堪用

PS. 文字、线条的功能都是由 Cntent Module 实现,现阶段不会太深入高级功能的开发,而是通过提供接口给增加功能的灵活性。所以只提供最基础的功能。