整合页眉页脚代码

This commit is contained in:
csh 2024-08-21 15:41:08 +08:00
parent 4357cfb529
commit 70ad4acbdb
7 changed files with 268 additions and 593 deletions

View File

@ -5,12 +5,12 @@ public
function SaveToFile(alias: string; file: string): integer; function SaveToFile(alias: string; file: string): integer;
function Transform(); function Transform();
function GetCurrentPoint(): Point;
function GetCachePath(image_path: string): string;
function GetPdf(): PdfFile; function GetPdf(): PdfFile;
function GetCurrentSectWare(): TSSectWare;
function GetCurrentTextPoint(): Point;
function GetCachePath(image_path: string): string;
function GetNextPage(page: TSPage): TSPage; function GetNextPage(page: TSPage): TSPage;
function AddPage(): TSPage;overload; function AddTSPage(flag: boolean): TSPage;
function AddPage(sect_ware: TSSectWare): TSPage;overload;
function AdjustPageNumber(page: TSPage; num: integer); function AdjustPageNumber(page: TSPage; num: integer);
function LinkToToc(anchor: string; page: TSPage; left: real; top: real); function LinkToToc(anchor: string; page: TSPage; left: real; top: real);
function AddToc(anchor: string; toc: TSToc); function AddToc(anchor: string; toc: TSToc);
@ -27,11 +27,12 @@ private
function InitSectWare(); function InitSectWare();
function AllocateElementsToSectWare(); function AllocateElementsToSectWare();
function ResetCoordinates(sect_ware: TSSectWare); function SetHdr(type: string);
function TransformP(sect_ware: TSSectWare; paragraph: P); function SetFtr(type: string);
function TransformTbl(sect_ware: TSSectWare; table: Tbl); function CalculateTextCoordinates();
function TransformSdt(sect_ware: TSSectWare; sdt: Sdt); function TransformP(var point: Point; paragraph: P; w: real; lb: real);
function TransformHeaderAndFooter(paragraph: P; type: string); 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 function PrintGrid(page: PdfPage; sect_ware: TSSectWare); // test
@ -42,16 +43,19 @@ private
sect_ware_array_: array of TSSectWare; // 页面布局组件数组 sect_ware_array_: array of TSSectWare; // 页面布局组件数组
font_ware_: TSFontWare; // 字体部件 font_ware_: TSFontWare; // 字体部件
current_page_: TSPage; current_page_: TSPage;
point_: TSPoint; // 定位坐标点
page_array_: array of TSPage; page_array_: array of TSPage;
sect_ware_: TSSectWare; sect_ware_: TSSectWare;
sect_pr_adapter_: SectPrAdapter; sect_pr_adapter_: SectPrAdapter;
toc_array_: tableArray; toc_array_: tableArray;
toc_unmacthed_array_: tableArray; toc_unmacthed_array_: tableArray;
range_page_number_array_: tableArray; range_page_number_array_: tableArray;
text_point_: Point; // 定位坐标点
hdr_point_: Point; // 页眉坐标
ftr_point_: Point; // 页脚坐标
even_and_odd_flag_: boolean;
end; end;
type TSPoint = class type Point = class
function Create(); function Create();
begin begin
{self.}X := 0; {self.}X := 0;
@ -70,11 +74,17 @@ begin
{self.}InitSectWare(); {self.}InitSectWare();
font_ware_ := new TSFontWare(pdf_); font_ware_ := new TSFontWare(pdf_);
current_page_ := nil; current_page_ := nil;
point_ := new TSPoint();
page_array_ := array(); page_array_ := array();
toc_array_ := array(); toc_array_ := array();
toc_unmacthed_array_ := array(); toc_unmacthed_array_ := array();
range_page_number_array_ := array(); range_page_number_array_ := array();
text_point_ := new Point();
hdr_point_ := new Point();
ftr_point_ := new Point();
settings := docx_components_ware_.Settings;
settings.XmlChildEvenAndOddHeaders.Deserialize();
even_and_odd_flag_ := settings.EvenAndOddHeaders ? true : false;
end; end;
function TSDocxToPdf.Destroy(); function TSDocxToPdf.Destroy();
@ -95,25 +105,32 @@ begin
begin begin
sect_ware_ := sect_ware; sect_ware_ := sect_ware;
sect_pr_adapter_ := new SectPrAdapter(sect_ware_.SectPr.GetObject()); sect_pr_adapter_ := new SectPrAdapter(sect_ware_.SectPr.GetObject());
{self.}AddPage(sect_ware); {self.}AddTSPage(true);
end end
elements := sect_ware.Elements; w := sect_ware_.SectPr.PgSz.W - sect_ware_.SectPr.PgMar.Right - sect_ware_.SectPr.PgMar.Left;
lb := sect_ware_.SectPr.PgMar.Bottom;
elements := sect_ware.Elements();
for _,element in elements do for _,element in elements do
begin begin
// if _ = 64 then // if _ = 109 then break;
// if _ = 19 then // if _ = 109 then
// println("_ = {}", _); // println("_ = {}", _);
if element.LocalName = "p" then {self.}TransformP(sect_ware, element); if element.LocalName = "p" then {self.}TransformP(text_point_, element, w, lb);
else if element.LocalName = "tbl" then {self.}TransformTbl(sect_ware, element); else if element.LocalName = "tbl" then {self.}TransformTbl(text_point_, element, w, lb);
else if element.LocalName = "sdt" then {self.}TransformSdt(sect_ware, element); else if element.LocalName = "sdt" then {self.}TransformSdt(sect_ware, element);
end end
end end
{self.}ProcessNumpages(); {self.}ProcessNumpages();
end; end;
function TSDocxToPdf.GetCurrentPoint(): Point; function TSDocxToPdf.GetCurrentTextPoint(): Point;
begin begin
return point_; return text_point_;
end;
function TSDocxToPdf.GetCurrentSectWare(): TSSectWare;
begin
return sect_ware_;
end; end;
function TSDocxToPdf.GetCachePath(image_path: string): string; function TSDocxToPdf.GetCachePath(image_path: string): string;
@ -193,76 +210,119 @@ begin
// println("sect_ware_array_ = {}", sect_ware_array_); // println("sect_ware_array_ = {}", sect_ware_array_);
end; end;
function TSDocxToPdf.AddPage(): TSPage;overload; function TSDocxToPdf.AddTSPage(flag: boolean = false): TSPage;
begin begin
page := pdf_.AddPage(); page := pdf_.AddPage();
page.SetWidth(sect_ware_.SectPr.PgSz.W); page.SetWidth(sect_ware_.SectPr.PgSz.W);
page.SetHeight(sect_ware_.SectPr.PgSz.H); page.SetHeight(sect_ware_.SectPr.PgSz.H);
len := length(page_array_); len := length(page_array_);
start := sect_ware.SectPr.PgNumType.Start;
println("start = {}, type = {}", start, ifInt(start));
current_page_ := new TSPage(); current_page_ := new TSPage();
current_page_.Index := len; current_page_.Index := len;
current_page_.PdfPage := page; current_page_.PdfPage := page;
current_page_.Number := len = 0 ? start : page_array_[len-1].Number + 1; current_page_.Number := flag ? sect_ware_.SectPr.PgNumType.Start : page_array_[len-1].Number + 1;
page_array_[len] := current_page_; page_array_[len] := current_page_;
// 页眉页脚 // 页眉页脚
{self.}SetHeaderAndFooter();
end;
function TSDocxToPdf.SetHeaderAndFooter();
begin
type_name := "default";
if current_page_.Index = 0 then if current_page_.Index = 0 then
type_name := "first"; type_name := "first";
header_reference := sect_pr_adapter_.GetHeaderReferenceByType(type_name); else if not even_and_odd_flag_ then
type_name := "default";
else if not odd(current_page_.Index) then
type_name := "even"
else
type_name := "default";
{self.}SetHdr(type_name);
{self.}SetFtr(type_name);
// 正文坐标
{self.}CalculateTextCoordinates();
if sysparams["_PDF_PAGE_GRID_DEBUG_"] then
{self.}PrintGrid(page, sect_ware_);
return current_page_;
end;
function TSDocxToPdf.CalculateTextCoordinates();
begin
text_point_.X := sect_ware_.SectPr.PgMar.Left;
text_point_.Y := min(sect_ware_.SectPr.PgSz.H - max(sect_ware_.SectPr.PgMar.Top, sect_ware_.SectPr.PgMar.Header), hdr_point_.Y);
end;
function TSDocxToPdf.SetFtr(type: string);
begin
ftr_point_.X := sect_ware_.SectPr.PgMar.Left;
ftr_point_.Y := sect_ware_.SectPr.PgMar.Bottom;
footer_reference := sect_pr_adapter_.GetFooterReferenceByType(type_name); footer_reference := sect_pr_adapter_.GetFooterReferenceByType(type_name);
if ifObj(header_reference) then
begin
rels_adapter := docx_components_ware_.GetDocumentRelsAdapter();
rel := rels_adapter.GetRelationshipById(header_reference.Id);
target := rel.Target;
index := replaceStr(target, "header", "");
index := replaceStr(index, ".xml", "");
header := docx_components_ware_.Headers(strtoint(index));
elements := header.Elements();
for _,element in elements do
begin
if element.LocalName = "p" then {self.}TransformHeaderAndFooter(element, "header");
end
end
if ifObj(footer_reference) then if ifObj(footer_reference) then
begin begin
rels_adapter := docx_components_ware_.GetDocumentRelsAdapter(); rels_adapter := docx_components_ware_.GetDocumentRelsAdapter();
rel := rels_adapter.GetRelationshipById(footer_reference.Id); rel := rels_adapter.GetRelationshipById(footer_reference.Id);
target := rel.Target; w := sect_ware_.SectPr.PgSz.W - sect_ware_.SectPr.PgMar.Right - sect_ware_.SectPr.PgMar.Left;
index := replaceStr(target, "footer", ""); lb := 0;
index := replaceStr(index, ".xml", ""); obj := docx_components_ware_.GetFtr(rel.Target);
header := docx_components_ware_.Footers(strtoint(index)); elements := obj.Elements();
elements := header.Elements();
for _,element in elements do for _,element in elements do
begin begin
if element.LocalName = "p" then {self.}TransformHeaderAndFooter(element, "footer"); if element.LocalName = "p" then {self.}TransformP(ftr_point_, element, w, lb);
end end
end end
end; end;
function TSDocxToPdf.TransformHeaderAndFooter(paragraph: P; type: string); function TSDocxToPdf.SetHdr(type: string);
begin begin
paragraph.Deserialize(); hdr_point_.X := sect_ware_.SectPr.PgMar.Left;
hdr_point_.Y := sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Header;
header_reference := sect_pr_adapter_.GetHeaderReferenceByType(type);
if ifObj(header_reference) then
begin
rels_adapter := docx_components_ware_.GetDocumentRelsAdapter();
rel := rels_adapter.GetRelationshipById(header_reference.Id);
w := sect_ware_.SectPr.PgSz.W - sect_ware_.SectPr.PgMar.Right - sect_ware_.SectPr.PgMar.Left; w := sect_ware_.SectPr.PgSz.W - sect_ware_.SectPr.PgMar.Right - sect_ware_.SectPr.PgMar.Left;
range := new TSPdfParagraphRange2(self, current_page_, docx_components_ware_, sect_ware_, paragraph); lb := 0;
y := type = "header" ? sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Header : sect_ware_.SectPr.PgMar.Footer; obj := docx_components_ware_.GetFtr(rel.Target);
range.StartX := point_.X; elements := obj.Elements();
range.StartY := y; for _,element in elements do
begin
if element.LocalName = "p" then {self.}TransformP(hdr_point_, element, w, lb);
end
end
end;
function TSDocxToPdf.TransformP(var point: Point; paragraph: P; w: real; lb: real);
begin
range := new TSPdfParagraphRange(self, current_page_, docx_components_ware_, paragraph);
range.StartX := point.X;
range.StartY := point.Y;
range.Width := w; range.Width := w;
range.LowerBound := lb;
r := range.Calc(); r := range.Calc();
if r then range.Do(); if r then range.Do();
else range_page_number_array_[length(range_page_number_array_)] := range; else range_page_number_array_[length(range_page_number_array_)] := range;
point.Y := range.EndY;
end; end;
function TSDocxToPdf.TransformTbl(var point: Point; table: Tbl; w: real; lb: real);
begin
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.Calc();
range.Do();
point.Y := range.EndY;
end;
function TSDocxToPdf.TransformSdt(var point: Point; sdt: Sdt; w: real; lb: real);
begin
ps := sdt.SdtContent.Ps();
for _,p in ps do
{self.}TransformP(point, p, w, lb);
end;
function TSDocxToPdf.ProcessNumpages(); function TSDocxToPdf.ProcessNumpages();
begin begin
nums := page_array_[length(page_array_)-1].Number; nums := page_array_[length(page_array_)-1].Number;
@ -274,29 +334,6 @@ begin
end end
end; end;
function TSDocxToPdf.AddPage(sect_ware: TSSectWare): TSPage;overload;
begin
page := pdf_.AddPage();
page.SetWidth(sect_ware.SectPr.PgSz.W);
page.SetHeight(sect_ware.SectPr.PgSz.H);
{self.}ResetCoordinates(sect_ware);
len := length(page_array_);
start := sect_ware.SectPr.PgNumType.Start;
current_page_ := new TSPage();
current_page_.Index := len;
current_page_.PdfPage := page;
current_page_.Number := len = 0 ? start : page_array_[len-1].Number + 1;
page_array_[len] := current_page_;
{self.}SetHeaderAndFooter();
if sysparams["_PDF_PAGE_GRID_DEBUG_"] then
{self.}PrintGrid(page, sect_ware);
return current_page_;
end;
function TSDocxToPdf.AdjustPageNumber(page: TSPage; num: integer); function TSDocxToPdf.AdjustPageNumber(page: TSPage; num: integer);
begin begin
for i:=page.Index to length(page_array_)-1 do for i:=page.Index to length(page_array_)-1 do
@ -308,12 +345,6 @@ begin
return page_array_[page.Index + 1]; return page_array_[page.Index + 1];
end; end;
function TSDocxToPdf.ResetCoordinates(sect_ware: TSSectWare);
begin
point_.X := sect_ware.SectPr.PgMar.Left;
point_.Y := sect_ware.SectPr.PgSz.H - max(sect_ware.SectPr.PgMar.Top, sect_ware.SectPr.PgMar.Header);
end;
function TSDocxToPdf.PrintGrid(page: PdfPage; sect_ware: TSSectWare); function TSDocxToPdf.PrintGrid(page: PdfPage; sect_ware: TSSectWare);
begin begin
i := 0; i := 0;
@ -353,37 +384,6 @@ begin
page.Stroke(); page.Stroke();
end; end;
function TSDocxToPdf.TransformP(sect_ware: TSSectWare; paragraph: P);
begin
w := sect_ware.SectPr.PgSz.W - sect_ware.SectPr.PgMar.Right - sect_ware.SectPr.PgMar.Left;
range := new TSPdfParagraphRange(self, current_page_, docx_components_ware_, sect_ware, paragraph);
range.StartX := point_.X;
range.StartY := point_.Y;
range.Width := w;
range.Calc();
range.Do();
point_.Y := range.EndY;
end;
function TSDocxToPdf.TransformTbl(sect_ware: TSSectWare; table: Tbl);
begin
w := sect_ware.SectPr.PgSz.W - sect_ware.SectPr.PgMar.Right - sect_ware.SectPr.PgMar.Left;
range := new TSPdfTableRange(self, current_page_, docx_components_ware_, sect_ware, table);
range.StartX := point_.X;
range.StartY := point_.Y;
range.Width := w;
range.Calc();
range.Do();
point_.Y := range.EndY;
end;
function TSDocxToPdf.TransformSdt(sect_ware: TSSectWare; sdt: Sdt);
begin
ps := sdt.SdtContent.Ps();
for _,p in ps do
{self.}TransformP(sect_ware, p);
end;
function TSDocxToPdf.AddToc(anchor: string; toc: TSToc); function TSDocxToPdf.AddToc(anchor: string; toc: TSToc);
begin begin
if ifarray(toc_array_[anchor]) then toc_array_[anchor] union= array(toc); if ifarray(toc_array_[anchor]) then toc_array_[anchor] union= array(toc);

