支持文本框

This commit is contained in:
csh 2024-08-26 15:03:35 +08:00
parent 70ad4acbdb
commit 4c6f4d6e09
3 changed files with 142 additions and 17 deletions

View File

@ -10,12 +10,14 @@ public
function GetCurrentTextPoint(): Point; function GetCurrentTextPoint(): Point;
function GetCachePath(image_path: string): string; function GetCachePath(image_path: string): string;
function GetNextPage(page: TSPage): TSPage; function GetNextPage(page: TSPage): TSPage;
function GetCurrentXmlFile(): string;
function AddTSPage(flag: boolean): TSPage; function AddTSPage(flag: boolean): TSPage;
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);
function SetHeaderAndFooter(); function SetHeaderAndFooter();
function ProcessNumpages(); function ProcessNumpages();
function CalculateTextCoordinates(): array of real;
property Font read ReadFont; property Font read ReadFont;
function ReadFont(); function ReadFont();
@ -29,7 +31,6 @@ private
function SetHdr(type: string); function SetHdr(type: string);
function SetFtr(type: string); function SetFtr(type: string);
function CalculateTextCoordinates();
function TransformP(var point: Point; paragraph: P; w: real; lb: real); function TransformP(var point: Point; paragraph: P; w: real; lb: real);
function TransformTbl(var point: Point; table: Tbl; 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 TransformSdt(var point: Point; sdt: Sdt; w: real; lb: real);
@ -53,6 +54,7 @@ private
hdr_point_: Point; // 页眉坐标 hdr_point_: Point; // 页眉坐标
ftr_point_: Point; // 页脚坐标 ftr_point_: Point; // 页脚坐标
even_and_odd_flag_: boolean; even_and_odd_flag_: boolean;
xml_file_: string;
end; end;
type Point = class type Point = class
@ -81,6 +83,7 @@ begin
text_point_ := new Point(); text_point_ := new Point();
hdr_point_ := new Point(); hdr_point_ := new Point();
ftr_point_ := new Point(); ftr_point_ := new Point();
xml_file_ := "document.xml";
settings := docx_components_ware_.Settings; settings := docx_components_ware_.Settings;
settings.XmlChildEvenAndOddHeaders.Deserialize(); settings.XmlChildEvenAndOddHeaders.Deserialize();
@ -106,6 +109,7 @@ 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.}AddTSPage(true); {self.}AddTSPage(true);
xml_file_ := "document.xml";
end end
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;
lb := sect_ware_.SectPr.PgMar.Bottom; lb := sect_ware_.SectPr.PgMar.Bottom;
@ -114,7 +118,7 @@ begin
begin begin
// if _ = 109 then break; // if _ = 109 then break;
// if _ = 109 then // if _ = 109 then
// println("_ = {}", _); println("_ = {}", _);
if element.LocalName = "p" then {self.}TransformP(text_point_, element, w, lb); 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 = "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);
@ -138,6 +142,11 @@ begin
return cache_path_ + extractFileName(image_path); return cache_path_ + extractFileName(image_path);
end; end;
function TSDocxToPdf.GetCurrentXmlFile(): string;
begin
return xml_file_;
end;
function TSDocxToPdf.GetPdf(): PdfFile; function TSDocxToPdf.GetPdf(): PdfFile;
begin begin
return pdf_; return pdf_;
@ -215,6 +224,7 @@ 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);
// println("W = {}, H = {}", sect_ware_.SectPr.PgSz.W, sect_ware_.SectPr.PgSz.H);
len := length(page_array_); len := length(page_array_);
current_page_ := new TSPage(); current_page_ := new TSPage();
@ -236,7 +246,9 @@ begin
{self.}SetFtr(type_name); {self.}SetFtr(type_name);
// 正文坐标 // 正文坐标
{self.}CalculateTextCoordinates(); [x, y] := {self.}CalculateTextCoordinates();
text_point_.X := x;
text_point_.Y := y;
if sysparams["_PDF_PAGE_GRID_DEBUG_"] then if sysparams["_PDF_PAGE_GRID_DEBUG_"] then
{self.}PrintGrid(page, sect_ware_); {self.}PrintGrid(page, sect_ware_);
@ -244,10 +256,11 @@ if sysparams["_PDF_PAGE_GRID_DEBUG_"] then
return current_page_; return current_page_;
end; end;
function TSDocxToPdf.CalculateTextCoordinates(); function TSDocxToPdf.CalculateTextCoordinates(): array of real;
begin begin
text_point_.X := sect_ware_.SectPr.PgMar.Left; 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); y := min(sect_ware_.SectPr.PgSz.H - max(sect_ware_.SectPr.PgMar.Top, sect_ware_.SectPr.PgMar.Header), hdr_point_.Y);
return array(x, y);
end; end;
function TSDocxToPdf.SetFtr(type: string); function TSDocxToPdf.SetFtr(type: string);
@ -262,6 +275,7 @@ begin
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;
lb := 0; lb := 0;
obj := docx_components_ware_.GetFtr(rel.Target); obj := docx_components_ware_.GetFtr(rel.Target);
xml_file_ := rel.Target;
elements := obj.Elements(); elements := obj.Elements();
for _,element in elements do for _,element in elements do
begin begin
@ -282,6 +296,7 @@ begin
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;
lb := 0; lb := 0;
obj := docx_components_ware_.GetFtr(rel.Target); obj := docx_components_ware_.GetFtr(rel.Target);
xml_file_ := rel.Target;
elements := obj.Elements(); elements := obj.Elements();
for _,element in elements do for _,element in elements do
begin begin
@ -350,7 +365,7 @@ begin
i := 0; i := 0;
while true do while true do
begin begin
y := point_.Y - i * sect_ware.SectPr.DocGrid.LinePitch; y := text_point_.Y - i * sect_ware.SectPr.DocGrid.LinePitch;
if y <= sect_ware.SectPr.PgMar.Bottom then break; if y <= sect_ware.SectPr.PgMar.Bottom then break;
page.SetLineWidth(0.05); page.SetLineWidth(0.05);
page.SetGrayStroke(0.75); page.SetGrayStroke(0.75);

