代码重构

fix:表格边框错误
注意:暂时移除脚注和公式的支持
This commit is contained in:
csh 2025-03-24 17:17:22 +08:00
parent a118ff6c26
commit 9f84a72595
5 changed files with 2015 additions and 2140 deletions

View File

@ -8,10 +8,9 @@ public
function GetCachePath(image_path: string): string; function GetCachePath(image_path: string): string;
function GetCurrentXmlFile(): string; function GetCurrentXmlFile(): string;
function GetCurrentNoteModule(): NoteModule;
function AddPage(flag: boolean): Page; function AddPage(flag: boolean): Page;
function ProcessNumpages(); function ProcessRealtimeRange();
// docx页码扩展 // docx页码扩展
function UpdateDocxPageNumPages(); function UpdateDocxPageNumPages();
@ -19,10 +18,13 @@ public
function SaveDocxFile(alias: string; file: string);overload; function SaveDocxFile(alias: string; file: string);overload;
property PdfFile read pdf_; property PdfFile read pdf_;
property DocxComponents read docx_components_module_;
property Font read font_module_; property Font read font_module_;
property PageManager read page_manager_module_; property PageManager read page_manager_module_;
property Toc read toc_module_; property Toc read toc_module_;
property Note read note_module_; property Note read note_module_;
property CurrentSect read current_sect_module_;
property CurrentPage read current_page_;
private private
function InitDocxComponents(alias: string; file: string); function InitDocxComponents(alias: string; file: string);
@ -31,16 +33,17 @@ private
function InitSectModule(); function InitSectModule();
function AllocateElementsToSectModule(); function AllocateElementsToSectModule();
function ClassifyCols(var point: Point; cols: Cols); function ClassifyCols(var point: Point; cols: Cols);
function RangesSpacing(range: BasicRange);
function SetHdr(type: string); function SetHdr(type: string);
function SetFtr(type: string); function SetFtr(type: string);
function TransformP(paragraph: P; x: real; y: real; w: real; lb: real): ParagraphRange; function TransformP(p: P);
function TransformTbl(table: Tbl; x: real; y: real; w: real; lb: real): TableRange; function TransformTbl(tbl: Tbl);
function TransformSdt(sdt: Sdt; x: real; y: real; w: real; lb: real): array of ParagraphRange; function TransformSdt(sdt: Sdt);
private private
pdf_: PdfFile; pdf_: PdfFile;
docx_components_module_: DocxComponentsModule; // TSDocxComponentsModule docx_components_module_: DocxComponentsModule; // DocxComponentsModule
cache_path_: string; // 临时目录,用来存放临时文件 cache_path_: string; // 临时目录,用来存放临时文件
font_module_: FontModule; // 字体模块 font_module_: FontModule; // 字体模块
sect_module_array_: array of SectModule; // 页面布局模块数组 sect_module_array_: array of SectModule; // 页面布局模块数组
@ -53,11 +56,13 @@ private
toc_module_: TocModule; // 目录模块 toc_module_: TocModule; // 目录模块
note_module_: NoteModule; // 脚注/尾注 note_module_: NoteModule; // 脚注/尾注
range_page_number_array_: tableArray;
xml_file_: string; xml_file_: string;
even_and_odd_flag_: boolean; even_and_odd_flag_: boolean;
realtime_range_array_: array of BasicRange; // 最后才能计算出来的range比如包含总页码的
last_range_: BasicRange; // 上一个range
// 回写docx // 回写docx
docx_page_arr_: tableArray; docx_page_arr_: tableArray;
update_docx_pages_: boolean; update_docx_pages_: boolean;
@ -77,13 +82,14 @@ begin
page_manager_module_ := new DTPModules.PageManagerModule(pdf_); page_manager_module_ := new DTPModules.PageManagerModule(pdf_);
toc_module_ := new DTPModules.TocModule(); toc_module_ := new DTPModules.TocModule();
range_page_number_array_ := array();
xml_file_ := "document.xml"; xml_file_ := "document.xml";
settings := docx_components_module_.Settings; settings := docx_components_module_.Settings;
settings.XmlChildEvenAndOddHeaders.Deserialize(); settings.XmlChildEvenAndOddHeaders.Deserialize();
even_and_odd_flag_ := settings.EvenAndOddHeaders ? true : false; even_and_odd_flag_ := settings.EvenAndOddHeaders ? true : false;
note_module_ := new ; note_module_ := new DTPModules.NoteModule(self);
realtime_range_array_ := array();
// 回写docx // 回写docx
docx_page_arr_ := array(); docx_page_arr_ := array();
@ -109,7 +115,6 @@ begin
current_sect_module_ := sect_module; current_sect_module_ := sect_module;
current_sect_pr_adapter_ := new SectPrAdapter(current_sect_module_.SectPr.GetObject()); current_sect_pr_adapter_ := new SectPrAdapter(current_sect_module_.SectPr.GetObject());
{self.}AddPage(true); {self.}AddPage(true);
xml_file_ := "document.xml";
end end
// 分栏 // 分栏
@ -120,28 +125,18 @@ begin
columns := {self.}ClassifyCols(current_page_.TextPoint, cols); columns := {self.}ClassifyCols(current_page_.TextPoint, cols);
end end
else begin 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);
for _,element in elements do for _,element in elements do
begin begin
x := current_page_.TextPoint.X; // if _ = 100 then break;
y := current_page_.TextPoint.Y; // if _ = 17 then
// if _ = 266 then break; // println("_ = {}, paraid = {}, xml_file_ = {}, error = {}", _, element.ParaId, xml_file_, pdf_.GetError());
// if _ = 20 then if element.LocalName = "p" then {self.}TransformP(element);
// println("_ = {}, xml_file_ = {}, error = {}", _, xml_file_, pdf_.GetError()); else if element.LocalName = "tbl" then {self.}TransformTbl(element);
range := nil; else if element.LocalName = "sdt" then {self.}TransformSdt(element);
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 end
end end
end end
end {self.}ProcessRealtimeRange();
{self.}ProcessNumpages();
end; end;
function TSDocxToPdf.GetCachePath(image_path: string): string; function TSDocxToPdf.GetCachePath(image_path: string): string;
@ -197,12 +192,13 @@ begin
sect.PgSz.Orient := sect.PgSz.Orient ? "portrait" : "landscape"; sect.PgSz.Orient := sect.PgSz.Orient ? "portrait" : "landscape";
sect.Type.Val := sect.Type.Val ?: "nextPage"; sect.Type.Val := sect.Type.Val ?: "nextPage";
module.SectPr := sect; module.SectPr := sect;
module.BaseSize := round(sect.DocGrid.LinePitch * 0.75);
end end
for i:=0 to length(elements)-1 do for i:=0 to length(elements)-1 do
begin begin
element := elements[i]; element := elements[i];
module.AddElement(element); module.AddElement(element);
if element.LocalName = "p" and ifObj(element.PPr.SectPr) then if element.LocalName = "p" and element.PPr.SectPr then
begin begin
##fp(module, element.PPr.SectPr); ##fp(module, element.PPr.SectPr);
sect_module_array_[length(sect_module_array_)] := module; sect_module_array_[length(sect_module_array_)] := module;
@ -224,22 +220,8 @@ begin
page := page_manager_module_.NewPage(); page := page_manager_module_.NewPage();
page.SectPr := current_sect_module_.SectPr; 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.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; 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);
// 页眉页脚 // 页眉页脚
if current_sect_module_.SectPr.TitlePg and current_page_.Index = 0 then if current_sect_module_.SectPr.TitlePg and current_page_.Index = 0 then
@ -251,11 +233,17 @@ begin
else else
type_name := "default"; type_name := "default";
bk_file := xml_file_;
{self.}SetHdr(type_name); {self.}SetHdr(type_name);
{self.}SetFtr(type_name); {self.}SetFtr(type_name);
xml_file_ := bk_file;
// 设置完页眉页脚计算正文坐标
page.TextPoint.X := page.SectPr.PgMar.Left;
page.TextPoint.Y := page.SectPr.PgSz.H - max(page.SectPr.PgMar.Top, page.SectPr.PgMar.Header);
page.TextPoint.Y := min(page.TextPoint.Y, page.HdrPoint.Y);
page.UpperBound := page.TextPoint.Y;
page.LowerBound := max(page.SectPr.PgMar.Bottom, page.FtrPoint.Y);
// println("len = {}, Number = {}", page_manager_module_.Count(), current_page_.Number);
// println("W = {}, H = {}", current_page_.SectPr.PgSz.W, current_page_.SectPr.PgSz.H); // println("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("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("Left = {}, Right = {}", current_page_.SectPr.PgMar.Left, current_page_.SectPr.PgMar.Right);
@ -264,121 +252,146 @@ begin
// println("HdrPoint.X = {}, HdrPoint.Y = {}", current_page_.HdrPoint.X, current_page_.HdrPoint.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); // println("FtrPoint.X = {}, FtrPoint.Y = {}", current_page_.FtrPoint.X, current_page_.FtrPoint.Y);
xml_file_ := "document.xml";
return current_page_; return current_page_;
end; end;
function TSDocxToPdf.SetFtr(type: string); function TSDocxToPdf.SetFtr(type: string);
begin begin
// 页脚:从下往上,需要调整
current_page_.FtrPoint.X := current_page_.SectPr.PgMar.Left;
current_page_.FtrPoint.Y := current_page_.SectPr.PgMar.Footer;
footer_reference := current_sect_pr_adapter_.GetFooterReferenceByType(type); footer_reference := current_sect_pr_adapter_.GetFooterReferenceByType(type);
ftr_range := array(); if not ifObj(footer_reference) then return;
if ifObj(footer_reference) then
begin
rels_adapter := docx_components_module_.GetDocumentRelsAdapter(); rels_adapter := docx_components_module_.GetDocumentRelsAdapter();
rel := rels_adapter.GetRelationshipById(footer_reference.Id); rel := rels_adapter.GetRelationshipById(footer_reference.Id);
w := current_page_.SectPr.PgSz.W - current_page_.SectPr.PgMar.Right - current_page_.SectPr.PgMar.Left; ftr := docx_components_module_.GetFtr(rel.Target);
lb := 0;
obj := docx_components_module_.GetFtr(rel.Target);
xml_file_ := rel.Target; xml_file_ := rel.Target;
elements := obj.Elements();
for _,element in elements do w := current_page_.SectPr.PgSz.W - current_page_.SectPr.PgMar.Right - current_page_.SectPr.PgMar.Left;
begin ftr_range := new FtrRange(self, ftr);
x := current_page_.FtrPoint.X; ftr_range.Width := w;
y := current_page_.FtrPoint.Y; ftr_range.Parent := self;
range := nil; ftr_range.StartX := current_page_.SectPr.PgMar.Left;
if element.LocalName = "p" then range := {self.}TransformP(element, x, y, w, lb); ftr_range.StartY := current_page_.SectPr.PgSz.H;
if ifObj(range) then ftr_range.StartPage := current_page_;
begin ftr_range.LowerBound := 0;
current_page_.FtrPoint.Y := range.EndY; if ftr_range.Calc() then
ftr_range[length(ftr_range)] := range; ftr_range.Do();
end else
end realtime_range_array_[length(realtime_range_array_)] := ftr_range;
end
last_range := ftr_range[length(ftr_range)-1]; current_page_.FtrPoint.Y := ftr_range.EndY;
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; end;
function TSDocxToPdf.SetHdr(type: string); function TSDocxToPdf.SetHdr(type: string);
begin begin
// 正文、页眉页脚坐标
// 页眉:从上往下,不需要调整
current_page_.HdrPoint.X := current_page_.SectPr.PgMar.Left;
current_page_.HdrPoint.Y := current_page_.SectPr.PgSz.H - current_page_.SectPr.PgMar.Header;
header_reference := current_sect_pr_adapter_.GetHeaderReferenceByType(type); header_reference := current_sect_pr_adapter_.GetHeaderReferenceByType(type);
if ifObj(header_reference) then if not ifObj(header_reference) then return;
begin
rels_adapter := docx_components_module_.GetDocumentRelsAdapter(); rels_adapter := docx_components_module_.GetDocumentRelsAdapter();
rel := rels_adapter.GetRelationshipById(header_reference.Id); rel := rels_adapter.GetRelationshipById(header_reference.Id);
w := current_page_.SectPr.PgSz.W - current_page_.SectPr.PgMar.Right - current_page_.SectPr.PgMar.Left; hdr := docx_components_module_.GetHdr(rel.Target);
lb := 0;
obj := docx_components_module_.GetHdr(rel.Target);
xml_file_ := rel.Target; xml_file_ := rel.Target;
elements := obj.Elements();
for _,element in elements do w := current_page_.SectPr.PgSz.W - current_page_.SectPr.PgMar.Right - current_page_.SectPr.PgMar.Left;
hdr_range := new HdrRange(self, hdr);
hdr_range.Width := w;
hdr_range.Parent := self;
hdr_range.StartX := current_page_.SectPr.PgMar.Left;
hdr_range.StartY := current_page_.SectPr.PgSz.H - current_page_.SectPr.PgMar.Header;
hdr_range.StartPage := current_page_;
hdr_range.LowerBound := 0;
if hdr_range.Calc() then
hdr_range.Do();
else
realtime_range_array_[length(realtime_range_array_)] := hdr_range;
current_page_.HdrPoint.Y := hdr_range.EndY;
end;
function TSDocxToPdf.RangesSpacing(range: BasicRange);
begin
if last_range_ then
begin begin
x := current_page_.HdrPoint.X; if last_range_ is class(PRange) and not ifnil(last_range_.PPrUnitDecorator.OutlineLvl.Val) and (range is class(TblRange) or ifnil(range.PPrUnitDecorator.OutlineLvl.Val)) then
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 begin
current_page_.HdrPoint.Y := range.EndY; if last_range_.PPrUnitDecorator.Spacing.AfterAutospacing then
begin
line_range := last_range_.PLineRanges();
line_range := line_range[length(line_range)-1];
y := line_range.EndY - line_range.TextMaxSize;
if y >= 0 then current_page_.TextPoint.Y := y;
end
end
if range is class(PRange) and not ifnil(range.PPrUnitDecorator.OutlineLvl.Val) and (last_range_ is class(TblRange) or ifnil(last_range_.PPrUnitDecorator.OutlineLvl.Val)) then
begin
if range.PPrUnitDecorator.Spacing.BeforeAutospacing then
begin
line_range := range.PLineRanges();
line_range := line_range[length(line_range)-1];
y := last_range_.EndY - line_range.TextMaxSize;
if y >= 0 then current_page_.TextPoint.Y := y;
end
end
end
last_range_ := range;
end;
function TSDocxToPdf.TransformP(p: P);
begin
w := current_page_.SectPr.PgSz.W - current_page_.SectPr.PgMar.Right - current_page_.SectPr.PgMar.Left;
range := new PRange(self, p);
range.Width := w;
range.Parent := self;
fg := range.Calc();
{self.}RangesSpacing(range);
range.StartX := current_page_.TextPoint.X;
range.StartY := current_page_.TextPoint.Y;
range.StartPage := current_page_;
range.LowerBound := current_page_.LowerBound;
range.Run();
if fg then
range.Do(); range.Do();
current_page_.TextPoint.Y := min(current_page_.TextPoint.Y, range.EndY); else
end realtime_range_array_[length(realtime_range_array_)] := range;
end current_page_.TextPoint.Y := range.EndY;
end
end; end;
function TSDocxToPdf.TransformP(paragraph: P; x: real; y: real; w: real; lb: real): ParagraphRange; function TSDocxToPdf.TransformTbl(tbl: Tbl);
begin begin
range := new ParagraphRange(self, current_page_, docx_components_module_, paragraph); w := current_page_.SectPr.PgSz.W - current_page_.SectPr.PgMar.Right - current_page_.SectPr.PgMar.Left;
range.StartX := x; range := new TblRange(self, tbl);
range.StartY := y;
range.Width := w; range.Width := w;
range.LowerBound := lb;
range.Parent := self; range.Parent := self;
r := range.Calc(); fg := range.Calc();
if r then return range; {self.}RangesSpacing(range);
else range_page_number_array_[length(range_page_number_array_)] := range; range.StartX := current_page_.TextPoint.X;
return nil; range.StartY := current_page_.TextPoint.Y;
range.StartPage := current_page_;
range.LowerBound := current_page_.LowerBound;
range.Run();
range.Do();
current_page_.TextPoint.Y := range.EndY;
end; end;
function TSDocxToPdf.TransformTbl(table: Tbl; x: real; y: real; w: real; lb: real): TableRange; function TSDocxToPdf.TransformSdt(sdt: Sdt);
begin
range := new TableRange(self, current_page_, docx_components_module_, table);
range.StartX := x;
range.StartY := y;
range.Width := w;
range.LowerBound := lb;
range.Parent := self;
range.Calc();
return range;
end;
function TSDocxToPdf.TransformSdt(sdt: Sdt; x: real; y: real; w: real; lb: real): array of ParagraphRange;
begin begin
ps := sdt.SdtContent.Ps(); ps := sdt.SdtContent.Ps();
arr := array();
for _,p in ps do for _,p in ps do
begin range := {self.}TransformP(p);
range := {self.}TransformP(p, x, y, w, lb);
if ifObj(range) then arr[length(arr)] := range;
end
return arr;
end; end;
function TSDocxToPdf.ProcessNumpages(); function TSDocxToPdf.ProcessRealtimeRange();
begin begin
nums := page_manager_module_[page_manager_module_.Count() - 1].Number; for _,range in realtime_range_array_ do
for _,range in range_page_number_array_ do
begin begin
range.SetNumPages(nums); range.ProcessRealtimeArray();
range.RangesToLines();
range.Offset(0, current_page_.SectPr.PgSz.H - current_page_.SectPr.PgMar.Bottom);
range.Do(); range.Do();
end end
end; end;
@ -398,14 +411,9 @@ begin
return docx_components_module_.SaveAs(alias, file); return docx_components_module_.SaveAs(alias, file);
end; end;
function TSDocxToPdf.GetCurrentNoteModule(): NoteModule;
begin
if ifnil(note_module_) then note_module_ := new NoteModule(current_sect_module_);
return note_module_;
end;
function TSDocxToPdf.ClassifyCols(var point: Point; cols: Cols); function TSDocxToPdf.ClassifyCols(var point: Point; cols: Cols);
begin begin
return;
bk_page := current_page_; bk_page := current_page_;
columns := array(); columns := array();
x := point.X; x := point.X;

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
unit DTPModules; unit DTPModules;
interface interface
uses TSPdfEnumerations, DocxMLAdapter, SharedMLAdapter; uses DTPAdvancedRanges, DocxMLAdapter, SharedMLAdapter;
type DocxComponentsModule = class(DocxComponents) type DocxComponentsModule = class(DocxComponents)
public public
@ -57,19 +57,21 @@ end;
type NoteModule = class type NoteModule = class
public public
function Create(sect_module: SectModule); function Create(docx_to_pdf: TSDocxToPdf);
function AddFootnoteId(id: string);
function GetFootnoteOrderNumber(): string; function GetFootnoteOrderNumber(): string;
function GetFootnoteIndex(): string; function GetFootnoteIndex(): string;
function AddFootnote();
private private
function CalculateNumber(num_fmt: string; num: integer): string; function CalculateNumber(num_fmt: string; num: integer): string;
function ChineseCountingThousand(n: integer): string; function ChineseCountingThousand(n: integer): string;
private private
footnote_reference_hash_: hash; [weakref]docx_to_pdf_: TSDocxToPdf;
footnote_hash_: hash;
footnote_index_: integer; footnote_index_: integer;
[weakref]sect_module_: SectModule; endnote_hash_: hash;
endnote_index_: integer;
end; end;
type NumberingModule = class type NumberingModule = class
@ -89,35 +91,21 @@ end;
type SectModule = class type SectModule = class
public public
function Create(); function Create();
function Destroy();
function Do();
function AddElement(element: tslobj); function AddElement(element: tslobj);
public public
Elements: array of tslobj;
SectPr: SectPrUnitDecorator; SectPr: SectPrUnitDecorator;
end; Elements: array of tslobj;
BaseSize: real;
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; end;
type TocModule = class type TocModule = class
public public
function Create(); function Create();
function UpdateDocxNumPages(); function UpdateDocxNumPages();
function LinkToToc(anchor: string; pg: Page; left: real; top: real); function CalculateRect(anchor: string);
function LinkToToc(anchor: string; range: BasicRange);
function AddToc(anchor: string; toc: Toc); function AddToc(anchor: string; toc: Toc);
function AddDocxPage(anchor: string; r: R); function AddDocxPage(anchor: string; r: R);
@ -154,11 +142,13 @@ public
Index: integer; Index: integer;
Number: integer; Number: integer;
SectPr: SectPrUnitDecorator; SectPr: SectPrUnitDecorator;
BaseSize: real;
TextPoint: Point; // 正文坐标 TextPoint: Point; // 正文坐标
FtrPoint: Point; // 页脚坐标 FtrPoint: Point; // 页脚坐标
HdrPoint: Point; // 页眉坐标 HdrPoint: Point; // 页眉坐标
UpperBound: real; // 上界
LowerBound: real; // 下界
private private
[weakref]pdf_file_: PdfFile; [weakref]pdf_file_: PdfFile;
pdf_page_: PdfPage; pdf_page_: PdfPage;
@ -371,9 +361,12 @@ begin
if bold and italic then if bold and italic then
font_name := "Times-BoldItalic"; font_name := "Times-BoldItalic";
else if bold then else if bold then
font_name += "Times-Bold"; font_name := "Times-Bold";
else if italic then else if italic then
font_name += "Times-Italic"; font_name := "Times-Italic";
end
else begin
font_name := "Courier";
end end
return pdf_.GetFont(font_name, ""); return pdf_.GetFont(font_name, "");
end; end;
@ -394,16 +387,65 @@ begin
end; end;
// NoteModule // NoteModule
function NoteModule.Create(sect_module: SectModule); function NoteModule.Create(docx_to_pdf: TSDocxToPdf);
begin begin
sect_module_ := sect_module; docx_to_pdf_ := docx_to_pdf;
footnote_reference_hash_ := array(); footnote_hash_ := array();
endnote_hash_ := array();
footnote_index_ := 0; footnote_index_ := 0;
endnote_index_ := 0;
end; end;
function NoteModule.AddFootnoteId(id: string);
begin
footnotes_adapter := docx_to_pdf_.DocxComponents.GetFootnotesAdapter();
footnote := footnotes_adapter.GetFootnoteById(id);
sect_pr := docx_to_pdf_.CurrentSect.SectPr;
w := sect_pr.SectPr.PgSz.W - sect_pr.SectPr.PgMar.Right - sect_pr.SectPr.PgMar.Left;
lb := 0;
arr := array();
elements := footnote.Elements();
for _,element in elements do
begin
if element.LocalName = "p" then
begin
range := new PRange(docx_to_pdf_, element);
range.Width := w;
range.LowerBound := lb;
range.Parent := self;
range.Calc();
arr[length(arr)] := range;
end
end
footnote_hash_[id] := arr;
end;
// function NoteModule.RunFootnote(id: string; x: real; y: real; pg: Page);
// begin
// sx := x;
// sy := y;
// spg := pg;
// height := 0;
// arr := array();
// hash := footnote_hash_[id];
// for id,range in hash do
// begin
// range.StartX := x;
// range.StartY := y;
// range.StartPage := spg;
// range.LowerBound := 0;
// range.Run();
// sy := range.EndY;
// height += range.DynamicHeight;
// arr union= range.PLineRanges();
// footnote_hash_[id] := arr;
// end
// return height;
// end;
function NoteModule.GetFootnoteOrderNumber(); function NoteModule.GetFootnoteOrderNumber();
begin begin
num_fmt := sect_module_.SectPr.FootnotePr.NumFmt.Val; num_fmt := docx_to_pdf_.CurrentSect.SectPr.FootnotePr.NumFmt.Val;
if ifnil(num_fmt) then num_fmt := "decimal"; if ifnil(num_fmt) then num_fmt := "decimal";
return CalculateNumber(num_fmt, ++footnote_index_); return CalculateNumber(num_fmt, ++footnote_index_);
end; end;
@ -640,16 +682,24 @@ begin
update_docx_num_pages_ := true; update_docx_num_pages_ := true;
end; end;
function TocModule.LinkToToc(anchor: string; pg: Page; left: real; top: real); function TocModule.CalculateRect(anchor: string);
begin
arr := toc_hash_[anchor];
for _,toc in arr do
toc.CalculateRect();
end;
function TocModule.LinkToToc(anchor: string; range: BasicRange);
begin begin
arr := toc_hash_[anchor]; arr := toc_hash_[anchor];
if ifnil(arr) then if ifnil(arr) then
begin begin
toc_unmatched_hash_[anchor] := array(pg, left, top); toc_unmatched_hash_[anchor] := range;
return; return;
end end
pg := range.EndPage;
dst := pg.PdfPage.CreateDestination(); dst := pg.PdfPage.CreateDestination();
dst.SetXYZ(left, top, 1); dst.SetXYZ(range.EndX, range.EndY + range.RPr.Sz.Val, 1);
for _,toc in arr do for _,toc in arr do
toc.LinkAnnot(dst); toc.LinkAnnot(dst);
toc.AddPageNumber(pg); toc.AddPageNumber(pg);
@ -679,41 +729,4 @@ begin
docx_page_hash_[anchor] := r; docx_page_hash_[anchor] := r;
end; 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. end.

