Compare commits

...
58 Commits
Author SHA1 Message Date
csh 7a46ccf838 适配officexml20250925 2025-09-25 17:58:36 +08:00
csh 7da30f77ab 性能优化:copy改成fallback模式 2025-06-04 15:20:13 +08:00
csh 4be804cb1b 性能优化1: 单位转换由装饰器方式改为方法 2025-06-03 16:27:41 +08:00
csh 5121a94b15 公式基准调整 2025-05-07 14:16:17 +08:00
csh 600ce2e358 初步refactor xml公式 2025-04-22 17:48:52 +08:00
csh 2e0aadd3d0 refactor 2025-04-03 17:52:39 +08:00
csh 9f84a72595 代码重构
fix:表格边框错误
注意:暂时移除脚注和公式的支持
2025-03-24 17:17:22 +08:00
csh a118ff6c26 update 2025-02-18 10:24:25 +08:00
csh 5c93255461 1. 重构代码
2. 优化中文和西文字符间距
2025-02-18 10:23:49 +08:00
csh 973f880dd7 update 2024-12-23 14:44:01 +08:00
csh bdbd201e44 1. 修复段落有首行间距,居中算法不对问题
2. 修复段前分页失效
2024-12-19 10:31:20 +08:00
csh 4c002f803f 1. 支持分栏
2. 支持简单的单个脚注
2024-12-13 17:19:52 +08:00
csh a677e5a843 1. 支持常用的中文标点符号不再第一个字符位置
2. 支持wmf图片(需升级dll)
2024-11-27 14:38:44 +08:00
csh 3b16e6969f 页码起始页为1 2024-11-25 09:55:15 +08:00
csh f251782186 表格边框优化 2024-11-25 09:54:41 +08:00
csh b1cb66fd48 update 2024-11-20 17:20:41 +08:00
csh 0437961953 新增修改docx页码接口UpdateDocxPageNumpages,以及保存修改docx文件接口SaveDocxFile 2024-11-20 17:08:13 +08:00
csh 8ab1670eea 修复填充色shd的值是clear表示不填充 2024-11-20 17:06:41 +08:00
csh 57f673f457 对目录文字到页码的连线进行优化,由文字"."改成画线方式 2024-11-15 15:29:34 +08:00
csh 5652980a97 项目符号采用ZapfDingbats字体 2024-11-13 17:40:46 +08:00
csh 003268fd40 1. 重构部分表格代码
2. 支持表格的边框样式`single`和`dashed`
3. 遇到不支持的项目符号采用数字代替
2024-11-13 16:38:43 +08:00
csh da65b2b6c3 1. 支持中文的“一二”等项目符号
2. 完善对页码类型的支持
2024-11-11 14:40:16 +08:00
csh 222577dd74 支持段前分页 2024-11-04 16:00:06 +08:00
csh 2d6632895b 支持表格固定高度 2024-11-04 15:42:29 +08:00
csh 535bdb20d4 1. 完善页码类型的支持
2. 修复auto颜色抛出异常问题
2024-10-28 14:45:48 +08:00
csh eb6e898ed7 1. fix跨页表格绘制
2. 段落支持对齐右边界
2024-10-28 13:23:46 +08:00
csh 4de1484ec3 修复重复图片bug 2024-10-25 15:45:15 +08:00
csh 9db7890278 支持emf格式的图片(word中插入excel表格) 2024-10-22 14:29:35 +08:00
csh 2a7027476a 1. 修复段落字体不一致问题
2. 修复图片(印章为例)的位置不正确
3. 修复其他报错问题
4. 项目符号用可中文能识别的符号替代
2024-10-11 10:52:10 +08:00
csh 68ce759668 1. 修复表格遇到边界报错问题
2. 支持表格的奇数行、偶数行样式
2024-09-26 11:40:23 +08:00
csh 5dc201c1a2 支持excel ole对象产生的emf文件 2024-09-20 14:09:02 +08:00
csh 448bbfc7e2 对依赖的OfficeXml性能优化版本做调整 2024-09-19 10:48:53 +08:00
csh 0417669eb2 修复跨页表格出现空白单元格 2024-09-11 09:13:29 +08:00
csh 9886040fa9 修复跨多页表格渲染错误问题 2024-09-10 15:12:27 +08:00
csh 43ffb5b5c0 fix bugs 2024-09-06 17:18:34 +08:00
csh 440788412b 1. 表格的对齐
2. 跨页表格的处理
2024-09-06 11:23:30 +08:00
csh 61b86d34e7 暂时移除外部字体文件 2024-09-06 11:21:40 +08:00
csh a0ea61af14 1. 优化单元格合并
2. 支持单元格垂直居中
2024-09-03 16:49:25 +08:00
csh ca18537538 完善对页眉页脚的支持 2024-08-27 15:59:44 +08:00
csh 4c6f4d6e09 支持文本框 2024-08-26 15:03:35 +08:00
csh 70ad4acbdb 整合页眉页脚代码 2024-08-21 15:41:08 +08:00
csh 4357cfb529 移除目录的边框线,wps显示目录不再有边框 2024-08-14 16:08:05 +08:00
csh d0de1aa227 修复空段落不正常输出空行 2024-08-14 13:34:00 +08:00
csh 1cd72f6247 1. 支持表格列合并
2. 支持表头背景填充样式
2024-08-14 11:05:47 +08:00
csh 9dc7a66b62 修复:目录换行位置计算错误 2024-08-08 11:40:12 +08:00
csh d687f45b3b 修复目录链接跳转位置不正确 2024-08-06 16:19:24 +08:00
csh 1eee1efc3a 支持简单的页眉页脚 2024-08-05 11:32:19 +08:00
csh 151eef66b7 修复单元格合并,边框显示不正确问题 2024-07-30 14:34:27 +08:00
csh e5dfdeadc0 修复标题在前,目录在后,页码无法定位 2024-07-29 15:43:45 +08:00
csh d14de26d58 支持目录 2024-07-19 14:49:22 +08:00
csh cfc2d74ab8 抽象page为tspage对象,增加索引 2024-07-11 14:14:54 +08:00
csh d3f9431b26 1. self.替换成{self.}
2. 修复table表格绘画失败问题
2024-07-10 16:17:44 +08:00
csh 615f4a5b39 新增对单例类的内存释放 2024-07-09 13:32:16 +08:00
csh 5fe2911608 fix 2024-07-08 16:55:43 +08:00
csh b167501fde update 2024-07-08 15:25:46 +08:00
csh 66ec96e167 修复内存泄漏;对空段落项目符号容错处理 2024-07-08 15:24:55 +08:00
csh 51dc8596be 对range进行重构 2024-07-04 11:20:10 +08:00
csh 999a7ef2d0 移除调试代码 2024-06-27 15:45:13 +08:00
28 changed files with 4672 additions and 1103 deletions
+1 -1
View File
@@ -33,4 +33,4 @@ TSDocxToPdf中的[Font](./ware/TSFontWare.tsf)属性是设置转PDF时的一些
1. `office_plugin.dll`
2. [PDF](https://git.mytsl.cn/tinysoft/Pdf)相关包
3. [Office](https://git.mytsl.cn/tinysoft/Office)相关包
3. [Office](https://git.mytsl.cn/tinysoft/OfficeXml)相关包
+359 -147
View File
@@ -1,57 +1,99 @@
type TSDocxToPdf = class
uses TSPdfEnumerations, DocxMLAdapters, DTPModules, DTPAdvancedRanges;
public
function Create(alias: string; file: string);
function Destroy();
function SaveToFile(alias: string; file: string): integer;
function Transform();
function GetCurrentPage(): PdfPage;
function GetCurrentPoint(): Point;
function GetCachePath(image_path: string): string;
function GetPdf(): PdfFile;
function GetNextPage(page: PdfPage): PdfPage;
function AddPage(sect_ware: TSSectWare): PdfPage;
function GetCurrentXmlFile(): string;
property Font read ReadFont;
function ReadFont();
function AddPage(flag: boolean): Page;
function ProcessRealtimeRange();
// docx页码扩展
function UpdateDocxPageNumPages();
function SaveDocxFile();overload;
function SaveDocxFile(alias: string; file: string);overload;
property PdfFile read pdf_;
property DocxComponents read docx_components_module_;
property Font read font_module_;
property PageManager read page_manager_module_;
property Toc read toc_module_;
property Note read note_module_;
property CurrentSect read current_sect_module_;
property CurrentPage read current_page_;
private
function InitDocxComponents(alias: string; file: string);
function InitCachePath(file: string);
function InitPdfEncoder();
function InitSectWare();
function AllocateElementsToSectWare();
function InitSectModule();
function AllocateElementsToSectModule();
function ClassifyCols(var point: Point; cols: Cols);
function RangesSpacing(range: BasicRange);
function ResetCoordinates(sect_ware: TSSectWare);
function TransformParagraph(sect_ware: TSSectWare; paragraph: P);
function TransformTable(sect_ware: TSSectWare; table: Tbl);
function PrintGrid(page: PdfPage; sect_ware: TSSectWare); // test
function SetHdr(type: string);
function SetFtr(type: string);
function TransformP(p: P);
function TransformTbl(tbl: Tbl);
function TransformSdt(sdt: Sdt);
private
pdf_: PdfFile;
docx_components_: Components; // Components@DOCX
docx_components_module_: DocxComponentsModule; // DocxComponentsModule
cache_path_: string; // 临时目录,用来存放临时文件
sect_ware_array_: array of TSSectWare; // 页面布局组件数组
font_ware_: TSFontWare; // 字体部件
current_page_: PdfPage;
point_: TSPoint; // 定位坐标点
page_array_: array of PdfPage;
page_index_: tableArray;
font_module_: FontModule; // 字体模块
sect_module_array_: array of SectModule; // 页面布局模块数组
current_sect_module_: SectModule;
current_sect_pr_adapter_: SectPr; // DocxMLAdapters.SectPr
page_manager_module_: PageManagerModule;
current_page_: Page;
toc_module_: TocModule; // 目录模块
note_module_: NoteModule; // 脚注/尾注
xml_file_: string;
even_and_odd_flag_: boolean;
realtime_range_array_: array of BasicRange; // 最后才能计算出来的range,比如包含总页码的
last_range_: BasicRange; // 上一个range
// 回写docx
docx_page_arr_: tableArray;
update_docx_pages_: boolean;
end;
function TSDocxToPdf.Create(alias: string; file: string);
begin
pdf_ := new PdfFile();
self.InitPdfEncoder();
self.InitDocxComponents(alias, file);
self.InitCachePath(file);
self.InitSectWare();
font_ware_ := new TSFontWare(pdf_);
pdf_.SetCompressionMode(TSPdfEnumerations.COMP_ALL);
font_module_ := new DTPModules.FontModule(pdf_);
{self.}InitPdfEncoder();
{self.}InitDocxComponents(alias, file);
{self.}InitCachePath(file);
{self.}InitSectModule();
current_page_ := nil;
point_ := new TSPoint();
page_array_ := array();
page_index_ := array();
page_manager_module_ := new DTPModules.PageManagerModule(pdf_);
toc_module_ := new DTPModules.TocModule();
xml_file_ := "document.xml";
settings := docx_components_module_.Settings;
settings.XmlChildEvenAndOddHeaders.Deserialize();
even_and_odd_flag_ := settings.EvenAndOddHeaders ? true : false;
note_module_ := new DTPModules.NoteModule(self);
realtime_range_array_ := array();
// 回写docx
docx_page_arr_ := array();
update_docx_pages_ := false;
end;
function TSDocxToPdf.Destroy();
@@ -66,33 +108,38 @@ end;
function TSDocxToPdf.Transform();
begin
prev := nil;
for _,sect_ware in sect_ware_array_ do
for _,sect_module in sect_module_array_ do
begin
if prev <> sect_ware then
if current_sect_module_ <> sect_module then
begin
self.AddPage(sect_ware);
prev := sect_ware;
current_sect_module_ := sect_module;
current_sect_pr_adapter_ := new DocxMLAdapters.SectPr(current_sect_module_.SectPr);
{self.}AddPage(true);
end
elements := sect_ware.Elements();
// 分栏
elements := sect_module.Elements();
cols := current_sect_module_.SectPr.Cols;
if cols.Num > 1 then
begin
columns := {self.}ClassifyCols(current_page_.TextPoint, cols);
end
else begin
for _,element in elements do
begin
println("_ = {}", _);
if _ = 266 then return;
if element.LocalName = "p" then self.TransformParagraph(sect_ware, element);
else if element.LocalName = "tbl" then self.TransformTable(sect_ware, element);
// if _ = 4 then break;
// if _ = 31 then
// if element.LocalName = "p" then
// println("_ = {}, paraid = {}, xml_file_ = {}, error = {}", _, element.ParaId, xml_file_, pdf_.GetError());
// println("_ = {}", _);
if element.LocalName = "p" then {self.}TransformP(element);
else if element.LocalName = "tbl" then {self.}TransformTbl(element);
else if element.LocalName = "sdt" then {self.}TransformSdt(element);
end
end
end;
function TSDocxToPdf.GetCurrentPage(): PdfPage;
begin
return current_page_;
end;
function TSDocxToPdf.GetCurrentPoint(): Point;
begin
return point_;
end
{self.}ProcessRealtimeRange();
end;
function TSDocxToPdf.GetCachePath(image_path: string): string;
@@ -100,14 +147,9 @@ begin
return cache_path_ + extractFileName(image_path);
end;
function TSDocxToPdf.GetPdf(): PdfFile;
function TSDocxToPdf.GetCurrentXmlFile(): string;
begin
return pdf_;
end;
function TSDocxToPdf.ReadFont();
begin
return font_ware_;
return xml_file_;
end;
function TSDocxToPdf.InitPdfEncoder();
@@ -119,10 +161,9 @@ end;
function TSDocxToPdf.InitDocxComponents(alias: string; file: string);
begin
namespace "DOCX";
docx_components_ := new Components();
[err, msg] := docx_components_.OpenFile(alias, file, nil);
if err then raise "Create obejct 'TSDocxFile' failed.";
docx_components_module_ := new DTPModules.DocxComponentsModule();
[err, msg] := docx_components_module_.Open(alias, file, nil);
if err then raise "Open file error.";
end;
function TSDocxToPdf.InitCachePath(file: string);
@@ -134,135 +175,306 @@ begin
createDir("", cache_path_);
end;
function TSDocxToPdf.InitSectWare();
function TSDocxToPdf.InitSectModule();
begin
document := docx_components_.Document;
sect_module_array_ := array();
current_sect_module_ := nil;
current_sect_pr_adapter_ := nil;
document := docx_components_module_.Document;
document.Deserialize();
sect_ware_array_ := array();
self.AllocateElementsToSectWare();
document.ConvertToPoint();
{self.}AllocateElementsToSectModule();
end;
function TSDocxToPdf.AllocateElementsToSectWare();
function TSDocxToPdf.AllocateElementsToSectModule();
begin
elements := docx_components_.Document.Body.Elements();
ware := new TSSectWare();
fp := function(ware, sect);
elements := docx_components_module_.Document.Body.Elements();
module := new DTPModules.SectModule();
fp := function(module, sect);
begin
sect := new SectPrUnitDecorator(sect);
sect.PgSz.Orient := sect.PgSz.Orient ? "portrait" : "landscape";
ware.SectPr := sect;
ware.Do();
sect.Type.Val := sect.Type.Val ?: "nextPage";
module.SectPr := sect;
module.BaseSize := round(sect.DocGrid.LinePitch * 0.75);
end
for i:=0 to length(elements)-1 do
begin
element := elements[i];
ware.Elements[length(ware.Elements)] := element;
if element.LocalName = "p" and ifObj(element.PPr.SectPr.XmlNode) then
module.AddElement(element);
if element.LocalName = "p" and element.PPr.SectPr then
begin
##fp(ware, element.PPr.SectPr);
sect_ware_array_[length(sect_ware_array_)] := ware;
ware := new TSSectWare();
##fp(module, element.PPr.SectPr);
sect_module_array_[length(sect_module_array_)] := module;
module := new DTPModules.SectModule();
end
else if element.LocalName = "sectPr" and i = length(elements)-1 then
begin
##fp(ware, element);
sect_ware_array_[length(sect_ware_array_)] := ware;
##fp(module, element);
sect_module_array_[length(sect_module_array_)] := module;
end
end
// println("sect_ware_array_ = {}", sect_ware_array_);
// println("sect_module_array_ = {}", sect_module_array_);
end;
function TSDocxToPdf.AddPage(sect_ware: TSSectWare): PdfPage;
function TSDocxToPdf.AddPage(flag: boolean = false): Page;
begin
current_page_ := pdf_.AddPage();
current_page_.SetWidth(sect_ware.SectPr.PgSz.W);
current_page_.SetHeight(sect_ware.SectPr.PgSz.H);
self.ResetCoordinates(sect_ware);
if current_sect_module_.SectPr.Type.Val = "continuous" and page_manager_module_.Count <> 0 then return;
len := length(page_array_);
page_array_[len] := current_page_;
page_index_[current_page_] := len;
page := page_manager_module_.NewPage();
page.SectPr := current_sect_module_.SectPr;
page.Number := flag ? ifnil(current_sect_module_.SectPr.PgNumType.Start) ? 1 : current_sect_module_.SectPr.PgNumType.Start : page_manager_module_[page_manager_module_.Count() - 2].Number + 1;
if sysparams["_PDF_PAGE_GRID_DEBUG_"] then
self.PrintGrid(current_page_, sect_ware);
current_page_ := page;
// 页眉页脚
if current_sect_module_.SectPr.TitlePg and current_page_.Index = 0 then
type_name := "first";
else if not even_and_odd_flag_ then
type_name := "default";
else if not odd(current_page_.Index) then
type_name := "even";
else
type_name := "default";
{self.}SetHdr(type_name);
{self.}SetFtr(type_name);
// 设置完页眉页脚计算正文坐标
page.TextPoint.X := page.SectPr.PgMar.Left;
page.TextPoint.Y := page.SectPr.PgSz.H - max(page.SectPr.PgMar.Top, page.SectPr.PgMar.Header);
page.TextPoint.Y := min(page.TextPoint.Y, page.HdrPoint.Y);
page.UpperBound := page.TextPoint.Y;
page.LowerBound := max(page.SectPr.PgMar.Bottom, page.FtrPoint.Y);
// println("len = {}, Number = {}", page_manager_module_.Count(), current_page_.Number);
// println("W = {}, H = {}", current_page_.SectPr.PgSz.W, current_page_.SectPr.PgSz.H);
// println("Top = {}, Bottom = {}", current_page_.SectPr.PgMar.Top, current_page_.SectPr.PgMar.Bottom);
// println("Left = {}, Right = {}", current_page_.SectPr.PgMar.Left, current_page_.SectPr.PgMar.Right);
// println("Header = {}", current_page_.SectPr.PgMar.Header);
// println("TextPoint.X = {}, TextPoint.Y = {}", current_page_.TextPoint.X, current_page_.TextPoint.Y);
// println("HdrPoint.X = {}, HdrPoint.Y = {}", current_page_.HdrPoint.X, current_page_.HdrPoint.Y);
// println("FtrPoint.X = {}, FtrPoint.Y = {}", current_page_.FtrPoint.X, current_page_.FtrPoint.Y);
xml_file_ := "document.xml";
return current_page_;
end;
function TSDocxToPdf.GetNextPage(page: PdfPage);
function TSDocxToPdf.SetFtr(type: string);
begin
pos := page_index_[page];
return page_array_[pos + 1];
// 页脚:从下往上,需要调整
current_page_.FtrPoint.X := current_page_.SectPr.PgMar.Left;
current_page_.FtrPoint.Y := current_page_.SectPr.PgMar.Footer;
footer_reference := current_sect_pr_adapter_.GetFooterReferenceByType(type);
if not ifObj(footer_reference) then return;
rels_adapter := docx_components_module_.GetDocumentRelsAdapter();
rel := rels_adapter.GetRelationshipById(footer_reference.Id);
ftr := docx_components_module_.GetFtr(rel.Target);
xml_file_ := rel.Target;
w := current_page_.SectPr.PgSz.W - current_page_.SectPr.PgMar.Right - current_page_.SectPr.PgMar.Left;
ftr_range := new DTPAdvancedRanges.FtrRange(self, ftr);
ftr_range.Width := w;
ftr_range.Parent := self;
ftr_range.LowerBound := 0;
flag := ftr_range.Calc();
// y_offset := current_page_.SectPr.PgSz.H - ftr_range.DynamicHeight - current_page_.SectPr.PgMar.Footer;
y_offset := current_page_.SectPr.PgMar.Footer + ftr_range.DynamicHeight;
ftr_range.Offset(current_page_.SectPr.PgMar.Left, y_offset, current_page_);
if flag then
ftr_range.Do();
else
realtime_range_array_[length(realtime_range_array_)] := ftr_range;
current_page_.FtrPoint.Y := ftr_range.StartY; // 向下偏移后的起始位置=正文的下边界
end;
function TSDocxToPdf.ResetCoordinates(sect_ware: TSSectWare);
function TSDocxToPdf.SetHdr(type: string);
begin
point_.X := sect_ware.SectPr.PgMar.Left;
point_.Y := sect_ware.SectPr.PgSz.H - max(sect_ware.SectPr.PgMar.Top, sect_ware.SectPr.PgMar.Header);
// 正文、页眉页脚坐标
// 页眉:从上往下,不需要调整
current_page_.HdrPoint.X := current_page_.SectPr.PgMar.Left;
current_page_.HdrPoint.Y := current_page_.SectPr.PgSz.H - current_page_.SectPr.PgMar.Header;
header_reference := current_sect_pr_adapter_.GetHeaderReferenceByType(type);
if not ifObj(header_reference) then return;
rels_adapter := docx_components_module_.GetDocumentRelsAdapter();
rel := rels_adapter.GetRelationshipById(header_reference.Id);
hdr := docx_components_module_.GetHdr(rel.Target);
xml_file_ := rel.Target;
w := current_page_.SectPr.PgSz.W - current_page_.SectPr.PgMar.Right - current_page_.SectPr.PgMar.Left;
hdr_range := new DTPAdvancedRanges.HdrRange(self, hdr);
hdr_range.Width := w;
hdr_range.Parent := self;
hdr_range.LowerBound := 0;
flag := hdr_range.Calc();
hdr_range.Offset(current_page_.SectPr.PgMar.Left, current_page_.SectPr.PgSz.H - current_page_.SectPr.PgMar.Header, current_page_);
if flag then
hdr_range.Do();
else
realtime_range_array_[length(realtime_range_array_)] := hdr_range;
current_page_.HdrPoint.Y := hdr_range.EndY;
end;
function TSDocxToPdf.PrintGrid(page: PdfPage; sect_ware: TSSectWare);
function TSDocxToPdf.RangesSpacing(range: BasicRange);
begin
i := 0;
while true do
if last_range_ then
begin
y := point_.Y - i * sect_ware.SectPr.DocGrid.LinePitch;
if y <= sect_ware.SectPr.PgMar.Bottom then break;
page.SetLineWidth(0.05);
page.SetGrayStroke(0.75);
page.MoveTo(sect_ware.SectPr.PgMar.Left, y);
page.LineTo(sect_ware.SectPr.PgSz.W- sect_ware.SectPr.PgMar.Right, y);
page.Stroke();
i++;
if last_range_ is class(DTPAdvancedRanges.PRange) and not ifnil(last_range_.P.PPr.OutlineLvl.Val) and (range is class(DTPAdvancedRanges.TblRange) or ifnil(range.P.PPr.OutlineLvl.Val)) then
begin
if last_range_.P.PPr.Spacing.AfterAutospacing then
begin
line_range := last_range_.PLineRanges();
line_range := line_range[length(line_range)-1];
y := line_range.EndY - line_range.TextMaxSize;
if y >= 0 then current_page_.TextPoint.Y := y;
end
x1 := sect_ware.SectPr.PgMar.Left;
y1 := sect_ware.SectPr.PgSz.H - sect_ware.SectPr.PgMar.Top;
x2 := sect_ware.SectPr.PgSz.W - sect_ware.SectPr.PgMar.Right;
y2 := y1;
x3 := x1;
y3 := sect_ware.SectPr.PgMar.Bottom;
x4 := x2;
y4 := y3;
page.SetLineWidth(0.05);
page.SetGrayStroke(0.5);
page.MoveTo(x1, y1);
page.LineTo(x2, y2);
page.Stroke();
page.MoveTo(x1, y1);
page.LineTo(x3, y3);
page.Stroke();
page.MoveTo(x2, y2);
page.LineTo(x4, y4);
page.Stroke();
page.MoveTo(x3, y3);
page.LineTo(x4, y4);
page.Stroke();
end
if range is class(DTPAdvancedRanges.PRange) and not ifnil(range.P.PPr.OutlineLvl.Val) and (last_range_ is class(DTPAdvancedRanges.TblRange) or ifnil(last_range_.P.PPr.OutlineLvl.Val)) then
begin
if range.P.PPr.Spacing.BeforeAutospacing then
begin
line_range := range.PLineRanges();
line_range := line_range[length(line_range)-1];
y := last_range_.EndY - line_range.TextMaxSize;
if y >= 0 then current_page_.TextPoint.Y := y;
end
end
end
last_range_ := range;
end;
function TSDocxToPdf.TransformParagraph(sect_ware: TSSectWare; paragraph: P);
function TSDocxToPdf.TransformP(p: P);
begin
w := sect_ware.SectPr.PgSz.W - sect_ware.SectPr.PgMar.Right - sect_ware.SectPr.PgMar.Left;
range := new TSPdfParagraphRange(self, current_page_, docx_components_, sect_ware, paragraph);
range.X := point_.X;
range.Y := point_.Y;
range.W := w;
range.H := 0;
range.Calc();
w := current_page_.SectPr.PgSz.W - current_page_.SectPr.PgMar.Right - current_page_.SectPr.PgMar.Left;
range := new DTPAdvancedRanges.PRange(self, p);
range.Width := w;
range.Parent := self;
range.LowerBound := current_page_.LowerBound;
fg := range.Calc();
{self.}RangesSpacing(range);
range.Offset(current_page_.TextPoint.X, current_page_.TextPoint.Y, current_page_);
if fg then
range.Do();
point_.Y := range.Y;
else
realtime_range_array_[length(realtime_range_array_)] := range;
current_page_.TextPoint.Y := range.EndY;
end;
function TSDocxToPdf.TransformTable(sect_ware: TSSectWare; table: Tbl);
function TSDocxToPdf.TransformTbl(tbl: Tbl);
begin
w := sect_ware.SectPr.PgSz.W - sect_ware.SectPr.PgMar.Right - sect_ware.SectPr.PgMar.Left;
range := new TSPdfTableRange(self, current_page_, docx_components_, sect_ware, table);
range.X := point_.X;
range.Y := point_.Y;
range.W := w;
range.H := 0;
range.Calc();
w := current_page_.SectPr.PgSz.W - current_page_.SectPr.PgMar.Right - current_page_.SectPr.PgMar.Left;
range := new DTPAdvancedRanges.TblRange(self, tbl);
range.Width := w;
range.Parent := self;
range.LowerBound := current_page_.LowerBound;
fg := range.Calc();
{self.}RangesSpacing(range);
range.Offset(current_page_.TextPoint.X, current_page_.TextPoint.Y, current_page_);
range.Do();
point_.Y := range.Y;
current_page_.TextPoint.Y := range.EndY;
end;
function TSDocxToPdf.TransformSdt(sdt: Sdt);
begin
ps := sdt.SdtContent.Ps();
for _,p in ps do
range := {self.}TransformP(p);
end;
function TSDocxToPdf.ProcessRealtimeRange();
begin
for _,range in realtime_range_array_ do
begin
range.ProcessRealtimeArray();
range.Do();
end
end;
function TSDocxToPdf.UpdateDocxPageNumPages();
begin
toc_module_.UpdateDocxNumPages();
end;
function TSDocxToPdf.SaveDocxFile();overload;
begin
return docx_components_module_.Save();
end;
function TSDocxToPdf.SaveDocxFile(alias: string; file: string);overload;
begin
return docx_components_module_.SaveAs(alias, file);
end;
function TSDocxToPdf.ClassifyCols(var point: Point; cols: Cols);
begin
return;
bk_page := current_page_;
columns := array();
x := point.X;
y := point.Y;
w := current_page_.SectPr.PgSz.W - current_page_.SectPr.PgMar.Right - current_page_.SectPr.PgMar.Left;
lb := current_page_.SectPr.PgMar.Bottom;
w_array := array();
ccols := cols.Cols();
for i:=0 to cols.Num-1 do
begin
rw := 0;
if cols.EqualWidth = "0" then
begin
rw := ccols[i].W;
if i > 0 then x += ccols[i-1].W + ccols[i-1].Space;
end
else begin
rw := w / 3;
x := point.X + i * rw + i * cols.Space;
end
range := new ColumnRange(self, current_page_, docx_components_module_);
range.StartX := x;
range.StartY := y;
range.Width := rw;
range.LowerBound := lb;
columns[length(columns)] := range;
end
i := 0;
elements := current_sect_module_.Elements();
range := columns[0];
for _,element in elements do
begin
if element.LocalName = "p" then
begin
p := new P();
sub_elements := element.Elements();
for _,sub in sub_elements do
begin
p.AppendChild(sub);
if sub.LocalName = "r" and sub.Br.Type = "column" then
begin
range.AddElement(p);
p := new P();
p.PPr.Copy(element.PPr);
range := columns[++i];
end
end
range.AddElement(p);
end
else begin
range.AddElement(element);
end
end
pg := nil;
max_y := nil;
for _,column in columns do
begin
column.Do();
page := column.GetLastPage();
if ifnil(pg) then pg := page;
if ifnil(max_y) then max_y := range.EndY;
if page.Index > pg.Index then max_y := range.EndY;
else if page.Index = pg.Index and max_y > range.EndY then max_y := range.EndY;
end
current_page_ := bk_page;
point.Y := max_y;
end;
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
File diff suppressed because it is too large Load Diff
@@ -1,4 +1,4 @@
unit TSColorToolKit;
unit DTPColorToolKit;
interface
function HexToRGB(hex);
+744
View File
@@ -0,0 +1,744 @@
unit DTPModules;
interface
uses DTPAdvancedRanges, DocxMLAdapters, SharedMLAdapters;
type DocxComponentsModule = class(DocxComponents)
public
function Create();
function GetStyles(): Styles;
function GetStylesAdapter(): StylesAdapter;
function GetDocumentRelsAdapter(): RelationShipsAdapter;
function GetNumberingModule(): NumberingModule;
function GetTblStylePrByType(style_id: string; type: string): TblStylePr;
function GetFtr(target: string): Ftr;
function GetHdr(target: string): Hdr;
function GetFtrRelsAdapter(target: string): RelationShipsAdapter;
function GetHdrRelsAdapter(target: string): RelationShipsAdapter;
function GetFootnotesAdapter(): FootnotesAdapter;
private
styles_deserialize_flag_: boolean;
styles_adapter_: StylesAdapter;
document_rels_adapter_: RelationShipsAdapter;
numbering_module_: NumberingModule;
tbl_style_pr_hash_: array of TblStylePr;
ftr_hash_: array of Ftr;
hdr_hash_: array of Hdr;
hdr_rel_hash_: array of RelationShipsAdapter;
ftr_rel_hash_: array of RelationShipsAdapter;
footnotes_adapter_: FootnotesAdapter;
end;
type FontModule = class
public
function Create(pdf: PdfFile);
function GetAsciiFont(name: string; bold: boolean; italic: boolean): PdfFont;
function GetCNSFont(name: string; bold: boolean; italic: boolean): PdfFont;
function GetSymbolFont(): PdfFont;
function GetZapfDingbatsFont(): PdfFont;
function UseExternalFont();
function SetSubstitutionRules(source: string; target: string);
function SetDefaultSz(value: real);
function GetDefaultSz(): real;
private
function GetExternalFont(name:string; bold: boolean; italic: boolean): PdfFont;
function GetBuiltInCNSFont(name:string; bold: boolean; italic: boolean): PdfFont;
function GetBuiltInAsciiFont(name:string; bold: boolean; italic: boolean): PdfFont;
private
[weakref]pdf_: PdfFile;
use_built_in_font_: boolean; // 是否使用内置字体
substitution_rules_: array of string; // 替换规则
external_reference_: array of string;
default_sz_: real;
end;
type NoteModule = class
public
function Create(docx_to_pdf: TSDocxToPdf);
function AddFootnoteId(id: string);
function GetFootnoteOrderNumber(): string;
function GetFootnoteIndex(): string;
private
function CalculateNumber(num_fmt: string; num: integer): string;
function ChineseCountingThousand(n: integer): string;
private
[weakref]docx_to_pdf_: TSDocxToPdf;
footnote_hash_: hash;
footnote_index_: integer;
endnote_hash_: hash;
endnote_index_: integer;
end;
type NumberingModule = class
public
function Create(number: NumberingAdapter);
function GetNumberLvl(ppr: PPr);
private
function CalculateNumber(num_fmt: string; num: integer): string;
function ChineseCountingThousand(n: integer): string;
private
numbering_adapter_: NumberingAdapter;
num_hash_: hash;
end;
type SectModule = class
public
function Create();
function AddElement(element: tslobj);
public
SectPr: SectPr;
Elements: array of tslobj;
BaseSize: real;
end;
type TocModule = class
public
function Create();
function UpdateDocxNumPages();
function CalculateRect(anchor: string);
function LinkToToc(anchor: string; range: BasicRange);overload;
function LinkToToc(anchor: string);overload;
function AddToc(anchor: string; toc: Toc);overload;
function AddDocxPage(anchor: string; r: R);
private
toc_hash_: hash;
toc_unmatched_hash_: hash;
update_docx_num_pages_: boolean; // 开放给docx文件是否更新docx文件的页码
docx_page_hash_: hash;
end;
// 坐标
type Point = class
public
function Create();
public
X: real;
Y: real;
end;
// Page延迟建立,存基本信息即可
type Page = class
public
function Create(pdf_file: PdfFile);
function OriginalTextCoordinates(): array of real;
function PrintGrid();
property PdfPage read ReadPdfPage;
function ReadPdfPage(): PdfPage;
public
Index: integer;
Number: integer;
SectPr: SectPr;
TextPoint: Point; // 正文坐标
FtrPoint: Point; // 页脚坐标
HdrPoint: Point; // 页眉坐标
UpperBound: real; // 上界
LowerBound: real; // 下界
private
[weakref]pdf_file_: PdfFile;
pdf_page_: PdfPage;
end;
type PageManagerModule = class
public
function Create(pdf_file: PdfFile);
function operator[](index: uinteger): Page;
function NewPage(): Page;
function NextPage(page: Page): Page;
function Count(): integer;
private
[weakref]pdf_file_: PdfFile;
page_array_: array of Page;
end;
implementation
// DocxComponentsModule
function DocxComponentsModule.Create();
begin
class(DocxComponents).Create();
tbl_style_pr_hash_ := array();
ftr_hash_ := array();
hdr_hash_ := array();
hdr_rel_hash_ := array();
ftr_rel_hash_ := array();
end;
function DocxComponentsModule.GetStyles(): Styles;
begin
if styles_deserialize_flag_ then return {self.}Styles;
{self.}Styles.Deserialize();
{self.}Styles.ConvertToPoint();
styles_deserialize_flag_ := true;
return {self.}Styles;
end;
function DocxComponentsModule.GetStylesAdapter(): StylesAdapter;
begin
if styles_adapter_ then return styles_adapter_;
styles_adapter_ := new DocxMLAdapters.Styles({self.}GetStyles());
return styles_adapter_;
end;
function DocxComponentsModule.GetDocumentRelsAdapter(): RelationShipsAdapter;
begin
if document_rels_adapter_ then return document_rels_adapter_;
{self.}DocumentRels.Deserialize();
document_rels_adapter_ := new SharedMLAdapters.RelationShips({self.}DocumentRels);
return document_rels_adapter_;
end;
function DocxComponentsModule.GetNumberingModule(): NumberingModule;
begin
if numbering_module_ then return numbering_module_;
if not {self.}Numbering then return nil;
{self.}Numbering.Deserialize();
{self.}Numbering.ConvertToPoint();
numbering_module_ := new NumberingModule({self.}Numbering);
return numbering_module_;
end;
function DocxComponentsModule.GetTblStylePrByType(style_id: string; type: string): TblStylePr;
begin
if tbl_style_pr_hash_[style_id][type] then return tbl_style_pr_hash_[style_id][type];
styles_adapter := {self.}GetStylesAdapter();
style := styles_adapter.GetStyleByStyleId(style_id);
style := new DocxMLAdapters.Style(style);
tbl_style_pr := style.GetTblStylePrByType(type);
tbl_style_pr_hash_[style_id][type] := tbl_style_pr;
return tbl_style_pr;
end;
function DocxComponentsModule.GetFtr(target: string): Ftr;
begin
if ftr_hash_[target] then return ftr_hash_[target];
index := replaceStr(replaceStr(target, "footer", ""), ".xml", "");
obj := {self.}Footers(strtoint(index));
obj.Deserialize();
obj.ConvertToPoint();
ftr_hash_[target] := obj;
return obj;
end;
function DocxComponentsModule.GetHdr(target: string): Hdr;
begin
if hdr_hash_[target] then return hdr_hash_[target];
index := replaceStr(replaceStr(target, "header", ""), ".xml", "");
obj := {self.}Headers(strtoint(index));
obj.Deserialize();
obj.ConvertToPoint();
hdr_hash_[target] := obj;
return obj;
end;
function DocxComponentsModule.GetHdrRelsAdapter(target: string): RelationShipsAdapter;
begin
if hdr_rel_hash_[target] then return hdr_rel_hash_[target];
index := replaceStr(replaceStr(target, "header", ""), ".xml", "");
obj := {self.}HeaderRels(strtoint(index));
obj.Deserialize();
rels_adapter := new SharedMLAdapters.RelationShips(obj);
hdr_rel_hash_[target] := rels_adapter;
return rels_adapter;
end;
function DocxComponentsModule.GetFtrRelsAdapter(target: string): RelationShipsAdapter;
begin
if ftr_rel_hash_[target] then return ftr_rel_hash_[target];
index := replaceStr(replaceStr(target, "footer", ""), ".xml", "");
obj := {self.}FooterRels(strtoint(index));
obj.Deserialize();
rels_adapter := new SharedMLAdapters.RelationShips(obj);
ftr_rel_hash_[target] := rels_adapter;
return rels_adapter;
end;
function DocxComponentsModule.GetFootnotesAdapter(): FootnotesAdapter;
begin
if footnotes_adapter_ then return footnotes_adapter_;
obj := {self.}Footnotes;
obj.Deserialize();
obj.ConvertToPoint();
footnotes_adapter_ := new DocxMLAdapters.Footnotes(obj);
return footnotes_adapter_;
end;
// FontModule
function FontModule.Create(pdf: PdfFile);
begin
pdf_ := pdf;
use_built_in_font_ := true;
substitution_rules_ := array("宋体": "SimSun",
"黑体": "SimHei",
"Courier New": "Courier",
"Helvetica": "Helvetica",
"Times New Roman": "Times-Roman",
);
external_reference_ := array();
default_sz_ := 10.5;
end;
function FontModule.SetDefaultSz(value: real);
begin
default_sz_ := value;
end;
function FontModule.GetDefaultSz();
begin
return default_sz_;
end;
function FontModule.UseExternalFont();
begin
use_built_in_font_ := false;
end;
function FontModule.GetExternalFont(name:string; bold: boolean; italic: boolean);
begin
if ifnil(name) or name = '' then name := "等线";
if not ifnil(external_font_cache_[name]) then return external_font_cache_[name];
value := external_reference_[name];
if ifnil(value) then return nil;
if value["ext"] = ".ttf" then
font_name := pdf_.LoadTTFontFromFile("", value["path"], true);
else if value["ext"] = ".ttc" then
font_name := pdf_.LoadTTFontFromFile2("", value["path"], 0, true);
if not ifString(font_name) then return nil;
font := pdf_.GetFont(font_name, "UTF-8");
external_font_cache_[name] := font;
return font;
end;
function FontModule.GetCNSFont(name: string; bold: boolean; italic: boolean): PdfFont;
begin
return use_built_in_font_ ? {self.}GetBuiltInCNSFont(name, bold, italic) : {self.}GetExternalFont(name, bold, italic);
end;
function FontModule.GetBuiltInCNSFont(name: string; bold: boolean; italic: boolean): PdfFont;
begin
font_name := substitution_rules_[name];
if ifnil(font_name) then font_name := "SimSun";
if bold and italic then
font_name += ",BoldItalic";
else if bold then
font_name += ",Bold";
else if italic then
font_name += ",Italic";
return pdf_.GetFont(font_name, "GBK-EUC-H");
end;
function FontModule.GetAsciiFont(name: string; bold: boolean; italic: boolean): PdfFont;
begin
return use_built_in_font_ ? {self.}GetBuiltInAsciiFont(name, bold, italic) : {self.}GetExternalFont(name, bold, italic);
end;
function FontModule.GetBuiltInAsciiFont(name:string; bold: boolean; italic: boolean): PdfFont;
begin
font_name := substitution_rules_[name];
if ifnil(font_name) then font_name := "Times-Roman";
if font_name = "Courier" or font_name = "Helvetica" then
begin
if bold and italic then
font_name += "-BoldOblique";
else if bold then
font_name += "-Bold";
else if italic then
font_name += "-Oblique";
end
else if font_name = "Times-Roman" then
begin
if bold and italic then
font_name := "Times-BoldItalic";
else if bold then
font_name := "Times-Bold";
else if italic then
font_name := "Times-Italic";
end
else begin
font_name := "Courier";
end
return pdf_.GetFont(font_name, "");
end;
function FontModule.SetSubstitutionRules(source: string; target: string);
begin
substitution_rules_[source] := target;
end;
function FontModule.GetSymbolFont(): PdfFont;
begin
return pdf_.GetFont("Symbol", "");
end;
function FontModule.GetZapfDingbatsFont(): PdfFont;
begin
return pdf_.GetFont("ZapfDingbats", "");
end;
// NoteModule
function NoteModule.Create(docx_to_pdf: TSDocxToPdf);
begin
docx_to_pdf_ := docx_to_pdf;
footnote_hash_ := array();
endnote_hash_ := array();
footnote_index_ := 0;
endnote_index_ := 0;
end;
function NoteModule.AddFootnoteId(id: string);
begin
footnotes_adapter := docx_to_pdf_.DocxComponents.GetFootnotesAdapter();
footnote := footnotes_adapter.GetFootnoteById(id);
sect_pr := docx_to_pdf_.CurrentSect.SectPr;
w := sect_pr.SectPr.PgSz.W - sect_pr.SectPr.PgMar.Right - sect_pr.SectPr.PgMar.Left;
lb := 0;
arr := array();
elements := footnote.Elements();
for _,element in elements do
begin
if element.LocalName = "p" then
begin
range := new PRange(docx_to_pdf_, element);
range.Width := w;
range.LowerBound := lb;
range.Parent := self;
range.Calc();
arr[length(arr)] := range;
end
end
footnote_hash_[id] := arr;
end;
// function NoteModule.RunFootnote(id: string; x: real; y: real; pg: Page);
// begin
// sx := x;
// sy := y;
// spg := pg;
// height := 0;
// arr := array();
// hash := footnote_hash_[id];
// for id,range in hash do
// begin
// range.StartX := x;
// range.StartY := y;
// range.StartPage := spg;
// range.LowerBound := 0;
// range.Run();
// sy := range.EndY;
// height += range.DynamicHeight;
// arr union= range.PLineRanges();
// footnote_hash_[id] := arr;
// end
// return height;
// end;
function NoteModule.GetFootnoteOrderNumber();
begin
num_fmt := docx_to_pdf_.CurrentSect.SectPr.FootnotePr.NumFmt.Val;
if ifnil(num_fmt) then num_fmt := "decimal";
return CalculateNumber(num_fmt, ++footnote_index_);
end;
function NoteModule.GetFootnoteIndex(): string;
begin
return inttostr(footnote_index_);
end;
function NoteModule.CalculateNumber(num_fmt: string; num: integer): string;
begin
if num_fmt = "decimal" then
return format("%d", num);
else if num_fmt = "chineseCountingThousand" then
return {self.}ChineseCountingThousand(num);
else
return format("%d", num);
end;
function NoteModule.ChineseCountingThousand(n: integer): string;
begin
chinese_digits := array("零", "一", "二", "三", "四", "五", "六", "七", "八", "九");
chinese_units := array("", "十", "百", "千");
if n < 10 then return chinese_digits[n];
result := "";
num_str := inttostr(n);
len := length(num_str);
for i:=1 to len do
begin
digit_int := strtoint(num_str[i]);
if digit_int <> 0 then
result += chinese_digits[digit_int] + chinese_units[len - i];
end
if length(result) >= 6 and result[:6] = "一十" then result := result[4:];
return result;
end;
// SectModule
function SectModule.Create();
begin
{self.}Elements := array();
{self.}SectPr := nil;
end;
function SectModule.AddElement(element: tslobj);
begin
{self.}Elements[length({self.}Elements)] := element;
end;
// NumberingModule
function NumberingModule.Create(number: NumberingAdapter);
begin
numbering_adapter_ := new DocxMLAdapters.Numbering(number);
num_hash_ := array();
end;
function NumberingModule.GetNumberLvl(ppr: PPr);
begin
num_id := ppr.NumPr.NumId.Val;
if ifnil(num_id) then return array("", nil);
ilvl := ppr.NumPr.Ilvl.Val;
pstyle := ppr.PStyle.Val;
num := numbering_adapter_.GetNumByNumId(num_id);
if ifnil(num) then return array("", nil);
abstract_id := num.AbstractNumId.Val;
abstract_num := numbering_adapter_.GetAbstractNumByAbstractNumId(abstract_id);
lvls := abstract_num.Lvls();
if ifnil(ilvl) then ilvl := "0";
for k,v in lvls do
begin
if ilvl and v.Ilvl = ilvl then
begin
lvl_text := v.LvlText.Val;
if not ifarray(num_hash_[num_id]) then num_hash_[num_id] := array(0, 0, 0, 0, 0, 0, 0, 0, 0);
ilvl_int := strtoint(ilvl);
for i:=0 to ilvl_int do
begin
source_str := "%" $ (i + 1);
n := num_hash_[num_id][i];
if i = ilvl_int then
begin
n := num_hash_[num_id][i] + 1;
for j:=i+1 to length(num_hash_[num_id])-1 do
num_hash_[num_id][j] := 0;
end
n := i = ilvl_int ? num_hash_[num_id][i] + 1 : num_hash_[num_id][i];
dest_str := {self.}CalculateNumber(v.NumFmt.Val, n);
lvl_text := replaceStr(lvl_text, source_str, dest_str);
end
num_hash_[num_id][ilvl_int]++;
if v.Suff.Val = "space" then lvl_text += " ";
return array(lvl_text, v);
end
end
return array("", nil);
end
function NumberingModule.CalculateNumber(num_fmt: string; num: integer): string;
begin
if num_fmt = "decimal" then
return format("%d", num);
else if num_fmt = "chineseCountingThousand" then
return {self.}ChineseCountingThousand(num);
else
return format("%d", num);
end;
function NumberingModule.ChineseCountingThousand(n: integer): string;
begin
chinese_digits := array("零", "一", "二", "三", "四", "五", "六", "七", "八", "九");
chinese_units := array("", "十", "百", "千");
if n < 10 then return chinese_digits[n];
result := "";
num_str := inttostr(n);
len := length(num_str);
for i:=1 to len do
begin
digit_int := strtoint(num_str[i]);
if digit_int <> 0 then
result += chinese_digits[digit_int] + chinese_units[len - i];
end
if length(result) >= 6 and result[:6] = "一十" then result := result[4:];
return result;
end;
// Page
function Page.Create(pdf_file: PdfFile);
begin
pdf_file_ := pdf_file;
{self.}TextPoint := new Point();
{self.}FtrPoint := new Point();
{self.}HdrPoint := new Point();
end;
function Page.OriginalTextCoordinates(): array of real;
begin
x := {self.}SectPr.PgMar.Left;
y := min({self.}SectPr.PgSz.H - max({self.}SectPr.PgMar.Top, {self.}SectPr.PgMar.Header), {self.}HdrPoint.Y);
return array(x, y);
end;
function Page.ReadPdfPage(): PdfPage;
begin
if ifnil(pdf_page_) then
begin
pdf_page_ := pdf_file_.AddPage();
pdf_page_.SetWidth({self.}SectPr.PgSz.W);
pdf_page_.SetHeight({self.}SectPr.PgSz.H);
if sysparams["_PDF_PAGE_GRID_DEBUG_"] then
{self.}PrintGrid();
end
return pdf_page_;
end;
function Page.PrintGrid();
begin
i := 0;
while true do
begin
y := {self.}SectPr.PgSz.H - max({self.}SectPr.PgMar.Top, {self.}SectPr.PgMar.Header);
y := min(y, {self.}HdrPoint.Y);
y := y - i * {self.}SectPr.DocGrid.LinePitch;
if y <= {self.}SectPr.PgMar.Bottom then break;
pdf_page_.SetLineWidth(0.05);
pdf_page_.SetGrayStroke(0.75);
pdf_page_.MoveTo({self.}SectPr.PgMar.Left, y);
pdf_page_.LineTo({self.}SectPr.PgSz.W- {self.}SectPr.PgMar.Right, y);
pdf_page_.Stroke();
i++;
end
x1 := {self.}SectPr.PgMar.Left;
y1 := {self.}SectPr.PgSz.H - {self.}SectPr.PgMar.Top;
x2 := {self.}SectPr.PgSz.W - {self.}SectPr.PgMar.Right;
y2 := y1;
x3 := x1;
y3 := {self.}SectPr.PgMar.Bottom;
x4 := x2;
y4 := y3;
pdf_page_.SetLineWidth(0.05);
pdf_page_.SetGrayStroke(0.70);
pdf_page_.MoveTo(x1, y1);
pdf_page_.LineTo(x2, y2);
pdf_page_.Stroke();
pdf_page_.MoveTo(x1, y1);
pdf_page_.LineTo(x3, y3);
pdf_page_.Stroke();
pdf_page_.MoveTo(x2, y2);
pdf_page_.LineTo(x4, y4);
pdf_page_.Stroke();
pdf_page_.MoveTo(x3, y3);
pdf_page_.LineTo(x4, y4);
pdf_page_.Stroke();
end;
// PageManagerModule
function PageManagerModule.Create(pdf_file: PdfFile);
begin
pdf_file_ := pdf_file;
page_array_ := array();
end;
function operator PageManagerModule.[](index: uinteger): Page;
begin
return page_array_[index];
end;
function PageManagerModule.NewPage(): Page;
begin
len := length(page_array_);
page := new Page(pdf_file_);
page.Index := len;
page_array_[len] := page;
return page;
end;
function PageManagerModule.Count(): integer;
begin
return length(page_array_);
end;
// TocModule
function TocModule.Create();
begin
toc_hash_ := array();
toc_unmatched_hash_ := array();
update_docx_num_pages_ := false;
docx_page_hash_ := array();
end;
function TocModule.UpdateDocxNumPages();
begin
update_docx_num_pages_ := true;
end;
function TocModule.CalculateRect(anchor: string);
begin
arr := toc_hash_[anchor];
for _,toc in arr do
toc.CalculateRect();
end;
function TocModule.LinkToToc(anchor: string; range: BasicRange);overload;
begin
arr := toc_hash_[anchor];
if ifnil(arr) then // 未匹配到链接,说明链接可能在后面
begin
toc_unmatched_hash_[anchor] := range;
return;
end
pg := range.EndPage;
dst := pg.PdfPage.CreateDestination();
dst.SetXYZ(range.EndX, range.EndY + range.RPr.Sz.Val, 1);
for _,toc in arr do
toc.LinkAnnot(dst);
toc.AddPageNumber(pg);
if update_docx_num_pages_ then
begin
r := docx_page_hash_[anchor];
r.T.Text := pg.Number;
r.Serialize();
end
end;
function TocModule.LinkToToc(anchor: string);overload;
begin
range := toc_unmatched_hash_[anchor];
if range then
begin
{self.}LinkToToc(anchor, range);
toc_unmatched_hash_[anchor] := nil;
end
end;
function TocModule.AddToc(anchor: string; toc: Toc);
begin
if ifarray(toc_hash_[anchor]) then toc_hash_[anchor] union= array(toc);
else toc_hash_[anchor] := array(toc);
end;
function TocModule.AddDocxPage(anchor: string; r: R);
begin
docx_page_hash_[anchor] := r;
end;
end.
+295
View File
@@ -0,0 +1,295 @@
unit DTPPrimitiveRanges;
interface
uses DTPColorToolKit, DTPUtils;
type BasicRange = class
public
function Create();
function Do();virtual;
function Offset(x: real; y: real; page: Page);virtual;
function AdjustOffset(x: real; y: real);virtual;
public
[weakref]Parent: tslobj;
[weakref]EndPage: Page; // 结束page
XOffset: real;
YOffset: real; // XOffset, YOffset是相对(0,0)的偏移位置
EndX: real;
EndY: real; // range的结束坐标(x,y)
Width: real;
DynamicHeight: real;
FixedHeight: real;
// StartX: real;
// StartY: real; // range的起始坐标(x,y)
end;
type TextRange = class(BasicRange)
public
function Create();
function Do();override;
public
RPr: RPr;
Text: string;
Font: PdfFont;
Type: integer; // 0:默认,1: 数字,2:英文,3:中文,4:中文标点,5:,.英文逗号和点
end;
type BordersRange = class(BasicRange)
public
function Create();
function Do();override;
function DoFill();
public
TcPr: TcPr;
Left: boolean;
Top: boolean;
Right: boolean;
Bottom: boolean;
private
function SetDash(val: string);
function DrawLine(border: Border; x1: real; y1: real; x2: real; y2: real);
end;
type ImageRange = class(BasicRange)
public
function Create();
function Do();override;
public
RPr: RPr;
Image: PdfImage;
Type: string;
end;
type LineRange = class(BasicRange)
public
function Create();
function Do();override;
public
LineWidth: real;
end;
implementation
// BasicRange
function BasicRange.Create();
begin
{self.}Parent := nil;
{self.}EndPage := nil;
{self.}XOffset := 0.0;
{self.}YOffset := 0.0;
{self.}EndX := 0.0;
{self.}EndY := 0.0;
{self.}Width := 0.0;
{self.}DynamicHeight := 0.0;
{self.}FixedHeight := 0.0;
// {self.}StartX := 0;
// {self.}StartY := 0;
end;
function BasicRange.Offset(x: real; y: real; page: Page);virtual;
begin
{self.}EndX := {self.}XOffset + x;
{self.}EndY := {self.}YOffset + y;
{self.}EndPage := page;
end;
function BasicRange.AdjustOffset(x: real; y: real);virtual;
begin
{self.}XOffset += x;
{self.}YOffset += y;
end;
// ImageRange
function ImageRange.Create();
begin
class(BasicRange).Create();
{self.}Image := nil;
{self.}Type := "";
end;
function ImageRange.Do();override;
begin
if {self.}RPr.Highlight.Val = "yellow" then
begin
{self.}EndPage.PdfPage.SetRGBFill(1, 1, 0);
x := {self.}EndX;
y := {self.}Parent.EndY;
w := {self.}Width;
h := {self.}Parent.DynamicHeight;
{self.}EndPage.PdfPage.Rectangle(x, y, w, h);
{self.}EndPage.PdfPage.Fill();
{self.}EndPage.PdfPage.SetRGBFill(0, 0, 0);
end
if {self.}Type = "emf" then
{self.}EndPage.PdfPage.DrawEmf({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
else if {self.}Type = "wmf" then
{self.}EndPage.PdfPage.DrawWmf({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
else
{self.}EndPage.PdfPage.DrawImage({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
if sysparams["_PDF_IMAGE_DEBUG_"] then
begin
{self.}EndPage.PdfPage.SetLineWidth(0.1);
{self.}EndPage.PdfPage.SetRGBStroke(0.8, 0.8, 0);
{self.}EndPage.PdfPage.Rectangle({self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
{self.}EndPage.PdfPage.Stroke();
end
end;
// BordersRange
function BordersRange.Create();
begin
class(BasicRange).Create();
{self.}TcPr := nil;
{self.}Left := false;
{self.}Top := false;
{self.}Right := false;
{self.}Bottom := false;
end;
function BordersRange.DoFill();
begin
borders := {self.}TcPr.TcBorders;
// println("TcPr.Shd.Val = {}", TcPr.Shd.Val);
if {self.}TcPr.Shd.Val = "clear" and {self.}TcPr.Shd.Fill and {self.}TcPr.Shd.Fill <> "auto" then
begin
[r, g, b] := DTPColorToolKit.HexToRGB({self.}TcPr.Shd.Fill);
{self.}EndPage.PdfPage.SetRGBFill(r/255, g/255, b/255);
x := {self.}EndX;
y := {self.}EndY - {self.}DynamicHeight;
w := {self.}Width;
h := {self.}DynamicHeight;
// tmp := borders.Left.Sz ? borders.Left.Sz / 2 : 0.25;
// x += tmp;
// w -= tmp;
// w -= borders.Right.Sz ? borders.Right.Sz / 2 : 0.25;
// tmp := borders.Bottom.Sz ? borders.Bottom.Sz / 2 : 0.25;
// y += tmp;
// h -= tmp;
// h -= borders.Top.Sz ? borders.Top.Sz / 2 : 0.25;
{self.}EndPage.PdfPage.Rectangle(x, y, w, h);
{self.}EndPage.PdfPage.Fill();
{self.}EndPage.PdfPage.SetRGBFill(0, 0, 0);
// {self.}Left := true;
end
end;
function BordersRange.Do();override;
begin
// println("Left = {}, Top = {}, Right = {}, Bottom = {}, Tl2Br = {}, Tr2Bl = {}", Left, Top, Right, Bottom, Tl2Br, Tr2Bl);
borders := {self.}TcPr.TcBorders;
if {self.}Left then
{self.}DrawLine(borders.Left, {self.}EndX, {self.}EndY, {self.}EndX, {self.}EndY - {self.}DynamicHeight);
if {self.}Top then
{self.}DrawLine(borders.Top, {self.}EndX, {self.}EndY, {self.}EndX + {self.}Width, {self.}EndY);
if {self.}Right then
{self.}DrawLine(borders.Right, {self.}EndX + {self.}Width, {self.}EndY, {self.}EndX + {self.}Width, {self.}EndY - {self.}DynamicHeight);
if {self.}Bottom then
{self.}DrawLine(borders.Bottom, {self.}EndX, {self.}EndY - {Self.}DynamicHeight, {self.}EndX + {self.}Width, {self.}EndY - {self.}DynamicHeight);
if borders.Tl2Br then
{self.}DrawLine(borders.Tl2Br, {self.}EndX, {self.}Y, {self.}EndX + {self.}Width, {self.}EndY - {self.}DynamicHeight);
if borders.Tr2Bl then
{self.}DrawLine(borders.Tr2Bl, {self.}EndX + {self.}Width, {self.}Y, {self.}EndX, {self.}EndY - {self.}DynamicHeight);
end;
function BordersRange.SetDash(val: string);
begin
if val = "single" or ifnil(val) then
{self.}EndPage.PdfPage.SetDash(array(), 0, 0);
else if val = "dashed" then
{self.}EndPage.PdfPage.SetDash(array(1), 1, 0);
end;
function BordersRange.DrawLine(border: Border; x1: real; y1: real; x2: real; y2: real);
begin
[r, g, b] := array(0, 0, 0);
line_width := border.Sz ?: 0.5;
{self.}SetDash(border.Val);
if border.Color and border.Color <> "auto" then [r, g, b] := DTPColorToolKit.HexToRGB(border.Color);
{self.}EndPage.PdfPage.SetRGBStroke(r/255, g/255, b/255);
{self.}EndPage.PdfPage.SetLineWidth(line_width);
{self.}EndPage.PdfPage.MoveTo(x1, y1);
{self.}EndPage.PdfPage.LineTo(x2, y2);
{self.}EndPage.PdfPage.Stroke();
{self.}EndPage.PdfPage.SetRGBStroke(0, 0, 0);
end;
// TextRange
function TextRange.Create();
begin
class(BasicRange).Create();
{self.}RPr := nil;
{self.}Text := "";
{self.}Font := nil;
{self.}Type := -1;
end;
function TextRange.Do();override;
begin
// println("text = {}, endx = {}, endy = {}, width = {}, page = {}", ansiToUtf8(text), endx, endy, width, page);
// println("Text = {}, sz = {}, szcs = {}, rpr.I = {}, rpr.B = {}, color = {}", ansiToUtf8({self.}Text), {self.}RPr.Sz.Val, {self.}RPr.SzCs.Val, {self.}RPr.I, {self.}RPr.B, {self.}RPr.Color.Val);
[r, g, b] := array(0, 0, 0);
if {self.}RPr.Color.Val and {self.}RPr.Color.Val <> "auto" then [r, g, b] := DTPColorToolKit.HexToRGB({self.}RPr.Color.Val);
y := {self.}EndY;
sz := {self.}RPr.Sz.Val;
if {self.}RPr.VertAlign.Val = "superscript" then
begin
y += sz / 3;
sz := sz * 2 / 3;
end
if {self.}RPr.Highlight.Val = "yellow" then
begin
{self.}EndPage.PdfPage.SetRGBFill(1, 1, 0);
x := {self.}EndX;
y := {self.}Parent.EndY;
w := {self.}Width;
h := {self.}Parent.DynamicHeight;
{self.}EndPage.PdfPage.Rectangle(x, y, w, h);
{self.}EndPage.PdfPage.Fill();
{self.}EndPage.PdfPage.SetRGBFill(0, 0, 0);
end
{self.}EndPage.PdfPage.SetRGBFill(r / 255, g / 255, b / 255);
{self.}EndPage.PdfPage.SetFontAndSize({self.}Font, sz);
{self.}EndPage.PdfPage.BeginText();
{self.}EndPage.PdfPage.TextOut({self.}EndX, y, {self.}Text);
{self.}EndPage.PdfPage.EndText();
{self.}EndPage.PdfPage.SetRGBFill(0, 0, 0);
if sysparams["_PDF_TEXT_DEBUG_"] then
begin
{self.}EndPage.PdfPage.SetLineWidth(0.1);
{self.}EndPage.PdfPage.SetRGBStroke(1.0, 0.5, 0.0);
{self.}EndPage.PdfPage.MoveTo(0, {self.}EndY);
{self.}EndPage.PdfPage.LineTo(600, {self.}EndY);
{self.}EndPage.PdfPage.Stroke();
end
end;
// LineRange
function LineRange.Create();
begin
class(BasicRange).Create();
{self.}LineWidth := 0;
end;
function LineRange.Do();override;
begin
// println("endx = {}, endy = {}, width = {}, line_width = {}", EndX, EndY, Width, LineWidth);
{self.}EndPage.PdfPage.SetLineWidth({self.}LineWidth);
{self.}EndPage.PdfPage.SetRGBStroke(0, 0, 0);
{self.}EndPage.PdfPage.MoveTo({self.}EndX, {self.}EndY);
{self.}EndPage.PdfPage.LineTo({self.}EndX + {self.}Width, {self.}EndY);
{self.}EndPage.PdfPage.Stroke();
end;
end.
+227
View File
@@ -0,0 +1,227 @@
unit DTPUtils;
interface
uses DTPPrimitiveRanges;
function Utf8CharLengthFromByte(byte: char): integer;
function IsChineseChar(str: utf8_string): boolean;
function IsChinesePunctuation(str: utf8_string): boolean;
type Point = class
public
function Create();
public
X: real;
Y: real;
end;
type Stack = class
public
function Create();
function Pop();
function Push(element: any);
function Empty(): boolean;
private
arr_: tableArray;
index_: integer;
end;
type FldType = class
public
function Create();
public
Page: boolean;
NumPages: boolean;
Quote: boolean;
PageRef: boolean;
end;
type FldStruct = class
public
function Create();
public
Type: FldType;
Arabic: boolean;
MergeFormat: boolean;
Status: integer; // 0: begin 1: separate 2: end
end;
type TrProperty = class
public
function Create();
public
TrPr: TrPr;
Height: real;
end;
type Region = class
public
function Create();
public
BordersRange: BordersRange;
RangeArr: array of BasicRange;
end;
type SymbolMapper = class
class function SymbolChr(symbol: string): string;
class function ZapfDingbatsChr(str: string): string;
private
static symbol_chr_hash_: array of chr;
static zapfdingbats_chr_hash_: array of chr;
end;
implementation
function Utf8CharLengthFromByte(byte: char): integer;
begin
if (_and(ord(byte), 0b10000000)) = 0 then
return 1;
else if (_and(ord(byte), 0b11100000)) = 0b11000000 then
return 2;
else if (_and(ord(byte), 0b11110000)) = 0b11100000 then
return 3;
else if (_and(ord(byte), 0b11111000)) = 0b11110000 then
return 4;
end;
function IsChineseChar(str: utf8_string): boolean;
begin
unicode_str := utf8ToUnicode(str);
codepoint := ord(unicode_str[1]);
return (codepoint >= 0x4E00 && codepoint <= 0x9FFF) or
(codepoint >= 0x3400 && codepoint <= 0x4DBF) or
(codepoint >= 0x20000 && codepoint <= 0x2A6DF);
end;
function IsChinesePunctuation(str: utf8_string): boolean;
begin
unicode_str := utf8ToUnicode(str);
codepoint := ord(unicode_str[1]);
return (codepoint >= 0x3000 && codepoint <= 0x303F) or
(codepoint >= 0xFF00 && codepoint <= 0xFFEF) or
(codepoint = 0x2018 || codepoint = 0x2019) or
(codepoint = 0x201C || codepoint = 0x201D) or
(codepoint = 0x2026 || codepoint = 0x2027);
end;
// Point
function Point.Create();
begin
{self.}X := 0;
{self.}Y := 0;
end;
// Stack
function Stack.Create();
begin
arr_ := array();
index_ := 0;
end;
function Stack.Pop();
begin
if index_ = 0 then return nil;
index_--;
ret := arr_[index_];
arr_[index_] := nil;
return ret;
end;
function Stack.Push(element: any);
begin
arr_[index_++] := element;
end;
function Stack.Empty(): boolean;
begin
return index_ = 0;
end;
// FldType
function FldType.Create();
begin
{self.}Page := false;
{self.}NumPages := false;
{self.}Quote := false;
{self.}PageRef := false;
end;
// FldStruct
function FldStruct.Create();
begin
{self.}Type := new FldType();
{self.}Arabic := false;
{self.}MergeFormat := false;
{self.}Status := 0;
end;
// TrProperty
function TrProperty.Create();
begin
{self.}TrPr := nil;
{self.}Height := 0;
end;
// Region
function Region.Create();
begin
BordersRange := new DTPPrimitiveRanges.BordersRange();
RangeArr := array();
end
// SymbolMapper
class function SymbolMapper.SymbolChr(symbol: string);
begin
if ifnil(symbol_chr_hash_) then
begin
symbol_chr_hash_ := array(
"": chr(0x2D),
"α": chr(0x61),
"β": chr(0x62),
"ε": chr(0x65),
"γ": chr(0x67),
"π": chr(0x70),
"θ": chr(0x71),
"{": chr(0x7B),
"}": chr(0x7D),
"∞": chr(0xA5),
"f": chr(0xA6),
"±": chr(0xB1),
"×": chr(0xB4),
"∂": chr(0xB6),
"∏": chr(0xD5),
"〈": chr(0xE1),
"∑": chr(0xE5),
"⌊": chr(0xEB),
"〉": chr(0xF1),
"Į": chr(0xF2),
"⌋": chr(0xFB),
// "": chr(0x),
);
end
return symbol_chr_hash_[symbol];
end;
class function SymbolMapper.ZapfDingbatsChr(str: string): string;
begin
if ifnil(zapfdingbats_chr_hash_) then
begin
zapfdingbats_chr_hash_ := array(
"": chr(118),
"": chr(110),
"": chr(108),
"": chr(117),
"": chr(108),
"o": chr(109),
"": chr(110),
);
end
return zapfdingbats_chr_hash_[symbol];
end;
end.
-10
View File
@@ -1,10 +0,0 @@
type TSPdfAbstractRange = class
public
function Do();virtual;
public
X: real;
Y: real; // range的起始坐标(x,y)
W: real; // range的宽度
H: real; // range的高度
end;
-21
View File
@@ -1,21 +0,0 @@
type TSPdfImageRange = class(TSPdfAbstractRange)
public
function Do();override;
public
Page: PdfPage;
Image: PdfImage;
end;
function TSPdfImageRange.Do();
begin
// println("image = {}, x = {}, y = {}, w = {}, h = {}", image, x, y, w, h);
self.Page.DrawImage(self.Image, self.X, self.Y, self.W, self.H);
if sysparams["_PDF_IMAGE_DEBUG_"] then
begin
self.Page.SetLineWidth(0.1);
self.Page.SetRGBStroke(0.8, 0.8, 0);
self.Page.Rectangle(X, Y, W, H);
self.Page.Stroke();
end
end;
-366
View File
@@ -1,366 +0,0 @@
type TSPdfParagraphRange = class(TSPdfAbstractRange)
public
function Create(docx_to_pdf: TSDocxToPdf; page: PdfPage; components: Components; sect_ware: TSSectWare; paragraph: P);
function Calc();
function Do();override;
function SetExtraStyleId(style_id: string);
private
function SetPPr(var ppr: PPr);
function SetPPrByStyleId(var ppr: PPr; style_id: string);
function SetRPr(var rpr; ppr: PPr);
function SetRPrByStyleId(var rpr: RPr; style_id: string);
function SetLvlText();
function GetImageFileType(data: binary): string;
function GetParagraphLineSpace(size: real; line: integer): real;
function RangesToLines(ppr: PPr): tableArray;
function CheckAndAddPage(y: real; offset: real): boolean;
function GetUtf8CharLength(byte: string): integer;
function RToTextRange(r: R; ppr: PPr);
function SplitTextToTextRange(text: string; rpr: RPr);
function RToDrawingRange(r: R; ppr: PPr);
function SetLinesAlignment(ppr: PPr);
function ResetCoordinates(ppr);
private
docx_to_pdf_: TSDocxToPdf;
docx_components_: Components;
sect_ware_: TSSectWare;
paragraph_: P;
extra_style_id_: string;
range_array_: array of TSPdfAbstractRange;
page_: PdfPage;
point_: TSPoint;
lines_range_array_: tableArray;
end;
function TSPdfParagraphRange.Create(docx_to_pdf: TSDocxToPdf; page: PdfPage; components: Components; sect_ware: TSSectWare; paragraph: P);
begin
docx_to_pdf_ := docx_to_pdf;
page_ := page;
docx_components_ := Components;
sect_ware_ := sect_ware;
paragraph_ := paragraph;
extra_style_id_ := "";
range_array_ := array();
point_ := new TSPoint(); // 动态记录段落的坐标位置
lines_range_array_ := array();
end;
function TSPdfParagraphRange.Calc(): tableArray;
begin
self.SetPPr(paragraph_.PPr);
self.SetLvlText();
ppr := new PPrUnitDecorator(paragraph_.PPr);
self.ResetCoordinates(ppr);
point_.X := self.X;
point_.Y := self.Y;
self.CheckAndAddPage(point_.Y, ppr.Spacing.Before);
point_.Y -= ppr.Spacing.Before;
rs := paragraph_.Rs();
if length(rs) = 0 then
begin
line_space := self.GetParagraphLineSpace(ppr.RPr.Sz.Val, ppr.Spacing.Line);
if not self.H then self.H := ppr.Spacing.After + line_space;
point_.Y -= self.H;
end
else begin
for _, r in rs do
begin
self.SetRPr(r.RPr, paragraph_.PPr);
if r.Br.Type = "page" then
self.CheckAndAddPage(sect_ware_.SectPr.PgMar.Bottom, 1);
else if ifObj(r.Drawing.XmlNode) then self.RToDrawingRange(r, ppr);
else self.RToTextRange(r, ppr);
end
end
self.RangesToLines(ppr);
end;
function TSPdfParagraphRange.Do();
begin
for _,line_range in lines_range_array_ do
for _,range in line_range do
range.Do();
end;
function TSPdfParagraphRange.SetExtraStyleId(style_id: string);
begin
extra_style_id_ := style_id;
end;
function TSPdfParagraphRange.RangesToLines(ppr: PPr);
begin
lines_range_array_ := array();
i := 0;
max_size := 0;
max_y := 0;
line_range := array();
total_height := 0;
while i <= length(range_array_)-1 do
begin
range := range_array_[i];
if i = 0 then point_.X += ppr.Ind.FirstLine;
if range is class(TSPdfTextRange) and range.RPr.Sz.Val > max_size then
max_size := range.RPr.Sz.Val;
if range.H > max_y then max_y := range.H;
line_space := self.GetParagraphLineSpace(max_size, ppr.Spacing.Line);
diff := point_.Y - sect_ware_.SectPr.PgMar.Bottom;
if self.CheckAndAddPage(point_.Y, max(line_space, range.H)) then
total_height += diff;
if_newline := point_.X + range.W - self.X > self.W + 1e-6;
if if_newline and range.W < self.W then
begin
offset := line_space > max_y ? (line_space - max_size) / 2 + max_size - max_size / 5 : max_y;
for _,item in line_range do
begin
item.Page := page_;
item.Y := point_.Y - offset;
end
lines_range_array_[length(lines_range_array_)] := line_range;
line_range := array();
max_value := max(line_space, max_y);
max_size := 0;
max_y := 0;
total_height += max_value;
point_.Y -= max_value;
point_.X := self.X;
// w:hanging
sz := range.RPr.SzCs.Val ? range.RPr.SzCs.Val : range.RPr.Sz.Val ? range.RPr.Sz.Val : docx_to_pdf_.Font.GetDefaultSz();
point_.X -= ppr.Ind.HangingChars ? ppr.Ind.HangingChars * sz : ppr.Ind.Hanging;
continue;
end
range.X := point_.X - range.X;
point_.X += range.W;
line_range[length(line_range)] := range;
i++;
if i = length(range_array_) then
begin
offset := line_space > max_y ? (line_space - max_size) / 2 + max_size - max_size / 5 : max_y;
for _,item in line_range do
begin
item.Page := page_;
item.Y := point_.Y - offset;
end
lines_range_array_[length(lines_range_array_)] := line_range;
max_value := max(line_space, max_y) + ppr.Spacing.After;
total_height += max_value;
point_.Y -= max_value;
end
end
self.SetLinesAlignment(ppr);
if not self.H then self.H := total_height;
self.Y := point_.Y;
end;
function TSPdfParagraphRange.SetLinesAlignment(ppr: PPr);
begin
if length(lines_range_array_) = 0 then return;
idx := length(lines_range_array_)-1;
line := lines_range_array_[idx];
offset := 0;
case ppr.Jc.Val of
"center":
begin
first := line[0];
last := line[length(line)-1];
offset := (self.W - last.X + first.X - last.W) / 2;
end
"right":
begin
first := line[0];
last := line[length(line)-1];
offset := self.W - last.X + first.X - last.W;
end
end;
if offset < 0 then return;
if offset then
for i:=0 to length(line)-1 do
line[i].X += offset;
end;
function TSPdfParagraphRange.CheckAndAddPage(y: real; offset: real): boolean;
begin
if y - offset < sect_ware_.SectPr.PgMar.Bottom then
begin
page_ := docx_to_pdf_.GetNextPage(page_);
if ifnil(page_) then page_ := docx_to_pdf_.AddPage(sect_ware_);
point := docx_to_pdf_.GetCurrentPoint();
point_.Y := point.Y;
return true;
end
return false;
end;
function TSPdfParagraphRange.GetUtf8CharLength(byte: string): integer;
begin
if (_and(ord(byte), 0b10000000)) = 0 then
return 1;
else if (_and(ord(byte), 0b11100000)) = 0b11000000 then
return 2;
else if (_and(ord(byte), 0b11110000)) = 0b11100000 then
return 3;
else if (_and(ord(byte), 0b11111000)) = 0b11110000 then
return 4;
end;
function TSPdfParagraphRange.RToTextRange(r: R; ppr: PPr);
begin
rpr := new RPrUnitDecorator(r.RPr);
text := r.T.Text;
if ifString(text) then self.SplitTextToTextRange(text, rpr);
end;
function TSPdfParagraphRange.SplitTextToTextRange(text: string; rpr: RPr);
begin
pos := 1;
while pos <= length(text) do
begin
num := self.GetUtf8CharLength(text[pos]);
word := text[pos : pos+num-1];
word := utf8ToAnsi(word);
pos += num;
font_name := rpr.RFonts.EastAsia ? rpr.RFonts.EastAsia : rpr.RFonts.Ascii;
font_obj := docx_to_pdf_.Font.GetFont(font_name, rpr.B, rpr.I);
if not rpr.Sz.Val then rpr.Sz.Val := rpr.SzCs.Val ? rpr.SzCs.Val : docx_to_pdf_.Font.GetDefaultSz();
page_.SetFontAndSize(font_obj, rpr.Sz.Val);
word_width := page_.TextWidth(word);
text_range := new TSPdfTextRange();
text_range.RPr := rpr;
text_range.Text := word;
text_range.Font := font_obj;
text_range.W := word_width;
text_range.H := 0;
text_range.X := 0;
text_range.Y := 0;
range_array_[length(range_array_)] := text_range;
end
end;
function TSPdfParagraphRange.RToDrawingRange(r: R; ppr: PPr);
begin
xfrm := new XfrmUnitDecorator(r.Drawing._Inline.Graphic.GraphicData.Pic.SpPr.Xfrm);
rels_adapter := class(TSPdfSingletonKit).GetComponent(docx_components_, "document_rels_adapter");
id := r.Drawing._Inline.Graphic.GraphicData.Pic.BlipFill.Blip.Embed;
rel := rels_adapter.Id(id);
image_path := "word/" + rel.Target;
image := docx_components_.Zip().Get(image_path);
data := image.Data();
image_path := docx_to_pdf_.GetCachePath(image_path);
writeFile(rwBinary(), "", image_path, 0, length(data)-1, data);
image := nil;
case self.GetImageFileType(data) of
"png":
image := docx_to_pdf_.GetPdf().LoadPngImageFromFile("", image_path);
"jpg":
image := docx_to_pdf_.GetPdf().LoadJpegImageFromFile("", image_path);
end;
image_range := new TSPdfImageRange();
image_range.Image := image;
image_range.X := xfrm.Off.X;
image_range.Y := xfrm.Off.Y;
image_range.W := xfrm.Ext.CX;
image_range.H := xfrm.Ext.CY;
fileDelete("", image_path);
range_array_[length(range_array_)] := image_range;
end;
function TSPdfParagraphRange.GetImageFileType(data: binary): string;
begin
stream := new TMemoryStream();
size := length(data);
stream.Write(data[0:size-1], size);
def := array(
('name': 'png', 'position': 0, 'value': array(0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A)),
('name': 'jpg', 'position': 0, 'value': array(0xFF, 0xD8)),
);
for i:=0 to length(def)-1 do
begin
value := def[i]['value'];
stream.Seek(def[i]['position']);
for j:=0 to length(value)-1 do
begin
r := 0;
stream.Read(r, 1);
if r <> value[j] then break;
if j = length(value)-1 then return def[i]['name'];
end
end
return '';
end;
function TSPdfParagraphRange.GetParagraphLineSpace(size: real; line: integer): real;
begin
if not line then line := 12;
lines := roundto(line / 12, -1);
multi := ceil(size / sect_ware_.BaseSize) * lines;
return sect_ware_.SectPr.DocGrid.LinePitch * multi;
end;
function TSPdfParagraphRange.SetPPr(var ppr: PPr);
begin
new_ppr := new PPr();
styles := class(TSPdfSingletonKit).GetComponent(docx_components_, "styles");
new_ppr.Copy(styles.DocDefaults.PPrDefault.PPr);
new_ppr.RPr.Copy(styles.DocDefaults.RPrDefault.RPr);
self.SetPPrByStyleId(new_ppr, extra_style_id_);
self.SetPPrByStyleId(new_ppr, ppr.PStyle.Val);
new_ppr.Copy(ppr);
ppr.Copy(new_ppr);
end;
function TSPdfParagraphRange.SetPPrByStyleId(var ppr: PPr; style_id: string);
begin
styles := class(TSPdfSingletonKit).GetComponent(docx_components_, "styles_adapter");
style := styles.StyleId(style_id);
if ifObj(style) then
begin
based_on := style.BasedOn.Val;
self.SetPPrByStyleId(ppr, based_on);
ppr.Copy(style.PPr);
ppr.RPr.Copy(style.RPr);
end
end;
function TSPdfParagraphRange.SetRPr(var rpr; ppr: PPr);
begin
// rpr,先继承ppr,再继承样式,最后继承自己
new_rpr := new RPr();
style_id := rpr.RStyle.Val;
new_rpr.Copy(ppr.RPr);
self.SetRPrByStyleId(new_rpr, style_id);
new_rpr.Copy(rpr);
rpr.Copy(new_rpr);
end;
function TSPdfParagraphRange.SetRPrByStyleId(var rpr: RPr; style_id: string);
begin
styles := class(TSPdfSingletonKit).GetComponent(docx_components_, "styles_adapter");
style := styles.StyleId(style_id);
if ifObj(style) then
begin
based_on := style.BasedOn.Val;
self.SetRPrByStyleId(rpr, based_on);
rpr.Copy(style.RPr);
end
end;
function TSPdfParagraphRange.SetLvlText();
begin
numbering_ware := class(TSPdfSingletonKit).GetComponent(docx_components_, "numbering_ware");
if not ifObj(numbering_ware) then return;
[lvl_text, lvl] := numbering_ware.GetNumberLvl(paragraph_.PPr);
if lvl_text = "" and ifnil(lvl) then return;
self.SetRPr(lvl.RPr, paragraph_.PPr);
rpr := new RPrUnitDecorator(lvl.RPr);
self.SplitTextToTextRange(lvl_text, rpr);
end;
function TSPdfParagraphRange.ResetCoordinates(ppr);
begin
// 根据段落的间距确定新的坐标
sz := ppr.RPr.SzCs.Val ? ppr.RPr.SzCs.Val : ppr.RPr.Sz.Val ? ppr.RPr.Sz.Val : docx_to_pdf_.Font.GetDefaultSz();
self.X += ppr.Ind.LeftChars ? ppr.Ind.LeftChars * sz : ppr.Ind.Left;
self.W -= ppr.Ind.LeftChars ? ppr.Ind.LeftChars * sz : ppr.Ind.Left;
self.W -= ppr.Ind.RightChars ? ppr.Ind.RightChars * sz : ppr.Ind.Right;
end;
-16
View File
@@ -1,16 +0,0 @@
type TSPdfRectRange = class(TSPdfAbstractRange)
public
function Do();override;
public
Page: PdfPage;
end;
function TSPdfRectRange.Do();override;
begin
// self.Page.SetRGBStroke(1.0, 0.0, 0.0);
self.Page.SetGrayStroke(0.5);
self.Page.SetLineWidth(0.5);
self.Page.Rectangle(self.X, self.Y - self.H, self.W, self.H);
self.Page.Stroke();
self.Page.SetGrayStroke(0);
end;
-273
View File
@@ -1,273 +0,0 @@
type TSPdfTableRange = class(TSPdfAbstractRange)
public
function Create(docx_to_pdf: TSDocxToPdf; page: PdfPage; components: Components; sect_ware: TSSectWare; paragraph: P);
function Calc();
function Do();override;
private
function ProcessTrData(grid_cols: array of GridCol; tr: Tr; tbl_pr: TblPr): array of TSPdfAbstractRange;
function ResetCoordinates(tbl_pr: TblPr; grid_cols: array of GridCol);
function CheckAndAddPage(y: real; offset: real): boolean;
function SetTblPr(tbl_pr: TblPr);
function SetTblPrByStyleId(var tbl_pr: TblPr; style_id: string);
function SetTrPr(var tr_pr: TrPr);
function SetTrPrByStyleId(var tr_pr: TrPr; style_id: string);
function SetTcPr(var tc_pr: TcPr);
function SetTcPrByStyleId(var tc_pr: TcPr; style_id: string);
private
docx_to_pdf_: TSDocxToPdf;
docx_components_: Components;
sect_ware_: TSSectWare;
table_: Tbl;
range_array_: tableArray;
page_: PdfPage;
point_: TSPoint;
end;
function TSPdfTableRange.Create(docx_to_pdf: TSDocxToPdf; page: PdfPage; components: Components; sect_ware: TSSectWare; table: Tbl);
begin
docx_to_pdf_ := docx_to_pdf;
page_ := page;
docx_components_ := Components;
sect_ware_ := sect_ware;
table_ := table;
range_array_ := array();
point_ := new TSPoint(); // 动态记录段落的坐标位置
end;
function TSPdfTableRange.Calc();
begin
self.SetTblPr(table_.TblPr);
tbl_pr := new TblPrUnitDecorator(table_.TblPr);
grid_cols := table_.TblGrid.GridCols();
for i:=0 to length(grid_cols)-1 do
grid_cols[i] := new GridColUnitDecorator(grid_cols[i]);
self.ResetCoordinates(tbl_pr, grid_cols);
point_.X := self.X;
point_.Y := self.Y;
// 如果是根据内容自适应,应该计算并调整grid_cols的值
trs := table_.Trs();
for i,tr in trs do
range_array_[i] := self.ProcessTrData(grid_cols, tr, tbl_pr);
end;
function TSPdfTableRange.Do();
begin
for _,row in range_array_ do
for _,range in row do
range.Do();
end;
function TSPdfTableRange.CheckAndAddPage(y: real; offset: real): boolean;
begin
if y - offset < sect_ware_.SectPr.PgMar.Bottom then
begin
page_ := docx_to_pdf_.GetNextPage(page_);
if ifnil(page_) then page_ := docx_to_pdf_.AddPage(sect_ware_);
point := docx_to_pdf_.GetCurrentPoint();
point_.Y := point.Y;
return true;
end
return false;
end;
function TSPdfTableRange.ProcessTrData(grid_cols: array of GridCol; tr: Tr; tbl_pr: TblPr): array of TSPdfAbstractRange;
begin
self.SetTrPr(tr.TrPr);
tr_pr := new TrPrUnitDecorator(tr.TrPr);
height := tr_pr.TrHeight.Val;
tcs := tr.Tcs();
tc_x := point_.X;
tc_y := point_.Y;
tc_h := height;
max_height := tc_h;
rows_range_array := array();
for i,tc in tcs do
begin
tc_w := grid_cols[i].W;
elements := tc.Elements();
rect_range := new TSPdfRectRange();
rect_range.X := tc_x;
rect_range.Y := tc_y;
rect_range.W := tc_w;
rect_range.H := tc_h;
rect_range.Page := page_;
rows_range_array[length(rows_range_array)] := rect_range;
cell_x := tc_x + tbl_pr.TblCellMar.Left.W;
cell_y := tc_y - tbl_pr.TblCellMar.Top.W;
cell_w := tc_w - tbl_pr.TblCellMar.Right.W - tbl_pr.TblCellMar.Left.W;
cell_total_h := 0;
for _,element in elements do
begin
range := nil;
if element.LocalName = "p" then
begin
range := new TSPdfParagraphRange(docx_to_pdf_, page_, docx_components_, sect_ware_, element);
range.SetExtraStyleId(tbl_pr.TblStyle.Val);
end
else if element.LocalName = "tbl" then
begin
range := new TSPdfTableRange(docx_to_pdf_, page_, docx_components_, sect_ware_, element);
end
if ifObj(range) then
begin
range.X := cell_x;
range.Y := cell_y;
range.W := cell_w;
range.H := tc_h;
range.Calc();
rows_range_array[length(rows_range_array)] := range;
cell_total_h += range.H;
cell_y -= range.H;
end
end
tc_x += tc_w;
if cell_total_h > max_height then max_height := cell_total_h;
end
// 判定是否跨页
total_height := max_height + tbl_pr.TblCellMar.Top.W + tbl_pr.TblCellMar.Bottom.W;
surplus := total_height - (point_.Y - sect_ware_.SectPr.PgMar.Bottom);
if not self.H and surplus > 0 then
begin
for _,range in rows_range_array do
range.H := point_.Y - sect_ware_.SectPr.PgMar.Bottom;
span := sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Top - sect_ware_.SectPr.PgMar.Bottom;
quotient := surplus div span;
remainder := surplus % span;
page := page_;
tc_y := point_.Y;
i := 0;
while i < quotient do
begin
tc_x := point_.X;
tc_y := sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Top;
tc_h := tc_y - sect_ware_.SectPr.PgMar.Bottom;
page := docx_to_pdf_.GetNextPage(page);
for j:=0 to length(tcs)-1 do
begin
tc_w := grid_cols[i].W;
rect_range := new TSPdfRectRange();
rect_range.X := tc_x;
rect_range.Y := tc_y;
rect_range.W := tc_w;
rect_range.H := tc_h;
rect_range.Page := page;
tc_x += tc_w;
rows_range_array[length(rows_range_array)] := rect_range;
end
i++;
end
if remainder then
begin
tc_x := point_.X;
tc_y := sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Top;
tc_h := remainder;
page := docx_to_pdf_.GetNextPage(page);
for j:=0 to length(tcs)-1 do
begin
tc_w := grid_cols[i].W;
rect_range := new TSPdfRectRange();
rect_range.X := tc_x;
rect_range.Y := tc_y;
rect_range.W := tc_w;
rect_range.H := tc_h;
rect_range.Page := page;
tc_x += tc_w;
rows_range_array[length(rows_range_array)] := rect_range;
end
end
point_.Y := tc_y - remainder;
self.Y := point_.Y;
page_ := page;
end
else begin
tc_h := tc_h ? tc_h : max_height;
for _,range in rows_range_array do
range.H := tc_h;
point_.Y -= tc_h;
self.Y := point_.Y;
end
return rows_range_array;
end;
function TSPdfTableRange.ResetCoordinates(tbl_pr: TblPr; grid_cols: array of GridCol);
begin
total_width := 0;
for _,grid_col in grid_cols do
total_width += grid_col.W;
diff := total_width - self.W;
case tbl_pr.jc.Val of
"center":
begin
offset := diff/2;
self.X -= offset;
end
"right":
begin
self.X -= diff;
end
end;
self.W := total_width;
end;
function TSPdfTableRange.SetTblPr(var tbl_pr: TblPr);
begin
new_tbl_pr := new TblPr();
self.SetTblPrByStyleId(new_tbl_pr, tbl_pr.TblStyle.Val);
new_tbl_pr.Copy(tbl_pr);
tbl_pr.Copy(new_tbl_pr);
end;
function TSPdfTableRange.SetTblPrByStyleId(var tbl_pr: TblPr; style_id: string);
begin
styles := class(TSPdfSingletonKit).GetComponent(docx_components_, "styles_adapter");
style := styles.StyleId(style_id);
if ifObj(style) then
begin
based_on := style.BasedOn.Val;
self.SetTblPrByStyleId(tbl_pr, based_on);
tbl_pr.Copy(style.TblPr);
end
end;
function TSPdfTableRange.SetTrPr(var tr_pr: TrPr);
begin
new_tr_pr := new TrPr();
self.SetTrPrByStyleId(new_tr_pr, table_.TblPr.TblStyle.Val);
new_tr_pr.Copy(tr_pr);
tr_pr.Copy(new_tr_pr);
end;
function TSPdfTableRange.SetTrPrByStyleId(var tr_pr: TrPr; style_id: string);
begin
styles := class(TSPdfSingletonKit).GetComponent(docx_components_, "styles_adapter");
style := styles.StyleId(style_id);
if ifObj(style) then
begin
based_on := style.BasedOn.Val;
self.SetTrPrByStyleId(tr_pr, based_on);
tr_pr.Copy(style.TrPr);
end
end;
function TSPdfTableRange.SetTcPr(var tc_pr: TcPr);
begin
new_tc_pr := new TcPr();
self.SetTcPrByStyleId(new_tc_pr, table_.TblPr.TblStyle.Val);
new_tc_pr.Copy(tc_pr);
tc_pr.Copy(new_tc_pr);
end;
function TSPdfTableRange.SetTcPrByStyleId(var tc_pr: TcPr; style_id: string);
begin
styles := class(TSPdfSingletonKit).GetComponent(docx_components_, "styles_adapter");
style := styles.StyleId(style_id);
if ifObj(style) then
begin
based_on := style.BasedOn.Val;
self.SetTcPrByStyleId(tc_pr, based_on);
tc_pr.Copy(style.TcPr);
end
end;
-34
View File
@@ -1,34 +0,0 @@
type TSPdfTextRange = class(TSPdfAbstractRange)
uses TSColorToolKit;
public
function Do();override;
public
RPr: RPr;
Text: string;
Font: PdfFont;
Page: PdfPage;
end;
function TSPdfTextRange.Do();
begin
// println("text = {}, x = {}, y = {}, w = {}, sz = {}", ansiToUtf8(text), x, y, w);
[r, g, b] := array(0, 0, 0);
if self.RPr.Color.Val then [r, g, b] := TSColorToolKit.HexToRGB(self.RPr.Color.Val);
self.Page.SetRGBFill(r / 255, g / 255, b / 255);
self.Page.SetFontAndSize(self.Font, self.RPr.Sz.Val);
self.Page.BeginText();
self.Page.TextOut(self.X, self.Y, self.Text);
self.Page.EndText();
self.Page.SetRGBFill(0, 0, 0);
if sysparams["_PDF_TEXT_DEBUG_"] then
begin
self.Page.SetLineWidth(0.1);
self.Page.SetRGBStroke(1.0, 0.5, 0.0);
self.Page.MoveTo(0, self.Y);
self.Page.LineTo(600, self.Y);
self.Page.Stroke();
end
end;
-59
View File
@@ -1,59 +0,0 @@
type TSPdfSingletonKit = class
public
function Create();
class function GetComponent(components: Components; type: string);
public
hash_: array of tslobj;
private
static singleton_: Singleton;
end;
function TSPdfSingletonKit.Create();
begin
hash_ := array();
end;
class function TSPdfSingletonKit.GetComponent(components: Components; type: string);
begin
if not ifObj(singleton_) then singleton_ := new TSPdfSingletonKit();
if ifnil(singleton_.hash_[components]) then singleton_.hash_[components] := array();
if ifObj(singleton_.hash_[components][type]) then return singleton_.hash_[components][type];
case type of
"styles":
begin
styles := components.Styles;
styles.Deserialize();
singleton_.hash_[components][type] := styles;
return styles;
end
"styles_adapter":
begin
styles := class(TSPdfSingletonKit).GetComponent(components, "styles");
styles_adapter := new StylesAdapter(styles);
singleton_.hash_[components][type] := styles_adapter;
return styles_adapter;
end
"numbering_ware":
begin
numbering := components.Numbering;
numbering_ware := nil;
if ifObj(numbering) then
begin
numbering.Deserialize();
numbering_ware := new TSNumberingWare(numbering);
end
singleton_.hash_[components][type] := numbering_ware;
return numbering_ware;
end
"document_rels_adapter":
begin
document_rels := components.DocumentRels;
document_rels.Deserialize();
rels_adapter := new RelationShipsAdapter(document_rels);
singleton_.hash_[components][type] := rels_adapter;
return rels_adapter;
end
end;
end;
-10
View File
@@ -1,10 +0,0 @@
type TSPoint = class
function Create();
begin
self.X := 0;
self.Y := 0;
end
X: real;
Y: real;
end;
-88
View File
@@ -1,88 +0,0 @@
type TSFontWare = class
public
function Create(pdf: PdfFile);
function GetFont(name: string; bold: boolean; italic: boolean);
function UseExternalFont();
function SetSubstitutionRules(source: string; target: string);
function SetDefaultSz(value: real);
function GetDefaultSz();
private
function GetExternalFont(name:string; bold: boolean; italic: boolean);
function GetBuiltInFont(name:string; bold: boolean; italic: boolean);
private
[weakref]pdf_: PdfFile;
is_linux_: boolean; // 是否是linux
use_built_in_font_: boolean; // 是否使用内置字体
substitution_rules_: array of string; // 替换规则
external_reference_: array of string;
default_sz_: real;
end;
function TSFontWare.Create(pdf: PdfFile);
begin
pdf_ := pdf;
use_built_in_font_ := true;
substitution_rules_ := array("宋体": "SimSun", "黑体": "SimHei");
external_reference_ := array();
default_sz_ := 10.5;
end;
function TSFontWare.SetDefaultSz(value: real);
begin
default_sz_ := value;
end;
function TSFontWare.GetDefaultSz();
begin
return default_sz_;
end;
function TSFontWare.UseExternalFont();
begin
use_built_in_font_ := false;
end;
function TSFontWare.GetExternalFont(name:string; bold: boolean; italic: boolean);
begin
if ifnil(name) or name = '' then name := "等线";
if not ifnil(external_font_cache_[name]) then return external_font_cache_[name];
value := external_reference_[name];
if ifnil(value) then return nil;
// if ifnil(value) then raise name + " is unsupported font.";
if value["ext"] = ".ttf" then
font_name := pdf_.LoadTTFontFromFile("", value["path"], true);
else if value["ext"] = ".ttc" then
font_name := pdf_.LoadTTFontFromFile2("", value["path"], 0, true);
// if not ifString(font_name) then raise "Load font error : " + format("%x", font_name);
if not ifString(font_name) then return nil;
font := pdf_.GetFont(font_name, "UTF-8");
external_font_cache_[name] := font;
return font;
end;
function TSFontWare.GetFont(name: string; bold: boolean; italic: boolean);
begin
return use_built_in_font_ ? self.GetBuiltInFont(name, bold, italic) : self.GetExternalFont(name, bold, italic);
end;
function TSFontWare.GetBuiltInFont(name: string; bold: boolean; italic: boolean);
begin
font_name := substitution_rules_["name"];
if ifnil(font_name) then font_name := "SimSun";
if bold and italic then
font_name += ",BoldItalic";
else if bold then
font_name += ",Bold";
else if italic then
font_name += ",Italic";
font := pdf_.GetFont(font_name, "GBK-EUC-H");
return font;
end;
function TSFontWare.SetSubstitutionRules(source: string; target: string);
begin
substitution_rules_[source] := target;
end;
-48
View File
@@ -1,48 +0,0 @@
type TSNumberingWare = class
public
function Create(number: NumberingAdapter);
function GetNumberLvl(ppr: PPr);
private
numbering_adapter_: NumberingAdapter;
num_hash_: array of tslobj;
end;
function TSNumberingWare.Create(number: NumberingAdapter);
begin
numbering_adapter_ := new NumberingAdapter(number);
num_hash_ := array();
end;
function TSNumberingWare.GetNumberLvl(ppr: PPr);
begin
num_id := ppr.NumPr.NumId.Val;
if ifnil(num_id) then return array("", nil);
ilvl := ppr.NumPr.Ilvl.Val;
pstyle := ppr.PStyle.Val;
num := numbering_adapter_.NumId(num_id);
abstract_id := num.AbstractNumId.Val;
abstract_num := numbering_adapter_.AbstractNumId(abstract_id);
lvls := abstract_num.Lvls();
if ifnil(ilvl) then ilvl := "0";
for k,v in lvls do
begin
if ilvl and v.Ilvl = ilvl then
begin
lvl_text := v.LvlText.Val;
if not ifarray(num_hash_[num_id]) then num_hash_[num_id] := array(0, 0, 0, 0, 0, 0, 0, 0, 0);
ilvl_int := strtoint(ilvl);
for i:=0 to ilvl_int do
begin
source_str := "%" $ (i + 1);
n := i = ilvl_int ? num_hash_[num_id][i] + 1 : num_hash_[num_id][i];
dest_str := format("%d", n);
lvl_text := replaceStr(lvl_text, source_str, dest_str);
end
num_hash_[num_id][ilvl_int]++;
if v.Suff.Val = "space" then lvl_text += " ";
return array(lvl_text, v);
end
end
return array("", nil);
end
-27
View File
@@ -1,27 +0,0 @@
type TSSectWare = class
public
function Create();
function Do();
public
Elements: array of tslobj;
SectPr: SectPr;
BaseSize: integer;
end;
function TSSectWare.Create();
begin
self.Elements := array();
self.SectPr := nil;
self.BaseSize := 0;
end;
function TSSectWare.Do();
begin
if ifObj(self.SectPr) then
self.BaseSize := round(self.SectPr.DocGrid.LinePitch * 0.75);
// println("LinePitch = {}, Type = {}", self.SectPr.DocGrid.LinePitch, self.SectPr.DocGrid.Type);
// println("Width = {}, Height = {}", self.SectPr.PgSz.W, self.SectPr.PgSz.H);
// println("Top = {}, Right = {}, Bottom = {}, Left = {}, Header = {}, Footer = {}\n",
// self.SectPr.PgMar.Top, self.SectPr.PgMar.Right, self.SectPr.PgMar.Bottom, self.SectPr.PgMar.Left, self.SectPr.PgMar.Header, self.SectPr.PgMar.Footer);
end;