Compare commits
58
Commits
f72b734cc4
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a46ccf838 | ||
|
|
7da30f77ab | ||
|
|
4be804cb1b | ||
|
|
5121a94b15 | ||
|
|
600ce2e358 | ||
|
|
2e0aadd3d0 | ||
|
|
9f84a72595 | ||
|
|
a118ff6c26 | ||
|
|
5c93255461 | ||
|
|
973f880dd7 | ||
|
|
bdbd201e44 | ||
|
|
4c002f803f | ||
|
|
a677e5a843 | ||
|
|
3b16e6969f | ||
|
|
f251782186 | ||
|
|
b1cb66fd48 | ||
|
|
0437961953 | ||
|
|
8ab1670eea | ||
|
|
57f673f457 | ||
|
|
5652980a97 | ||
|
|
003268fd40 | ||
|
|
da65b2b6c3 | ||
|
|
222577dd74 | ||
|
|
2d6632895b | ||
|
|
535bdb20d4 | ||
|
|
eb6e898ed7 | ||
|
|
4de1484ec3 | ||
|
|
9db7890278 | ||
|
|
2a7027476a | ||
|
|
68ce759668 | ||
|
|
5dc201c1a2 | ||
|
|
448bbfc7e2 | ||
|
|
0417669eb2 | ||
|
|
9886040fa9 | ||
|
|
43ffb5b5c0 | ||
|
|
440788412b | ||
|
|
61b86d34e7 | ||
|
|
a0ea61af14 | ||
|
|
ca18537538 | ||
|
|
4c6f4d6e09 | ||
|
|
70ad4acbdb | ||
|
|
4357cfb529 | ||
|
|
d0de1aa227 | ||
|
|
1cd72f6247 | ||
|
|
9dc7a66b62 | ||
|
|
d687f45b3b | ||
|
|
1eee1efc3a | ||
|
|
151eef66b7 | ||
|
|
e5dfdeadc0 | ||
|
|
d14de26d58 | ||
|
|
cfc2d74ab8 | ||
|
|
d3f9431b26 | ||
|
|
615f4a5b39 | ||
|
|
5fe2911608 | ||
|
|
b167501fde | ||
|
|
66ec96e167 | ||
|
|
51dc8596be | ||
|
|
999a7ef2d0 |
@@ -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
@@ -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;
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
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);
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
type TSPoint = class
|
||||
function Create();
|
||||
begin
|
||||
self.X := 0;
|
||||
self.Y := 0;
|
||||
end
|
||||
X: real;
|
||||
Y: real;
|
||||
end;
|
||||
|
||||
@@ -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;
|
||||
@@ -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
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user