Compare commits
No commits in common. "a118ff6c26fdaf45a22cf6ec6202595e7e44f2a5" and "973f880dd7433673285da671a9490a929ebde36e" have entirely different histories.
a118ff6c26
...
973f880dd7
469
TSDocxToPdf.tsf
469
TSDocxToPdf.tsf
|
|
@ -1,89 +1,116 @@
|
|||
type TSDocxToPdf = class
|
||||
uses TSPdfEnumerations, DocxML, DocxMLAdapter, DocxMLUnitDecorator, DTPModules, DTPUtils, DTPAdvancedRanges;
|
||||
public
|
||||
function Create(alias: string; file: string);
|
||||
function Destroy();
|
||||
function SaveToFile(alias: string; file: string): integer;
|
||||
function Transform();
|
||||
|
||||
function GetPdf(): PdfFile;
|
||||
function GetCurrentSectWare(): TSSectWare;
|
||||
function GetCurrentTextPoint(): Point;
|
||||
function GetCurrentHdrPoint(): Point;
|
||||
function GetCurrentFtrPoint(): Point;
|
||||
function GetCurrentNoteWare(): TSNoteWare;
|
||||
function GetCachePath(image_path: string): string;
|
||||
function GetNextPage(page: TSPage): TSPage;
|
||||
function GetCurrentXmlFile(): string;
|
||||
function GetCurrentNoteModule(): NoteModule;
|
||||
|
||||
function AddPage(flag: boolean): Page;
|
||||
function AddTSPage(flag: boolean): TSPage;
|
||||
function LinkToToc(anchor: string; page: TSPage; left: real; top: real);
|
||||
function AddToc(anchor: string; toc: TSToc);
|
||||
function SetHeaderAndFooter();
|
||||
function ProcessNumpages();
|
||||
function CalculateTextCoordinates(): array of real;
|
||||
function GetSymbol(symbol: string);
|
||||
function AddDocxPage(pg: TSPage; r: R);
|
||||
function AddColIndex();
|
||||
|
||||
// docx页码扩展
|
||||
function UpdateDocxPageNumPages();
|
||||
function UpdateDocxPageNumpages();
|
||||
function SaveDocxFile();overload;
|
||||
function SaveDocxFile(alias: string; file: string);overload;
|
||||
|
||||
property PdfFile read pdf_;
|
||||
property Font read font_module_;
|
||||
property PageManager read page_manager_module_;
|
||||
property Toc read toc_module_;
|
||||
property Note read note_module_;
|
||||
property Font read ReadFont;
|
||||
function ReadFont();
|
||||
|
||||
private
|
||||
function InitDocxComponents(alias: string; file: string);
|
||||
function InitCachePath(file: string);
|
||||
function InitPdfEncoder();
|
||||
function InitSectModule();
|
||||
function AllocateElementsToSectModule();
|
||||
function InitSectWare();
|
||||
function InitSymbol();
|
||||
function AllocateElementsToSectWare();
|
||||
function ClassifyCols(var point: Point; cols: Cols);
|
||||
|
||||
function SetHdr(type: string);
|
||||
function SetFtr(type: string);
|
||||
function TransformP(paragraph: P; x: real; y: real; w: real; lb: real): ParagraphRange;
|
||||
function TransformTbl(table: Tbl; x: real; y: real; w: real; lb: real): TableRange;
|
||||
function TransformSdt(sdt: Sdt; x: real; y: real; w: real; lb: real): array of ParagraphRange;
|
||||
function TransformP(var point: Point; paragraph: P; w: real; lb: real);
|
||||
function TransformTbl(var point: Point; table: Tbl; w: real; lb: real);
|
||||
function TransformSdt(var point: Point; sdt: Sdt; w: real; lb: real);
|
||||
|
||||
function PrintGrid(page: PdfPage; sect_ware: TSSectWare); // test
|
||||
|
||||
private
|
||||
pdf_: PdfFile;
|
||||
docx_components_module_: DocxComponentsModule; // TSDocxComponentsModule
|
||||
docx_components_ware_: TSDocxComponentsWare; // TSDocxComponentsWare
|
||||
cache_path_: string; // 临时目录,用来存放临时文件
|
||||
font_module_: FontModule; // 字体模块
|
||||
sect_module_array_: array of SectModule; // 页面布局模块数组
|
||||
current_sect_module_: SectModule;
|
||||
font_ware_: TSFontWare; // 字体部件
|
||||
sect_ware_array_: array of TSSectWare; // 页面布局部件数组
|
||||
current_sect_ware_: TSSectWare;
|
||||
current_sect_pr_adapter_: SectPrAdapter;
|
||||
symbol_: tableArray;
|
||||
|
||||
page_manager_module_: PageManagerModule;
|
||||
current_page_: Page;
|
||||
|
||||
toc_module_: TocModule; // 目录模块
|
||||
note_module_: NoteModule; // 脚注/尾注
|
||||
|
||||
current_page_: TSPage;
|
||||
page_array_: array of TSPage;
|
||||
toc_array_: tableArray;
|
||||
toc_unmacthed_array_: tableArray;
|
||||
range_page_number_array_: tableArray;
|
||||
text_point_: Point; // 定位坐标点
|
||||
hdr_point_: Point; // 页眉坐标
|
||||
ftr_point_: Point; // 页脚坐标
|
||||
|
||||
xml_file_: string;
|
||||
even_and_odd_flag_: boolean;
|
||||
note_ware_: TSNoteWare; // 脚注/尾注
|
||||
|
||||
// 回写docx
|
||||
docx_page_arr_: tableArray;
|
||||
update_docx_pages_: boolean;
|
||||
end;
|
||||
|
||||
type Point = class
|
||||
function Create();
|
||||
begin
|
||||
{self.}X := 0;
|
||||
{self.}Y := 0;
|
||||
end
|
||||
X: real;
|
||||
Y: real;
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.Create(alias: string; file: string);
|
||||
begin
|
||||
pdf_ := new PdfFile();
|
||||
pdf_.SetCompressionMode(TSPdfEnumerations.COMP_ALL);
|
||||
font_module_ := new DTPModules.FontModule(pdf_);
|
||||
font_ware_ := new TSFontWare(pdf_);
|
||||
{self.}InitPdfEncoder();
|
||||
{self.}InitDocxComponents(alias, file);
|
||||
{self.}InitCachePath(file);
|
||||
{self.}InitSectModule();
|
||||
{self.}InitSectWare();
|
||||
{self.}InitSymbol();
|
||||
|
||||
current_page_ := nil;
|
||||
page_manager_module_ := new DTPModules.PageManagerModule(pdf_);
|
||||
|
||||
toc_module_ := new DTPModules.TocModule();
|
||||
page_array_ := array();
|
||||
toc_array_ := array();
|
||||
toc_unmacthed_array_ := array();
|
||||
range_page_number_array_ := array();
|
||||
text_point_ := new Point();
|
||||
hdr_point_ := new Point();
|
||||
ftr_point_ := new Point();
|
||||
|
||||
xml_file_ := "document.xml";
|
||||
settings := docx_components_module_.Settings;
|
||||
settings := docx_components_ware_.Settings;
|
||||
settings.XmlChildEvenAndOddHeaders.Deserialize();
|
||||
even_and_odd_flag_ := settings.EvenAndOddHeaders ? true : false;
|
||||
note_module_ := new ;
|
||||
note_ware_ := nil;
|
||||
|
||||
// 回写docx
|
||||
docx_page_arr_ := array();
|
||||
|
|
@ -102,48 +129,60 @@ end;
|
|||
|
||||
function TSDocxToPdf.Transform();
|
||||
begin
|
||||
for _,sect_module in sect_module_array_ do
|
||||
for _,sect_ware in sect_ware_array_ do
|
||||
begin
|
||||
if current_sect_module_ <> sect_module then
|
||||
if current_sect_ware_ <> sect_ware then
|
||||
begin
|
||||
current_sect_module_ := sect_module;
|
||||
current_sect_pr_adapter_ := new SectPrAdapter(current_sect_module_.SectPr.GetObject());
|
||||
{self.}AddPage(true);
|
||||
current_sect_ware_ := sect_ware;
|
||||
current_sect_pr_adapter_ := new SectPrAdapter(current_sect_ware_.SectPr.GetObject());
|
||||
{self.}AddTSPage(true);
|
||||
xml_file_ := "document.xml";
|
||||
end
|
||||
|
||||
// 分栏
|
||||
elements := sect_module.Elements();
|
||||
cols := current_sect_module_.SectPr.Cols;
|
||||
elements := sect_ware.Elements();
|
||||
cols := current_sect_ware_.SectPr.Cols;
|
||||
if cols.Num > 1 then
|
||||
begin
|
||||
columns := {self.}ClassifyCols(current_page_.TextPoint, cols);
|
||||
columns := {self.}ClassifyCols(text_point_, cols);
|
||||
end
|
||||
else begin
|
||||
w := current_page_.SectPr.PgSz.W - current_page_.SectPr.PgMar.Right - current_page_.SectPr.PgMar.Left;
|
||||
lb := max(current_page_.SectPr.PgMar.Bottom, current_page_.FtrPoint.Y);
|
||||
w := current_sect_ware_.SectPr.PgSz.W - current_sect_ware_.SectPr.PgMar.Right - current_sect_ware_.SectPr.PgMar.Left;
|
||||
lb := current_sect_ware_.SectPr.PgMar.Bottom;
|
||||
for _,element in elements do
|
||||
begin
|
||||
x := current_page_.TextPoint.X;
|
||||
y := current_page_.TextPoint.Y;
|
||||
// if _ = 266 then break;
|
||||
// if _ = 20 then
|
||||
// println("_ = {}, xml_file_ = {}, error = {}", _, xml_file_, pdf_.GetError());
|
||||
range := nil;
|
||||
if element.LocalName = "p" then range := {self.}TransformP(element, x, y, w, lb);
|
||||
else if element.LocalName = "tbl" then range := {self.}TransformTbl(element, x, y, w, lb);
|
||||
else if element.LocalName = "sdt" then {self.}TransformSdt(element, x, y, w, lb);
|
||||
if ifObj(range) then
|
||||
begin
|
||||
current_page_.TextPoint.Y := range.EndY;
|
||||
range.Do();
|
||||
end
|
||||
// if _ = 8 then break;
|
||||
// if _ = 3 then
|
||||
// println("_ = {}, xml_file_ = {}", _, xml_file_);
|
||||
if element.LocalName = "p" then {self.}TransformP(text_point_, element, w, lb);
|
||||
else if element.LocalName = "tbl" then {self.}TransformTbl(text_point_, element, w, lb);
|
||||
else if element.LocalName = "sdt" then {self.}TransformSdt(text_point_, element, w, lb);
|
||||
end
|
||||
end
|
||||
end
|
||||
{self.}ProcessNumpages();
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.GetCurrentTextPoint(): Point;
|
||||
begin
|
||||
return text_point_;
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.GetCurrentHdrPoint(): Point;
|
||||
begin
|
||||
return hdr_point_;
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.GetCurrentFtrPoint(): Point;
|
||||
begin
|
||||
return ftr_point_;
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.GetCurrentSectWare(): TSSectWare;
|
||||
begin
|
||||
return current_sect_ware_;
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.GetCachePath(image_path: string): string;
|
||||
begin
|
||||
return cache_path_ + extractFileName(image_path);
|
||||
|
|
@ -154,6 +193,16 @@ begin
|
|||
return xml_file_;
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.GetPdf(): PdfFile;
|
||||
begin
|
||||
return pdf_;
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.ReadFont();
|
||||
begin
|
||||
return font_ware_;
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.InitPdfEncoder();
|
||||
begin
|
||||
pdf_.UseCNSFonts();
|
||||
|
|
@ -163,8 +212,9 @@ end;
|
|||
|
||||
function TSDocxToPdf.InitDocxComponents(alias: string; file: string);
|
||||
begin
|
||||
docx_components_module_ := new DTPModules.DocxComponentsModule();
|
||||
[err, msg] := docx_components_module_.Open(alias, file, nil);
|
||||
namespace "DOCX";
|
||||
docx_components_ware_ := new TSDocxComponentsWare();
|
||||
[err, msg] := docx_components_ware_.Open(alias, file, nil);
|
||||
if err then raise "Open file error.";
|
||||
end;
|
||||
|
||||
|
|
@ -177,72 +227,78 @@ begin
|
|||
createDir("", cache_path_);
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.InitSectModule();
|
||||
function TSDocxToPdf.InitSectWare();
|
||||
begin
|
||||
sect_module_array_ := array();
|
||||
current_sect_module_ := nil;
|
||||
sect_ware_array_ := array();
|
||||
current_sect_ware_ := nil;
|
||||
current_sect_pr_adapter_ := nil;
|
||||
document := docx_components_module_.Document;
|
||||
document := docx_components_ware_.Document;
|
||||
document.Deserialize();
|
||||
{self.}AllocateElementsToSectModule();
|
||||
{self.}AllocateElementsToSectWare();
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.AllocateElementsToSectModule();
|
||||
function TSDocxToPdf.InitSymbol();
|
||||
begin
|
||||
elements := docx_components_module_.Document.Body.Elements();
|
||||
module := new DTPModules.SectModule();
|
||||
fp := function(module, sect);
|
||||
symbol_ := array(
|
||||
"": chr(118),
|
||||
"": chr(110),
|
||||
"": chr(108),
|
||||
"": chr(117),
|
||||
"": chr(108),
|
||||
"o": chr(109),
|
||||
"": chr(110),
|
||||
);
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.AllocateElementsToSectWare();
|
||||
begin
|
||||
elements := docx_components_ware_.Document.Body.Elements();
|
||||
ware := new TSSectWare();
|
||||
fp := function(ware, sect);
|
||||
begin
|
||||
sect := new SectPrUnitDecorator(sect);
|
||||
sect.PgSz.Orient := sect.PgSz.Orient ? "portrait" : "landscape";
|
||||
sect.Type.Val := sect.Type.Val ?: "nextPage";
|
||||
module.SectPr := sect;
|
||||
ware.SectPr := sect;
|
||||
ware.Do();
|
||||
end
|
||||
for i:=0 to length(elements)-1 do
|
||||
begin
|
||||
element := elements[i];
|
||||
module.AddElement(element);
|
||||
ware.AddElement(element);
|
||||
if element.LocalName = "p" and ifObj(element.PPr.SectPr) then
|
||||
begin
|
||||
##fp(module, element.PPr.SectPr);
|
||||
sect_module_array_[length(sect_module_array_)] := module;
|
||||
module := new DTPModules.SectModule();
|
||||
##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(module, element);
|
||||
sect_module_array_[length(sect_module_array_)] := module;
|
||||
##fp(ware, element);
|
||||
sect_ware_array_[length(sect_ware_array_)] := ware;
|
||||
end
|
||||
end
|
||||
// println("sect_module_array_ = {}", sect_module_array_);
|
||||
// println("sect_ware_array_ = {}", sect_ware_array_);
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.AddPage(flag: boolean = false): Page;
|
||||
function TSDocxToPdf.AddTSPage(flag: boolean = false): TSPage;
|
||||
begin
|
||||
if current_sect_module_.SectPr.Type.Val = "continuous" and page_manager_module_.Count <> 0 then return;
|
||||
if current_sect_ware_.SectPr.Type.Val = "continuous" and length(page_array_) <> 0 then return;
|
||||
page := pdf_.AddPage();
|
||||
page.SetWidth(current_sect_ware_.SectPr.PgSz.W);
|
||||
page.SetHeight(current_sect_ware_.SectPr.PgSz.H);
|
||||
// println("W = {}, H = {}", current_sect_ware_.SectPr.PgSz.W, current_sect_ware_.SectPr.PgSz.H);
|
||||
|
||||
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;
|
||||
page.BaseSize := round(page.SectPr.DocGrid.LinePitch * 0.75);
|
||||
|
||||
// 正文、页眉页脚坐标
|
||||
// 页眉:从上往下,不需要调整
|
||||
page.HdrPoint.X := page.SectPr.PgMar.Left;
|
||||
page.HdrPoint.Y := page.SectPr.PgSz.H - page.SectPr.PgMar.Header;
|
||||
// 页脚:从下往上,需要调整
|
||||
page.FtrPoint.X := page.SectPr.PgMar.Left;
|
||||
page.FtrPoint.Y := page.SectPr.PgSz.H;
|
||||
// 正文:运行完页眉页脚后需要再次计算
|
||||
page.TextPoint.X := page.SectPr.PgMar.Left;
|
||||
page.TextPoint.Y := page.SectPr.PgSz.H - max(page.SectPr.PgMar.Top, page.SectPr.PgMar.Header);
|
||||
|
||||
current_page_ := page;
|
||||
// println("TextPoint.X = {}, TextPoint.Y = {}", current_page_.TextPoint.X, current_page_.TextPoint.Y);
|
||||
// println("len = {}, Number = {}", page_manager_module_.Count(), current_page_.Number);
|
||||
len := length(page_array_);
|
||||
current_page_ := new TSPage();
|
||||
current_page_.Index := len;
|
||||
current_page_.PdfPage := page;
|
||||
current_page_.Number := flag ? ifnil(current_sect_ware_.SectPr.PgNumType.Start) ? 1 : current_sect_ware_.SectPr.PgNumType.Start : page_array_[len-1].Number + 1;
|
||||
// println("len = {}, Number = {}", len, current_page_.Number);
|
||||
page_array_[len] := current_page_;
|
||||
|
||||
// 页眉页脚
|
||||
if current_sect_module_.SectPr.TitlePg and current_page_.Index = 0 then
|
||||
if current_sect_ware_.SectPr.TitlePg and current_page_.Index = 0 then
|
||||
type_name := "first";
|
||||
else if not even_and_odd_flag_ then
|
||||
type_name := "default";
|
||||
|
|
@ -256,152 +312,217 @@ begin
|
|||
{self.}SetFtr(type_name);
|
||||
xml_file_ := bk_file;
|
||||
|
||||
// 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);
|
||||
// 正文坐标
|
||||
[x, y] := {self.}CalculateTextCoordinates();
|
||||
text_point_.X := x;
|
||||
text_point_.Y := y;
|
||||
|
||||
if sysparams["_PDF_PAGE_GRID_DEBUG_"] then
|
||||
{self.}PrintGrid(page, current_sect_ware_);
|
||||
|
||||
return current_page_;
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.CalculateTextCoordinates(): array of real;
|
||||
begin
|
||||
x := current_sect_ware_.SectPr.PgMar.Left;
|
||||
y := min(current_sect_ware_.SectPr.PgSz.H - max(current_sect_ware_.SectPr.PgMar.Top, current_sect_ware_.SectPr.PgMar.Header), hdr_point_.Y);
|
||||
return array(x, y);
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.SetFtr(type: string);
|
||||
begin
|
||||
ftr_point_.X := current_sect_ware_.SectPr.PgMar.Left;
|
||||
ftr_point_.Y := current_sect_ware_.SectPr.PgMar.Bottom;
|
||||
footer_reference := current_sect_pr_adapter_.GetFooterReferenceByType(type);
|
||||
ftr_range := array();
|
||||
if ifObj(footer_reference) then
|
||||
begin
|
||||
rels_adapter := docx_components_module_.GetDocumentRelsAdapter();
|
||||
rels_adapter := docx_components_ware_.GetDocumentRelsAdapter();
|
||||
rel := rels_adapter.GetRelationshipById(footer_reference.Id);
|
||||
w := current_page_.SectPr.PgSz.W - current_page_.SectPr.PgMar.Right - current_page_.SectPr.PgMar.Left;
|
||||
w := current_sect_ware_.SectPr.PgSz.W - current_sect_ware_.SectPr.PgMar.Right - current_sect_ware_.SectPr.PgMar.Left;
|
||||
lb := 0;
|
||||
obj := docx_components_module_.GetFtr(rel.Target);
|
||||
obj := docx_components_ware_.GetFtr(rel.Target);
|
||||
xml_file_ := rel.Target;
|
||||
elements := obj.Elements();
|
||||
for _,element in elements do
|
||||
begin
|
||||
x := current_page_.FtrPoint.X;
|
||||
y := current_page_.FtrPoint.Y;
|
||||
range := nil;
|
||||
if element.LocalName = "p" then range := {self.}TransformP(element, x, y, w, lb);
|
||||
if ifObj(range) then
|
||||
begin
|
||||
current_page_.FtrPoint.Y := range.EndY;
|
||||
ftr_range[length(ftr_range)] := range;
|
||||
end
|
||||
if element.LocalName = "p" then {self.}TransformP(ftr_point_, element, w, lb);
|
||||
end
|
||||
end
|
||||
last_range := ftr_range[length(ftr_range)-1];
|
||||
y_offset := last_range.EndY - current_page_.SectPr.PgMar.Bottom;
|
||||
height := 0;
|
||||
for _,range in ftr_range do
|
||||
begin
|
||||
range.Offset(0, y_offset);
|
||||
range.Do();
|
||||
height += range.DynamicHeight;
|
||||
end
|
||||
current_page_.FtrPoint.Y := current_page_.SectPr.PgMar.Bottom + height;
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.SetHdr(type: string);
|
||||
begin
|
||||
hdr_point_.X := current_sect_ware_.SectPr.PgMar.Left;
|
||||
hdr_point_.Y := current_sect_ware_.SectPr.PgSz.H - current_sect_ware_.SectPr.PgMar.Header;
|
||||
header_reference := current_sect_pr_adapter_.GetHeaderReferenceByType(type);
|
||||
if ifObj(header_reference) then
|
||||
begin
|
||||
rels_adapter := docx_components_module_.GetDocumentRelsAdapter();
|
||||
rels_adapter := docx_components_ware_.GetDocumentRelsAdapter();
|
||||
rel := rels_adapter.GetRelationshipById(header_reference.Id);
|
||||
w := current_page_.SectPr.PgSz.W - current_page_.SectPr.PgMar.Right - current_page_.SectPr.PgMar.Left;
|
||||
w := current_sect_ware_.SectPr.PgSz.W - current_sect_ware_.SectPr.PgMar.Right - current_sect_ware_.SectPr.PgMar.Left;
|
||||
lb := 0;
|
||||
obj := docx_components_module_.GetHdr(rel.Target);
|
||||
obj := docx_components_ware_.GetHdr(rel.Target);
|
||||
xml_file_ := rel.Target;
|
||||
elements := obj.Elements();
|
||||
for _,element in elements do
|
||||
begin
|
||||
x := current_page_.HdrPoint.X;
|
||||
y := current_page_.HdrPoint.Y;
|
||||
range := nil;
|
||||
if element.LocalName = "p" then range := {self.}TransformP(element, x, y, w, lb);
|
||||
if ifObj(range) then
|
||||
begin
|
||||
current_page_.HdrPoint.Y := range.EndY;
|
||||
range.Do();
|
||||
current_page_.TextPoint.Y := min(current_page_.TextPoint.Y, range.EndY);
|
||||
end
|
||||
if element.LocalName = "p" then {self.}TransformP(hdr_point_, element, w, lb);
|
||||
end
|
||||
end
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.TransformP(paragraph: P; x: real; y: real; w: real; lb: real): ParagraphRange;
|
||||
function TSDocxToPdf.TransformP(var point: Point; paragraph: P; w: real; lb: real);
|
||||
begin
|
||||
range := new ParagraphRange(self, current_page_, docx_components_module_, paragraph);
|
||||
range.StartX := x;
|
||||
range.StartY := y;
|
||||
range := new TSPdfParagraphRange(self, current_page_, docx_components_ware_, paragraph);
|
||||
range.StartX := point.X;
|
||||
range.StartY := point.Y;
|
||||
range.Width := w;
|
||||
range.LowerBound := lb;
|
||||
range.Parent := self;
|
||||
r := range.Calc();
|
||||
if r then return range;
|
||||
if r then range.Do();
|
||||
else range_page_number_array_[length(range_page_number_array_)] := range;
|
||||
return nil;
|
||||
point.Y := range.EndY;
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.TransformTbl(table: Tbl; x: real; y: real; w: real; lb: real): TableRange;
|
||||
function TSDocxToPdf.TransformTbl(var point: Point; table: Tbl; w: real; lb: real);
|
||||
begin
|
||||
range := new TableRange(self, current_page_, docx_components_module_, table);
|
||||
range.StartX := x;
|
||||
range.StartY := y;
|
||||
range := new TSPdfTableRange(self, current_page_, docx_components_ware_, table);
|
||||
range.StartX := point.X;
|
||||
range.StartY := point.Y;
|
||||
range.Width := w;
|
||||
range.LowerBound := lb;
|
||||
range.Parent := self;
|
||||
range.Calc();
|
||||
return range;
|
||||
range.Do();
|
||||
point.Y := range.EndY;
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.TransformSdt(sdt: Sdt; x: real; y: real; w: real; lb: real): array of ParagraphRange;
|
||||
function TSDocxToPdf.TransformSdt(var point: Point; sdt: Sdt; w: real; lb: real);
|
||||
begin
|
||||
ps := sdt.SdtContent.Ps();
|
||||
arr := array();
|
||||
for _,p in ps do
|
||||
begin
|
||||
range := {self.}TransformP(p, x, y, w, lb);
|
||||
if ifObj(range) then arr[length(arr)] := range;
|
||||
end
|
||||
return arr;
|
||||
{self.}TransformP(point, p, w, lb);
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.ProcessNumpages();
|
||||
begin
|
||||
nums := page_manager_module_[page_manager_module_.Count() - 1].Number;
|
||||
nums := page_array_[length(page_array_)-1].Number;
|
||||
for _,range in range_page_number_array_ do
|
||||
begin
|
||||
range.SetNumPages(nums);
|
||||
range.RangesToLines();
|
||||
range.Offset(0, current_page_.SectPr.PgSz.H - current_page_.SectPr.PgMar.Bottom);
|
||||
range.Do();
|
||||
end
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.UpdateDocxPageNumPages();
|
||||
function TSDocxToPdf.GetNextPage(page: TSPage);
|
||||
begin
|
||||
toc_module_.UpdateDocxNumPages();
|
||||
return page_array_[page.Index + 1];
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.PrintGrid(page: PdfPage; sect_ware: TSSectWare);
|
||||
begin
|
||||
i := 0;
|
||||
while true do
|
||||
begin
|
||||
y := text_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.AddToc(anchor: string; toc: TSToc);
|
||||
begin
|
||||
if ifarray(toc_array_[anchor]) then toc_array_[anchor] union= array(toc);
|
||||
else toc_array_[anchor] := array(toc);
|
||||
if toc_unmacthed_array_[anchor] then
|
||||
begin
|
||||
toc := toc_unmacthed_array_[anchor];
|
||||
{self.}LinkToToc(anchor, toc[0], toc[1], toc[2]);
|
||||
toc_unmacthed_array_[anchor] := nil;
|
||||
end
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.LinkToToc(anchor: string; page: TSPage; left: real; top: real);
|
||||
begin
|
||||
arr := toc_array_[anchor];
|
||||
if ifnil(arr) then
|
||||
begin
|
||||
toc_unmacthed_array_[anchor] := array(page, left, top);
|
||||
return;
|
||||
end
|
||||
dst := page.PdfPage.CreateDestination();
|
||||
dst.SetXYZ(left, top, 1);
|
||||
for _,toc in arr do
|
||||
toc.LinkAnnot(dst);
|
||||
toc.AddPageNumber(page);
|
||||
|
||||
if update_docx_pages_ then
|
||||
begin
|
||||
r := docx_page_arr_[anchor];
|
||||
r.T.Text := page.Number;
|
||||
r.Serialize();
|
||||
end
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.GetSymbol(symbol: string);
|
||||
begin
|
||||
// println("symbol = {}, symbol_ = {}", symbol, symbol_);
|
||||
return symbol_[symbol];
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.AddDocxPage(anchor: string; r: R);
|
||||
begin
|
||||
docx_page_arr_[anchor] := r;
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.UpdateDocxPageNumpages();
|
||||
begin
|
||||
update_docx_pages_ := true;
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.SaveDocxFile();overload;
|
||||
begin
|
||||
return docx_components_module_.Save();
|
||||
return docx_components_ware_.Save();
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.SaveDocxFile(alias: string; file: string);overload;
|
||||
begin
|
||||
return docx_components_module_.SaveAs(alias, file);
|
||||
return docx_components_ware_.SaveAs(alias, file);
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.GetCurrentNoteModule(): NoteModule;
|
||||
function TSDocxToPdf.GetCurrentNoteWare(): TSNoteWare;
|
||||
begin
|
||||
if ifnil(note_module_) then note_module_ := new NoteModule(current_sect_module_);
|
||||
return note_module_;
|
||||
if ifnil(note_ware_) then note_ware_ := new TSNoteWare(current_sect_ware_);
|
||||
return note_ware_;
|
||||
end;
|
||||
|
||||
function TSDocxToPdf.ClassifyCols(var point: Point; cols: Cols);
|
||||
|
|
@ -410,8 +531,8 @@ begin
|
|||
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 := current_sect_ware_.SectPr.PgSz.W - current_sect_ware_.SectPr.PgMar.Right - current_sect_ware_.SectPr.PgMar.Left;
|
||||
lb := current_sect_ware_.SectPr.PgMar.Bottom;
|
||||
w_array := array();
|
||||
ccols := cols.Cols();
|
||||
for i:=0 to cols.Num-1 do
|
||||
|
|
@ -426,7 +547,7 @@ begin
|
|||
rw := w / 3;
|
||||
x := point.X + i * rw + i * cols.Space;
|
||||
end
|
||||
range := new ColumnRange(self, current_page_, docx_components_module_);
|
||||
range := new TSPdfColumnRange(self, current_page_, docx_components_ware_);
|
||||
range.StartX := x;
|
||||
range.StartY := y;
|
||||
range.Width := rw;
|
||||
|
|
@ -434,7 +555,7 @@ begin
|
|||
columns[length(columns)] := range;
|
||||
end
|
||||
i := 0;
|
||||
elements := current_sect_module_.Elements();
|
||||
elements := current_sect_ware_.Elements();
|
||||
range := columns[0];
|
||||
for _,element in elements do
|
||||
begin
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,719 +0,0 @@
|
|||
unit DTPModules;
|
||||
interface
|
||||
uses TSPdfEnumerations, DocxMLAdapter, SharedMLAdapter;
|
||||
|
||||
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(sect_module: SectModule);
|
||||
function GetFootnoteOrderNumber(): string;
|
||||
function GetFootnoteIndex(): string;
|
||||
function AddFootnote();
|
||||
|
||||
private
|
||||
function CalculateNumber(num_fmt: string; num: integer): string;
|
||||
function ChineseCountingThousand(n: integer): string;
|
||||
|
||||
private
|
||||
footnote_reference_hash_: hash;
|
||||
footnote_index_: integer;
|
||||
[weakref]sect_module_: SectModule;
|
||||
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 Destroy();
|
||||
function Do();
|
||||
function AddElement(element: tslobj);
|
||||
|
||||
public
|
||||
Elements: array of tslobj;
|
||||
SectPr: SectPrUnitDecorator;
|
||||
end;
|
||||
|
||||
type Toc = class
|
||||
public
|
||||
function Create(ppr: PPrUnitDecorator; rect: array of real; page: Page; x: real; y: real; font: PdfFont);
|
||||
function LinkAnnot(dst: PdfDestination);
|
||||
function AddPageNumber(page: Page);
|
||||
|
||||
private
|
||||
[weakref]page_: Page;
|
||||
ppr_: PPrUnitDecorator;
|
||||
rect_: array of real;
|
||||
font_: PdfFont;
|
||||
x_;
|
||||
y_;
|
||||
end;
|
||||
|
||||
type TocModule = class
|
||||
public
|
||||
function Create();
|
||||
function UpdateDocxNumPages();
|
||||
function LinkToToc(anchor: string; pg: Page; left: real; top: real);
|
||||
function AddToc(anchor: string; toc: Toc);
|
||||
|
||||
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: SectPrUnitDecorator;
|
||||
BaseSize: real;
|
||||
TextPoint: Point; // 正文坐标
|
||||
FtrPoint: Point; // 页脚坐标
|
||||
HdrPoint: Point; // 页眉坐标
|
||||
|
||||
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();
|
||||
styles_deserialize_flag_ := true;
|
||||
return {self.}Styles;
|
||||
end;
|
||||
|
||||
function DocxComponentsModule.GetStylesAdapter(): StylesAdapter;
|
||||
begin
|
||||
if styles_adapter_ then return styles_adapter_;
|
||||
styles_adapter_ := new StylesAdapter({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 RelationShipsAdapter({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();
|
||||
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 StyleAdapter(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();
|
||||
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();
|
||||
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 RelationShipsAdapter(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 RelationShipsAdapter(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();
|
||||
footnotes_adapter_ := new FootnotesAdapter(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
|
||||
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(sect_module: SectModule);
|
||||
begin
|
||||
sect_module_ := sect_module;
|
||||
footnote_reference_hash_ := array();
|
||||
footnote_index_ := 0;
|
||||
end;
|
||||
|
||||
function NoteModule.GetFootnoteOrderNumber();
|
||||
begin
|
||||
num_fmt := sect_module_.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 NumberingAdapter(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.}TextPoint.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.5);
|
||||
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.LinkToToc(anchor: string; pg: Page; left: real; top: real);
|
||||
begin
|
||||
arr := toc_hash_[anchor];
|
||||
if ifnil(arr) then
|
||||
begin
|
||||
toc_unmatched_hash_[anchor] := array(pg, left, top);
|
||||
return;
|
||||
end
|
||||
dst := pg.PdfPage.CreateDestination();
|
||||
dst.SetXYZ(left, top, 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.AddToc(anchor: string; toc: Toc);
|
||||
begin
|
||||
if ifarray(toc_hash_[anchor]) then toc_hash_[anchor] union= array(toc);
|
||||
else toc_hash_[anchor] := array(toc);
|
||||
if toc_unmatched_hash_[anchor] then
|
||||
begin
|
||||
toc := toc_unmatched_hash_[anchor];
|
||||
{self.}LinkToToc(anchor, toc[0], toc[1], toc[2]);
|
||||
toc_unmatched_hash_[anchor] := nil;
|
||||
end
|
||||
end;
|
||||
|
||||
function TocModule.AddDocxPage(anchor: string; r: R);
|
||||
begin
|
||||
docx_page_hash_[anchor] := r;
|
||||
end;
|
||||
|
||||
// Toc
|
||||
function Toc.Create(ppr: PPrUnitDecorator; rect: array of real; pg: Page; x: real; y: real; font: PdfFont);
|
||||
begin
|
||||
ppr_ := ppr;
|
||||
rect_ := rect;
|
||||
page_ := pg;
|
||||
x_ := x;
|
||||
y_ := y;
|
||||
font_ := font;
|
||||
end;
|
||||
|
||||
function Toc.LinkAnnot(dst: PdfDestination);
|
||||
begin
|
||||
annot := page_.PdfPage.CreateLinkAnnot(rect_, dst);
|
||||
annot.LinkAnnotSetHighlightMode(TSPdfEnumerations.ANNOT_NO_HIGHTLIGHT);
|
||||
annot.LinkAnnotSetBorderStyle(0, 0, 0);
|
||||
end;
|
||||
|
||||
function Toc.AddPageNumber(pg: Page);
|
||||
begin
|
||||
number := tostring(pg.Number);
|
||||
page_.PdfPage.SetFontAndSize(font_, ppr_.RPr.Sz.Val);
|
||||
number_sz := page_.PdfPage.TextWidth(number);
|
||||
x := rect_[2] - number_sz;
|
||||
page_.PdfPage.BeginText();
|
||||
page_.PdfPage.TextOut(x, y_, number);
|
||||
page_.PdfPage.EndText();
|
||||
|
||||
page_.PdfPage.SetRGBStroke(0, 0, 0);
|
||||
page_.PdfPage.SetDash(array(0.5, 2), 2, 0);
|
||||
page_.PdfPage.SetLineWidth(0.5);
|
||||
page_.PdfPage.SetLineCap(TSPdfEnumerations.ROUND_END);
|
||||
page_.PdfPage.MoveTo(x_+1, y_);
|
||||
page_.PdfPage.LineTo(x-0.5, y_);
|
||||
page_.PdfPage.Stroke();
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -1,245 +0,0 @@
|
|||
unit DTPPrimitiveRanges;
|
||||
interface
|
||||
uses DTPColorToolKit, DTPUtils;
|
||||
|
||||
type TextRange = class(BasicRange)
|
||||
public
|
||||
function Create();
|
||||
function Do();override;
|
||||
|
||||
public
|
||||
RPr: RPr;
|
||||
Text: string;
|
||||
Font: PdfFont;
|
||||
Type: integer; // 0:默认,1: 数字,2:英文,3:中文,4:中文标点
|
||||
end;
|
||||
|
||||
type BordersRange = class(BasicRange)
|
||||
public
|
||||
function Create();
|
||||
function Do();override;
|
||||
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
|
||||
Image: PdfImage;
|
||||
Type: string;
|
||||
|
||||
end;
|
||||
|
||||
type LineRange = class(BasicRange)
|
||||
public
|
||||
function Create();
|
||||
function Do();override;
|
||||
|
||||
public
|
||||
LineWidth: real;
|
||||
end;
|
||||
|
||||
type BasicRange = class
|
||||
public
|
||||
function Create();
|
||||
function Do();virtual;
|
||||
|
||||
public
|
||||
StartX: real;
|
||||
StartY: real; // range的起始坐标(x,y)
|
||||
EndX: real;
|
||||
EndY: real; // range的结束坐标(x,y)
|
||||
Width: real;
|
||||
FixedHeight: real;
|
||||
DynamicHeight: real;
|
||||
LowerBound: real;
|
||||
[weakref]Parent: tslobj;
|
||||
[weakref]Page: Page;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
// BasicRange
|
||||
function BasicRange.Create();
|
||||
begin
|
||||
{self.}StartX := 0;
|
||||
{self.}StartY := 0;
|
||||
{self.}EndX := 0;
|
||||
{self.}EndY := 0;
|
||||
{self.}Width := 0;
|
||||
{self.}DynamicHeight := 0;
|
||||
{self.}LowerBound := 0;
|
||||
{self.}FixedHeight := 0;
|
||||
{self.}Page := nil;
|
||||
end;
|
||||
|
||||
// ImageRange
|
||||
function ImageRange.Create();
|
||||
begin
|
||||
class(BasicRange).Create();
|
||||
{self.}Image := nil;
|
||||
{self.}Type := "";
|
||||
end;
|
||||
|
||||
function ImageRange.Do();override;
|
||||
begin
|
||||
// println("image = {}, type = {}, x = {}, y = {}, w = {}, h = {}", {self.}image, {self.}Type, {self.}endx, {self.}endy, {self.}width, {self.}DynamicHeight);
|
||||
if {self.}Type = "emf" then
|
||||
{self.}Page.PdfPage.DrawEmf({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
|
||||
else if {self.}Type = "wmf" then
|
||||
{self.}Page.PdfPage.DrawWmf({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
|
||||
else
|
||||
{self.}Page.PdfPage.DrawImage({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
|
||||
|
||||
if sysparams["_PDF_IMAGE_DEBUG_"] then
|
||||
begin
|
||||
{self.}Page.PdfPage.SetLineWidth(0.1);
|
||||
{self.}Page.PdfPage.SetRGBStroke(0.8, 0.8, 0);
|
||||
{self.}Page.PdfPage.Rectangle({self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
|
||||
{self.}Page.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.Do();override;
|
||||
begin
|
||||
// println("Left = {}, Top = {}, Right = {}, Bottom = {}, Tl2Br = {}, Tr2Bl = {}", Left, Top, Right, Bottom, Tl2Br, Tr2Bl);
|
||||
borders := {self.}TcPr.TcBorders;
|
||||
if {self.}TcPr.Shd.Fill and {self.}TcPr.Shd.Fill <> "auto" then
|
||||
begin
|
||||
[r, g, b] := DTPColorToolKit.HexToRGB({self.}TcPr.Shd.Fill);
|
||||
{self.}Page.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.}Page.PdfPage.Rectangle(x, y, w, h);
|
||||
{self.}Page.PdfPage.Fill();
|
||||
{self.}Page.PdfPage.SetRGBFill(0, 0, 0);
|
||||
{self.}Left := true;
|
||||
end
|
||||
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.}Page.PdfPage.SetDash(array(), 0, 0);
|
||||
if val = "dashed" then
|
||||
{self.}Page.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.}Page.PdfPage.SetRGBStroke(r, g, b);
|
||||
{self.}Page.PdfPage.SetLineWidth(line_width);
|
||||
{self.}Page.PdfPage.MoveTo(x1, y1);
|
||||
{self.}Page.PdfPage.LineTo(x2, y2);
|
||||
{self.}Page.PdfPage.Stroke();
|
||||
{self.}Page.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
|
||||
{self.}Page.PdfPage.SetRGBFill(r / 255, g / 255, b / 255);
|
||||
{self.}Page.PdfPage.SetFontAndSize({self.}Font, sz);
|
||||
{self.}Page.PdfPage.BeginText();
|
||||
{self.}Page.PdfPage.TextOut({self.}EndX, y, {self.}Text);
|
||||
{self.}Page.PdfPage.EndText();
|
||||
{self.}Page.PdfPage.SetRGBFill(0, 0, 0);
|
||||
|
||||
|
||||
if sysparams["_PDF_TEXT_DEBUG_"] then
|
||||
begin
|
||||
{self.}Page.PdfPage.SetLineWidth(0.1);
|
||||
{self.}Page.PdfPage.SetRGBStroke(1.0, 0.5, 0.0);
|
||||
{self.}Page.PdfPage.MoveTo(0, {self.}EndY);
|
||||
{self.}Page.PdfPage.LineTo(600, {self.}EndY);
|
||||
{self.}Page.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 = {}", EndX, EndY, Width);
|
||||
{self.}Page.PdfPage.SetLineWidth({self.}LineWidth);
|
||||
{self.}Page.PdfPage.SetRGBStroke(0, 0, 0);
|
||||
{self.}Page.PdfPage.MoveTo({self.}EndX, {self.}EndY);
|
||||
{self.}Page.PdfPage.LineTo({self.}EndX + {self.}Width, {self.}EndY);
|
||||
{self.}Page.PdfPage.Stroke();
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -1,248 +0,0 @@
|
|||
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 FldStruct = class
|
||||
public
|
||||
function Create();
|
||||
public
|
||||
FldLock: boolean;
|
||||
MergeFormat: boolean;
|
||||
Quote: boolean;
|
||||
Separate: boolean;
|
||||
PageArabicMergeFormat: boolean;
|
||||
NumPages: boolean;
|
||||
ArabicMergeFormat: boolean;
|
||||
EndFld: boolean;
|
||||
end;
|
||||
|
||||
type FldType = class
|
||||
public
|
||||
function Create();
|
||||
|
||||
public
|
||||
Page: boolean;
|
||||
NumPages: boolean;
|
||||
Quote: boolean;
|
||||
PageRef: boolean;
|
||||
end;
|
||||
|
||||
type FldStruct2 = class
|
||||
public
|
||||
function Create();
|
||||
|
||||
public
|
||||
Type: FldType;
|
||||
Arabic: boolean;
|
||||
MergeFormat: boolean;
|
||||
end;
|
||||
|
||||
type TrProperty = class
|
||||
public
|
||||
function Create();
|
||||
|
||||
public
|
||||
TrPr: TrPrUnitDecorator;
|
||||
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;
|
||||
|
||||
// FldStruct
|
||||
function FldStruct.Create();
|
||||
begin
|
||||
FldLock := false;
|
||||
MergeFormat := false;
|
||||
Quote := false;
|
||||
Separate := false;
|
||||
PageArabicMergeFormat := false;
|
||||
NumPages := false;
|
||||
ArabicMergeFormat := false;
|
||||
EndFld := false;
|
||||
end;
|
||||
|
||||
// FldType
|
||||
function FldType.Create();
|
||||
begin
|
||||
{self.}Page := false;
|
||||
{self.}NumPages := false;
|
||||
{self.}Quote := false;
|
||||
{self.}PageRef := false;
|
||||
end;
|
||||
|
||||
// FldStruct
|
||||
function FldStruct2.Create();
|
||||
begin
|
||||
{self.}Type := new FldType();
|
||||
{self.}Arabic := false;
|
||||
{self.}MergeFormat := false;
|
||||
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(0x71),
|
||||
"{": chr(0x7B),
|
||||
"}": chr(0x7D),
|
||||
"∞": chr(0xA5),
|
||||
"f": chr(0xA6),
|
||||
"±": chr(0xB1),
|
||||
"∂": chr(0xB6),
|
||||
"∏": chr(0xD5),
|
||||
"〈": chr(0xE1),
|
||||
"∑": chr(0xE5),
|
||||
"〉": chr(0xF1),
|
||||
"Į": chr(0xF2),
|
||||
// "": 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.
|
||||
|
|
@ -0,0 +1,360 @@
|
|||
type TSPdfCellRange = class(TSPdfBasicRange)
|
||||
public
|
||||
function Create(table_range: TSPdfTableRange; docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; tc: Tc; tbl_pr: TblPr; trp: TSTrProperty);
|
||||
function Calc();
|
||||
function Do();override;
|
||||
function SetTSPage(page: TSPage);
|
||||
function GetLastPage();
|
||||
function AlignHeight(height: real);
|
||||
function SetVAlign();
|
||||
function IsReComputeByCantSplit(): boolean;
|
||||
function IfRemoveEmptyRectangle(): boolean;
|
||||
function SetTop();
|
||||
|
||||
property Tc read tc_;
|
||||
|
||||
private
|
||||
function GetCellPrType(): string;
|
||||
function SetBorderRange(range: TSPdfBordersRange);
|
||||
|
||||
public
|
||||
RemoveFlag: boolean;
|
||||
Row: integer;
|
||||
Col: integer;
|
||||
VMerge: integer;
|
||||
[weakref]TSTrPr: TSTrProperty;
|
||||
|
||||
private
|
||||
[weakref]parent_: TSPdfTableRange;
|
||||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||||
[weakref]last_page_: TSPage;
|
||||
[weakref]docx_components_ware_: TSDocxComponentsWare;
|
||||
[weakref]tc_: Tc;
|
||||
[weakref]tbl_pr_: TblPr;
|
||||
tc_pr_unit_decorator_: TcPrUnitDecorator;
|
||||
region_array_: array of Region; // 单元格可能跨页,所以可能存在多个
|
||||
top_: boolean;
|
||||
end;
|
||||
|
||||
type Region = class
|
||||
function Create();
|
||||
begin
|
||||
BordersRange := new TSPdfBordersRange();
|
||||
RangeArr := array();
|
||||
end
|
||||
|
||||
BordersRange: TSPdfBordersRange;
|
||||
RangeArr: array of TSPdfBasicRange;
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.Create(table_range: TSPdfTableRange; docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; tc: Tc; tbl_pr: TblPr; trp: TSTrProperty);
|
||||
begin
|
||||
parent_ := table_range;
|
||||
docx_to_pdf_ := docx_to_pdf;
|
||||
last_page_ := pg;
|
||||
docx_components_ware_ := components;
|
||||
tc_ := tc;
|
||||
tbl_pr_ := tbl_pr;
|
||||
region_array_ := array();
|
||||
top_ := false;
|
||||
tc_pr_unit_decorator_ := new TcPrUnitDecorator(tc_.TcPr);
|
||||
{self.}TSTrPr := trp;
|
||||
{self.}Tc := tc;
|
||||
{self.}VMerge := 1;
|
||||
{self.}TSPage := last_page_;
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.Calc();
|
||||
begin
|
||||
region_array_ := array();
|
||||
region := new Region();
|
||||
region.BordersRange.EndX := {self.}StartX;
|
||||
region.BordersRange.EndY := {self.}StartY;
|
||||
region.BordersRange.Width := {self.}Width;
|
||||
region.BordersRange.FixedHeight := {self.}FixedHeight;
|
||||
region.BordersRange.TSPage := last_page_;
|
||||
region.BordersRange.TcPr := tc_pr_unit_decorator_;
|
||||
{self.}SetBorderRange(region.BordersRange);
|
||||
region_array_[length(region_array_)] := region;
|
||||
|
||||
{self.}EndX := {self.}StartX;
|
||||
{self.}EndY := {self.}StartY;
|
||||
{self.}DynamicHeight := 0;
|
||||
cell_x := {self.}EndX + tbl_pr_.TblCellMar.Left.W;
|
||||
cell_y := {self.}EndY - tbl_pr_.TblCellMar.Top.W;
|
||||
cell_w := {self.}Width - tbl_pr_.TblCellMar.Right.W - tbl_pr_.TblCellMar.Left.W;
|
||||
cell_h := {self.}FixedHeight;
|
||||
elements := tc_.Elements();
|
||||
for _,element in elements do
|
||||
begin
|
||||
range := nil;
|
||||
if element.LocalName = "p" then
|
||||
begin
|
||||
range := new TSPdfParagraphRange(docx_to_pdf_, last_page_, docx_components_ware_, element);
|
||||
range.SetTblStyleIdAndType(tbl_pr_.TblStyle.Val, {self.}GetCellPrType());
|
||||
end
|
||||
else if element.LocalName = "tbl" then
|
||||
begin
|
||||
range := new TSPdfTableRange(docx_to_pdf_, last_page_, docx_components_ware_, element);
|
||||
continue; // TODO:表中表存在不可靠问题
|
||||
end
|
||||
if ifObj(range) then
|
||||
begin
|
||||
range.StartX := cell_x;
|
||||
range.StartY := cell_y;
|
||||
range.Width := cell_w;
|
||||
range.FixedHeight := cell_h;
|
||||
range.LowerBound := {self.}LowerBound;
|
||||
range.Calc();
|
||||
region.RangeArr[length(region.RangeArr)] := range;
|
||||
{self.}DynamicHeight += range.DynamicHeight;
|
||||
cell_y := range.EndY;
|
||||
last_page_ := range.GetLastPage();
|
||||
end
|
||||
end
|
||||
{self.}EndY := cell_y - tbl_pr_.TblCellMar.Bottom.W;
|
||||
{self.}DynamicHeight += tbl_pr_.TblCellMar.Top.W + tbl_pr_.TblCellMar.Bottom.W;
|
||||
|
||||
if {self.}EndY < {self.}LowerBound and not range.Empty() then
|
||||
begin
|
||||
last_page_ := docx_to_pdf_.GetNextPage(last_page_);
|
||||
if ifnil(last_page_) then last_page_ := docx_to_pdf_.AddTSPage();
|
||||
point := docx_to_pdf_.GetCurrentTextPoint();
|
||||
{self.}StartY := point.Y;
|
||||
{self.}Calc();
|
||||
end
|
||||
if {self.}TSTrPr.TrPr.TrHeight.HRule <> "exact" and {self.}DynamicHeight > {self.}FixedHeight then
|
||||
begin
|
||||
region.BordersRange.FixedHeight := {self.}DynamicHeight;
|
||||
{self.}FixedHeight := {self.}DynamicHeight;
|
||||
end
|
||||
if not {self.}Tc.TcPr.VMerge and {self.}DynamicHeight > {self.}TSTrPr.Height then
|
||||
{self.}TSTrPr.Height := {self.}DynamicHeight;
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.Do();override;
|
||||
begin
|
||||
for _,region in region_array_ do
|
||||
begin
|
||||
if _ = 0 and {self.}RemoveFlag then continue;
|
||||
// println("Row = {}, Col = {}", {self.}Row, {self.}Col);
|
||||
region.BordersRange.Do();
|
||||
for _,range in region.RangeArr do
|
||||
range.Do();
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.SetTSPage(page: TSPage);
|
||||
begin
|
||||
last_page_ := page;
|
||||
{self.}TSPage := page;
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.AlignHeight(height: real);
|
||||
begin
|
||||
region := region_array_[0];
|
||||
y_lowerbound := {self.}StartY - {self.}LowerBound;
|
||||
surplus := height - y_lowerbound;
|
||||
if surplus < 1e-6 then
|
||||
begin
|
||||
region.BordersRange.DynamicHeight := height;
|
||||
{self.}SetBorderRange(region.BordersRange);
|
||||
{self.}EndY := {self.}StartY - region.BordersRange.DynamicHeight;
|
||||
return;
|
||||
end
|
||||
region.BordersRange.DynamicHeight := y_lowerbound;
|
||||
arr := region.RangeArr;
|
||||
region.RangeArr := array();
|
||||
hash := array(region.BordersRange.TSPage.Index: region);
|
||||
last_page_ := {self.}TSPage;
|
||||
[x, y] := docx_to_pdf_.CalculateTextCoordinates();
|
||||
ftr_point := docx_to_pdf_.GetCurrentFtrPoint();
|
||||
span := y - ftr_point.Y;
|
||||
while surplus > span do
|
||||
begin
|
||||
last_page_ := docx_to_pdf_.GetNextPage(last_page_);
|
||||
region := new Region();
|
||||
region.BordersRange.EndX := {self.}StartX;
|
||||
region.BordersRange.EndY := y;
|
||||
region.BordersRange.Width := {self.}Width;
|
||||
region.BordersRange.DynamicHeight := span;
|
||||
region.BordersRange.TSPage := last_page_;
|
||||
region.BordersRange.TcPr := tc_pr_unit_decorator_;
|
||||
region.BordersRange.Top := true;
|
||||
region.BordersRange.Bottom := true;
|
||||
{self.}SetBorderRange(region.BordersRange);
|
||||
region_array_[length(region_array_)] := region;
|
||||
surplus -= span;
|
||||
hash[region.BordersRange.TSPage.Index] := region;
|
||||
end
|
||||
if surplus > 1e-6 then
|
||||
begin
|
||||
last_page_ := docx_to_pdf_.GetNextPage(last_page_);
|
||||
region := new Region();
|
||||
region.BordersRange.EndX := {self.}StartX;
|
||||
region.BordersRange.EndY := y;
|
||||
region.BordersRange.Width := {self.}Width;
|
||||
region.BordersRange.DynamicHeight := surplus;
|
||||
region.BordersRange.TSPage := last_page_;
|
||||
region.BordersRange.TcPr := tc_pr_unit_decorator_;
|
||||
region.BordersRange.Top := true;
|
||||
{self.}SetBorderRange(region.BordersRange);
|
||||
region_array_[length(region_array_)] := region;
|
||||
hash[region.BordersRange.TSPage.Index] := region;
|
||||
{self.}EndY := region.BordersRange.EndY - surplus;
|
||||
end
|
||||
for _,range in arr do
|
||||
begin
|
||||
if range is class(TSPdfParagraphRange) then
|
||||
begin
|
||||
line_arr := range.GetLineRangeArr();
|
||||
for _,r in line_arr do
|
||||
begin
|
||||
region := hash[r.TSPage.Index];
|
||||
region.RangeArr[length(region.RangeArr)] := r;
|
||||
end
|
||||
end
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.GetLastPage();
|
||||
begin
|
||||
return last_page_;
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.SetVAlign();
|
||||
begin
|
||||
val := tc_.TcPr.VAlign.Val;
|
||||
region := region_array_[0];
|
||||
arr := region.RangeArr;
|
||||
if length(arr) = 0 then return;
|
||||
last_y := arr[length(arr)-1].EndY;
|
||||
offset := last_y - (region.BordersRange.EndY - region.BordersRange.DynamicHeight) - tbl_pr_.TblCellMar.Bottom.W;
|
||||
case val of
|
||||
"center":
|
||||
begin
|
||||
offset /= 2;
|
||||
for _,range in arr do
|
||||
range.AdjustRangeOffset(region.BordersRange.TSPage, nil, -offset);
|
||||
end
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.IsReComputeByCantSplit(): boolean;
|
||||
begin
|
||||
if {self.}Tc.TcPr.VMerge then return false;
|
||||
return {self.}TSTrPr.TrPr.CantSplit and last_page_ <> {self.}TSPage;
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.IfRemoveEmptyRectangle(): boolean;
|
||||
begin
|
||||
if length(region_array_) < 2 then return false;
|
||||
return length(region_array_[0].RangeArr) ? false : true;
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.GetCellPrType(): string;
|
||||
begin
|
||||
if {self.}Row = 0 then return "firstRow";
|
||||
else if ({self.}Row + 1) % 2 = 0 then return "band1Horz";
|
||||
else return "band2Horz";
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.SetBorderRange(range: TSPdfBordersRange);
|
||||
begin
|
||||
if top_ then range.Top := true;
|
||||
if ifObj(tbl_pr_.TblBorders) then
|
||||
begin
|
||||
if {self.}Row = 0 then
|
||||
begin
|
||||
if tbl_pr_.TblBorders.Top then
|
||||
begin
|
||||
if not tc_pr_unit_decorator_.TcBorders.Top then
|
||||
tc_pr_unit_decorator_.TcBorders.Top.Copy(tbl_pr_.TblBorders.Top);
|
||||
range.Top := true;
|
||||
end
|
||||
if tbl_pr_.TblBorders.InsideH and {self.}VMerge <> parent_.Rows()-1 then
|
||||
begin
|
||||
if not tc_pr_unit_decorator_.TcBorders.Bottom then
|
||||
tc_pr_unit_decorator_.TcBorders.Bottom.Copy(tbl_pr_.TblBorders.InsideH);
|
||||
range.Bottom := true;
|
||||
end
|
||||
if tbl_pr_.TblBorders.InsideV and {self.}Col <> parent_.Cols()-1 then
|
||||
begin
|
||||
if not tc_pr_unit_decorator_.TcBorders.Right then
|
||||
tc_pr_unit_decorator_.TcBorders.Right.Copy(tbl_pr_.TblBorders.InsideV);
|
||||
range.Right := true;
|
||||
end
|
||||
if tbl_pr_.TblBorders.Bottom and {self.}VMerge = parent_.Rows()-1 then
|
||||
begin
|
||||
if not tc_pr_unit_decorator_.TcBorders.Bottom then
|
||||
tc_pr_unit_decorator_.TcBorders.Bottom.Copy(tbl_pr_.TblBorders.Bottom);
|
||||
range.Bottom := true;
|
||||
end
|
||||
end
|
||||
else if {self.}Row = parent_.Rows()-1 then
|
||||
begin
|
||||
if tbl_pr_.TblBorders.Bottom then
|
||||
begin
|
||||
if not tc_pr_unit_decorator_.TcBorders.Bottom then
|
||||
tc_pr_unit_decorator_.TcBorders.Bottom.Copy(tbl_pr_.TblBorders.Bottom);
|
||||
range.Bottom := true;
|
||||
end
|
||||
if tbl_pr_.TblBorders.InsideV and {self.}Col <> parent_.Cols()-1 then
|
||||
begin
|
||||
if not tc_pr_unit_decorator_.TcBorders.Right then
|
||||
tc_pr_unit_decorator_.TcBorders.Right.Copy(tbl_pr_.TblBorders.InsideV);
|
||||
range.Right := true;
|
||||
end
|
||||
end
|
||||
else begin
|
||||
if tbl_pr_.TblBorders.Bottom and {self.}VMerge = parent_.Rows()-1 then
|
||||
begin
|
||||
if not tc_pr_unit_decorator_.TcBorders.Bottom then
|
||||
tc_pr_unit_decorator_.TcBorders.Bottom.Copy(tbl_pr_.TblBorders.Bottom);
|
||||
range.Bottom := true;
|
||||
end
|
||||
if tbl_pr_.TblBorders.InsideH and {self.}VMerge <> parent_.Rows()-1 then
|
||||
begin
|
||||
if not tc_pr_unit_decorator_.TcBorders.Bottom then
|
||||
tc_pr_unit_decorator_.TcBorders.Bottom.Copy(tbl_pr_.TblBorders.InsideH);
|
||||
range.Bottom := true;
|
||||
end
|
||||
if tbl_pr_.TblBorders.InsideV and {self.}Col <> parent_.Cols()-1 then
|
||||
begin
|
||||
if not tc_pr_unit_decorator_.TcBorders.Right then
|
||||
tc_pr_unit_decorator_.TcBorders.Right.Copy(tbl_pr_.TblBorders.InsideV);
|
||||
range.Right := true;
|
||||
end
|
||||
end
|
||||
|
||||
if {self.}Col = 0 then
|
||||
begin
|
||||
if tbl_pr_.TblBorders.Left then
|
||||
begin
|
||||
if not tc_pr_unit_decorator_.TcBorders.Left then
|
||||
tc_pr_unit_decorator_.TcBorders.Left.Copy(tbl_pr_.TblBorders.Left);
|
||||
range.Left := true;
|
||||
end
|
||||
end
|
||||
if {self.}Col = parent_.Cols()-1 then
|
||||
begin
|
||||
if tbl_pr_.TblBorders.Right then
|
||||
begin
|
||||
if not tc_pr_unit_decorator_.TcBorders.Right then
|
||||
tc_pr_unit_decorator_.TcBorders.Right.Copy(tbl_pr_.TblBorders.Right);
|
||||
range.Right := true;
|
||||
end
|
||||
end
|
||||
end
|
||||
else begin
|
||||
range.Left := {self.}Col = 0;
|
||||
range.Top := {self.}Row = 0;
|
||||
range.Right := true;
|
||||
range.Bottom := true;
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfCellRange.SetTop();
|
||||
begin
|
||||
top_ := true;
|
||||
end;
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
type TSPdfColumnRange = class(TSPdfBasicRange)
|
||||
public
|
||||
function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare);
|
||||
function AddElement(ele: Element);
|
||||
function Elements(): array of Element;
|
||||
function GetLastPage(): TSPage;
|
||||
function Do();override;
|
||||
|
||||
private
|
||||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||||
[weakref]docx_components_ware_: TSDocxComponentsWare;
|
||||
[weakref]page_: TSPage;
|
||||
elements_: array of Elements;
|
||||
paragraph_: P;
|
||||
last_y_: real;
|
||||
end;
|
||||
|
||||
function TSPdfColumnRange.Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare);
|
||||
begin
|
||||
docx_to_pdf_ := docx_to_pdf;
|
||||
page_ := pg;
|
||||
docx_components_ware_ := components;
|
||||
elements_ := array();
|
||||
last_y_ := 0;
|
||||
end;
|
||||
|
||||
function TSPdfColumnRange.AddElement(ele: Element);
|
||||
begin
|
||||
elements_[length(elements_)] := ele;
|
||||
end;
|
||||
|
||||
function TSPdfColumnRange.Elements(): array of Element;
|
||||
begin
|
||||
return elements_;
|
||||
end;
|
||||
|
||||
function TSPdfColumnRange.Do();override;
|
||||
begin
|
||||
x := {self.}StartX;
|
||||
y := {self.}StartY;
|
||||
for _,element in elements_ do
|
||||
begin
|
||||
range := nil;
|
||||
if element.LocalName = "p" then
|
||||
range := new TSPdfParagraphRange(docx_to_pdf_, page_, docx_components_ware_, element);
|
||||
else if element.LocalName = "tbl" then
|
||||
range := new TSPdfTableRange(docx_to_pdf_, page_, docx_components_ware_, element);
|
||||
if ifnil(range) then continue;
|
||||
range.StartX := x;
|
||||
range.StartY := y;
|
||||
range.Width := {self.}Width;
|
||||
range.LowerBound := {self.}LowerBound;
|
||||
range.Calc();
|
||||
range.Do();
|
||||
y := range.EndY;
|
||||
page_ := range.GetLastPage();
|
||||
end
|
||||
{self.}EndY := y;
|
||||
end;
|
||||
|
||||
function TSPdfColumnRange.GetLastPage(): TSPage;
|
||||
begin
|
||||
return page_;
|
||||
end;
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
type TSPdfLineRange = class(TSPdfBasicRange)
|
||||
public
|
||||
function Create(pg: TSPage);
|
||||
function Do();override;
|
||||
function AddRange(range: TSPdfBasicRange);
|
||||
function SetAllRangeProp(pg: TSPage; sx: real; sy: real; ex: real; ey: real; w: real; fh: real; dh: real);
|
||||
function Align(jc: string);
|
||||
function AdjustRangeOffset(page: TSPage; x_offset: real; y_offset: real);
|
||||
function AlignRightBound(right_bound: real);
|
||||
function Offset(x_offset: real; y_offset; real);
|
||||
|
||||
private
|
||||
range_array_: array of TSPdfBasicRange;
|
||||
end;
|
||||
|
||||
function TSPdfLineRange.Create(pg: TSPage);
|
||||
begin
|
||||
{self.}TSPage := pg;
|
||||
range_array_ := array();
|
||||
end;
|
||||
|
||||
function TSPdfLineRange.AddRange(range: TSPdfBasicRange);
|
||||
begin
|
||||
range_array_[length(range_array_)] := range;
|
||||
end;
|
||||
|
||||
function TSPdfLineRange.Do();override;
|
||||
begin
|
||||
for _,range in range_array_ do
|
||||
range.Do();
|
||||
end;
|
||||
|
||||
function TSPdfLineRange.SetAllRangeProp(pg: TSPage; sx: real; sy: real; ex: real; ey: real; w: real; fh: real; dh: real);
|
||||
begin
|
||||
for _,range in range_array_ do
|
||||
begin
|
||||
if not ifnil(pg) then range.TSPage := pg;
|
||||
if not ifnil(sx) then range.StartX := sx;
|
||||
if not ifnil(sy) then range.StartY := sy;
|
||||
if not ifnil(ex) then range.EndX := ex;
|
||||
if not ifnil(ey) then range.EndY := ey;
|
||||
if not ifnil(w) then range.Width := w;
|
||||
if not ifnil(fh) then range.FixedHeight := fh;
|
||||
if not ifnil(dh) then range.DynamicHeight := dh;
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfLineRange.Align(jc: string);
|
||||
begin
|
||||
offset := 0;
|
||||
first := range_array_[0];
|
||||
last := range_array_[length(range_array_)-1];
|
||||
case jc of
|
||||
"center":
|
||||
offset := ({self.}Width + StartX - last.EndX - last.Width) / 2;
|
||||
"right":
|
||||
offset := {self.}Width - last.EndX + first.EndX - last.Width;
|
||||
end;
|
||||
if offset <= 0 then return;
|
||||
for _,range in range_array_ do
|
||||
range.EndX += offset;
|
||||
end;
|
||||
|
||||
function TSPdfLineRange.AdjustRangeOffset(page: TSPage; x_offset: real; y_offset: real);
|
||||
begin
|
||||
if page <> {self.}TSPage then return;
|
||||
for _,range in range_array_ do
|
||||
begin
|
||||
if not ifnil(x_offset) then range.EndX += x_offset;
|
||||
if not ifnil(y_offset) then range.EndY += y_offset;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSPdfLineRange.AlignRightBound(right_bound: real);
|
||||
begin
|
||||
last := range_array_[length(range_array_)-1];
|
||||
diff := right_bound - (last.EndX + last.Width);
|
||||
if diff > 1e-6 then
|
||||
begin
|
||||
avg := diff / (length(range_array_) - 1);
|
||||
for i:=1 to length(range_array_)-1 do
|
||||
range_array_[i].EndX += avg * i;
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfLineRange.Offset(x_offset: real; y_offset; real);
|
||||
begin
|
||||
for _,range in range_array_ do
|
||||
begin
|
||||
range.EndX += x_offset;
|
||||
range.EndY -= y_offset;
|
||||
end
|
||||
end;
|
||||
|
|
@ -0,0 +1,963 @@
|
|||
type TSPdfParagraphRange = class(TSPdfBasicRange)
|
||||
public
|
||||
function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; paragraph: P);
|
||||
function Calc();
|
||||
function Do();override;
|
||||
function SetTblStyleIdAndType(style_id: string; type: string);
|
||||
function SetNumPages(num: integer);
|
||||
function RangesToLines();
|
||||
function GetLastPage(): TSPage;
|
||||
function AdjustRangeOffset(page: TSPage; x_offset: real; y_offset: real);
|
||||
function GetLineRangeArr(): array of TSPdfLineRange;
|
||||
function Empty(): boolean;
|
||||
function Offset(x: real; y: real);
|
||||
|
||||
private
|
||||
function SetPPr(var ppr: PPr);
|
||||
function SetPPrByStyleId(var ppr: PPr; style_id: string);
|
||||
function SetRPr(var rpr; ppr: PPrUnitDecorator);
|
||||
function SetRPrByStyleId(var rpr: RPr; style_id: string);
|
||||
function SetRPrByTblStyleId(var rpr: RPr; style_id: string);
|
||||
function SetLvlText();
|
||||
function GetImageFileType(data: binary): string;
|
||||
function GetImageData(id: string): PdfImage;
|
||||
function GetParagraphLineSpace(size: real; line: integer; line_rule: string): real;
|
||||
function BasicRangesToLineRange(): tableArray;
|
||||
function CheckAndAddPage(y: real; offset: real): boolean;
|
||||
function GetUtf8CharLength(byte: string): integer;
|
||||
function SplitTextToTextRange(text: string; rpr: RPrUnitDecorator; link: string);
|
||||
function RToTextRange(r: R; link: string);
|
||||
function RDrawing(r: R);
|
||||
function RAlternateContent(r: R);
|
||||
function RFootnoteReference(r: R);
|
||||
function RObject(r: R);
|
||||
function RFldChar(r: R; stack: Stack);
|
||||
function RFootnoteRef(r: R);
|
||||
function SetLinesAlignment();
|
||||
function ResetCoordinates();
|
||||
function NewLineRange(): TSPdfLineRange;
|
||||
function BookMarkLinkToc();
|
||||
function HyperlinkToToc();
|
||||
function HyperlinkToTextRange(hyperlink: Hyperlink; ppr: PPrUnitDecorator);
|
||||
function GetXYCordinates(): array of real;
|
||||
function AlignRightBound();
|
||||
function Init();
|
||||
|
||||
private
|
||||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||||
[weakref]docx_components_ware_: TSDocxComponentsWare;
|
||||
[weakref]paragraph_: P;
|
||||
[weakref]page_: TSPage;
|
||||
range_array_: array of TSPdfBasicRange;
|
||||
line_range_array_: array of TSPdfLineRange;
|
||||
hyperlink_array_: tableArray;
|
||||
bookmark_array_: tableArray;
|
||||
ppr_unit_decorator_: PPrUnitDecorator;
|
||||
placeholder_array_: tableArray;
|
||||
table_style_id_: string;
|
||||
table_style_type_: string;
|
||||
empty_: boolean;
|
||||
right_bound_: real;
|
||||
end;
|
||||
|
||||
type FldStruct = class
|
||||
public
|
||||
function create();
|
||||
begin
|
||||
FldLock := false;
|
||||
MergeFormat := false;
|
||||
Quote := false;
|
||||
Separate := false;
|
||||
PageArabicMergeFormat := false;
|
||||
NumPages := false;
|
||||
ArabicMergeFormat := false;
|
||||
EndFld := false;
|
||||
end;
|
||||
public
|
||||
FldLock: boolean;
|
||||
MergeFormat: boolean;
|
||||
Quote: boolean;
|
||||
Separate: boolean;
|
||||
PageArabicMergeFormat: boolean;
|
||||
NumPages: boolean;
|
||||
ArabicMergeFormat: boolean;
|
||||
EndFld: boolean;
|
||||
end;
|
||||
|
||||
type Stack = class
|
||||
public
|
||||
function create();
|
||||
begin
|
||||
arr_ := array();
|
||||
index_ := 0;
|
||||
end;
|
||||
function Pop();
|
||||
begin
|
||||
if index_ = 0 then return nil;
|
||||
index_--;
|
||||
ret := arr_[index_];
|
||||
arr_[index_] := nil;
|
||||
return ret;
|
||||
end;
|
||||
function Push(element: any);
|
||||
begin
|
||||
arr_[index_++] := element;
|
||||
end;
|
||||
function Empty(): boolean;
|
||||
begin
|
||||
return index_ = 0;
|
||||
end;
|
||||
private
|
||||
arr_: tableArray;
|
||||
index_: integer;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; paragraph: P);
|
||||
begin
|
||||
docx_to_pdf_ := docx_to_pdf;
|
||||
page_ := pg;
|
||||
docx_components_ware_ := components;
|
||||
paragraph_ := paragraph;
|
||||
table_style_id_ := "";
|
||||
table_style_type_ := "";
|
||||
range_array_ := array();
|
||||
line_range_array_ := array();
|
||||
hyperlink_array_ := array();
|
||||
bookmark_array_ := array();
|
||||
empty_ := false;
|
||||
{self.}TSPage := page_;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.Init();
|
||||
begin
|
||||
range_array_ := array();
|
||||
right_bound_ := {self.}StartX + {self.}Width;
|
||||
{self.}ResetCoordinates();
|
||||
{self.}EndX := {self.}StartX;
|
||||
{self.}EndY := {self.}StartY;
|
||||
{self.}CheckAndAddPage({self.}EndY, ppr_unit_decorator_.Spacing.Before);
|
||||
{self.}EndY -= ppr_unit_decorator_.Spacing.Before;
|
||||
{self.}DynamicHeight += ppr_unit_decorator_.Spacing.Before;
|
||||
{self.}SetLvlText();
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.Calc(): tableArray;
|
||||
begin
|
||||
// ppr.rpr是无效的,应该以ppr.pStyle为准
|
||||
if ifnil(paragraph_.XmlChildPPr) then paragraph_.XmlChildPPr := new PPr();
|
||||
{self.}SetPPr(paragraph_.PPr);
|
||||
ppr_unit_decorator_ := new PPrUnitDecorator(paragraph_.PPr);
|
||||
{self.}Init();
|
||||
if not ppr_unit_decorator_.RPr.Sz.Val then ppr_unit_decorator_.RPr.Sz.Val := docx_to_pdf_.Font.GetDefaultSz();
|
||||
if paragraph_.PPr.PageBreakBefore then
|
||||
{self.}CheckAndAddPage({self.}LowerBound, 1);
|
||||
|
||||
elements := paragraph_.Elements();
|
||||
empty_flag := true;
|
||||
bookmark_id := '';
|
||||
bookmark_name := '';
|
||||
bookmark_flag := false;
|
||||
fld_stack := new Stack();
|
||||
for _,element in elements do
|
||||
begin
|
||||
if element.LocalName = "r" then
|
||||
begin
|
||||
empty_flag := false;
|
||||
if ifnil(element.XmlChildRPr) then element.XmlChildRPr := new RPr();
|
||||
{self.}SetRPr(element.RPr, ppr_unit_decorator_);
|
||||
|
||||
if element.FldChar.FldCharType = "begin" then
|
||||
begin
|
||||
fld_struct := new FldStruct();
|
||||
fld_stack.Push(fld_struct);
|
||||
end
|
||||
if not fld_stack.Empty() then
|
||||
begin
|
||||
{self.}RFldChar(element, fld_stack);
|
||||
continue;
|
||||
end
|
||||
|
||||
if element.Br.Type = "page" then
|
||||
{self.}EndY := {self.}LowerBound;
|
||||
// {self.}CheckAndAddPage({self.}LowerBound, 1);
|
||||
else if ifObj(element.Drawing) then {self.}RDrawing(element);
|
||||
else if ifObj(element.AlternateContent) then {self.}RAlternateContent(element);
|
||||
else if ifObj(element.FootnoteReference) then {self.}RFootnoteReference(element);
|
||||
else if ifObj(element.Object) then {self.}RObject(element);
|
||||
else if element.FootnoteRef then {self.}RFootnoteRef(element);
|
||||
else {self.}RToTextRange(element, bookmark_name);
|
||||
end
|
||||
else if element.LocalName = "fldSimple" then
|
||||
begin
|
||||
if ifString(element.Instr) and trim(element.Instr) = "NUMPAGES \\* Arabic \\* MERGEFORMAT" then
|
||||
begin
|
||||
rpr := new RPrUnitDecorator(element.Rs(0).RPr);
|
||||
numpages_index := length(range_array_);
|
||||
placeholder_array_ := array(numpages_index, rpr);
|
||||
end
|
||||
end
|
||||
else if element.LocalName = "hyperlink" then
|
||||
begin
|
||||
empty_flag := false;
|
||||
{self.}HyperlinkToTextRange(element, ppr_unit_decorator_);
|
||||
end
|
||||
else if element.LocalName = "bookmarkStart" then
|
||||
begin
|
||||
bookmark_id := element.Id;
|
||||
bookmark_name := element.Name;
|
||||
bookmark_array_[bookmark_name] := array();
|
||||
end
|
||||
else if element.LocalName = "bookmarkEnd" then
|
||||
begin
|
||||
bookmark_id := '';
|
||||
bookmark_name := '';
|
||||
end
|
||||
end
|
||||
if empty_flag then
|
||||
begin
|
||||
line_space := {self.}GetParagraphLineSpace(ppr_unit_decorator_.RPr.Sz.Val, ppr_unit_decorator_.Spacing.Line, ppr_unit_decorator_.Spacing.LineRule);
|
||||
{self.}DynamicHeight += line_space;
|
||||
{self.}EndY -= {self.}DynamicHeight;
|
||||
empty_ := true;
|
||||
end
|
||||
if placeholder_array_ then return false;
|
||||
{self.}RangesToLines();
|
||||
if hyperlink_array_ then {self.}HyperlinkToToc();
|
||||
if bookmark_array_ then {self.}BookMarkLinkToc();
|
||||
return true;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.SetNumPages(num: integer);
|
||||
begin
|
||||
text := tostring(num);
|
||||
last_index := length(range_array_);
|
||||
{self.}SplitTextToTextRange(text, placeholder_array_[1], link);
|
||||
arr := array();
|
||||
len := length(range_array_);
|
||||
for i:=last_index to len-1 do
|
||||
arr[length(arr)] := range_array_[i];
|
||||
diff := len - last_index;
|
||||
for i:=len-1 downto placeholder_array_[0] do
|
||||
range_array_[i] := range_array_[i-diff];
|
||||
k := 0;
|
||||
for i:=placeholder_array_[0] to placeholder_array_[0]+diff-1 do
|
||||
range_array_[i] := arr[k++];
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.BookMarkLinkToc();
|
||||
begin
|
||||
for name,arr in bookmark_array_ do
|
||||
if arr[0] then docx_to_pdf_.LinkToToc(name, arr[0].TSPage, arr[0].EndX, arr[0].EndY + arr[0].RPr.Sz.Val);
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.HyperlinkToToc();
|
||||
begin
|
||||
ppr := ppr_unit_decorator_;
|
||||
max_size := 0;
|
||||
for anchor,arr in hyperlink_array_ do // 整理hyperlink发送到docx_to_pdf_
|
||||
begin
|
||||
pg := arr[0].TSPage;
|
||||
left := {self.}StartX;
|
||||
right := {self.}StartX + {self.}Width;
|
||||
top := {self.}StartY;
|
||||
bottom := {self.}StartY;
|
||||
x := arr[0].EndX;
|
||||
y := arr[0].EndY;
|
||||
if top - {self.}GetParagraphLineSpace(arr[0].RPr.Sz.Val, ppr.Spacing.Line, ppr.Spacing.LineRule) then
|
||||
begin
|
||||
top := docx_to_pdf_.GetCurrentTextPoint().Y;
|
||||
bottom := top;
|
||||
end
|
||||
for _,range in arr do
|
||||
begin
|
||||
if x + range.Width - {self.}StartX > {self.}Width + 1e-6 then // 换行
|
||||
begin
|
||||
line_space := {self.}GetParagraphLineSpace(max_size, ppr.Spacing.Line, ppr.Spacing.LineRule);
|
||||
bottom -= line_space;
|
||||
max_size := 0;
|
||||
if range.TSPage <> pg then
|
||||
begin
|
||||
rect := array(left, bottom, right, top);
|
||||
toc := new TSToc(ppr, rect, pg, x, y);
|
||||
docx_to_pdf_.AddToc(anchor, toc);
|
||||
pg := range.TSPage;
|
||||
bottom := {self.}StartY;
|
||||
end
|
||||
end
|
||||
if range.RPr.Sz.Val > max_size then max_size := range.RPr.Sz.Val;
|
||||
x := range.EndX + range.Width;
|
||||
y := range.EndY;
|
||||
end
|
||||
font_name := ppr.RPr.RFonts.EastAsia ? ppr.RPr.RFonts.EastAsia : ppr.RPr.RFonts.Ascii;
|
||||
font_obj := docx_to_pdf_.Font.GetCNSFont(font_name, ppr.RPr.B, ppr.RPr.I);
|
||||
line_space := {self.}GetParagraphLineSpace(max_size, ppr.Spacing.Line, ppr.Spacing.LineRule);
|
||||
pg.PdfPage.SetFontAndSize(font_obj, max_size);
|
||||
bottom -= line_space;
|
||||
num_width := pg.PdfPage.TextWidth("." + tostring(pg.Number));
|
||||
if x + num_width - {self.}StartX > {self.}Width + 1e-6 then // 换行
|
||||
begin
|
||||
offset := (line_space - max_size) / 2 + max_size - max_size / 5;
|
||||
diff := {self.}EndY - {self.}LowerBound;
|
||||
if {self.}CheckAndAddPage({self.}EndY, line_space) then
|
||||
begin
|
||||
{self.}DynamicHeight += diff;
|
||||
pg := page_;
|
||||
rect := array(left, bottom, right, top);
|
||||
toc := new TSToc(ppr, rect, pg, x, y);
|
||||
docx_to_pdf_.AddToc(anchor, toc);
|
||||
bottom := {self.}StartY;
|
||||
end
|
||||
else begin
|
||||
bottom -= line_space;
|
||||
x := {self.}StartX;
|
||||
y := {self.}EndY - offset;
|
||||
{self.}EndY -= line_space;
|
||||
{self.}DynamicHeight += line_space;
|
||||
end
|
||||
end
|
||||
rect := array(left, bottom, right, top);
|
||||
toc := new TSToc(ppr, rect, pg, x, y, font_obj);
|
||||
docx_to_pdf_.AddToc(anchor, toc);
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.HyperlinkToTextRange(hyperlink: Hyperlink; ppr: PPrUnitDecorator);
|
||||
begin
|
||||
i := length(range_array_);
|
||||
rs := hyperlink.Rs();
|
||||
char_type := false;
|
||||
separate := false;
|
||||
for _,r in rs do
|
||||
begin
|
||||
if r.FldChar.FldCharType = "begin" then char_type := true;
|
||||
// TODO:officexml项目是否应该保留赋值接口,如何统一
|
||||
if char_type then
|
||||
begin
|
||||
if r.FldChar.FldCharType = "separate" then
|
||||
begin
|
||||
separate := true;
|
||||
continue;
|
||||
end
|
||||
if r.FldChar.FldCharType = "end" then
|
||||
separate := char_type := false;
|
||||
if separate then
|
||||
docx_to_pdf_.AddDocxPage(hyperlink.Anchor, r);
|
||||
end
|
||||
else begin
|
||||
if ifnil(r.XmlChildRPr) then r.XmlChildRPr := new RPr();
|
||||
{self.}SetRPr(r.RPr, ppr_unit_decorator_);
|
||||
r.RPr.Color.Val := nil;
|
||||
{self.}RToTextRange(r, hyperlink.Anchor);
|
||||
end
|
||||
end
|
||||
arr := array();
|
||||
while i < length(range_array_) do
|
||||
begin
|
||||
arr[length(arr)] := range_array_[i];
|
||||
i++;
|
||||
end
|
||||
hyperlink_array_[hyperlink.Anchor] := arr;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.Do();override;
|
||||
begin
|
||||
for _,line_range in line_range_array_ do
|
||||
line_range.Do();
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.SetTblStyleIdAndType(style_id: string; type: string);
|
||||
begin
|
||||
table_style_id_ := style_id;
|
||||
table_style_type_ := type;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.NewLineRange(): TSPdfLineRange;
|
||||
begin
|
||||
line_range := new TSPdfLineRange(page_);
|
||||
line_range.StartX := {self.}StartX;
|
||||
line_range.StartY := {self.}EndY;
|
||||
line_range.Width := {self.}Width;
|
||||
return line_range;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.RangesToLines();overload;
|
||||
begin
|
||||
{self.}BasicRangesToLineRange();
|
||||
{self.}DynamicHeight += ppr_unit_decorator_.Spacing.After;
|
||||
{self.}EndY -= ppr_unit_decorator_.Spacing.After;
|
||||
if ppr_unit_decorator_.PBdr.Bottom.Val = "single" then
|
||||
begin
|
||||
sect_ware := docx_to_pdf_.GetCurrentSectWare();
|
||||
page_.PdfPage.SetLineWidth(0.05);
|
||||
page_.PdfPage.SetGrayStroke(0.25);
|
||||
page_.PdfPage.MoveTo(sect_ware.SectPr.PgMar.Left, {self.}EndY);
|
||||
page_.PdfPage.LineTo(sect_ware.SectPr.PgSz.W - sect_ware.SectPr.PgMar.Right, {self.}EndY);
|
||||
page_.PdfPage.Stroke();
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.BasicRangesToLineRange();
|
||||
begin
|
||||
ppr := ppr_unit_decorator_;
|
||||
line_range := {self.}NewLineRange();
|
||||
i := 0;
|
||||
max_size := 0;
|
||||
max_y := 0;
|
||||
while i <= length(range_array_)-1 do
|
||||
begin
|
||||
range := range_array_[i];
|
||||
if i = 0 then {self.}EndX += ppr.Ind.FirstLine;
|
||||
if range is class(TSPdfTextRange) and range.RPr.Sz.Val > max_size then
|
||||
max_size := range.RPr.Sz.Val;
|
||||
if range.DynamicHeight > max_y then max_y := range.DynamicHeight;
|
||||
line_space := {self.}GetParagraphLineSpace(max_size, ppr.Spacing.Line, ppr.Spacing.LineRule);
|
||||
diff := {self.}EndY - {self.}LowerBound;
|
||||
if {self.}CheckAndAddPage({self.}EndY, max(line_space, range.DynamicHeight)) then
|
||||
{self.}DynamicHeight += diff;
|
||||
if_newline := {self.}EndX + range.Width - {self.}StartX > {self.}Width + 1e-6;
|
||||
if i = 0 then if_newline := 0;
|
||||
if if_newline and (range is class(TSPdfTextRange)) and (AnsiToUtf8(range.Text) in array(";", ":", "。", "“", "”", "!", "?", ",")) then
|
||||
if_newline := 0;
|
||||
if if_newline and range.Width < {self.}Width then
|
||||
begin
|
||||
offset := line_space > max_y ? (line_space - max_size) / 2 + max_size - max_size / 5 : max_y;
|
||||
max_value := max(line_space, max_y);
|
||||
line_range.TSPage := page_;
|
||||
line_range.EndY := {self.}EndY - max_value;
|
||||
line_range.DynamicHeight := max_value;
|
||||
line_range.SetAllRangeProp(pg: page_, ey: {self.}EndY - offset);
|
||||
line_range_array_[length(line_range_array_)] := line_range;
|
||||
|
||||
line_range := {self.}NewLineRange();
|
||||
max_size := 0;
|
||||
max_y := 0;
|
||||
{self.}DynamicHeight += max_value;
|
||||
{self.}EndY -= max_value;
|
||||
{self.}EndX := {self.}StartX;
|
||||
// w:hanging
|
||||
if range is class(TSPdfTextRange) then
|
||||
sz := range.RPr.SzCs.Val ? range.RPr.SzCs.Val : range.RPr.Sz.Val ? range.RPr.Sz.Val : docx_to_pdf_.Font.GetDefaultSz();
|
||||
else
|
||||
sz := docx_to_pdf_.Font.GetDefaultSz();
|
||||
{self.}EndX -= ppr.Ind.HangingChars ? ppr.Ind.HangingChars * sz : ppr.Ind.Hanging;
|
||||
continue;
|
||||
end
|
||||
range.EndX := {self.}EndX - range.StartX;
|
||||
{self.}EndX += range.Width;
|
||||
line_range.AddRange(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;
|
||||
max_value := max(line_space, max_y);
|
||||
line_range.TSPage := page_;
|
||||
line_range.EndY := {self.}EndY - max_value;
|
||||
line_range.DynamicHeight := max_value;
|
||||
line_range.SetAllRangeProp(pg: page_, ey: {self.}EndY - offset);
|
||||
line_range_array_[length(line_range_array_)] := line_range;
|
||||
{self.}DynamicHeight += max_value;
|
||||
{self.}EndY -= max_value;
|
||||
end
|
||||
end
|
||||
{self.}SetLinesAlignment();
|
||||
{self.}AlignRightBound();
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.SetLinesAlignment();
|
||||
begin
|
||||
for _,line_range in line_range_array_ do
|
||||
line_range.Align(ppr_unit_decorator_.Jc.Val);
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.AlignRightBound();
|
||||
begin
|
||||
len := length(line_range_array_);
|
||||
if len = 1 then return;
|
||||
for i:=0 to len-2 do
|
||||
line_range_array_[i].AlignRightBound(right_bound_);
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.CheckAndAddPage(y: real; offset: real): boolean;
|
||||
begin
|
||||
if y - offset < {self.}LowerBound then
|
||||
begin
|
||||
page_ := docx_to_pdf_.GetNextPage(page_);
|
||||
if ifnil(page_) then page_ := docx_to_pdf_.AddTSPage();
|
||||
point := docx_to_pdf_.GetCurrentTextPoint();
|
||||
{self.}EndY := 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; link: string);
|
||||
begin
|
||||
if r.Anchor then
|
||||
begin
|
||||
{self.}HyperlinkToTextRange(r);
|
||||
end
|
||||
else begin
|
||||
rpr := new RPrUnitDecorator(r.RPr);
|
||||
text := r.T.Text;
|
||||
if ifString(text) then {self.}SplitTextToTextRange(text, rpr, link);
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.SplitTextToTextRange(text: string; rpr: RPrUnitDecorator; link: string);
|
||||
begin
|
||||
pos := 1;
|
||||
while pos <= length(text) do
|
||||
begin
|
||||
num := {self.}GetUtf8CharLength(text[pos]);
|
||||
a_word := text[pos : pos+num-1];
|
||||
word := utf8ToAnsi(a_word);
|
||||
if num <> 1 and word = "?" then
|
||||
begin
|
||||
word := docx_to_pdf_.GetSymbol(a_word);
|
||||
if ifnil(word) then word := "u";
|
||||
font_obj := docx_to_pdf_.Font.GetSymbolFont();
|
||||
end
|
||||
else begin
|
||||
font_name := rpr.RFonts.EastAsia ? rpr.RFonts.EastAsia : rpr.RFonts.Ascii;
|
||||
font_obj := docx_to_pdf_.Font.GetCNSFont(font_name, rpr.B, rpr.I);
|
||||
end
|
||||
if not rpr.Sz.Val then rpr.Sz.Val := rpr.SzCs.Val ? rpr.SzCs.Val : docx_to_pdf_.Font.GetDefaultSz();
|
||||
page_.PdfPage.SetFontAndSize(font_obj, rpr.Sz.Val);
|
||||
word_width := page_.PdfPage.TextWidth(word);
|
||||
text_range := new TSPdfTextRange();
|
||||
text_range.RPr := rpr;
|
||||
text_range.Text := word;
|
||||
text_range.Font := font_obj;
|
||||
text_range.Width := word_width;
|
||||
range_array_[length(range_array_)] := text_range;
|
||||
if ifarray(bookmark_array_[link]) then bookmark_array_[link] union= array(text_range);
|
||||
pos += num;
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.RDrawing(r: R);
|
||||
begin
|
||||
if ifObj(r.Drawing._Inline) then
|
||||
begin
|
||||
id := r.Drawing._Inline.Graphic.GraphicData.Pic.BlipFill.Blip.Embed;
|
||||
[image_type, image] := {self.}GetImageData(id);
|
||||
if not image then return;
|
||||
xfrm := new XfrmUnitDecorator(r.Drawing._Inline.Graphic.GraphicData.Pic.SpPr.Xfrm);
|
||||
image_range := new TSPdfImageRange();
|
||||
image_range.Image := image;
|
||||
image_range.Type := image_type;
|
||||
image_range.StartX := xfrm.Off.X;
|
||||
image_range.StartY := xfrm.Off.Y;
|
||||
image_range.Width := xfrm.Ext.CX;
|
||||
image_range.DynamicHeight := xfrm.Ext.CY;
|
||||
range_array_[length(range_array_)] := image_range;
|
||||
end
|
||||
else if ifObj(r.Drawing.Anchor) then
|
||||
begin
|
||||
anchor := r.Drawing.Anchor;
|
||||
id := anchor.Graphic.GraphicData.Pic.BlipFill.Blip.Embed;
|
||||
[image_type, image] := {self.}GetImageData(id);
|
||||
if not image then return;
|
||||
[x, y] := {self.}GetXYCordinates();
|
||||
xfrm := new XfrmUnitDecorator(anchor.Graphic.GraphicData.Pic.SpPr.Xfrm);
|
||||
position_h := new PositionHUnitDecorator(anchor.PositionH);
|
||||
position_v := new PositionVUnitDecorator(anchor.PositionV);
|
||||
if position_h.RelativeFrom = "paragraph" then
|
||||
x := {self.}StartY;
|
||||
if position_v.RelativeFrom = "paragraph" then
|
||||
y := {self.}StartY;
|
||||
image_range := new TSPdfImageRange();
|
||||
image_range.Image := image;
|
||||
image_range.Type := image_type;
|
||||
image_range.EndX := x + position_h.PosOffset.Text;
|
||||
image_range.EndY := y - position_v.PosOffset.Text - xfrm.Ext.CY;
|
||||
image_range.Width := xfrm.Ext.CX;
|
||||
image_range.DynamicHeight := xfrm.Ext.CY;
|
||||
image_range.TSPage := page_;
|
||||
image_range.Do();
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.RAlternateContent(r: R);
|
||||
begin
|
||||
anchor := r.AlternateContent.Choice.Drawing.Anchor;
|
||||
wsp := anchor.Graphic.GraphicData.Wsp;
|
||||
[x, y] := {self.}GetXYCordinates();
|
||||
xfrm := new XfrmUnitDecorator(wsp.SpPr.Xfrm);
|
||||
position_h := new PositionHUnitDecorator(anchor.PositionH);
|
||||
position_v := new PositionVUnitDecorator(anchor.PositionV);
|
||||
if position_h.RelativeFrom = "paragraph" then
|
||||
x := {self.}StartY;
|
||||
if position_v.RelativeFrom = "paragraph" then
|
||||
y := {self.}StartY;
|
||||
x += position_h.PosOffset.Text;
|
||||
y -= position_v.PosOffset.Text;
|
||||
w := xfrm.Ext.CX;
|
||||
body_pr := new BodyPrUnitDecorator(wsp.BodyPr);
|
||||
x += body_pr.LIns;
|
||||
w -= (body_pr.LIns + body_pr.RIns);
|
||||
ps := wsp.Txbx.TxbxContent.Ps();
|
||||
for _,p in ps do
|
||||
begin
|
||||
range := new TSPdfParagraphRange(docx_to_pdf_, page_, docx_components_ware_, p);
|
||||
range.StartX := x;
|
||||
range.StartY := y;
|
||||
range.Width := w;
|
||||
range.Calc();
|
||||
range.Do();
|
||||
y := range.EndY;
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.RFootnoteReference(r: R);
|
||||
begin
|
||||
id := R.FootnoteReference.Id;
|
||||
footnotes_adapter := docx_components_ware_.GetFootnotesAdapter();
|
||||
footnote := footnotes_adapter.GetFootnoteById(id);
|
||||
sect_ware := docx_to_pdf_.GetCurrentSectWare();
|
||||
w := sect_ware.SectPr.PgSz.W - sect_ware.SectPr.PgMar.Right - sect_ware.SectPr.PgMar.Left;
|
||||
lb := {self.}LowerBound;
|
||||
[x, y] := docx_to_pdf_.CalculateTextCoordinates();
|
||||
elements := footnote.Elements();
|
||||
for _,element in elements do
|
||||
begin
|
||||
if element.LocalName = "p" then
|
||||
begin
|
||||
range := new TSPdfParagraphRange(docx_to_pdf_, page_, docx_components_ware_, element);
|
||||
range.StartX := x;
|
||||
range.StartY := y;
|
||||
range.Width := w;
|
||||
range.LowerBound := {self.}LowerBound;
|
||||
range.Calc();
|
||||
range.Offset(0, y - range.DynamicHeight - {self.}LowerBound);
|
||||
range.Do();
|
||||
{self.}LowerBound += range.DynamicHeight;
|
||||
rpr := new RPrUnitDecorator(r.RPr);
|
||||
text := docx_to_pdf_.GetCurrentNoteWare().GetIndex();
|
||||
if ifString(text) then {self.}SplitTextToTextRange(text, rpr, nil);
|
||||
return;
|
||||
// break;
|
||||
end
|
||||
end
|
||||
// range := new TSPdfParagraphRange(self, page_, docx_components_ware_, );
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.RObject(r: R);
|
||||
begin
|
||||
id := r.Object.Shape.Imagedata.Id;
|
||||
[image_type, image] := {self.}GetImageData(id);
|
||||
if not image then return;
|
||||
style := r.Object.Shape.Style;
|
||||
style_arr := str2array(style, ";");
|
||||
for _,str in style_arr do
|
||||
begin
|
||||
if startsStr("width:", str) then w := strtofloat(str[7:length(str)-2]);
|
||||
else if startsStr("height:", str) then h := strtofloat(str[8:length(str)-2]);
|
||||
end
|
||||
image_range := new TSPdfImageRange();
|
||||
image_range.Image := image;
|
||||
image_range.Type := image_type;
|
||||
image_range.StartX := 0;
|
||||
image_range.StartY := 0;
|
||||
image_range.Width := w;
|
||||
image_range.DynamicHeight := h;
|
||||
range_array_[length(range_array_)] := image_range;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.RFldChar(r: R; stack: Stack);
|
||||
begin
|
||||
fld_struct := stack.Pop();
|
||||
|
||||
if r.FldChar.FldCharType = "begin" then
|
||||
fld_struct.EndFld := false;
|
||||
else if r.FldChar.FldCharType = "end" then
|
||||
fld_struct.EndFld := true;
|
||||
else if r.FldChar.FldCharType = "separate" then
|
||||
fld_struct.Separate := true;
|
||||
if r.FldChar.FldLock then
|
||||
fld_struct.FldLock := true;
|
||||
|
||||
instr_text := ifString(r.InstrText.Text) ? trim(r.InstrText.Text) : "";
|
||||
if instr_text <> "" then
|
||||
begin
|
||||
if instr_text = "QUOTE" then
|
||||
fld_struct.Quote := true;
|
||||
else if instr_text = "\\* MERGEFORMAT" then
|
||||
fld_struct.MergeFormat := true;
|
||||
else if instr_text = "PAGE \\* Arabic \\* MERGEFORMAT" or instr_text = "PAGE \\* MERGEFORMAT" then
|
||||
fld_struct.PageArabicMergeFormat := true;
|
||||
else if instr_text = "NUMPAGES" then
|
||||
fld_struct.NumPages := true;
|
||||
else if instr_text = "\\* Arabic \\* MERGEFORMAT" then
|
||||
fld_struct.ArabicMergeFormat := true;
|
||||
else if instr_text = "NUMPAGES \\* Arabic \\* MERGEFORMAT" then
|
||||
fld_struct.NumPages := fld_struct.ArabicMergeFormat := true;
|
||||
end
|
||||
if fld_struct.Quote then
|
||||
begin
|
||||
if not fld_struct.EndFld and not fld_struct.Separate then
|
||||
begin
|
||||
stack.Push(fld_struct);
|
||||
return;
|
||||
end
|
||||
end
|
||||
else if fld_struct.PageArabicMergeFormat then
|
||||
begin
|
||||
if fld_struct.Separate then
|
||||
begin
|
||||
r.T.Text := tostring(page_.Number);
|
||||
{self.}RToTextRange(r, nil);
|
||||
fld_struct.PageArabicMergeFormat := false;
|
||||
end
|
||||
end
|
||||
else if fld_struct.ArabicMergeFormat then
|
||||
begin
|
||||
if fld_struct.Separate then
|
||||
begin
|
||||
rpr := new RPrUnitDecorator(r.RPr);
|
||||
numpages_index := length(range_array_);
|
||||
placeholder_array_ := array(numpages_index, rpr);
|
||||
fld_struct.NumPages := false;
|
||||
end
|
||||
end
|
||||
if not fld_struct.EndFld then
|
||||
begin
|
||||
stack.Push(fld_struct);
|
||||
end
|
||||
if ifObj(r.Drawing) then {self.}RDrawing(r);
|
||||
else if ifObj(r.AlternateContent) then {self.}RAlternateContent(r);
|
||||
else if ifObj(r.FootnoteReference) then {self.}RFootnoteReference(r);
|
||||
else if ifObj(r.Object) then {self.}RObject(r);
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.GetXYCordinates(): array of real;
|
||||
begin
|
||||
xml_file := docx_to_pdf_.GetCurrentXmlFile();
|
||||
if xml_file = "document.xml" then
|
||||
[x, y] := docx_to_pdf_.CalculateTextCoordinates();
|
||||
else begin
|
||||
sect_ware := docx_to_pdf_.GetCurrentSectWare();
|
||||
x := sect_ware.SectPr.PgMar.Left;
|
||||
if ansiContainsStr(xml_file, "footer") then
|
||||
y := sect_ware.SectPr.PgMar.Bottom;
|
||||
else if ansiContainsStr(xml_file, "header") then
|
||||
y := sect_ware.SectPr.PgSz.H - sect_ware.SectPr.PgMar.Header;
|
||||
end
|
||||
return array(x, y);
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.GetImageData(id: string): PdfImage;
|
||||
begin
|
||||
xml_file := docx_to_pdf_.GetCurrentXmlFile();
|
||||
if xml_file = "document.xml" then
|
||||
rels_adapter := docx_components_ware_.GetDocumentRelsAdapter();
|
||||
else if ansiContainsStr(xml_file, "footer") then
|
||||
rels_adapter := docx_components_ware_.GetFtrRelsAdapter(xml_file);
|
||||
else if ansiContainsStr(xml_file, "header") then
|
||||
rels_adapter := docx_components_ware_.GetHdrRelsAdapter(xml_file);
|
||||
rel := rels_adapter.GetRelationshipById(id);
|
||||
image_path := "word/" + rel.Target;
|
||||
image := docx_components_ware_.Zip().Get(image_path);
|
||||
data := image.Data();
|
||||
image_path := docx_to_pdf_.GetCachePath(image_path);
|
||||
writeFile(rwBinary(), "", image_path, 0, length(data), data);
|
||||
image := nil;
|
||||
image_type := GetImageFileType(data);
|
||||
case image_type of
|
||||
"png":
|
||||
image := docx_to_pdf_.GetPdf().LoadPngImageFromFile("", image_path);
|
||||
"jpg":
|
||||
image := docx_to_pdf_.GetPdf().LoadJpegImageFromFile("", image_path);
|
||||
"emf":
|
||||
image := docx_to_pdf_.GetPdf().LoadEmfImageFromFile("", image_path);
|
||||
"wmf":
|
||||
image := docx_to_pdf_.GetPdf().LoadWmfImageFromFile("", image_path);
|
||||
end;
|
||||
fileDelete("", image_path);
|
||||
return array(image_type, image);
|
||||
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)),
|
||||
('name': 'emf', 'position': 40, 'value': array(0x20, 0x45, 0x4d, 0x46)),
|
||||
('name': 'wmf', 'position': 0, 'value': array(0xd7, 0xcd, 0xc6, 0x9a)),
|
||||
);
|
||||
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; line_rule: string): real;
|
||||
begin
|
||||
sect_ware := docx_to_pdf_.GetCurrentSectWare();
|
||||
if not line then line := 240;
|
||||
if line_rule = "exact" or line_rule = "atLeast" then
|
||||
begin
|
||||
lines := line / 240;
|
||||
return size + lines;
|
||||
end
|
||||
else begin
|
||||
lines := roundto(line / 240, -1);
|
||||
multi := ceil(size / sect_ware.BaseSize);
|
||||
if (not ifnil(ppr_unit_decorator_.SnapToGrid) and not ppr_unit_decorator_.SnapToGrid) or
|
||||
((ifnil(ppr_unit_decorator_.SnapToGrid) or ppr_unit_decorator_.SnapToGrid) and lines > multi) then
|
||||
multi *= lines;
|
||||
return sect_ware.SectPr.DocGrid.LinePitch * multi;
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.SetPPr(var ppr: PPr);
|
||||
begin
|
||||
new_ppr := new PPr();
|
||||
styles := docx_components_ware_.GetStyles();
|
||||
new_ppr.Copy(styles.DocDefaults.PPrDefault.PPr);
|
||||
new_ppr.RPr.Copy(styles.DocDefaults.RPrDefault.RPr);
|
||||
{self.}SetPPrByStyleId(new_ppr, table_style_id_);
|
||||
{self.}SetPPrByStyleId(new_ppr, ppr.PStyle.Val);
|
||||
if ifObj(ppr) then
|
||||
begin
|
||||
new_ppr.Copy(ppr);
|
||||
ppr.Copy(new_ppr);
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.SetPPrByStyleId(var ppr: PPr; style_id: string);
|
||||
begin
|
||||
styles := docx_components_ware_.GetStylesAdapter();
|
||||
style := styles.GetStyleByStyleId(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: PPrUnitDecorator);
|
||||
begin
|
||||
new_rpr := new RPr();
|
||||
styles := docx_components_ware_.GetStyles();
|
||||
new_rpr.Copy(styles.DocDefaults.RPrDefault.RPr);
|
||||
{self.}SetRPrByTblStyleId(new_rpr, table_style_id_);
|
||||
{self.}SetRPrByStyleId(new_rpr, ppr.PStyle.Val);
|
||||
{self.}SetRPrByStyleId(new_rpr, rpr.RStyle.Val);
|
||||
if ifObj(rpr) then
|
||||
begin
|
||||
new_rpr.Copy(rpr);
|
||||
rpr.Copy(new_rpr);
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.SetRPrByTblStyleId(var rpr: RPr; style_id: string);
|
||||
begin
|
||||
styles := docx_components_ware_.GetStylesAdapter();
|
||||
style := styles.GetStyleByStyleId(style_id);
|
||||
if ifObj(style) then
|
||||
begin
|
||||
based_on := style.BasedOn.Val;
|
||||
{self.}SetRPrByTblStyleId(rpr, based_on);
|
||||
rpr.Copy(style.RPr);
|
||||
end
|
||||
if table_style_type_ then
|
||||
begin
|
||||
tbl_style_pr := docx_components_ware_.GetTblStylePrByType(table_style_id_, table_style_type_);
|
||||
if tbl_style_pr then rpr.Copy(tbl_style_pr.RPr);
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.SetRPrByStyleId(var rpr: RPr; style_id: string);
|
||||
begin
|
||||
styles := docx_components_ware_.GetStylesAdapter();
|
||||
style := styles.GetStyleByStyleId(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 := docx_components_ware_.GetNumberingWare();
|
||||
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();
|
||||
begin
|
||||
// 根据段落的间距确定新的坐标
|
||||
ppr := ppr_unit_decorator_;
|
||||
sz := ppr.RPr.SzCs.Val ? ppr.RPr.SzCs.Val : ppr.RPr.Sz.Val ? ppr.RPr.Sz.Val : docx_to_pdf_.Font.GetDefaultSz();
|
||||
{self.}StartX += ppr.Ind.LeftChars ? ppr.Ind.LeftChars * sz : ppr.Ind.Left;
|
||||
{self.}Width -= ppr.Ind.LeftChars ? ppr.Ind.LeftChars * sz : ppr.Ind.Left;
|
||||
{self.}Width -= ppr.Ind.RightChars ? ppr.Ind.RightChars * sz : ppr.Ind.Right;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.GetLastPage(): TSPage;
|
||||
begin
|
||||
return page_;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.AdjustRangeOffset(page: TSPage; x_offset: real; y_offset: real);
|
||||
begin
|
||||
for _,line_range in line_range_array_ do
|
||||
line_range.AdjustRangeOffset(page, x_offset, y_offset);
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.GetLineRangeArr(): array of TSPdfLineRange;
|
||||
begin
|
||||
return line_range_array_;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.Empty(): boolean;
|
||||
begin
|
||||
return empty_;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.Offset(x: real; y: real);
|
||||
begin
|
||||
for _,line_range in line_range_array_ do
|
||||
line_range.Offset(x, y);
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.RFootnoteRef(r: R);
|
||||
begin
|
||||
note_ware := docx_to_pdf_.GetCurrentNoteWare();
|
||||
rpr := new RPrUnitDecorator(r.RPr);
|
||||
text := note_ware.GetFootnoteOrderNumber();
|
||||
if ifString(text) then {self.}SplitTextToTextRange(text, rpr, nil);
|
||||
end;
|
||||
|
|
@ -0,0 +1,342 @@
|
|||
type TSPdfTableRange = class(TSPdfBasicRange)
|
||||
public
|
||||
function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: Components; table: Tbl);
|
||||
function Do();override;
|
||||
function Calc();
|
||||
function GetLastPage(): TSPage;
|
||||
function Rows(): integer;
|
||||
function Cols(): integer;
|
||||
|
||||
private
|
||||
function GetCellMatrix(grid_cols: array of GridColUnitDecorator);
|
||||
function CreateTableMatrix(grid_cols: array of GridColUnitDecorator; trs: array of Tr);
|
||||
function ComputeMatrixCells();
|
||||
function ResetCoordinates(tbl_pr: TblPrUnitDecorator; grid_cols: array of GridCol);
|
||||
function SetTblTblPr(var table: Tbl);
|
||||
function SetTblPrByStyleId(var tbl_pr: TblPr; style_id: string);
|
||||
function SetTrTrPr(var tr_pr: TrPr);
|
||||
function SetTrPrByStyleId(var tr_pr: TrPr; style_id: string);
|
||||
function SetTcTcPr(var tc: Tc);
|
||||
function SetTcPrByStyleId(var tc_pr: TcPr; style_id: string);
|
||||
function OverrideTcPrByTblStylePrType(var tc_pr: TcPr; type: string);
|
||||
|
||||
private
|
||||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||||
[weakref]last_page_: TSPage;
|
||||
[weakref]docx_components_ware_: Components;
|
||||
[weakref]table_: Tbl;
|
||||
tbl_pr_unit_decorator_: TblPrUnitDecorator;
|
||||
ts_trpr_array_: array of TSTrProperty;
|
||||
cell_range_matrix_: array of TSPdfCellRange;
|
||||
rows_: integer;
|
||||
cols_: integer;
|
||||
end;
|
||||
|
||||
function TSPdfTableRange.Create(docx_to_pdf: TSDocxToPdf; pg: PdfPage; components: Components; table: Tbl);
|
||||
begin
|
||||
docx_to_pdf_ := docx_to_pdf;
|
||||
last_page_ := pg;
|
||||
docx_components_ware_ := Components;
|
||||
table_ := table;
|
||||
ts_trpr_array_ := array();
|
||||
cell_range_matrix_ := array();
|
||||
rows_ := 0;
|
||||
cols_ := 0;
|
||||
{self.}TSPage := last_page_;
|
||||
end;
|
||||
|
||||
function TSPdfTableRange.Calc();
|
||||
begin
|
||||
{self.}SetTblTblPr(table_);
|
||||
tbl_pr_unit_decorator_ := new TblPrUnitDecorator(table_.TblPr);
|
||||
tbl_grid_unit_decorator := new TblGridUnitDecorator(table_.TblGrid);
|
||||
grid_cols := tbl_grid_unit_decorator.GridCols();
|
||||
{self.}ResetCoordinates(tbl_pr_unit_decorator_, grid_cols);
|
||||
{self.}EndX := {self.}StartX;
|
||||
{self.}EndY := {self.}StartY;
|
||||
// 如果是根据内容自适应,应该计算并调整grid_cols的值
|
||||
{self.}GetCellMatrix(grid_cols);
|
||||
end;
|
||||
|
||||
function TSPdfTableRange.Do();override;
|
||||
begin
|
||||
for _,row in cell_range_matrix_ do
|
||||
begin
|
||||
flag := nil;
|
||||
for __,range in row do
|
||||
begin
|
||||
if ifnil(flag) and ifObj(range) then flag := range.IfRemoveEmptyRectangle();
|
||||
if ifnil(range) then continue;
|
||||
if flag <> range.IfRemoveEmptyRectangle() then
|
||||
begin
|
||||
flag := false;
|
||||
break;
|
||||
end
|
||||
end
|
||||
for __,range in row do
|
||||
begin
|
||||
if ifObj(range) then
|
||||
begin
|
||||
range.RemoveFlag := flag;
|
||||
range.Do();
|
||||
end
|
||||
end
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfTableRange.GetCellMatrix(grid_cols: array of GridColUnitDecorator);
|
||||
begin
|
||||
trs := table_.Trs();
|
||||
rows_ := length(trs);
|
||||
cols_ := length(grid_cols);
|
||||
cell_range_matrix_ := nils(rows_, cols_);
|
||||
// 先构建一个矩阵
|
||||
{self.}CreateTableMatrix(grid_cols, trs);
|
||||
// 遍历矩阵后进行计算合并
|
||||
{self.}ComputeMatrixCells();
|
||||
end;
|
||||
|
||||
function TSPdfTableRange.CreateTableMatrix(grid_cols: array of GridColUnitDecorator; trs: array of Tr);
|
||||
begin
|
||||
for i,tr in trs do
|
||||
begin
|
||||
{self.}SetTrTrPr(tr);
|
||||
tr_pr := new TrPrUnitDecorator(tr.TrPr);
|
||||
tc_x := {self.}EndX;
|
||||
tcs := tr.Tcs();
|
||||
trp := new TSTrProperty();
|
||||
trp.TrPr := tr_pr;
|
||||
ts_trpr_array_[i] := trp;
|
||||
pos := 0;
|
||||
for j,tc in tcs do
|
||||
begin
|
||||
{self.}SetTcTcPr(tc);
|
||||
if i = 0 then {self.}OverrideTcPrByTblStylePrType(tc.TcPr, "firstRow");
|
||||
else if i = length(trs)-1 then {self.}OverrideTcPrByTblStylePrType(tc.TcPr, "lastRow")
|
||||
else if (i + 1) % 2 = 0 then {self.}OverrideTcPrByTblStylePrType(tc.TcPr, "band1Horz");
|
||||
else {self.}OverrideTcPrByTblStylePrType(tc.TcPr, "band2Horz");
|
||||
|
||||
grid_span := new GridSpanUnitDecorator(tc.TcPr.GridSpan);
|
||||
if tc.TcPr.VMerge and tc.TcPr.VMerge <> "restart" then
|
||||
begin
|
||||
tc_x += grid_cols[pos++].W;
|
||||
for k:=grid_span.Val-1 downto 1 do
|
||||
tc_x += grid_cols[pos++].W;
|
||||
continue;
|
||||
end
|
||||
cell_range := new TSPdfCellRange(self, docx_to_pdf_, last_page_, docx_components_ware_, tc, tbl_pr_unit_decorator_, trp);
|
||||
cell_range.StartX := tc_x;
|
||||
cell_range.Width := grid_cols[pos].W;
|
||||
cell_range.LowerBound := {self.}LowerBound;
|
||||
cell_range.FixedHeight := tr_pr.TrHeight.Val;
|
||||
cell_range.Row := i;
|
||||
cell_range.Col := pos;
|
||||
cell_range_matrix_[i][pos] := cell_range;
|
||||
pos++;
|
||||
for k:=grid_span.Val-1 downto 1 do
|
||||
cell_range.Width += grid_cols[pos++].W;
|
||||
tc_x += cell_range.Width;
|
||||
end
|
||||
end
|
||||
|
||||
// for i,arr in cell_range_matrix_ do
|
||||
// println("i = {}, arr = {}", i, arr);
|
||||
// println("\n");
|
||||
return;
|
||||
end;
|
||||
|
||||
function TSPdfTableRange.ComputeMatrixCells();
|
||||
begin
|
||||
i := 0;
|
||||
merge_arr := array();
|
||||
vmerge_height := array();
|
||||
while i < rows_ do
|
||||
begin
|
||||
j := 0;
|
||||
tc_y := {self.}EndY;
|
||||
recompute_flag := false;
|
||||
while j < cols_ do
|
||||
begin
|
||||
range := cell_range_matrix_[i][j];
|
||||
if ifnil(range) then
|
||||
begin
|
||||
j++;
|
||||
continue;
|
||||
end
|
||||
range.StartY := tc_y;
|
||||
range.SetTSPage(last_page_);
|
||||
range.Calc();
|
||||
if range.IsReComputeByCantSplit() then
|
||||
begin
|
||||
// 调整上一行的下边界
|
||||
arr := cell_range_matrix_[i-1];
|
||||
for _,r in arr do
|
||||
begin
|
||||
if ifnil(r) then
|
||||
begin
|
||||
pos := i-2;
|
||||
while pos > 0 do
|
||||
begin
|
||||
rr := cell_range_matrix_[pos][_];
|
||||
pos--;
|
||||
if ifnil(rr) then continue;
|
||||
rr.LowerBound := tc_y;
|
||||
break;
|
||||
end
|
||||
end
|
||||
if not ifnil(r) then r.LowerBound := tc_y;
|
||||
end
|
||||
last_page_ := docx_to_pdf_.GetNextPage(last_page_);
|
||||
[x, y] := docx_to_pdf_.CalculateTextCoordinates();
|
||||
{self.}EndY := y;
|
||||
j := 0;
|
||||
recompute_flag := true;
|
||||
arr := cell_range_matrix_[i];
|
||||
for _,r in arr do
|
||||
if not ifnil(r) then r.SetTop();
|
||||
break;
|
||||
end
|
||||
if range.Tc.TcPr.VMerge then
|
||||
begin
|
||||
b_merge_index := i;
|
||||
e_merge_index := i + 1;
|
||||
while ifnil(cell_range_matrix_[e_merge_index+1][j]) and e_merge_index < rows_-1 do
|
||||
e_merge_index++;
|
||||
merge_arr[e_merge_index][j] := b_merge_index;
|
||||
range.VMerge := e_merge_index;
|
||||
if ifnil(vmerge_height[e_merge_index]) or range.DynamicHeight > vmerge_height[e_merge_index] then
|
||||
vmerge_height[e_merge_index] := range.DynamicHeight;
|
||||
end
|
||||
j++;
|
||||
end
|
||||
if recompute_flag then continue;
|
||||
i_height := 0;
|
||||
for k,v in merge_arr[i] do
|
||||
begin
|
||||
i_height := ts_trpr_array_[i].Height;
|
||||
r := cell_range_matrix_[v][k];
|
||||
total_height := 0;
|
||||
for index:=v to i-1 do
|
||||
total_height += ts_trpr_array_[index].Height;
|
||||
h := vmerge_height[i];
|
||||
if h > total_height + i_height then
|
||||
i_height := h - total_height;
|
||||
else
|
||||
h := total_height + i_height;
|
||||
r.AlignHeight(h);
|
||||
r.SetVAlign();
|
||||
end
|
||||
if i_height then ts_trpr_array_[i].Height := i_height;
|
||||
for _,range in cell_range_matrix_[i] do
|
||||
begin
|
||||
if not ifObj(range) or range.Tc.TcPr.VMerge then continue;
|
||||
range.AlignHeight(ts_trpr_array_[i].Height);
|
||||
range.SetVAlign();
|
||||
{self.}EndY := range.EndY;
|
||||
last_page_ := range.GetLastPage();
|
||||
end
|
||||
i++;
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfTableRange.OverrideTcPrByTblStylePrType(var tc_pr: TcPr; type: string);
|
||||
begin
|
||||
// tc_pr应该是经过外层copy的
|
||||
tbl_style_pr := docx_components_ware_.GetTblStylePrByType(tbl_pr_unit_decorator_.TblStyle.Val, type);
|
||||
if tbl_style_pr then tc_pr.Copy(tbl_style_pr.TcPr);
|
||||
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.}Width;
|
||||
case tbl_pr.Jc.Val of
|
||||
"center":
|
||||
begin
|
||||
offset := diff/2;
|
||||
{self.}StartX -= offset;
|
||||
end
|
||||
"right":
|
||||
begin
|
||||
{self.}StartX -= diff;
|
||||
end
|
||||
end;
|
||||
{self.}Width := total_width;
|
||||
end;
|
||||
|
||||
function TSPdfTableRange.SetTblTblPr(var tbl: Tbl);
|
||||
begin
|
||||
new_tbl_pr := new TblPr();
|
||||
{self.}SetTblPrByStyleId(new_tbl_pr, tbl.TblPr.TblStyle.Val);
|
||||
new_tbl_pr.Copy(tbl.TblPr);
|
||||
tbl.TblPr.Copy(new_tbl_pr);
|
||||
end;
|
||||
|
||||
function TSPdfTableRange.SetTblPrByStyleId(var tbl_pr: TblPr; style_id: string);
|
||||
begin
|
||||
styles := docx_components_ware_.GetStylesAdapter();
|
||||
style := styles.GetStyleByStyleId(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.SetTrTrPr(var tr: Tr);
|
||||
begin
|
||||
new_tr_pr := new TrPr();
|
||||
{self.}SetTrPrByStyleId(new_tr_pr, tbl_pr_unit_decorator_.TblStyle.Val);
|
||||
new_tr_pr.Copy(tr.TrPr);
|
||||
tr.TrPr.Copy(new_tr_pr);
|
||||
end;
|
||||
|
||||
function TSPdfTableRange.SetTrPrByStyleId(var tr_pr: TrPr; style_id: string);
|
||||
begin
|
||||
styles := docx_components_ware_.GetStylesAdapter();
|
||||
style := styles.GetStyleByStyleId(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.SetTcTcPr(var tc: Tc);
|
||||
begin
|
||||
new_tc_pr := new TcPr();
|
||||
{self.}SetTcPrByStyleId(new_tc_pr, tbl_pr_unit_decorator_.TblStyle.Val);
|
||||
new_tc_pr.Copy(tc.TcPr);
|
||||
tc.TcPr.Copy(new_tc_pr);
|
||||
end;
|
||||
|
||||
function TSPdfTableRange.SetTcPrByStyleId(var tc_pr: TcPr; style_id: string);
|
||||
begin
|
||||
styles := docx_components_ware_.GetStylesAdapter();
|
||||
style := styles.GetStyleByStyleId(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;
|
||||
|
||||
function TSPdfTableRange.GetLastPage(): TSPage;
|
||||
begin
|
||||
return last_page_;
|
||||
end;
|
||||
|
||||
function TSPdfTableRange.Rows(): integer;
|
||||
begin
|
||||
return rows_;
|
||||
end;
|
||||
|
||||
function TSPdfTableRange.Cols(): integer;
|
||||
begin
|
||||
return cols_;
|
||||
end;
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
type TSPdfBasicRange = class
|
||||
public
|
||||
function Create();
|
||||
function Do();virtual;
|
||||
|
||||
public
|
||||
StartX: real;
|
||||
StartY: real; // range的起始坐标(x,y)
|
||||
EndX: real;
|
||||
EndY: real; // range的结束坐标(x,y)
|
||||
Width: real;
|
||||
FixedHeight: real;
|
||||
DynamicHeight: real;
|
||||
LowerBound: real;
|
||||
[weakref]TSPage: TSPage;
|
||||
end;
|
||||
|
||||
function TSPdfBasicRange.Create();
|
||||
begin
|
||||
{self.}StartX := 0;
|
||||
{self.}StartY := 0;
|
||||
{self.}EndX := 0;
|
||||
{self.}EndY := 0;
|
||||
{self.}Width := 0;
|
||||
{self.}FixedHeight := 0;
|
||||
{self.}DynamicHeight := 0;
|
||||
{self.}LowerBound := 0;
|
||||
{self.}TSPage := nil;
|
||||
end;
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
type TSPdfBordersRange = class(TSPdfBasicRange)
|
||||
uses TSColorToolKit;
|
||||
public
|
||||
function Create();
|
||||
function Do();override;
|
||||
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;
|
||||
|
||||
function TSPdfBordersRange.Create();
|
||||
begin
|
||||
class(TSPdfBasicRange).Create();
|
||||
{self.}TcPr := nil;
|
||||
{self.}Left := false;
|
||||
{self.}Top := false;
|
||||
{self.}Right := false;
|
||||
{self.}Bottom := false;
|
||||
end;
|
||||
|
||||
function TSPdfBordersRange.Do();override;
|
||||
begin
|
||||
// println("Left = {}, Top = {}, Right = {}, Bottom = {}, Tl2Br = {}, Tr2Bl = {}", Left, Top, Right, Bottom, Tl2Br, Tr2Bl);
|
||||
borders := {self.}TcPr.TcBorders;
|
||||
if {self.}TcPr.Shd.Fill and {self.}TcPr.Shd.Fill <> "auto" then
|
||||
begin
|
||||
[r, g, b] := TSColorToolKit.HexToRGB({self.}TcPr.Shd.Fill);
|
||||
{self.}TSPage.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.}TSPage.PdfPage.Rectangle(x, y, w, h);
|
||||
{self.}TSPage.PdfPage.Fill();
|
||||
{self.}TSPage.PdfPage.SetRGBFill(0, 0, 0);
|
||||
{self.}Left := true;
|
||||
end
|
||||
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 TSPdfBordersRange.SetDash(val: string);
|
||||
begin
|
||||
if val = "single" or ifnil(val) then
|
||||
{self.}TSPage.PdfPage.SetDash(array(), 0, 0);
|
||||
if val = "dashed" then
|
||||
{self.}TSPage.PdfPage.SetDash(array(1), 1, 0);
|
||||
end;
|
||||
|
||||
function TSPdfBordersRange.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] := TSColorToolKit.HexToRGB(border.Color);
|
||||
{self.}TSPage.PdfPage.SetRGBStroke(r, g, b);
|
||||
{self.}TSPage.PdfPage.SetLineWidth(line_width);
|
||||
{self.}TSPage.PdfPage.MoveTo(x1, y1);
|
||||
{self.}TSPage.PdfPage.LineTo(x2, y2);
|
||||
{self.}TSPage.PdfPage.Stroke();
|
||||
{self.}TSPage.PdfPage.SetRGBStroke(0, 0, 0);
|
||||
end;
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
type TSPdfImageRange = class(TSPdfBasicRange)
|
||||
public
|
||||
function Create();
|
||||
function Do();override;
|
||||
|
||||
public
|
||||
Image: PdfImage;
|
||||
Type: string;
|
||||
end;
|
||||
|
||||
function TSPdfImageRange.Create();
|
||||
begin
|
||||
class(TSPdfBasicRange).Create();
|
||||
{self.}Image := nil;
|
||||
{self.}Type := "";
|
||||
end;
|
||||
|
||||
function TSPdfImageRange.Do();
|
||||
begin
|
||||
// println("image = {}, type = {}, x = {}, y = {}, w = {}, h = {}", {self.}image, {self.}Type, {self.}endx, {self.}endy, {self.}width, {self.}DynamicHeight);
|
||||
if {self.}Type = "emf" then
|
||||
{self.}TSPage.PdfPage.DrawEmf({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
|
||||
else if {self.}Type = "wmf" then
|
||||
{self.}TSPage.PdfPage.DrawWmf({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
|
||||
else
|
||||
{self.}TSPage.PdfPage.DrawImage({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
|
||||
|
||||
if sysparams["_PDF_IMAGE_DEBUG_"] then
|
||||
begin
|
||||
{self.}TSPage.PdfPage.SetLineWidth(0.1);
|
||||
{self.}TSPage.PdfPage.SetRGBStroke(0.8, 0.8, 0);
|
||||
{self.}TSPage.PdfPage.Rectangle({self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
|
||||
{self.}TSPage.PdfPage.Stroke();
|
||||
end
|
||||
end;
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
type TSPdfTextRange = class(TSPdfBasicRange)
|
||||
uses TSColorToolKit;
|
||||
public
|
||||
function Create();
|
||||
function Do();override;
|
||||
|
||||
public
|
||||
RPr: RPr;
|
||||
Text: string;
|
||||
Font: PdfFont;
|
||||
end;
|
||||
|
||||
function TSPdfTextRange.Create();
|
||||
begin
|
||||
class(TSPdfBasicRange).Create();
|
||||
{self.}RPr := nil;
|
||||
{self.}Text := "";
|
||||
{self.}Font := nil;
|
||||
end;
|
||||
|
||||
function TSPdfTextRange.Do();
|
||||
begin
|
||||
// println("text = {}, endx = {}, endy = {}, width = {}, page = {}", ansiToUtf8(text), endx, endy, width, page);
|
||||
// println("Text = {}, sz = {}, szcs = {}, rpr.I = {}, color = {}", ansiToUtf8({self.}Text), {self.}RPr.Sz.Val, {self.}RPr.SzCs.Val, {self.}RPr.I, {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] := TSColorToolKit.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
|
||||
{self.}TSPage.PdfPage.SetRGBFill(r / 255, g / 255, b / 255);
|
||||
{self.}TSPage.PdfPage.SetFontAndSize({self.}Font, sz);
|
||||
{self.}TSPage.PdfPage.BeginText();
|
||||
{self.}TSPage.PdfPage.TextOut({self.}EndX, y, {self.}Text);
|
||||
{self.}TSPage.PdfPage.EndText();
|
||||
{self.}TSPage.PdfPage.SetRGBFill(0, 0, 0);
|
||||
|
||||
|
||||
if sysparams["_PDF_TEXT_DEBUG_"] then
|
||||
begin
|
||||
{self.}TSPage.PdfPage.SetLineWidth(0.1);
|
||||
{self.}TSPage.PdfPage.SetRGBStroke(1.0, 0.5, 0.0);
|
||||
{self.}TSPage.PdfPage.MoveTo(0, {self.}EndY);
|
||||
{self.}TSPage.PdfPage.LineTo(600, {self.}EndY);
|
||||
{self.}TSPage.PdfPage.Stroke();
|
||||
end
|
||||
end;
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
unit DTPColorToolKit;
|
||||
unit TSColorToolKit;
|
||||
interface
|
||||
function HexToRGB(hex);
|
||||
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
type TSPage = class
|
||||
public
|
||||
PdfPage: PdfPage;
|
||||
Index: integer;
|
||||
Number: integer; // 页码
|
||||
end;
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
type TSToc = class
|
||||
uses TSPdfEnumerations;
|
||||
public
|
||||
function Create(ppr: PPrUnitDecorator; rect: array of real; page: TSPage; x: real; y: real; font: PdfFont);
|
||||
function LinkAnnot(dst: PdfDestination);
|
||||
function AddPageNumber(page: TSPage);
|
||||
|
||||
private
|
||||
ppr_: PPrUnitDecorator;
|
||||
rect_: array of real;
|
||||
font_: PdfFont;
|
||||
[weakref]tspage_: TSPage;
|
||||
x_;
|
||||
y_;
|
||||
end;
|
||||
|
||||
function TSToc.Create(ppr: PPrUnitDecorator; rect: array of real; page: TSPage; x: real; y: real; font: PdfFont);
|
||||
begin
|
||||
ppr_ := ppr;
|
||||
rect_ := rect;
|
||||
tspage_ := page;
|
||||
x_ := x;
|
||||
y_ := y;
|
||||
font_ := font;
|
||||
end;
|
||||
|
||||
function TSToc.LinkAnnot(dst: PdfDestination);
|
||||
begin
|
||||
annot := tspage_.PdfPage.CreateLinkAnnot(rect_, dst);
|
||||
annot.LinkAnnotSetHighlightMode(TSPdfEnumerations.ANNOT_NO_HIGHTLIGHT);
|
||||
annot.LinkAnnotSetBorderStyle(0, 0, 0);
|
||||
end;
|
||||
|
||||
function TSToc.AddPageNumber(page: TSPage);
|
||||
begin
|
||||
number := tostring(page.Number);
|
||||
tspage_.PdfPage.SetFontAndSize(font_, ppr_.RPr.Sz.Val);
|
||||
number_sz := tspage_.PdfPage.TextWidth(number);
|
||||
x := rect_[2] - number_sz;
|
||||
tspage_.PdfPage.BeginText();
|
||||
tspage_.PdfPage.TextOut(x, y_, number);
|
||||
tspage_.PdfPage.EndText();
|
||||
|
||||
tspage_.PdfPage.SetRGBStroke(0, 0, 0);
|
||||
tspage_.PdfPage.SetDash(array(0.5, 2), 2, 0);
|
||||
tspage_.PdfPage.SetLineWidth(0.5);
|
||||
tspage_.PdfPage.SetLineCap(TSPdfEnumerations.ROUND_END);
|
||||
tspage_.PdfPage.MoveTo(x_+1, y_);
|
||||
tspage_.PdfPage.LineTo(x-0.5, y_);
|
||||
tspage_.PdfPage.Stroke();
|
||||
end;
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
type TSTrProperty = class
|
||||
function Create();
|
||||
public
|
||||
TrPr: TrPrUnitDecorator;
|
||||
Height: real;
|
||||
end;
|
||||
|
||||
function TSTrProperty.Create();
|
||||
begin
|
||||
{self.}TrPr := nil;
|
||||
{self.}Height := 0;
|
||||
end;
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
type TSDocxComponentsWare = class(Components)
|
||||
public
|
||||
function Create();
|
||||
function GetStyles(): Styles;
|
||||
function GetStylesAdapter(): StylesAdapter;
|
||||
function GetDocumentRelsAdapter(): RelationShipsAdapter;
|
||||
function GetNumberingWare(): TSNumberingWare;
|
||||
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_ware_: TSNumberingWare;
|
||||
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;
|
||||
|
||||
function TSDocxComponentsWare.Create();
|
||||
begin
|
||||
class(Components).Create();
|
||||
tbl_style_pr_hash_ := array();
|
||||
ftr_hash_ := array();
|
||||
hdr_hash_ := array();
|
||||
hdr_rel_hash_ := array();
|
||||
ftr_rel_hash_ := array();
|
||||
end;
|
||||
|
||||
function TSDocxComponentsWare.GetStyles(): Styles;
|
||||
begin
|
||||
if styles_deserialize_flag_ then return {self.}Styles;
|
||||
{self.}Styles.Deserialize();
|
||||
styles_deserialize_flag_ := true;
|
||||
return {self.}Styles;
|
||||
end;
|
||||
|
||||
function TSDocxComponentsWare.GetStylesAdapter(): StylesAdapter;
|
||||
begin
|
||||
if styles_adapter_ then return styles_adapter_;
|
||||
styles_adapter_ := new StylesAdapter({self.}GetStyles());
|
||||
return styles_adapter_;
|
||||
end;
|
||||
|
||||
function TSDocxComponentsWare.GetDocumentRelsAdapter(): RelationShipsAdapter;
|
||||
begin
|
||||
if document_rels_adapter_ then return document_rels_adapter_;
|
||||
{self.}DocumentRels.Deserialize();
|
||||
document_rels_adapter_ := new RelationShipsAdapter({self.}DocumentRels);
|
||||
return document_rels_adapter_;
|
||||
end;
|
||||
|
||||
function TSDocxComponentsWare.GetNumberingWare(): TSNumberingWare;
|
||||
begin
|
||||
if numbering_ware_ then return numbering_ware_;
|
||||
if not {self.}Numbering then return nil;
|
||||
{self.}Numbering.Deserialize();
|
||||
numbering_ware_ := new TSNumberingWare({self.}Numbering);
|
||||
return numbering_ware_;
|
||||
end;
|
||||
|
||||
function TSDocxComponentsWare.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 StyleAdapter(style);
|
||||
tbl_style_pr := style.GetTblStylePrByType(type);
|
||||
tbl_style_pr_hash_[style_id][type] := tbl_style_pr;
|
||||
return tbl_style_pr;
|
||||
end;
|
||||
|
||||
function TSDocxComponentsWare.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();
|
||||
ftr_hash_[target] := obj;
|
||||
return obj;
|
||||
end;
|
||||
|
||||
function TSDocxComponentsWare.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();
|
||||
hdr_hash_[target] := obj;
|
||||
return obj;
|
||||
end;
|
||||
|
||||
function TSDocxComponentsWare.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 RelationShipsAdapter(obj);
|
||||
hdr_rel_hash_[target] := rels_adapter;
|
||||
return rels_adapter;
|
||||
end;
|
||||
|
||||
function TSDocxComponentsWare.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 RelationShipsAdapter(obj);
|
||||
ftr_rel_hash_[target] := rels_adapter;
|
||||
return rels_adapter;
|
||||
end;
|
||||
|
||||
function TSDocxComponentsWare.GetFootnotesAdapter(): FootnotesAdapter;
|
||||
begin
|
||||
if footnotes_adapter_ then return footnotes_adapter_;
|
||||
obj := {self.}Footnotes;
|
||||
obj.Deserialize();
|
||||
footnotes_adapter_ := new FootnotesAdapter(obj);
|
||||
return footnotes_adapter_;
|
||||
end;
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
type TSFontWare = 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 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;
|
||||
|
||||
function TSFontWare.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 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 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 TSFontWare.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 TSFontWare.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 TSFontWare.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 TSFontWare.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
|
||||
return pdf_.GetFont(font_name, "");
|
||||
end;
|
||||
|
||||
function TSFontWare.SetSubstitutionRules(source: string; target: string);
|
||||
begin
|
||||
substitution_rules_[source] := target;
|
||||
end;
|
||||
|
||||
function TSFontWare.GetSymbolFont(): PdfFont;
|
||||
begin
|
||||
return pdf_.GetFont("ZapfDingbats", "");
|
||||
end;
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
type TSNoteWare = class
|
||||
public
|
||||
function Create(sect_ware: TSSectWare);
|
||||
function GetFootnoteOrderNumber(): string;
|
||||
function GetIndex(): string;
|
||||
|
||||
private
|
||||
function CalculateNumber(num_fmt: string; num: integer): string;
|
||||
function ChineseCountingThousand(n: integer): string;
|
||||
|
||||
private
|
||||
[weakref]sect_ware_: TSSectWare;
|
||||
index_: integer;
|
||||
end;
|
||||
|
||||
function TSNoteWare.Create(sect_ware: TSSectWare);
|
||||
begin
|
||||
sect_ware_ := sect_ware;
|
||||
index_ := 0;
|
||||
end;
|
||||
|
||||
function TSNoteWare.GetFootnoteOrderNumber();
|
||||
begin
|
||||
num_fmt := sect_ware_.SectPr.FootnotePr.NumFmt.Val;
|
||||
if ifnil(num_fmt) then num_fmt := "decimal";
|
||||
return CalculateNumber(num_fmt, ++index_);
|
||||
end;
|
||||
|
||||
function TSNoteWare.GetIndex(): string;
|
||||
begin
|
||||
return inttostr(index_);
|
||||
end;
|
||||
|
||||
function TSNoteWare.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 TSNoteWare.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;
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
type TSNumberingWare = 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_: 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_.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 TSNumberingWare.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 TSNumberingWare.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;
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
type TSSectWare = class
|
||||
public
|
||||
function Create();
|
||||
function Destroy();
|
||||
function Do();
|
||||
function AddElement(element: tslobj);
|
||||
|
||||
public
|
||||
Elements: array of tslobj;
|
||||
SectPr: SectPrUnitDecorator;
|
||||
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;
|
||||
|
||||
function TSSectWare.AddElement(element: tslobj);
|
||||
begin
|
||||
{self.}Elements[length({self.}Elements)] := element;
|
||||
end;
|
||||
Loading…
Reference in New Issue