271 lines
7.7 KiB
Plaintext
271 lines
7.7 KiB
Plaintext
type TSDocxToPdf = class
|
|
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;
|
|
|
|
property Font read ReadFont;
|
|
function ReadFont();
|
|
|
|
private
|
|
function InitDocxComponents(alias: string; file: string);
|
|
function InitCachePath(file: string);
|
|
function InitPdfEncoder();
|
|
function InitSectWare();
|
|
function AllocateElementsToSectWare();
|
|
|
|
function ResetCoordinates(sect_ware: TSSectWare);
|
|
function TransformP(sect_ware: TSSectWare; paragraph: P);
|
|
function TransformTbl(sect_ware: TSSectWare; table: Tbl);
|
|
function TransformSdt(sect_ware: TSSectWare; sdt: Sdt);
|
|
|
|
function PrintGrid(page: PdfPage; sect_ware: TSSectWare); // test
|
|
|
|
private
|
|
pdf_: PdfFile;
|
|
docx_components_: Components; // Components@DOCX
|
|
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;
|
|
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_);
|
|
current_page_ := nil;
|
|
point_ := new TSPoint();
|
|
page_array_ := array();
|
|
page_index_ := array();
|
|
end;
|
|
|
|
function TSDocxToPdf.Destroy();
|
|
begin
|
|
removeDir("", cache_path_);
|
|
class(TSPdfSingletonKit).Release(docx_components_);
|
|
end;
|
|
|
|
function TSDocxToPdf.SaveToFile(alias: string; file: string): integer;
|
|
begin
|
|
return pdf_.SaveToFile(alias, file);
|
|
end;
|
|
|
|
function TSDocxToPdf.Transform();
|
|
begin
|
|
prev := nil;
|
|
for _,sect_ware in sect_ware_array_ do
|
|
begin
|
|
if prev <> sect_ware then
|
|
begin
|
|
self.AddPage(sect_ware);
|
|
prev := sect_ware;
|
|
end
|
|
elements := sect_ware.Elements;
|
|
for _,element in elements do
|
|
begin
|
|
if element.LocalName = "p" then self.TransformP(sect_ware, element);
|
|
else if element.LocalName = "tbl" then self.TransformTbl(sect_ware, element);
|
|
end
|
|
end
|
|
end;
|
|
|
|
function TSDocxToPdf.GetCurrentPage(): PdfPage;
|
|
begin
|
|
return current_page_;
|
|
end;
|
|
|
|
function TSDocxToPdf.GetCurrentPoint(): Point;
|
|
begin
|
|
return point_;
|
|
end;
|
|
|
|
function TSDocxToPdf.GetCachePath(image_path: string): string;
|
|
begin
|
|
return cache_path_ + extractFileName(image_path);
|
|
end;
|
|
|
|
function TSDocxToPdf.GetPdf(): PdfFile;
|
|
begin
|
|
return pdf_;
|
|
end;
|
|
|
|
function TSDocxToPdf.ReadFont();
|
|
begin
|
|
return font_ware_;
|
|
end;
|
|
|
|
function TSDocxToPdf.InitPdfEncoder();
|
|
begin
|
|
pdf_.UseCNSFonts();
|
|
pdf_.UseCNSEncodings();
|
|
// pdf_.UseUTFEncodings();
|
|
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.";
|
|
end;
|
|
|
|
function TSDocxToPdf.InitCachePath(file: string);
|
|
begin
|
|
path := format("%s_%s", extractFileName(file), formatDatetime("YYYYMMDDHHNNSSZZZ", now()));
|
|
cache_dir := format("%s/funcext/PdfConverter/.cache", extractFileDir(sysExecName()));
|
|
createDir("", cache_dir);
|
|
cache_path_ := format("%s/%s/", cache_dir, path);
|
|
createDir("", cache_path_);
|
|
end;
|
|
|
|
function TSDocxToPdf.InitSectWare();
|
|
begin
|
|
document := docx_components_.Document;
|
|
document.Deserialize();
|
|
sect_ware_array_ := array();
|
|
self.AllocateElementsToSectWare();
|
|
end;
|
|
|
|
function TSDocxToPdf.AllocateElementsToSectWare();
|
|
begin
|
|
elements := docx_components_.Document.Body.Elements();
|
|
ware := new TSSectWare();
|
|
fp := function(ware, sect);
|
|
begin
|
|
sect := new SectPrUnitDecorator(sect);
|
|
sect.PgSz.Orient := sect.PgSz.Orient ? "portrait" : "landscape";
|
|
ware.SectPr := sect;
|
|
ware.Do();
|
|
end
|
|
for i:=0 to length(elements)-1 do
|
|
begin
|
|
element := elements[i];
|
|
ware.AddElement(element);
|
|
if element.LocalName = "p" and ifObj(element.PPr.SectPr.XmlNode) then
|
|
begin
|
|
##fp(ware, element.PPr.SectPr);
|
|
sect_ware_array_[length(sect_ware_array_)] := ware;
|
|
ware := new TSSectWare();
|
|
end
|
|
else if element.LocalName = "sectPr" and i = length(elements)-1 then
|
|
begin
|
|
##fp(ware, element);
|
|
sect_ware_array_[length(sect_ware_array_)] := ware;
|
|
end
|
|
end
|
|
// println("sect_ware_array_ = {}", sect_ware_array_);
|
|
end;
|
|
|
|
function TSDocxToPdf.AddPage(sect_ware: TSSectWare): PdfPage;
|
|
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);
|
|
|
|
len := length(page_array_);
|
|
page_array_[len] := current_page_;
|
|
page_index_[current_page_] := len;
|
|
|
|
if sysparams["_PDF_PAGE_GRID_DEBUG_"] then
|
|
self.PrintGrid(current_page_, sect_ware);
|
|
|
|
return current_page_;
|
|
end;
|
|
|
|
function TSDocxToPdf.GetNextPage(page: PdfPage);
|
|
begin
|
|
pos := page_index_[page];
|
|
return page_array_[pos + 1];
|
|
end;
|
|
|
|
function TSDocxToPdf.ResetCoordinates(sect_ware: TSSectWare);
|
|
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);
|
|
end;
|
|
|
|
function TSDocxToPdf.PrintGrid(page: PdfPage; sect_ware: TSSectWare);
|
|
begin
|
|
i := 0;
|
|
while true do
|
|
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++;
|
|
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;
|
|
|
|
function TSDocxToPdf.TransformP(sect_ware: TSSectWare; paragraph: 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.StartX := point_.X;
|
|
range.StartY := point_.Y;
|
|
range.Width := w;
|
|
range.Calc();
|
|
range.Do();
|
|
point_.Y := range.EndY;
|
|
end;
|
|
|
|
function TSDocxToPdf.TransformTbl(sect_ware: TSSectWare; table: 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.StartX := point_.X;
|
|
range.StartY := point_.Y;
|
|
range.Width := w;
|
|
range.Calc();
|
|
range.Do();
|
|
point_.Y := range.EndY;
|
|
end;
|
|
|
|
function TSDocxToPdf.TransformSdt(sect_ware: TSSectWare; sdt: Sdt);
|
|
begin
|
|
w := sect_ware.SectPr.PgSz.W - sect_ware.SectPr.PgMar.Right - sect_ware.SectPr.PgMar.Left;
|
|
end;
|