View File

@ -1,6 +1,6 @@
type TSPdfCellRange = class(TSPdfBasicRange) type TSPdfCellRange = class(TSPdfBasicRange)
public public
function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; sect_ware: TSSectWare; tc: Tc; tbl_pr: TblPr); function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; tc: Tc; tbl_pr: TblPr);
function Calc(); function Calc();
function AlignHeight(height: real; surplus: real); function AlignHeight(height: real; surplus: real);
function GetLastPage(); function GetLastPage();
@ -15,7 +15,6 @@ private
[weakref]docx_to_pdf_: TSDocxToPdf; [weakref]docx_to_pdf_: TSDocxToPdf;
[weakref]page_: TSPage; [weakref]page_: TSPage;
[weakref]docx_components_ware_: TSDocxComponentsWare; [weakref]docx_components_ware_: TSDocxComponentsWare;
[weakref]sect_ware_: TSSectWare;
[weakref]tc_: Tc; [weakref]tc_: Tc;
[weakref]tbl_pr_: TblPr; [weakref]tbl_pr_: TblPr;
region_array_: array of Region; // 单元格可能跨页,所以可能存在多个 region_array_: array of Region; // 单元格可能跨页,所以可能存在多个
@ -32,12 +31,11 @@ type Region = class
RangeArr: array of TSPdfAbstractRange; RangeArr: array of TSPdfAbstractRange;
end; end;
function TSPdfCellRange.Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; sect_ware: TSSectWare; tc: Tc; tbl_pr: TblPr); function TSPdfCellRange.Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; tc: Tc; tbl_pr: TblPr);
begin begin
docx_to_pdf_ := docx_to_pdf; docx_to_pdf_ := docx_to_pdf;
page_ := pg; page_ := pg;
docx_components_ware_ := components; docx_components_ware_ := components;
sect_ware_ := sect_ware;
tc_ := tc; tc_ := tc;
tbl_pr_ := tbl_pr; tbl_pr_ := tbl_pr;
region_array_ := array(); region_array_ := array();
@ -68,12 +66,12 @@ begin
range := nil; range := nil;
if element.LocalName = "p" then if element.LocalName = "p" then
begin begin
range := new TSPdfParagraphRange(docx_to_pdf_, page_, docx_components_ware_, sect_ware_, element); range := new TSPdfParagraphRange(docx_to_pdf_, page_, docx_components_ware_, element);
range.SetExtraStyleId(tbl_pr_.TblStyle.Val); range.SetExtraStyleId(tbl_pr_.TblStyle.Val);
end end
else if element.LocalName = "tbl" then else if element.LocalName = "tbl" then
begin begin
range := new TSPdfTableRange(docx_to_pdf_, page_, docx_components_ware_, sect_ware_, element); range := new TSPdfTableRange(docx_to_pdf_, page_, docx_components_ware_, element);
end end
if ifObj(range) then if ifObj(range) then
begin begin
@ -81,6 +79,7 @@ begin
range.StartY := cell_y; range.StartY := cell_y;
range.Width := cell_w; range.Width := cell_w;
range.FixedHeight := cell_h; range.FixedHeight := cell_h;
range.LowerBound := {self.}LowerBound;
range.Calc(); range.Calc();
region.RangeArr[length(region.RangeArr)] := range; region.RangeArr[length(region.RangeArr)] := range;
{self.}DynamicHeight += range.DynamicHeight; {self.}DynamicHeight += range.DynamicHeight;
@ -111,10 +110,11 @@ begin
{self.}EndY := {self.}StartY - region.RectangleRange.DynamicHeight; {self.}EndY := {self.}StartY - region.RectangleRange.DynamicHeight;
return; return;
end end
region.RectangleRange.DynamicHeight := {self.}StartY - sect_ware_.SectPr.PgMar.Bottom; region.RectangleRange.DynamicHeight := {self.}StartY - {self.}LowerBound;
arr := region.RangeArr; arr := region.RangeArr;
region.RangeArr := array(); region.RangeArr := array();
span := sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Top - sect_ware_.SectPr.PgMar.Bottom; sect_ware := docx_to_pdf_.GetCurrentSectWare();
span := sect_ware.SectPr.PgSz.H - sect_ware.SectPr.PgMar.Top - sect_ware.SectPr.PgMar.Bottom;
hash := array(region.RectangleRange.TSPage.Index: region); hash := array(region.RectangleRange.TSPage.Index: region);
while surplus > span do while surplus > span do
begin begin
@ -135,7 +135,7 @@ begin
page_ := docx_to_pdf_.GetNextPage(page_); page_ := docx_to_pdf_.GetNextPage(page_);
region := new Region(); region := new Region();
region.RectangleRange.EndX := {self.}StartX; region.RectangleRange.EndX := {self.}StartX;
region.RectangleRange.EndY := sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Top; region.RectangleRange.EndY := sect_ware.SectPr.PgSz.H - sect_ware.SectPr.PgMar.Top;
region.RectangleRange.Width := {self.}Width; region.RectangleRange.Width := {self.}Width;
region.RectangleRange.DynamicHeight := surplus; region.RectangleRange.DynamicHeight := surplus;
region.RectangleRange.TSPage := page_; region.RectangleRange.TSPage := page_;