View File

@ -14,6 +14,7 @@ private
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 GetImageData(id: string): PdfImage;
function GetParagraphLineSpace(size: real; line: integer): real; function GetParagraphLineSpace(size: real; line: integer): real;
function BasicRangesToLineRange(): tableArray; function BasicRangesToLineRange(): tableArray;
function CheckAndAddPage(y: real; offset: real): boolean; function CheckAndAddPage(y: real; offset: real): boolean;
@ -21,12 +22,14 @@ private
function RToTextRange(r: R; 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); function RToDrawingRange(r: R);
function RAlternateContentToRange(r: R);
function SetLinesAlignment(); function SetLinesAlignment();
function ResetCoordinates(); function ResetCoordinates();
function NewLineRange(): TSPdfLineRange; function NewLineRange(): TSPdfLineRange;
function BookMarkLinkToc(); function BookMarkLinkToc();
function HyperlinkToToc(); function HyperlinkToToc();
function HyperlinkToTextRange(hyperlink: Hyperlink; ppr: PPrUnitDecorator); function HyperlinkToTextRange(hyperlink: Hyperlink; ppr: PPrUnitDecorator);
function GetXYCordinates(): array of real;
private private
[weakref]docx_to_pdf_: TSDocxToPdf; [weakref]docx_to_pdf_: TSDocxToPdf;
@ -106,6 +109,7 @@ begin
else if element.Br.Type = "page" then else if element.Br.Type = "page" then
{self.}CheckAndAddPage({self.}LowerBound, 1); {self.}CheckAndAddPage({self.}LowerBound, 1);
else if ifObj(element.Drawing.XmlNode) then {self.}RToDrawingRange(element); else if ifObj(element.Drawing.XmlNode) then {self.}RToDrawingRange(element);
else if ifObj(element.AlternateContent.XmlNode) then {self.}RAlternateContentToRange(element);
else if not fld then {self.}RToTextRange(element, bookmark_name); else if not fld then {self.}RToTextRange(element, bookmark_name);
end end
else if element.LocalName = "hyperlink" then else if element.LocalName = "hyperlink" then
@ -420,9 +424,93 @@ end;
function TSPdfParagraphRange.RToDrawingRange(r: R); function TSPdfParagraphRange.RToDrawingRange(r: R);
begin begin
xfrm := new XfrmUnitDecorator(r.Drawing._Inline.Graphic.GraphicData.Pic.SpPr.Xfrm); if ifObj(r.Drawing._Inline.XmlNode) then
rels_adapter := docx_components_ware_.GetDocumentRelsAdapter(); begin
id := r.Drawing._Inline.Graphic.GraphicData.Pic.BlipFill.Blip.Embed; id := r.Drawing._Inline.Graphic.GraphicData.Pic.BlipFill.Blip.Embed;
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.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.XmlNode) then
begin
anchor := r.Drawing.Anchor;
id := anchor.Graphic.GraphicData.Pic.BlipFill.Blip.Embed;
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);
image_range := new TSPdfImageRange();
image_range.Image := image;
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.RAlternateContentToRange(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);
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.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); rel := rels_adapter.GetRelationshipById(id);
image_path := "word/" + rel.Target; image_path := "word/" + rel.Target;
image := docx_components_ware_.Zip().Get(image_path); image := docx_components_ware_.Zip().Get(image_path);
@ -436,14 +524,8 @@ begin
"jpg": "jpg":
image := docx_to_pdf_.GetPdf().LoadJpegImageFromFile("", image_path); image := docx_to_pdf_.GetPdf().LoadJpegImageFromFile("", image_path);
end; 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); fileDelete("", image_path);
range_array_[length(range_array_)] := image_range; return image;
end; end;
function TSPdfParagraphRange.GetImageFileType(data: binary): string; function TSPdfParagraphRange.GetImageFileType(data: binary): string;

