diff --git a/TSDocxToPdf.tsf b/TSDocxToPdf.tsf index 378bfe6..493acf0 100644 --- a/TSDocxToPdf.tsf +++ b/TSDocxToPdf.tsf @@ -5,12 +5,12 @@ public function SaveToFile(alias: string; file: string): integer; function Transform(); - function GetCurrentPoint(): Point; - function GetCachePath(image_path: string): string; function GetPdf(): PdfFile; + function GetCurrentSectWare(): TSSectWare; + function GetCurrentTextPoint(): Point; + function GetCachePath(image_path: string): string; function GetNextPage(page: TSPage): TSPage; - function AddPage(): TSPage;overload; - function AddPage(sect_ware: TSSectWare): TSPage;overload; + 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); @@ -27,11 +27,12 @@ private function InitSectWare(); function AllocateElementsToSectWare(); - function ResetCoordinates(sect_ware: TSSectWare); - function TransformP(sect_ware: TSSectWare; paragraph: P); - function TransformTbl(sect_ware: TSSectWare; table: Tbl); - function TransformSdt(sect_ware: TSSectWare; sdt: Sdt); - function TransformHeaderAndFooter(paragraph: P; type: string); + 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); function PrintGrid(page: PdfPage; sect_ware: TSSectWare); // test @@ -42,16 +43,19 @@ private sect_ware_array_: array of TSSectWare; // 页面布局组件数组 font_ware_: TSFontWare; // 字体部件 current_page_: TSPage; - point_: TSPoint; // 定位坐标点 page_array_: array of TSPage; sect_ware_: TSSectWare; sect_pr_adapter_: SectPrAdapter; toc_array_: tableArray; toc_unmacthed_array_: tableArray; range_page_number_array_: tableArray; + text_point_: Point; // 定位坐标点 + hdr_point_: Point; // 页眉坐标 + ftr_point_: Point; // 页脚坐标 + even_and_odd_flag_: boolean; end; -type TSPoint = class +type Point = class function Create(); begin {self.}X := 0; @@ -70,11 +74,17 @@ begin {self.}InitSectWare(); font_ware_ := new TSFontWare(pdf_); current_page_ := nil; - point_ := new TSPoint(); page_array_ := array(); toc_array_ := array(); toc_unmacthed_array_ := array(); range_page_number_array_ := array(); + text_point_ := new Point(); + hdr_point_ := new Point(); + ftr_point_ := new Point(); + + settings := docx_components_ware_.Settings; + settings.XmlChildEvenAndOddHeaders.Deserialize(); + even_and_odd_flag_ := settings.EvenAndOddHeaders ? true : false; end; function TSDocxToPdf.Destroy(); @@ -95,25 +105,32 @@ begin begin sect_ware_ := sect_ware; sect_pr_adapter_ := new SectPrAdapter(sect_ware_.SectPr.GetObject()); - {self.}AddPage(sect_ware); + {self.}AddTSPage(true); 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 begin - // if _ = 64 then - // if _ = 19 then - // println("_ = {}", _); - if element.LocalName = "p" then {self.}TransformP(sect_ware, element); - else if element.LocalName = "tbl" then {self.}TransformTbl(sect_ware, element); + // if _ = 109 then break; + // if _ = 109 then + // 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); end end {self.}ProcessNumpages(); end; -function TSDocxToPdf.GetCurrentPoint(): Point; +function TSDocxToPdf.GetCurrentTextPoint(): Point; begin - return point_; + return text_point_; +end; + +function TSDocxToPdf.GetCurrentSectWare(): TSSectWare; +begin + return sect_ware_; end; function TSDocxToPdf.GetCachePath(image_path: string): string; @@ -193,76 +210,119 @@ begin // println("sect_ware_array_ = {}", sect_ware_array_); end; -function TSDocxToPdf.AddPage(): TSPage;overload; +function TSDocxToPdf.AddTSPage(flag: boolean = false): TSPage; begin page := pdf_.AddPage(); page.SetWidth(sect_ware_.SectPr.PgSz.W); page.SetHeight(sect_ware_.SectPr.PgSz.H); len := length(page_array_); - start := sect_ware.SectPr.PgNumType.Start; - println("start = {}, type = {}", start, ifInt(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; + current_page_.Number := flag ? sect_ware_.SectPr.PgNumType.Start : page_array_[len-1].Number + 1; page_array_[len] := current_page_; // 页眉页脚 - {self.}SetHeaderAndFooter(); -end; - -function TSDocxToPdf.SetHeaderAndFooter(); -begin - type_name := "default"; if current_page_.Index = 0 then 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); - 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 begin rels_adapter := docx_components_ware_.GetDocumentRelsAdapter(); rel := rels_adapter.GetRelationshipById(footer_reference.Id); - target := rel.Target; - index := replaceStr(target, "footer", ""); - index := replaceStr(index, ".xml", ""); - header := docx_components_ware_.Footers(strtoint(index)); - elements := header.Elements(); + 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); + elements := obj.Elements(); for _,element in elements do 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; -function TSDocxToPdf.TransformHeaderAndFooter(paragraph: P; type: string); +function TSDocxToPdf.SetHdr(type: string); begin - paragraph.Deserialize(); - 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); - y := type = "header" ? sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Header : sect_ware_.SectPr.PgMar.Footer; - range.StartX := point_.X; - range.StartY := y; + 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; + lb := 0; + obj := docx_components_ware_.GetFtr(rel.Target); + elements := obj.Elements(); + 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.LowerBound := lb; r := range.Calc(); if r then range.Do(); else range_page_number_array_[length(range_page_number_array_)] := range; + point.Y := range.EndY; 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(); begin nums := page_array_[length(page_array_)-1].Number; @@ -274,29 +334,6 @@ begin 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); begin for i:=page.Index to length(page_array_)-1 do @@ -308,12 +345,6 @@ begin return page_array_[page.Index + 1]; 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); begin i := 0; @@ -353,37 +384,6 @@ begin page.Stroke(); 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); begin if ifarray(toc_array_[anchor]) then toc_array_[anchor] union= array(toc); diff --git a/range/Advanced/TSPdfCellRange.tsf b/range/Advanced/TSPdfCellRange.tsf index d68aec8..6865081 100644 --- a/range/Advanced/TSPdfCellRange.tsf +++ b/range/Advanced/TSPdfCellRange.tsf @@ -1,6 +1,6 @@ type TSPdfCellRange = class(TSPdfBasicRange) 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 AlignHeight(height: real; surplus: real); function GetLastPage(); @@ -15,7 +15,6 @@ private [weakref]docx_to_pdf_: TSDocxToPdf; [weakref]page_: TSPage; [weakref]docx_components_ware_: TSDocxComponentsWare; - [weakref]sect_ware_: TSSectWare; [weakref]tc_: Tc; [weakref]tbl_pr_: TblPr; region_array_: array of Region; // 单元格可能跨页,所以可能存在多个 @@ -32,12 +31,11 @@ type Region = class RangeArr: array of TSPdfAbstractRange; 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 docx_to_pdf_ := docx_to_pdf; page_ := pg; docx_components_ware_ := components; - sect_ware_ := sect_ware; tc_ := tc; tbl_pr_ := tbl_pr; region_array_ := array(); @@ -68,12 +66,12 @@ begin range := nil; if element.LocalName = "p" then 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); end else if element.LocalName = "tbl" then 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 if ifObj(range) then begin @@ -81,6 +79,7 @@ begin range.StartY := cell_y; range.Width := cell_w; range.FixedHeight := cell_h; + range.LowerBound := {self.}LowerBound; range.Calc(); region.RangeArr[length(region.RangeArr)] := range; {self.}DynamicHeight += range.DynamicHeight; @@ -111,10 +110,11 @@ begin {self.}EndY := {self.}StartY - region.RectangleRange.DynamicHeight; return; end - region.RectangleRange.DynamicHeight := {self.}StartY - sect_ware_.SectPr.PgMar.Bottom; + region.RectangleRange.DynamicHeight := {self.}StartY - {self.}LowerBound; arr := region.RangeArr; 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); while surplus > span do begin @@ -135,7 +135,7 @@ begin page_ := docx_to_pdf_.GetNextPage(page_); region := new Region(); 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.DynamicHeight := surplus; region.RectangleRange.TSPage := page_; diff --git a/range/Advanced/TSPdfParagraphRange.tsf b/range/Advanced/TSPdfParagraphRange.tsf index 4159f19..db899cb 100644 --- a/range/Advanced/TSPdfParagraphRange.tsf +++ b/range/Advanced/TSPdfParagraphRange.tsf @@ -1,35 +1,36 @@ type TSPdfParagraphRange = class(TSPdfBasicRange) 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 Do();override; function SetExtraStyleId(style_id: string); + function SetNumPages(num: integer); + function RangesToLines(); private function SetPPr(var ppr: PPr); 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 SetLvlText(); function GetImageFileType(data: binary): string; function GetParagraphLineSpace(size: real; line: integer): real; - function RangesToLines(ppr: PPrUnitDecorator): tableArray; + function BasicRangesToLineRange(): tableArray; function CheckAndAddPage(y: real; offset: real): boolean; 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 RToDrawingRange(r: R; ppr: PPrUnitDecorator); - function SetLinesAlignment(ppr: PPrUnitDecorator); - function ResetCoordinates(ppr: PPrUnitDecorator); + function RToDrawingRange(r: R); + function SetLinesAlignment(); + function ResetCoordinates(); function NewLineRange(): TSPdfLineRange; function BookMarkLinkToc(); - function HyperlinkToToc(ppr: PPrUnitDecorator); + function HyperlinkToToc(); function HyperlinkToTextRange(hyperlink: Hyperlink; ppr: PPrUnitDecorator); 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; @@ -37,14 +38,15 @@ private line_range_array_: array of TSPdfLineRange; hyperlink_array_: tableArray; bookmark_array_: tableArray; + ppr_unit_decorator_: PPrUnitDecorator; + placeholder_array_: tableArray; 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 docx_to_pdf_ := docx_to_pdf; page_ := pg; docx_components_ware_ := components; - sect_ware_ := sect_ware; paragraph_ := paragraph; extra_style_id_ := ""; range_array_ := array(); @@ -59,14 +61,14 @@ begin // ppr.rpr是无效的,应该以ppr.pStyle为准 {self.}SetPPr(paragraph_.PPr); {self.}SetLvlText(); - ppr := new PPrUnitDecorator(paragraph_.PPr); - if not ppr.RPr.Sz.Val then ppr.RPr.Sz.Val := docx_to_pdf_.Font.GetDefaultSz(); - {self.}ResetCoordinates(ppr); + ppr_unit_decorator_ := new PPrUnitDecorator(paragraph_.PPr); + if not ppr_unit_decorator_.RPr.Sz.Val then ppr_unit_decorator_.RPr.Sz.Val := docx_to_pdf_.Font.GetDefaultSz(); + {self.}ResetCoordinates(); {self.}EndX := {self.}StartX; {self.}EndY := {self.}StartY; - {self.}CheckAndAddPage({self.}EndY, ppr.Spacing.Before); - {self.}EndY -= ppr.Spacing.Before; - {self.}DynamicHeight += ppr.Spacing.Before; + {self.}CheckAndAddPage({self.}EndY, ppr_unit_decorator_.Spacing.Before); + {self.}EndY -= ppr_unit_decorator_.Spacing.Before; + {self.}DynamicHeight += ppr_unit_decorator_.Spacing.Before; elements := paragraph_.Elements(); empty_flag := true; @@ -79,16 +81,37 @@ begin if element.LocalName = "r" then begin empty_flag := false; - {self.}SetRPr(element.RPr, ppr); - if element.Br.Type = "page" then - {self.}CheckAndAddPage(sect_ware_.SectPr.PgMar.Bottom, 1); - else if ifObj(element.Drawing.XmlNode) then {self.}RToDrawingRange(element, ppr); - else {self.}RToTextRange(element, ppr, bookmark_name); + {self.}SetRPr(element.RPr, ppr_unit_decorator_); + 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, 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 else if element.LocalName = "hyperlink" then begin empty_flag := false; - {self.}HyperlinkToTextRange(element, ppr); + {self.}HyperlinkToTextRange(element, ppr_unit_decorator_); end else if element.LocalName = "bookmarkStart" then begin @@ -104,26 +127,43 @@ begin end if empty_flag then 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.}EndY -= {self.}DynamicHeight; end - {self.}RangesToLines(ppr); - if hyperlink_array_ then {self.}HyperlinkToToc(ppr); + if placeholder_array_ then return false; + {self.}RangesToLines(); + if hyperlink_array_ then {self.}HyperlinkToToc(); if bookmark_array_ then {self.}BookMarkLinkToc(); - {self.}DynamicHeight += ppr.Spacing.After; - {self.}EndY -= ppr.Spacing.After; return true; end; +function TSPdfParagraphRange.SetNumPages(num: integer); +begin + text := tostring(num); + last_index := length(range_array_); + {self.}SplitTextToTextRange(text, placeholder_array_[1], link); + arr := array(); + len := length(range_array_); + for i:=last_index to len-1 do + arr[length(arr)] := range_array_[i]; + diff := len - last_index; + for i:=len-1 downto placeholder_array_[0] do + range_array_[i] := range_array_[i-diff]; + k := 0; + for i:=placeholder_array_[0] to placeholder_array_[0]+diff-1 do + range_array_[i] := arr[k++]; +end; + function TSPdfParagraphRange.BookMarkLinkToc(); begin for name,arr in bookmark_array_ do if arr[0] then docx_to_pdf_.LinkToToc(name, arr[0].TSPage, arr[0].EndX, arr[0].EndY + arr[0].RPr.Sz.Val); end; -function TSPdfParagraphRange.HyperlinkToToc(ppr: PPrUnitDecorator); +function TSPdfParagraphRange.HyperlinkToToc(); begin + ppr := ppr_unit_decorator_; max_size := 0; for anchor,arr in hyperlink_array_ do // 整理hyperlink发送到docx_to_pdf_ begin @@ -136,7 +176,7 @@ begin y := arr[0].EndY; if top - {self.}GetParagraphLineSpace(arr[0].RPr.Sz.Val, ppr.Spacing.Line) then begin - top := docx_to_pdf_.GetCurrentPoint().Y; + top := docx_to_pdf_.GetCurrentTextPoint().Y; bottom := top; end for _,range in arr do @@ -168,7 +208,7 @@ begin if x + num_width - {self.}StartX > {self.}Width + 1e-6 then // 换行 begin offset := (line_space - max_size) / 2 + max_size - max_size / 5; - diff := {self.}EndY - sect_ware_.SectPr.PgMar.Bottom; + diff := {self.}EndY - {self.}LowerBound; if {self.}CheckAndAddPage({self.}EndY, line_space) then begin {self.}DynamicHeight += diff; @@ -200,8 +240,8 @@ begin begin if r.FldChar.FldCharType = "begin" then break; r.RPr := new RPr(); - {self.}SetRPr(r.RPr, ppr); - {self.}RToTextRange(r, ppr, hyperlink.Anchor); + {self.}SetRPr(r.RPr, ppr_unit_decorator_); + {self.}RToTextRange(r, hyperlink.Anchor); end arr := array(); while i < length(range_array_) do @@ -232,8 +272,25 @@ begin return line_range; end; -function TSPdfParagraphRange.RangesToLines(ppr: PPrUnitDecorator); +function TSPdfParagraphRange.RangesToLines();overload; begin + {self.}BasicRangesToLineRange(); + {self.}DynamicHeight += ppr_unit_decorator_.Spacing.After; + {self.}EndY -= ppr_unit_decorator_.Spacing.After; + if ppr_unit_decorator_.PBdr.Bottom.Val = "single" then + begin + sect_ware := docx_to_pdf_.GetCurrentSectWare(); + page_.PdfPage.SetLineWidth(0.05); + page_.PdfPage.SetGrayStroke(0.25); + page_.PdfPage.MoveTo(sect_ware.SectPr.PgMar.Left, {self.}EndY); + page_.PdfPage.LineTo(sect_ware.SectPr.PgSz.W - sect_ware.SectPr.PgMar.Right, {self.}EndY); + page_.PdfPage.Stroke(); + end +end; + +function TSPdfParagraphRange.BasicRangesToLineRange(); +begin + ppr := ppr_unit_decorator_; line_range := {self.}NewLineRange(); i := 0; max_size := 0; @@ -246,7 +303,7 @@ begin 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); - diff := {self.}EndY - sect_ware_.SectPr.PgMar.Bottom; + diff := {self.}EndY - {self.}LowerBound; if {self.}CheckAndAddPage({self.}EndY, max(line_space, range.DynamicHeight)) then {self.}DynamicHeight += diff; if_newline := {self.}EndX + range.Width - {self.}StartX > {self.}Width + 1e-6; @@ -288,24 +345,24 @@ begin {self.}EndY -= max_value; end end - {self.}SetLinesAlignment(ppr); + {self.}SetLinesAlignment(); end; -function TSPdfParagraphRange.SetLinesAlignment(ppr: PPrUnitDecorator); +function TSPdfParagraphRange.SetLinesAlignment(); 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); + line_range.Align(ppr_unit_decorator_.Jc.Val); end; function TSPdfParagraphRange.CheckAndAddPage(y: real; offset: real): boolean; begin - if y - offset < sect_ware_.SectPr.PgMar.Bottom then + if y - offset < {self.}LowerBound then begin page_ := docx_to_pdf_.GetNextPage(page_); - if ifnil(page_) then page_ := docx_to_pdf_.AddPage(sect_ware_); - point := docx_to_pdf_.GetCurrentPoint(); + if ifnil(page_) then page_ := docx_to_pdf_.AddTSPage(); + point := docx_to_pdf_.GetCurrentTextPoint(); {self.}EndY := point.Y; return true; end @@ -324,11 +381,11 @@ begin return 4; end; -function TSPdfParagraphRange.RToTextRange(r: R; ppr: PPrUnitDecorator; link: string); +function TSPdfParagraphRange.RToTextRange(r: R; link: string); begin if r.Anchor then begin - {self.}HyperlinkToTextRange(r, ppr); + {self.}HyperlinkToTextRange(r); end else begin rpr := new RPrUnitDecorator(r.RPr); @@ -361,7 +418,7 @@ begin end end; -function TSPdfParagraphRange.RToDrawingRange(r: R; ppr: PPrUnitDecorator); +function TSPdfParagraphRange.RToDrawingRange(r: R); begin xfrm := new XfrmUnitDecorator(r.Drawing._Inline.Graphic.GraphicData.Pic.SpPr.Xfrm); rels_adapter := docx_components_ware_.GetDocumentRelsAdapter(); @@ -415,10 +472,11 @@ end; function TSPdfParagraphRange.GetParagraphLineSpace(size: real; line: integer): real; begin + sect_ware := docx_to_pdf_.GetCurrentSectWare(); 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; + multi := ceil(size / sect_ware.BaseSize) * lines; + return sect_ware.SectPr.DocGrid.LinePitch * multi; end; function TSPdfParagraphRange.SetPPr(var ppr: PPr); @@ -446,7 +504,7 @@ begin end end; -function TSPdfParagraphRange.SetRPr(var rpr; ppr: PPr); +function TSPdfParagraphRange.SetRPr(var rpr; ppr: PPrUnitDecorator); begin new_rpr := new RPr(); styles := docx_components_ware_.GetStyles(); @@ -480,9 +538,10 @@ begin {self.}SplitTextToTextRange(lvl_text, rpr); end; -function TSPdfParagraphRange.ResetCoordinates(ppr: PPrUnitDecorator); +function TSPdfParagraphRange.ResetCoordinates(); begin // 根据段落的间距确定新的坐标 + ppr := ppr_unit_decorator_; sz := ppr.RPr.SzCs.Val ? ppr.RPr.SzCs.Val : ppr.RPr.Sz.Val ? ppr.RPr.Sz.Val : docx_to_pdf_.Font.GetDefaultSz(); {self.}StartX += ppr.Ind.LeftChars ? ppr.Ind.LeftChars * sz : ppr.Ind.Left; {self.}Width -= ppr.Ind.LeftChars ? ppr.Ind.LeftChars * sz : ppr.Ind.Left; diff --git a/range/Advanced/TSPdfParagraphRange2.tsf b/range/Advanced/TSPdfParagraphRange2.tsf deleted file mode 100644 index 4c8f02f..0000000 --- a/range/Advanced/TSPdfParagraphRange2.tsf +++ /dev/null @@ -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; diff --git a/range/Advanced/TSPdfTableRange.tsf b/range/Advanced/TSPdfTableRange.tsf index 6c825fa..de0daf6 100644 --- a/range/Advanced/TSPdfTableRange.tsf +++ b/range/Advanced/TSPdfTableRange.tsf @@ -1,6 +1,6 @@ type TSPdfTableRange = class(TSPdfBasicRange) 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 Do();override; @@ -18,18 +18,16 @@ private private [weakref]docx_to_pdf_: TSDocxToPdf; [weakref]docx_components_ware_: Components; - [weakref]sect_ware_: TSSectWare; [weakref]table_: Tbl; [weakref]page_: TSPage; range_array_: tableArray; 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 docx_to_pdf_ := docx_to_pdf; page_ := pg; docx_components_ware_ := Components; - sect_ware_ := sect_ware; table_ := table; range_array_ := array(); {self.}TSPage := page_; @@ -73,11 +71,12 @@ begin for j,tc in tcs do begin 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.StartY := tc_y; cell_range.FixedHeight := tc_h; cell_range.Width := grid_cols[pos].W; + cell_range.LowerBound := {self.}LowerBound; range_array_[i][pos] := cell_range; grid_span := new GridSpanUnitDecorator(tc.TcPr.GridSpan); pos++; @@ -88,7 +87,7 @@ begin if cell_range.DynamicHeight > max_height then max_height := cell_range.DynamicHeight; end 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]; for _,range in arr do begin diff --git a/range/basic/TSPdfBasicRange.tsf b/range/basic/TSPdfBasicRange.tsf index ba82216..47aaab9 100644 --- a/range/basic/TSPdfBasicRange.tsf +++ b/range/basic/TSPdfBasicRange.tsf @@ -11,6 +11,7 @@ public Width: real; FixedHeight: real; DynamicHeight: real; + LowerBound: real; [weakref]TSPage: TSPage; end; @@ -23,5 +24,6 @@ begin {self.}Width := 0; {self.}FixedHeight := 0; {self.}DynamicHeight := 0; + {self.}LowerBound := 0; {self.}TSPage := nil; end; diff --git a/ware/TSDocxComponentsWare.tsf b/ware/TSDocxComponentsWare.tsf index 8899aa6..5e9678b 100644 --- a/ware/TSDocxComponentsWare.tsf +++ b/ware/TSDocxComponentsWare.tsf @@ -6,6 +6,8 @@ public function GetDocumentRelsAdapter(): RelationShipsAdapter; function GetNumberingWare(): TSNumberingWare; function GetTblStylePrByType(style_id: string; type: string): TblStylePr; + function GetFtr(target: string): Ftr; + function GetHdr(target: string): Hdr; private styles_deserialize_flag_; @@ -13,12 +15,16 @@ private document_rels_adapter_; numbering_ware_; tbl_style_pr_hash_; + ftr_hash_; + hdr_hash_; end; function TSDocxComponentsWare.Create(); begin class(Components).Create(); tbl_style_pr_hash_ := array(); + ftr_hash_ := array(); + hdr_hash_ := array(); end; function TSDocxComponentsWare.GetStyles(): Styles; @@ -63,3 +69,23 @@ begin tbl_style_pr_hash_[style_id][type] := tbl_style_pr; return tbl_style_pr; end; + +function TSDocxComponentsWare.GetFtr(target: string): Ftr; +begin + if ftr_hash_[target] then return ftr_hash_[target]; + index := replaceStr(replaceStr(target, "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;