View File

@ -1,35 +1,36 @@
type TSPdfParagraphRange = class(TSPdfBasicRange) type TSPdfParagraphRange = class(TSPdfBasicRange)
public public
function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; sect_ware: TSSectWare; paragraph: P); function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; paragraph: P);
function Calc(); function Calc();
function Do();override; function Do();override;
function SetExtraStyleId(style_id: string); function SetExtraStyleId(style_id: string);
function SetNumPages(num: integer);
function RangesToLines();
private private
function SetPPr(var ppr: PPr); function SetPPr(var ppr: PPr);
function SetPPrByStyleId(var ppr: PPr; style_id: string); function SetPPrByStyleId(var ppr: PPr; style_id: string);
function SetRPr(var rpr; ppr: PPr); function SetRPr(var rpr; ppr: PPrUnitDecorator);
function SetRPrByStyleId(var rpr: RPr; style_id: string); function SetRPrByStyleId(var rpr: RPr; style_id: string);
function SetLvlText(); function SetLvlText();
function GetImageFileType(data: binary): string; function GetImageFileType(data: binary): string;
function GetParagraphLineSpace(size: real; line: integer): real; function GetParagraphLineSpace(size: real; line: integer): real;
function RangesToLines(ppr: PPrUnitDecorator): tableArray; function BasicRangesToLineRange(): tableArray;
function CheckAndAddPage(y: real; offset: real): boolean; function CheckAndAddPage(y: real; offset: real): boolean;
function GetUtf8CharLength(byte: string): integer; function GetUtf8CharLength(byte: string): integer;
function RToTextRange(r: R; ppr: PPrUnitDecorator; link: string); function RToTextRange(r: R; link: string);
function SplitTextToTextRange(text: string; rpr: RPrUnitDecorator; link: string); function SplitTextToTextRange(text: string; rpr: RPrUnitDecorator; link: string);
function RToDrawingRange(r: R; ppr: PPrUnitDecorator); function RToDrawingRange(r: R);
function SetLinesAlignment(ppr: PPrUnitDecorator); function SetLinesAlignment();
function ResetCoordinates(ppr: PPrUnitDecorator); function ResetCoordinates();
function NewLineRange(): TSPdfLineRange; function NewLineRange(): TSPdfLineRange;
function BookMarkLinkToc(); function BookMarkLinkToc();
function HyperlinkToToc(ppr: PPrUnitDecorator); function HyperlinkToToc();
function HyperlinkToTextRange(hyperlink: Hyperlink; ppr: PPrUnitDecorator); function HyperlinkToTextRange(hyperlink: Hyperlink; ppr: PPrUnitDecorator);
private private
[weakref]docx_to_pdf_: TSDocxToPdf; [weakref]docx_to_pdf_: TSDocxToPdf;
[weakref]docx_components_ware_: TSDocxComponentsWare; [weakref]docx_components_ware_: TSDocxComponentsWare;
[weakref]sect_ware_: TSSectWare;
[weakref]paragraph_: P; [weakref]paragraph_: P;
[weakref]page_: TSPage; [weakref]page_: TSPage;
extra_style_id_: string; extra_style_id_: string;
@ -37,14 +38,15 @@ private
line_range_array_: array of TSPdfLineRange; line_range_array_: array of TSPdfLineRange;
hyperlink_array_: tableArray; hyperlink_array_: tableArray;
bookmark_array_: tableArray; bookmark_array_: tableArray;
ppr_unit_decorator_: PPrUnitDecorator;
placeholder_array_: tableArray;
end; end;
function TSPdfParagraphRange.Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; sect_ware: TSSectWare; paragraph: P); function TSPdfParagraphRange.Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; paragraph: P);
begin begin
docx_to_pdf_ := docx_to_pdf; docx_to_pdf_ := docx_to_pdf;
page_ := pg; page_ := pg;
docx_components_ware_ := components; docx_components_ware_ := components;
sect_ware_ := sect_ware;
paragraph_ := paragraph; paragraph_ := paragraph;
extra_style_id_ := ""; extra_style_id_ := "";
range_array_ := array(); range_array_ := array();
@ -59,14 +61,14 @@ begin
// ppr.rpr是无效的应该以ppr.pStyle为准 // ppr.rpr是无效的应该以ppr.pStyle为准
{self.}SetPPr(paragraph_.PPr); {self.}SetPPr(paragraph_.PPr);
{self.}SetLvlText(); {self.}SetLvlText();
ppr := new PPrUnitDecorator(paragraph_.PPr); ppr_unit_decorator_ := new PPrUnitDecorator(paragraph_.PPr);
if not ppr.RPr.Sz.Val then ppr.RPr.Sz.Val := docx_to_pdf_.Font.GetDefaultSz(); if not ppr_unit_decorator_.RPr.Sz.Val then ppr_unit_decorator_.RPr.Sz.Val := docx_to_pdf_.Font.GetDefaultSz();
{self.}ResetCoordinates(ppr); {self.}ResetCoordinates();
{self.}EndX := {self.}StartX; {self.}EndX := {self.}StartX;
{self.}EndY := {self.}StartY; {self.}EndY := {self.}StartY;
{self.}CheckAndAddPage({self.}EndY, ppr.Spacing.Before); {self.}CheckAndAddPage({self.}EndY, ppr_unit_decorator_.Spacing.Before);
{self.}EndY -= ppr.Spacing.Before; {self.}EndY -= ppr_unit_decorator_.Spacing.Before;
{self.}DynamicHeight += ppr.Spacing.Before; {self.}DynamicHeight += ppr_unit_decorator_.Spacing.Before;
elements := paragraph_.Elements(); elements := paragraph_.Elements();
empty_flag := true; empty_flag := true;
@ -79,16 +81,37 @@ begin
if element.LocalName = "r" then if element.LocalName = "r" then
begin begin
empty_flag := false; empty_flag := false;
{self.}SetRPr(element.RPr, ppr); {self.}SetRPr(element.RPr, ppr_unit_decorator_);
if element.Br.Type = "page" then if element.FldChar.FldCharType = "separate" then
{self.}CheckAndAddPage(sect_ware_.SectPr.PgMar.Bottom, 1); fld := true;
else if ifObj(element.Drawing.XmlNode) then {self.}RToDrawingRange(element, ppr); else if element.FldChar.FldCharType = "end" then
else {self.}RToTextRange(element, ppr, bookmark_name); fld := false;
else if element.InstrText.Text = "PAGE \\* Arabic \\* MERGEFORMAT" then
page_number := true;
else if element.InstrText.Text = " NUMPAGES " then
numpages := true;
else if fld and page_number then
begin
element.T.Text := tostring(page_.Number);
{self.}RToTextRange(element, nil);
page_number := false;
end
else if fld and numpages then
begin
rpr := new RPrUnitDecorator(element.RPr);
numpages_index := length(range_array_);
placeholder_array_ := array(numpages_index, rpr);
numpages := false;
end
else if element.Br.Type = "page" then
{self.}CheckAndAddPage({self.}LowerBound, 1);
else if ifObj(element.Drawing.XmlNode) then {self.}RToDrawingRange(element);
else if not fld then {self.}RToTextRange(element, bookmark_name);
end end
else if element.LocalName = "hyperlink" then else if element.LocalName = "hyperlink" then
begin begin
empty_flag := false; empty_flag := false;
{self.}HyperlinkToTextRange(element, ppr); {self.}HyperlinkToTextRange(element, ppr_unit_decorator_);
end end
else if element.LocalName = "bookmarkStart" then else if element.LocalName = "bookmarkStart" then
begin begin
@ -104,26 +127,43 @@ begin
end end
if empty_flag then if empty_flag then
begin begin
line_space := {self.}GetParagraphLineSpace(ppr.RPr.Sz.Val, ppr.Spacing.Line); line_space := {self.}GetParagraphLineSpace(ppr_unit_decorator_.RPr.Sz.Val, ppr_unit_decorator_.Spacing.Line);
{self.}DynamicHeight += line_space; {self.}DynamicHeight += line_space;
{self.}EndY -= {self.}DynamicHeight; {self.}EndY -= {self.}DynamicHeight;
end end
{self.}RangesToLines(ppr); if placeholder_array_ then return false;
if hyperlink_array_ then {self.}HyperlinkToToc(ppr); {self.}RangesToLines();
if hyperlink_array_ then {self.}HyperlinkToToc();
if bookmark_array_ then {self.}BookMarkLinkToc(); if bookmark_array_ then {self.}BookMarkLinkToc();
{self.}DynamicHeight += ppr.Spacing.After;
{self.}EndY -= ppr.Spacing.After;
return true; return true;
end; 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(); function TSPdfParagraphRange.BookMarkLinkToc();
begin begin
for name,arr in bookmark_array_ do 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); if arr[0] then docx_to_pdf_.LinkToToc(name, arr[0].TSPage, arr[0].EndX, arr[0].EndY + arr[0].RPr.Sz.Val);
end; end;
function TSPdfParagraphRange.HyperlinkToToc(ppr: PPrUnitDecorator); function TSPdfParagraphRange.HyperlinkToToc();
begin begin
ppr := ppr_unit_decorator_;
max_size := 0; max_size := 0;
for anchor,arr in hyperlink_array_ do // 整理hyperlink发送到docx_to_pdf_ for anchor,arr in hyperlink_array_ do // 整理hyperlink发送到docx_to_pdf_
begin begin
@ -136,7 +176,7 @@ begin
y := arr[0].EndY; y := arr[0].EndY;
if top - {self.}GetParagraphLineSpace(arr[0].RPr.Sz.Val, ppr.Spacing.Line) then if top - {self.}GetParagraphLineSpace(arr[0].RPr.Sz.Val, ppr.Spacing.Line) then
begin begin
top := docx_to_pdf_.GetCurrentPoint().Y; top := docx_to_pdf_.GetCurrentTextPoint().Y;
bottom := top; bottom := top;
end end
for _,range in arr do for _,range in arr do
@ -168,7 +208,7 @@ begin
if x + num_width - {self.}StartX > {self.}Width + 1e-6 then // 换行 if x + num_width - {self.}StartX > {self.}Width + 1e-6 then // 换行
begin begin
offset := (line_space - max_size) / 2 + max_size - max_size / 5; offset := (line_space - max_size) / 2 + max_size - max_size / 5;
diff := {self.}EndY - sect_ware_.SectPr.PgMar.Bottom; diff := {self.}EndY - {self.}LowerBound;
if {self.}CheckAndAddPage({self.}EndY, line_space) then if {self.}CheckAndAddPage({self.}EndY, line_space) then
begin begin
{self.}DynamicHeight += diff; {self.}DynamicHeight += diff;
@ -200,8 +240,8 @@ begin
begin begin
if r.FldChar.FldCharType = "begin" then break; if r.FldChar.FldCharType = "begin" then break;
r.RPr := new RPr(); r.RPr := new RPr();
{self.}SetRPr(r.RPr, ppr); {self.}SetRPr(r.RPr, ppr_unit_decorator_);
{self.}RToTextRange(r, ppr, hyperlink.Anchor); {self.}RToTextRange(r, hyperlink.Anchor);
end end
arr := array(); arr := array();
while i < length(range_array_) do while i < length(range_array_) do
@ -232,8 +272,25 @@ begin
return line_range; return line_range;
end; end;
function TSPdfParagraphRange.RangesToLines(ppr: PPrUnitDecorator); function TSPdfParagraphRange.RangesToLines();overload;
begin 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(); line_range := {self.}NewLineRange();
i := 0; i := 0;
max_size := 0; max_size := 0;
@ -246,7 +303,7 @@ begin
max_size := range.RPr.Sz.Val; max_size := range.RPr.Sz.Val;
if range.DynamicHeight > max_y then max_y := range.DynamicHeight; if range.DynamicHeight > max_y then max_y := range.DynamicHeight;
line_space := {self.}GetParagraphLineSpace(max_size, ppr.Spacing.Line); line_space := {self.}GetParagraphLineSpace(max_size, ppr.Spacing.Line);
diff := {self.}EndY - sect_ware_.SectPr.PgMar.Bottom; diff := {self.}EndY - {self.}LowerBound;
if {self.}CheckAndAddPage({self.}EndY, max(line_space, range.DynamicHeight)) then if {self.}CheckAndAddPage({self.}EndY, max(line_space, range.DynamicHeight)) then
{self.}DynamicHeight += diff; {self.}DynamicHeight += diff;
if_newline := {self.}EndX + range.Width - {self.}StartX > {self.}Width + 1e-6; if_newline := {self.}EndX + range.Width - {self.}StartX > {self.}Width + 1e-6;
@ -288,24 +345,24 @@ begin
{self.}EndY -= max_value; {self.}EndY -= max_value;
end end
end end
{self.}SetLinesAlignment(ppr); {self.}SetLinesAlignment();
end; end;
function TSPdfParagraphRange.SetLinesAlignment(ppr: PPrUnitDecorator); function TSPdfParagraphRange.SetLinesAlignment();
begin begin
if length(line_range_array_) = 0 then return; if length(line_range_array_) = 0 then return;
idx := length(line_range_array_)-1; idx := length(line_range_array_)-1;
line_range := line_range_array_[idx]; line_range := line_range_array_[idx];
line_range.Align(ppr.Jc.Val); line_range.Align(ppr_unit_decorator_.Jc.Val);
end; end;
function TSPdfParagraphRange.CheckAndAddPage(y: real; offset: real): boolean; function TSPdfParagraphRange.CheckAndAddPage(y: real; offset: real): boolean;
begin begin
if y - offset < sect_ware_.SectPr.PgMar.Bottom then if y - offset < {self.}LowerBound then
begin begin
page_ := docx_to_pdf_.GetNextPage(page_); page_ := docx_to_pdf_.GetNextPage(page_);
if ifnil(page_) then page_ := docx_to_pdf_.AddPage(sect_ware_); if ifnil(page_) then page_ := docx_to_pdf_.AddTSPage();
point := docx_to_pdf_.GetCurrentPoint(); point := docx_to_pdf_.GetCurrentTextPoint();
{self.}EndY := point.Y; {self.}EndY := point.Y;
return true; return true;
end end
@ -324,11 +381,11 @@ begin
return 4; return 4;
end; end;
function TSPdfParagraphRange.RToTextRange(r: R; ppr: PPrUnitDecorator; link: string); function TSPdfParagraphRange.RToTextRange(r: R; link: string);
begin begin
if r.Anchor then if r.Anchor then
begin begin
{self.}HyperlinkToTextRange(r, ppr); {self.}HyperlinkToTextRange(r);
end end
else begin else begin
rpr := new RPrUnitDecorator(r.RPr); rpr := new RPrUnitDecorator(r.RPr);
@ -361,7 +418,7 @@ begin
end end
end; end;
function TSPdfParagraphRange.RToDrawingRange(r: R; ppr: PPrUnitDecorator); function TSPdfParagraphRange.RToDrawingRange(r: R);
begin begin
xfrm := new XfrmUnitDecorator(r.Drawing._Inline.Graphic.GraphicData.Pic.SpPr.Xfrm); xfrm := new XfrmUnitDecorator(r.Drawing._Inline.Graphic.GraphicData.Pic.SpPr.Xfrm);
rels_adapter := docx_components_ware_.GetDocumentRelsAdapter(); rels_adapter := docx_components_ware_.GetDocumentRelsAdapter();
@ -415,10 +472,11 @@ end;
function TSPdfParagraphRange.GetParagraphLineSpace(size: real; line: integer): real; function TSPdfParagraphRange.GetParagraphLineSpace(size: real; line: integer): real;
begin begin
sect_ware := docx_to_pdf_.GetCurrentSectWare();
if not line then line := 12; if not line then line := 12;
lines := roundto(line / 12, -1); lines := roundto(line / 12, -1);
multi := ceil(size / sect_ware_.BaseSize) * lines; multi := ceil(size / sect_ware.BaseSize) * lines;
return sect_ware_.SectPr.DocGrid.LinePitch * multi; return sect_ware.SectPr.DocGrid.LinePitch * multi;
end; end;
function TSPdfParagraphRange.SetPPr(var ppr: PPr); function TSPdfParagraphRange.SetPPr(var ppr: PPr);
@ -446,7 +504,7 @@ begin
end end
end; end;
function TSPdfParagraphRange.SetRPr(var rpr; ppr: PPr); function TSPdfParagraphRange.SetRPr(var rpr; ppr: PPrUnitDecorator);
begin begin
new_rpr := new RPr(); new_rpr := new RPr();
styles := docx_components_ware_.GetStyles(); styles := docx_components_ware_.GetStyles();
@ -480,9 +538,10 @@ begin
{self.}SplitTextToTextRange(lvl_text, rpr); {self.}SplitTextToTextRange(lvl_text, rpr);
end; end;
function TSPdfParagraphRange.ResetCoordinates(ppr: PPrUnitDecorator); function TSPdfParagraphRange.ResetCoordinates();
begin 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(); 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.}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.LeftChars ? ppr.Ind.LeftChars * sz : ppr.Ind.Left;

