From 4c6f4d6e09dddba9133b83a0fbebabc828fecaea Mon Sep 17 00:00:00 2001 From: csh Date: Mon, 26 Aug 2024 15:03:35 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=96=87=E6=9C=AC=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TSDocxToPdf.tsf | 29 +++++-- range/Advanced/TSPdfParagraphRange.tsf | 102 ++++++++++++++++++++++--- ware/TSDocxComponentsWare.tsf | 28 +++++++ 3 files changed, 142 insertions(+), 17 deletions(-) diff --git a/TSDocxToPdf.tsf b/TSDocxToPdf.tsf index 493acf0..5509fef 100644 --- a/TSDocxToPdf.tsf +++ b/TSDocxToPdf.tsf @@ -10,12 +10,14 @@ public function GetCurrentTextPoint(): Point; function GetCachePath(image_path: string): string; function GetNextPage(page: TSPage): TSPage; + function GetCurrentXmlFile(): string; function AddTSPage(flag: boolean): TSPage; function AdjustPageNumber(page: TSPage; num: integer); function LinkToToc(anchor: string; page: TSPage; left: real; top: real); function AddToc(anchor: string; toc: TSToc); function SetHeaderAndFooter(); function ProcessNumpages(); + function CalculateTextCoordinates(): array of real; property Font read ReadFont; function ReadFont(); @@ -29,7 +31,6 @@ private function SetHdr(type: string); function SetFtr(type: string); - function CalculateTextCoordinates(); function TransformP(var point: Point; paragraph: P; w: real; lb: real); function TransformTbl(var point: Point; table: Tbl; w: real; lb: real); function TransformSdt(var point: Point; sdt: Sdt; w: real; lb: real); @@ -53,6 +54,7 @@ private hdr_point_: Point; // 页眉坐标 ftr_point_: Point; // 页脚坐标 even_and_odd_flag_: boolean; + xml_file_: string; end; type Point = class @@ -81,6 +83,7 @@ begin text_point_ := new Point(); hdr_point_ := new Point(); ftr_point_ := new Point(); + xml_file_ := "document.xml"; settings := docx_components_ware_.Settings; settings.XmlChildEvenAndOddHeaders.Deserialize(); @@ -106,6 +109,7 @@ begin sect_ware_ := sect_ware; sect_pr_adapter_ := new SectPrAdapter(sect_ware_.SectPr.GetObject()); {self.}AddTSPage(true); + xml_file_ := "document.xml"; end w := sect_ware_.SectPr.PgSz.W - sect_ware_.SectPr.PgMar.Right - sect_ware_.SectPr.PgMar.Left; lb := sect_ware_.SectPr.PgMar.Bottom; @@ -114,7 +118,7 @@ begin begin // if _ = 109 then break; // if _ = 109 then - // println("_ = {}", _); + println("_ = {}", _); if element.LocalName = "p" then {self.}TransformP(text_point_, element, w, lb); else if element.LocalName = "tbl" then {self.}TransformTbl(text_point_, element, w, lb); else if element.LocalName = "sdt" then {self.}TransformSdt(sect_ware, element); @@ -138,6 +142,11 @@ begin return cache_path_ + extractFileName(image_path); end; +function TSDocxToPdf.GetCurrentXmlFile(): string; +begin + return xml_file_; +end; + function TSDocxToPdf.GetPdf(): PdfFile; begin return pdf_; @@ -215,6 +224,7 @@ begin page := pdf_.AddPage(); page.SetWidth(sect_ware_.SectPr.PgSz.W); page.SetHeight(sect_ware_.SectPr.PgSz.H); + // println("W = {}, H = {}", sect_ware_.SectPr.PgSz.W, sect_ware_.SectPr.PgSz.H); len := length(page_array_); current_page_ := new TSPage(); @@ -236,7 +246,9 @@ begin {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 {self.}PrintGrid(page, sect_ware_); @@ -244,10 +256,11 @@ if sysparams["_PDF_PAGE_GRID_DEBUG_"] then return current_page_; end; -function TSDocxToPdf.CalculateTextCoordinates(); +function TSDocxToPdf.CalculateTextCoordinates(): array of real; 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); + x := sect_ware_.SectPr.PgMar.Left; + 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; 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; lb := 0; obj := docx_components_ware_.GetFtr(rel.Target); + xml_file_ := rel.Target; elements := obj.Elements(); for _,element in elements do begin @@ -282,6 +296,7 @@ begin w := sect_ware_.SectPr.PgSz.W - sect_ware_.SectPr.PgMar.Right - sect_ware_.SectPr.PgMar.Left; lb := 0; obj := docx_components_ware_.GetFtr(rel.Target); + xml_file_ := rel.Target; elements := obj.Elements(); for _,element in elements do begin @@ -350,7 +365,7 @@ begin i := 0; while true do 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; page.SetLineWidth(0.05); page.SetGrayStroke(0.75); diff --git a/range/Advanced/TSPdfParagraphRange.tsf b/range/Advanced/TSPdfParagraphRange.tsf index db899cb..1e52920 100644 --- a/range/Advanced/TSPdfParagraphRange.tsf +++ b/range/Advanced/TSPdfParagraphRange.tsf @@ -14,6 +14,7 @@ private function SetRPrByStyleId(var rpr: RPr; style_id: string); function SetLvlText(); function GetImageFileType(data: binary): string; + function GetImageData(id: string): PdfImage; function GetParagraphLineSpace(size: real; line: integer): real; function BasicRangesToLineRange(): tableArray; function CheckAndAddPage(y: real; offset: real): boolean; @@ -21,12 +22,14 @@ private function RToTextRange(r: R; link: string); function SplitTextToTextRange(text: string; rpr: RPrUnitDecorator; link: string); function RToDrawingRange(r: R); + function RAlternateContentToRange(r: R); function SetLinesAlignment(); function ResetCoordinates(); function NewLineRange(): TSPdfLineRange; function BookMarkLinkToc(); function HyperlinkToToc(); function HyperlinkToTextRange(hyperlink: Hyperlink; ppr: PPrUnitDecorator); + function GetXYCordinates(): array of real; private [weakref]docx_to_pdf_: TSDocxToPdf; @@ -106,6 +109,7 @@ begin else if element.Br.Type = "page" then {self.}CheckAndAddPage({self.}LowerBound, 1); 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); end else if element.LocalName = "hyperlink" then @@ -420,9 +424,93 @@ end; function TSPdfParagraphRange.RToDrawingRange(r: R); 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; + if ifObj(r.Drawing._Inline.XmlNode) then + begin + 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); image_path := "word/" + rel.Target; image := docx_components_ware_.Zip().Get(image_path); @@ -436,14 +524,8 @@ begin "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; + return image; end; function TSPdfParagraphRange.GetImageFileType(data: binary): string; diff --git a/ware/TSDocxComponentsWare.tsf b/ware/TSDocxComponentsWare.tsf index 5e9678b..0bcc437 100644 --- a/ware/TSDocxComponentsWare.tsf +++ b/ware/TSDocxComponentsWare.tsf @@ -8,6 +8,8 @@ public function GetTblStylePrByType(style_id: string; type: string): TblStylePr; function GetFtr(target: string): Ftr; function GetHdr(target: string): Hdr; + function GetFtrRelsAdapter(target: string): RelationShipsAdapter; + function GetHdrRelsAdapter(target: string): RelationShipsAdapter; private styles_deserialize_flag_; @@ -17,6 +19,8 @@ private tbl_style_pr_hash_; ftr_hash_; hdr_hash_; + hdr_rel_hash_; + ftr_rel_hash_; end; function TSDocxComponentsWare.Create(); @@ -25,6 +29,8 @@ begin tbl_style_pr_hash_ := array(); ftr_hash_ := array(); hdr_hash_ := array(); + hdr_rel_hash_ := array(); + ftr_rel_hash_ := array(); end; function TSDocxComponentsWare.GetStyles(): Styles; @@ -89,3 +95,25 @@ begin hdr_hash_[target] := obj; return obj; end; + +function TSDocxComponentsWare.GetHdrRelsAdapter(target: string): RelationShipsAdapter; +begin + if hdr_rel_hash_[target] then return hdr_rel_hash_[target]; + index := replaceStr(replaceStr(target, "header", ""), ".xml", ""); + obj := {self.}HeaderRels(strtoint(index)); + obj.Deserialize(); + rels_adapter := new RelationShipsAdapter(obj); + hdr_rel_hash_[target] := rels_adapter; + return rels_adapter; +end; + +function TSDocxComponentsWare.GetFtrRelsAdapter(target: string): RelationShipsAdapter; +begin + if ftr_rel_hash_[target] then return ftr_rel_hash_[target]; + index := replaceStr(replaceStr(target, "header", ""), ".xml", ""); + obj := {self.}FooterRels(strtoint(index)); + obj.Deserialize(); + rels_adapter := new RelationShipsAdapter(obj); + ftr_rel_hash_[target] := rels_adapter; + return rels_adapter; +end;