View File

@ -8,6 +8,8 @@ public
function GetTblStylePrByType(style_id: string; type: string): TblStylePr; function GetTblStylePrByType(style_id: string; type: string): TblStylePr;
function GetFtr(target: string): Ftr; function GetFtr(target: string): Ftr;
function GetHdr(target: string): Hdr; function GetHdr(target: string): Hdr;
function GetFtrRelsAdapter(target: string): RelationShipsAdapter;
function GetHdrRelsAdapter(target: string): RelationShipsAdapter;
private private
styles_deserialize_flag_; styles_deserialize_flag_;
@ -17,6 +19,8 @@ private
tbl_style_pr_hash_; tbl_style_pr_hash_;
ftr_hash_; ftr_hash_;
hdr_hash_; hdr_hash_;
hdr_rel_hash_;
ftr_rel_hash_;
end; end;
function TSDocxComponentsWare.Create(); function TSDocxComponentsWare.Create();
@ -25,6 +29,8 @@ begin
tbl_style_pr_hash_ := array(); tbl_style_pr_hash_ := array();
ftr_hash_ := array(); ftr_hash_ := array();
hdr_hash_ := array(); hdr_hash_ := array();
hdr_rel_hash_ := array();
ftr_rel_hash_ := array();
end; end;
function TSDocxComponentsWare.GetStyles(): Styles; function TSDocxComponentsWare.GetStyles(): Styles;
@ -89,3 +95,25 @@ begin
hdr_hash_[target] := obj; hdr_hash_[target] := obj;
return obj; return obj;
end; 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, "header", ""), ".xml", "");
obj := {self.}FooterRels(strtoint(index));
obj.Deserialize();
rels_adapter := new RelationShipsAdapter(obj);
ftr_rel_hash_[target] := rels_adapter;
return rels_adapter;
end;