View File

@ -1,411 +0,0 @@
type TSPdfParagraphRange2 = class(TSPdfBasicRange)
public
function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; sect_ware: TSSectWare; paragraph: P);
function Calc();
function Do();override;
function SetExtraStyleId(style_id: string);
function RangesToLines();overload;
function SetNumPages(num: integer);
private
function SetPPr(var ppr: PPr);
function SetPPrByStyleId(var ppr: PPr; style_id: string);
function SetRPr(var rpr; ppr: PPr);
function SetRPrByStyleId(var rpr: RPr; style_id: string);
function SetLvlText();
function GetImageFileType(data: binary): string;
function GetParagraphLineSpace(size: real; line: integer): real;
function CheckAndAddPage(y: real; offset: real): boolean;
function GetUtf8CharLength(byte: string): integer;
function RToTextRange(r: R; ppr: PPrUnitDecorator; link: string);
function SplitTextToTextRange(text: string; rpr: RPrUnitDecorator; link: string);
function RToDrawingRange(r: R; ppr: PPrUnitDecorator);
function SetLinesAlignment(ppr: PPrUnitDecorator);
function ResetCoordinates(ppr: PPrUnitDecorator);
function NewLineRange(): TSPdfLineRange;
function RangesToLines(ppr: PPrUnitDecorator);overload;
private
[weakref]docx_to_pdf_: TSDocxToPdf;
[weakref]docx_components_ware_: TSDocxComponentsWare;
[weakref]sect_ware_: TSSectWare;
[weakref]paragraph_: P;
[weakref]page_: TSPage;
extra_style_id_: string;
range_array_: array of TSPdfBasicRange;
line_range_array_: array of TSPdfLineRange;
hyperlink_array_: tableArray;
bookmark_array_: tableArray;
ppr_unit_decorator_: PPrUnitDecorator;
placeholder_array_: tableArray;
end;
function TSPdfParagraphRange2.Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; sect_ware: TSSectWare; paragraph: P);
begin
docx_to_pdf_ := docx_to_pdf;
page_ := pg;
docx_components_ware_ := components;
paragraph_ := paragraph;
sect_ware_ := sect_ware;
extra_style_id_ := "";
range_array_ := array();
line_range_array_ := array();
hyperlink_array_ := array();
bookmark_array_ := array();
placeholder_array_ := array();
{self.}TSPage := page_;
end;
function TSPdfParagraphRange2.Calc(): tableArray;
begin
// ppr.rpr是无效的应该以ppr.pStyle为准
{self.}SetPPr(paragraph_.PPr);
{self.}SetLvlText();
ppr_unit_decorator_ := new PPrUnitDecorator(paragraph_.PPr);
ppr := ppr_unit_decorator_;
{self.}ResetCoordinates(ppr);
{self.}EndX := {self.}StartX;
{self.}EndY := {self.}StartY;
{self.}EndY -= ppr.Spacing.Before;
{self.}DynamicHeight += ppr.Spacing.Before;
elements := paragraph_.Elements();
for _,element in elements do
begin
if not ifObj(element.XmlNode) then continue;
if element.LocalName = "r" then
begin
{self.}SetRPr(element.RPr, ppr);
if element.FldChar.FldCharType = "separate" then
fld := true;
else if element.FldChar.FldCharType = "end" then
fld := false;
else if element.InstrText.Text = "PAGE \\* Arabic \\* MERGEFORMAT" then
page_number := true;
else if element.InstrText.Text = " NUMPAGES " then
numpages := true;
else if fld and page_number then
begin
element.T.Text := tostring(page_.Number);
{self.}RToTextRange(element, ppr, nil);
page_number := false;
end
else if fld and numpages then
begin
rpr := new RPrUnitDecorator(element.RPr);
numpages_index := length(range_array_);
placeholder_array_ := array(numpages_index, rpr);
numpages := false;
end
else if not fld then {self.}RToTextRange(element, ppr, bookmark_name);
end
end
if placeholder_array_ then return false;
{self.}RangesToLines();
return true;
end;
function TSPdfParagraphRange2.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 TSPdfParagraphRange2.Do();override;
begin
for _,line_range in line_range_array_ do
line_range.Do();
end;
function TSPdfParagraphRange2.SetExtraStyleId(style_id: string);
begin
extra_style_id_ := style_id;
end;
function TSPdfParagraphRange2.NewLineRange(): TSPdfLineRange;
begin
line_range := new TSPdfLineRange(page_);
line_range.StartX := {self.}EndX;
line_range.StartY := {self.}EndY;
line_range.Width := {self.}Width;
return line_range;
end;
function TSPdfParagraphRange2.RangesToLines();overload;
begin
{self.}RangesToLines(ppr_unit_decorator_);
{self.}DynamicHeight += ppr_unit_decorator_.Spacing.After;
{self.}EndY -= ppr_unit_decorator_.Spacing.After;
if ppr_unit_decorator_.PBdr.Bottom.Val = "single" then
begin
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 TSPdfParagraphRange2.RangesToLines(ppr: PPrUnitDecorator);overload;
begin
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);
if_newline := {self.}EndX + range.Width - {self.}StartX > {self.}Width + 1e-6;
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
sz := range.RPr.SzCs.Val ? range.RPr.SzCs.Val : range.RPr.Sz.Val ? range.RPr.Sz.Val : 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(ppr);
end;
function TSPdfParagraphRange2.SetLinesAlignment(ppr: PPrUnitDecorator);
begin
if length(line_range_array_) = 0 then return;
idx := length(line_range_array_)-1;
line_range := line_range_array_[idx];
line_range.Align(ppr.Jc.Val);
end;
function TSPdfParagraphRange2.CheckAndAddPage(y: real; offset: real): boolean;
begin
if y - offset < sect_ware_.SectPr.PgMar.Bottom then
begin
page_ := docx_to_pdf_.GetNextPage(page_);
if ifnil(page_) then page_ := docx_to_pdf_.AddPage(sect_ware_);
point := docx_to_pdf_.GetCurrentPoint();
{self.}EndY := point.Y;
return true;
end
return false;
end;
function TSPdfParagraphRange2.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 TSPdfParagraphRange2.RToTextRange(r: R; ppr: PPrUnitDecorator; link: string);
begin
if r.Anchor then
begin
{self.}HyperlinkToTextRange(r, ppr);
end
else begin
rpr := new RPrUnitDecorator(r.RPr);
text := r.T.Text;
if ifString(text) then {self.}SplitTextToTextRange(text, rpr, link);
end
end;
function TSPdfParagraphRange2.SplitTextToTextRange(text: string; rpr: RPrUnitDecorator; link: string);
begin
pos := 1;
while pos <= length(text) do
begin
num := {self.}GetUtf8CharLength(text[pos]);
word := text[pos : pos+num-1];
word := utf8ToAnsi(word);
pos += num;
font_name := rpr.RFonts.EastAsia ? rpr.RFonts.EastAsia : rpr.RFonts.Ascii;
font_obj := docx_to_pdf_.Font.GetFont(font_name, rpr.B, rpr.I);
if not rpr.Sz.Val then rpr.Sz.Val := rpr.SzCs.Val ? rpr.SzCs.Val : docx_to_pdf_.Font.GetDefaultSz();
page_.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;
end
end;
function TSPdfParagraphRange2.RToDrawingRange(r: R; ppr: PPrUnitDecorator);
begin
xfrm := new XfrmUnitDecorator(r.Drawing._Inline.Graphic.GraphicData.Pic.SpPr.Xfrm);
rels_adapter := docx_components_ware_.GetDocumentRelsAdapter();
id := r.Drawing._Inline.Graphic.GraphicData.Pic.BlipFill.Blip.Embed;
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)-1, data);
image := nil;
case {self.}GetImageFileType(data) of
"png":
image := docx_to_pdf_.GetPdf().LoadPngImageFromFile("", image_path);
"jpg":
image := docx_to_pdf_.GetPdf().LoadJpegImageFromFile("", image_path);
end;
image_range := new TSPdfImageRange();
image_range.Image := image;
image_range.StartX := xfrm.Off.X;
image_range.StartY := xfrm.Off.Y;
image_range.Width := xfrm.Ext.CX;
image_range.DynamicHeight := xfrm.Ext.CY;
fileDelete("", image_path);
range_array_[length(range_array_)] := image_range;
end;
function TSPdfParagraphRange2.GetImageFileType(data: binary): string;
begin
stream := new TMemoryStream();
size := length(data);
stream.Write(data[0:size-1], size);
def := array(
('name': 'png', 'position': 0, 'value': array(0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A)),
('name': 'jpg', 'position': 0, 'value': array(0xFF, 0xD8)),
);
for i:=0 to length(def)-1 do
begin
value := def[i]['value'];
stream.Seek(def[i]['position']);
for j:=0 to length(value)-1 do
begin
r := 0;
stream.Read(r, 1);
if r <> value[j] then break;
if j = length(value)-1 then return def[i]['name'];
end
end
return '';
end;
function TSPdfParagraphRange2.GetParagraphLineSpace(size: real; line: integer): real;
begin
if not line then line := 12;
lines := roundto(line / 12, -1);
multi := ceil(size / sect_ware_.BaseSize) * lines;
return sect_ware_.SectPr.DocGrid.LinePitch * multi;
end;
function TSPdfParagraphRange2.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, extra_style_id_);
{self.}SetPPrByStyleId(new_ppr, ppr.PStyle.Val);
new_ppr.Copy(ppr);
ppr.Copy(new_ppr);
end;
function TSPdfParagraphRange2.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 TSPdfParagraphRange2.SetRPr(var rpr; ppr: PPr);
begin
new_rpr := new RPr();
styles := docx_components_ware_.GetStyles();
new_rpr.Copy(styles.DocDefaults.RPrDefault.RPr);
{self.}SetRPrByStyleId(new_rpr, ppr.PStyle.Val);
{self.}SetRPrByStyleId(new_rpr, rpr.RStyle.Val);
new_rpr.Copy(rpr);
rpr.Copy(new_rpr);
end;
function TSPdfParagraphRange2.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 TSPdfParagraphRange2.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 TSPdfParagraphRange2.ResetCoordinates(ppr: PPrUnitDecorator);
begin
// 根据段落的间距确定新的坐标
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;