View File

@ -11,13 +11,14 @@ public
RPr: RPr; RPr: RPr;
Text: string; Text: string;
Font: PdfFont; Font: PdfFont;
Type: integer; // 0默认1: 数字2英文3中文4中文标点 Type: integer; // 0默认1: 数字2英文3中文4中文标点5,.英文逗号和点
end; end;
type BordersRange = class(BasicRange) type BordersRange = class(BasicRange)
public public
function Create(); function Create();
function Do();override; function Do();override;
function DoFill();
public public
TcPr: TcPr; TcPr: TcPr;
Left: boolean; Left: boolean;
@ -65,7 +66,8 @@ public
DynamicHeight: real; DynamicHeight: real;
LowerBound: real; LowerBound: real;
[weakref]Parent: tslobj; [weakref]Parent: tslobj;
[weakref]Page: Page; [weakref]StartPage: Page; // 起始page
[weakref]EndPage: Page; // 结束page
end; end;
implementation implementation
@ -81,7 +83,7 @@ begin
{self.}DynamicHeight := 0; {self.}DynamicHeight := 0;
{self.}LowerBound := 0; {self.}LowerBound := 0;
{self.}FixedHeight := 0; {self.}FixedHeight := 0;
{self.}Page := nil; {self.}EndPage := nil;
end; end;
// ImageRange // ImageRange
@ -96,18 +98,18 @@ function ImageRange.Do();override;
begin begin
// println("image = {}, type = {}, x = {}, y = {}, w = {}, h = {}", {self.}image, {self.}Type, {self.}endx, {self.}endy, {self.}width, {self.}DynamicHeight); // println("image = {}, type = {}, x = {}, y = {}, w = {}, h = {}", {self.}image, {self.}Type, {self.}endx, {self.}endy, {self.}width, {self.}DynamicHeight);
if {self.}Type = "emf" then if {self.}Type = "emf" then
{self.}Page.PdfPage.DrawEmf({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight); {self.}EndPage.PdfPage.DrawEmf({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
else if {self.}Type = "wmf" then else if {self.}Type = "wmf" then
{self.}Page.PdfPage.DrawWmf({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight); {self.}EndPage.PdfPage.DrawWmf({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
else else
{self.}Page.PdfPage.DrawImage({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight); {self.}EndPage.PdfPage.DrawImage({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
if sysparams["_PDF_IMAGE_DEBUG_"] then if sysparams["_PDF_IMAGE_DEBUG_"] then
begin begin
{self.}Page.PdfPage.SetLineWidth(0.1); {self.}EndPage.PdfPage.SetLineWidth(0.1);
{self.}Page.PdfPage.SetRGBStroke(0.8, 0.8, 0); {self.}EndPage.PdfPage.SetRGBStroke(0.8, 0.8, 0);
{self.}Page.PdfPage.Rectangle({self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight); {self.}EndPage.PdfPage.Rectangle({self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
{self.}Page.PdfPage.Stroke(); {self.}EndPage.PdfPage.Stroke();
end end
end; end;
@ -122,32 +124,37 @@ begin
{self.}Bottom := false; {self.}Bottom := false;
end; end;
function BordersRange.Do();override; function BordersRange.DoFill();
begin begin
// println("Left = {}, Top = {}, Right = {}, Bottom = {}, Tl2Br = {}, Tr2Bl = {}", Left, Top, Right, Bottom, Tl2Br, Tr2Bl);
borders := {self.}TcPr.TcBorders; borders := {self.}TcPr.TcBorders;
if {self.}TcPr.Shd.Fill and {self.}TcPr.Shd.Fill <> "auto" then if {self.}TcPr.Shd.Fill and {self.}TcPr.Shd.Fill <> "auto" then
begin begin
[r, g, b] := DTPColorToolKit.HexToRGB({self.}TcPr.Shd.Fill); [r, g, b] := DTPColorToolKit.HexToRGB({self.}TcPr.Shd.Fill);
{self.}Page.PdfPage.SetRGBFill(r/255, g/255, b/255); {self.}EndPage.PdfPage.SetRGBFill(r/255, g/255, b/255);
x := {self.}EndX; x := {self.}EndX;
y := {self.}EndY - {self.}DynamicHeight; y := {self.}EndY - {self.}DynamicHeight;
w := {self.}Width; w := {self.}Width;
h := {self.}DynamicHeight; h := {self.}DynamicHeight;
tmp := borders.Left.Sz ? borders.Left.Sz / 2 : 0.25; // tmp := borders.Left.Sz ? borders.Left.Sz / 2 : 0.25;
x += tmp; // x += tmp;
w -= tmp; // w -= tmp;
w -= borders.Right.Sz ? borders.Right.Sz / 2 : 0.25; // w -= borders.Right.Sz ? borders.Right.Sz / 2 : 0.25;
tmp := borders.Bottom.Sz ? borders.Bottom.Sz / 2 : 0.25; // tmp := borders.Bottom.Sz ? borders.Bottom.Sz / 2 : 0.25;
y += tmp; // y += tmp;
h -= tmp; // h -= tmp;
h -= borders.Top.Sz ? borders.Top.Sz / 2 : 0.25; // h -= borders.Top.Sz ? borders.Top.Sz / 2 : 0.25;
{self.}Page.PdfPage.Rectangle(x, y, w, h); {self.}EndPage.PdfPage.Rectangle(x, y, w, h);
{self.}Page.PdfPage.Fill(); {self.}EndPage.PdfPage.Fill();
{self.}Page.PdfPage.SetRGBFill(0, 0, 0); {self.}EndPage.PdfPage.SetRGBFill(0, 0, 0);
{self.}Left := true; // {self.}Left := true;
end end
end;
function BordersRange.Do();override;
begin
// println("Left = {}, Top = {}, Right = {}, Bottom = {}, Tl2Br = {}, Tr2Bl = {}", Left, Top, Right, Bottom, Tl2Br, Tr2Bl);
borders := {self.}TcPr.TcBorders;
if {self.}Left then if {self.}Left then
{self.}DrawLine(borders.Left, {self.}EndX, {self.}EndY, {self.}EndX, {self.}EndY - {self.}DynamicHeight); {self.}DrawLine(borders.Left, {self.}EndX, {self.}EndY, {self.}EndX, {self.}EndY - {self.}DynamicHeight);
if {self.}Top then if {self.}Top then
@ -165,9 +172,9 @@ end;
function BordersRange.SetDash(val: string); function BordersRange.SetDash(val: string);
begin begin
if val = "single" or ifnil(val) then if val = "single" or ifnil(val) then
{self.}Page.PdfPage.SetDash(array(), 0, 0); {self.}EndPage.PdfPage.SetDash(array(), 0, 0);
if val = "dashed" then else if val = "dashed" then
{self.}Page.PdfPage.SetDash(array(1), 1, 0); {self.}EndPage.PdfPage.SetDash(array(1), 1, 0);
end; end;
function BordersRange.DrawLine(border: Border; x1: real; y1: real; x2: real; y2: real); function BordersRange.DrawLine(border: Border; x1: real; y1: real; x2: real; y2: real);
@ -176,12 +183,12 @@ begin
line_width := border.Sz ?: 0.5; line_width := border.Sz ?: 0.5;
{self.}SetDash(border.Val); {self.}SetDash(border.Val);
if border.Color and border.Color <> "auto" then [r, g, b] := DTPColorToolKit.HexToRGB(border.Color); if border.Color and border.Color <> "auto" then [r, g, b] := DTPColorToolKit.HexToRGB(border.Color);
{self.}Page.PdfPage.SetRGBStroke(r, g, b); {self.}EndPage.PdfPage.SetRGBStroke(r/255, g/255, b/255);
{self.}Page.PdfPage.SetLineWidth(line_width); {self.}EndPage.PdfPage.SetLineWidth(line_width);
{self.}Page.PdfPage.MoveTo(x1, y1); {self.}EndPage.PdfPage.MoveTo(x1, y1);
{self.}Page.PdfPage.LineTo(x2, y2); {self.}EndPage.PdfPage.LineTo(x2, y2);
{self.}Page.PdfPage.Stroke(); {self.}EndPage.PdfPage.Stroke();
{self.}Page.PdfPage.SetRGBStroke(0, 0, 0); {self.}EndPage.PdfPage.SetRGBStroke(0, 0, 0);
end; end;
// TextRange // TextRange
@ -207,21 +214,21 @@ begin
y += sz / 3; y += sz / 3;
sz := sz * 2 / 3; sz := sz * 2 / 3;
end end
{self.}Page.PdfPage.SetRGBFill(r / 255, g / 255, b / 255); {self.}EndPage.PdfPage.SetRGBFill(r / 255, g / 255, b / 255);
{self.}Page.PdfPage.SetFontAndSize({self.}Font, sz); {self.}EndPage.PdfPage.SetFontAndSize({self.}Font, sz);
{self.}Page.PdfPage.BeginText(); {self.}EndPage.PdfPage.BeginText();
{self.}Page.PdfPage.TextOut({self.}EndX, y, {self.}Text); {self.}EndPage.PdfPage.TextOut({self.}EndX, y, {self.}Text);
{self.}Page.PdfPage.EndText(); {self.}EndPage.PdfPage.EndText();
{self.}Page.PdfPage.SetRGBFill(0, 0, 0); {self.}EndPage.PdfPage.SetRGBFill(0, 0, 0);
if sysparams["_PDF_TEXT_DEBUG_"] then if sysparams["_PDF_TEXT_DEBUG_"] then
begin begin
{self.}Page.PdfPage.SetLineWidth(0.1); {self.}EndPage.PdfPage.SetLineWidth(0.1);
{self.}Page.PdfPage.SetRGBStroke(1.0, 0.5, 0.0); {self.}EndPage.PdfPage.SetRGBStroke(1.0, 0.5, 0.0);
{self.}Page.PdfPage.MoveTo(0, {self.}EndY); {self.}EndPage.PdfPage.MoveTo(0, {self.}EndY);
{self.}Page.PdfPage.LineTo(600, {self.}EndY); {self.}EndPage.PdfPage.LineTo(600, {self.}EndY);
{self.}Page.PdfPage.Stroke(); {self.}EndPage.PdfPage.Stroke();
end end
end; end;
@ -235,11 +242,11 @@ end;
function LineRange.Do();override; function LineRange.Do();override;
begin begin
// println("endx = {}, endy = {}, width = {}", EndX, EndY, Width); // println("endx = {}, endy = {}, width = {}", EndX, EndY, Width);
{self.}Page.PdfPage.SetLineWidth({self.}LineWidth); {self.}EndPage.PdfPage.SetLineWidth({self.}LineWidth);
{self.}Page.PdfPage.SetRGBStroke(0, 0, 0); {self.}EndPage.PdfPage.SetRGBStroke(0, 0, 0);
{self.}Page.PdfPage.MoveTo({self.}EndX, {self.}EndY); {self.}EndPage.PdfPage.MoveTo({self.}EndX, {self.}EndY);
{self.}Page.PdfPage.LineTo({self.}EndX + {self.}Width, {self.}EndY); {self.}EndPage.PdfPage.LineTo({self.}EndX + {self.}Width, {self.}EndY);
{self.}Page.PdfPage.Stroke(); {self.}EndPage.PdfPage.Stroke();
end; end;
end. end.

View File

@ -27,20 +27,6 @@ private
index_: integer; index_: integer;
end; 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 type FldType = class
public public
function Create(); function Create();
@ -52,7 +38,7 @@ public
PageRef: boolean; PageRef: boolean;
end; end;
type FldStruct2 = class type FldStruct = class
public public
function Create(); function Create();
@ -60,6 +46,7 @@ public
Type: FldType; Type: FldType;
Arabic: boolean; Arabic: boolean;
MergeFormat: boolean; MergeFormat: boolean;
Status: integer; // 0: begin 1: separate 2: end
end; end;
type TrProperty = class type TrProperty = class
@ -155,19 +142,6 @@ begin
return index_ = 0; return index_ = 0;
end; end;
// FldStruct
function FldStruct.Create();
begin
FldLock := false;
MergeFormat := false;
Quote := false;
Separate := false;
PageArabicMergeFormat := false;
NumPages := false;
ArabicMergeFormat := false;
EndFld := false;
end;
// FldType // FldType
function FldType.Create(); function FldType.Create();
begin begin
@ -178,11 +152,12 @@ begin
end; end;
// FldStruct // FldStruct
function FldStruct2.Create(); function FldStruct.Create();
begin begin
{self.}Type := new FldType(); {self.}Type := new FldType();
{self.}Arabic := false; {self.}Arabic := false;
{self.}MergeFormat := false; {self.}MergeFormat := false;
{self.}Status := 0;
end; end;
// TrProperty // TrProperty