View File

@ -1,6 +1,6 @@
type TSPdfTableRange = class(TSPdfBasicRange) type TSPdfTableRange = class(TSPdfBasicRange)
public public
function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: Components; sect_ware: TSSectWare; paragraph: P); function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: Components; table: Tbl);
function Calc(); function Calc();
function Do();override; function Do();override;
@ -18,18 +18,16 @@ private
private private
[weakref]docx_to_pdf_: TSDocxToPdf; [weakref]docx_to_pdf_: TSDocxToPdf;
[weakref]docx_components_ware_: Components; [weakref]docx_components_ware_: Components;
[weakref]sect_ware_: TSSectWare;
[weakref]table_: Tbl; [weakref]table_: Tbl;
[weakref]page_: TSPage; [weakref]page_: TSPage;
range_array_: tableArray; range_array_: tableArray;
end; end;
function TSPdfTableRange.Create(docx_to_pdf: TSDocxToPdf; pg: PdfPage; components: Components; sect_ware: TSSectWare; table: Tbl); function TSPdfTableRange.Create(docx_to_pdf: TSDocxToPdf; pg: PdfPage; components: Components; table: Tbl);
begin begin
docx_to_pdf_ := docx_to_pdf; docx_to_pdf_ := docx_to_pdf;
page_ := pg; page_ := pg;
docx_components_ware_ := Components; docx_components_ware_ := Components;
sect_ware_ := sect_ware;
table_ := table; table_ := table;
range_array_ := array(); range_array_ := array();
{self.}TSPage := page_; {self.}TSPage := page_;
@ -73,11 +71,12 @@ begin
for j,tc in tcs do for j,tc in tcs do
begin begin
if i = 0 then {self.}SetTblStylePr(tc.TcPr, "firstRow"); if i = 0 then {self.}SetTblStylePr(tc.TcPr, "firstRow");
cell_range := new TSPdfCellRange(docx_to_pdf_, page_, docx_components_ware_, sect_ware_, tc, table_.TblPr); cell_range := new TSPdfCellRange(docx_to_pdf_, page_, docx_components_ware_, tc, table_.TblPr);
cell_range.StartX := tc_x; cell_range.StartX := tc_x;
cell_range.StartY := tc_y; cell_range.StartY := tc_y;
cell_range.FixedHeight := tc_h; cell_range.FixedHeight := tc_h;
cell_range.Width := grid_cols[pos].W; cell_range.Width := grid_cols[pos].W;
cell_range.LowerBound := {self.}LowerBound;
range_array_[i][pos] := cell_range; range_array_[i][pos] := cell_range;
grid_span := new GridSpanUnitDecorator(tc.TcPr.GridSpan); grid_span := new GridSpanUnitDecorator(tc.TcPr.GridSpan);
pos++; pos++;
@ -88,7 +87,7 @@ begin
if cell_range.DynamicHeight > max_height then max_height := cell_range.DynamicHeight; if cell_range.DynamicHeight > max_height then max_height := cell_range.DynamicHeight;
end end
if tc_h > max_height then max_height := tc_h; if tc_h > max_height then max_height := tc_h;
surplus := max_height - ({self.}EndY - sect_ware_.SectPr.PgMar.Bottom); surplus := max_height - ({self.}EndY - {self.}LowerBound);
arr := range_array_[i]; arr := range_array_[i];
for _,range in arr do for _,range in arr do
begin begin

View File

@ -11,6 +11,7 @@ public
Width: real; Width: real;
FixedHeight: real; FixedHeight: real;
DynamicHeight: real; DynamicHeight: real;
LowerBound: real;
[weakref]TSPage: TSPage; [weakref]TSPage: TSPage;
end; end;
@ -23,5 +24,6 @@ begin
{self.}Width := 0; {self.}Width := 0;
{self.}FixedHeight := 0; {self.}FixedHeight := 0;
{self.}DynamicHeight := 0; {self.}DynamicHeight := 0;
{self.}LowerBound := 0;
{self.}TSPage := nil; {self.}TSPage := nil;
end; end;

View File

@ -6,6 +6,8 @@ public
function GetDocumentRelsAdapter(): RelationShipsAdapter; function GetDocumentRelsAdapter(): RelationShipsAdapter;
function GetNumberingWare(): TSNumberingWare; function GetNumberingWare(): TSNumberingWare;
function GetTblStylePrByType(style_id: string; type: string): TblStylePr; function GetTblStylePrByType(style_id: string; type: string): TblStylePr;
function GetFtr(target: string): Ftr;
function GetHdr(target: string): Hdr;
private private
styles_deserialize_flag_; styles_deserialize_flag_;
@ -13,12 +15,16 @@ private
document_rels_adapter_; document_rels_adapter_;
numbering_ware_; numbering_ware_;
tbl_style_pr_hash_; tbl_style_pr_hash_;
ftr_hash_;
hdr_hash_;
end; end;
function TSDocxComponentsWare.Create(); function TSDocxComponentsWare.Create();
begin begin
class(Components).Create(); class(Components).Create();
tbl_style_pr_hash_ := array(); tbl_style_pr_hash_ := array();
ftr_hash_ := array();
hdr_hash_ := array();
end; end;
function TSDocxComponentsWare.GetStyles(): Styles; function TSDocxComponentsWare.GetStyles(): Styles;
@ -63,3 +69,23 @@ begin
tbl_style_pr_hash_[style_id][type] := tbl_style_pr; tbl_style_pr_hash_[style_id][type] := tbl_style_pr;
return tbl_style_pr; return tbl_style_pr;
end; end;
function TSDocxComponentsWare.GetFtr(target: string): Ftr;
begin
if ftr_hash_[target] then return ftr_hash_[target];
index := replaceStr(replaceStr(target, "header", ""), ".xml", "");
obj := {self.}Headers(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.}Footers(strtoint(index));
obj.Deserialize();
hdr_hash_[target] := obj;
return obj;
end;