diff --git a/TSDocxToPdf.tsf b/TSDocxToPdf.tsf index c9723bc..02e7c93 100644 --- a/TSDocxToPdf.tsf +++ b/TSDocxToPdf.tsf @@ -8,6 +8,8 @@ public function GetPdf(): PdfFile; function GetCurrentSectWare(): TSSectWare; function GetCurrentTextPoint(): Point; + function GetCurrentHdrPoint(): Point; + function GetCurrentFtrPoint(): Point; function GetCachePath(image_path: string): string; function GetNextPage(page: TSPage): TSPage; function GetCurrentXmlFile(): string; @@ -132,6 +134,16 @@ begin return text_point_; end; +function TSDocxToPdf.GetCurrentHdrPoint(): Point; +begin + return hdr_point_; +end; + +function TSDocxToPdf.GetCurrentFtrPoint(): Point; +begin + return ftr_point_; +end; + function TSDocxToPdf.GetCurrentSectWare(): TSSectWare; begin return sect_ware_; diff --git a/range/Advanced/TSPdfCellRange.tsf b/range/Advanced/TSPdfCellRange.tsf index aa6e137..f952051 100644 --- a/range/Advanced/TSPdfCellRange.tsf +++ b/range/Advanced/TSPdfCellRange.tsf @@ -1,24 +1,27 @@ type TSPdfCellRange = class(TSPdfBasicRange) public - function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; tc: Tc; tbl_pr: TblPr); + function Create(table_range: TSPdfTableRange; docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; tc: Tc; tbl_pr: TblPr; tr_pr: TrPr); function Calc(); function Do();override; function SetTSPage(page: TSPage); function GetLastPage(); - function AlignHeight(height: real; surplus: real); + function AlignHeight(height: real); function IsSamePage(): boolean; function FirstValidTSPage(): TSPage; - function SetVAlign(val: string); + function SetVAlign(); + function IsReComputeByCantSplit(): boolean; public VMerge; private + [weakref]parent_: TSPdfTableRange; [weakref]docx_to_pdf_: TSDocxToPdf; [weakref]page_: TSPage; [weakref]docx_components_ware_: TSDocxComponentsWare; [weakref]tc_: Tc; [weakref]tbl_pr_: TblPr; + [weakref]tr_pr_: TrPr; region_array_: array of Region; // 单元格可能跨页,所以可能存在多个 end; @@ -33,13 +36,15 @@ type Region = class RangeArr: array of TSPdfAbstractRange; end; -function TSPdfCellRange.Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; tc: Tc; tbl_pr: TblPr); +function TSPdfCellRange.Create(table_range: TSPdfTableRange; docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; tc: Tc; tbl_pr: TblPr; tr_pr: TrPr); begin + parent_ := table_range; docx_to_pdf_ := docx_to_pdf; page_ := pg; docx_components_ware_ := components; tc_ := tc; tbl_pr_ := tbl_pr; + tr_pr_ := tr_pr; region_array_ := array(); {self.}TSPage := page_; {self.}VMerge := 0; @@ -47,6 +52,7 @@ end; function TSPdfCellRange.Calc(); begin + region_array_ := array(); region := new Region(); region.RectangleRange.EndX := {self.}StartX; region.RectangleRange.EndY := {self.}StartY; @@ -58,6 +64,7 @@ begin {self.}EndX := {self.}StartX; {self.}EndY := {self.}StartY; + {self.}DynamicHeight := 0; cell_x := {self.}EndX + tbl_pr_.TblCellMar.Left.W; cell_y := {self.}EndY - tbl_pr_.TblCellMar.Top.W; cell_w := {self.}Width - tbl_pr_.TblCellMar.Right.W - tbl_pr_.TblCellMar.Left.W; @@ -74,6 +81,7 @@ begin else if element.LocalName = "tbl" then begin range := new TSPdfTableRange(docx_to_pdf_, page_, docx_components_ware_, element); + continue; // TODO:表中表存在不可靠问题 end if ifObj(range) then begin @@ -110,23 +118,26 @@ begin {self.}TSPage := page; end; -function TSPdfCellRange.AlignHeight(height: real; surplus: real); +function TSPdfCellRange.AlignHeight(height: real); begin + if {self.}FixedHeight > height then height := {self.}FixedHeight; region := region_array_[0]; + surplus := height - ({self.}StartY - {self.}LowerBound); if surplus < 1e-6 then begin region.RectangleRange.DynamicHeight := height; - if region.RectangleRange.FixedHeight then region.RectangleRange.DynamicHeight := region.RectangleRange.FixedHeight; + if {self.}FixedHeight then region.RectangleRange.DynamicHeight := {self.}FixedHeight; {self.}EndY := {self.}StartY - region.RectangleRange.DynamicHeight; return; end region.RectangleRange.DynamicHeight := {self.}StartY - {self.}LowerBound; arr := region.RangeArr; region.RangeArr := array(); - 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); page_ := {self.}TSPage; + [x, y] := docx_to_pdf_.CalculateTextCoordinates(); + ftr_point := docx_to_pdf_.GetCurrentFtrPoint(); + span := y - ftr_point.Y; while surplus > span do begin page_ := docx_to_pdf_.GetNextPage(page_); @@ -146,7 +157,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 := y; region.RectangleRange.Width := {self.}Width; region.RectangleRange.DynamicHeight := surplus; region.RectangleRange.TSPage := page_; @@ -157,9 +168,15 @@ begin end for _,range in arr do begin - region := hash[range.FirstValidTSPage().Index]; - // region := hash[range.TSPage.Index]; - region.RangeArr[length(region.RangeArr)] := range; + if range is class(TSPdfParagraphRange) then + begin + line_arr := range.GetLineRangeArr(); + for _,r in line_arr do + begin + region := hash[r.TSPage.Index]; + region.RangeArr[length(region.RangeArr)] := r; + end + end end end; @@ -168,8 +185,9 @@ begin return page_; end; -function TSPdfCellRange.SetVAlign(val: string); +function TSPdfCellRange.SetVAlign(); begin + val := tc_.TcPr.VAlign.Val; region := region_array_[0]; arr := region.RangeArr; if length(arr) = 0 then return; @@ -180,7 +198,7 @@ begin begin offset /= 2; for _,range in arr do - range.AdjustRangeOffset(nil, -offset); + range.AdjustRangeOffset(region.RectangleRange.TSPage, nil, -offset); end end; end; @@ -194,3 +212,9 @@ function TSPdfCellRange.FirstValidTSPage(): TSPage; begin return region_array_[0].RangeArr[0].TSPage; end; + +function TSPdfCellRange.IsReComputeByCantSplit(): boolean; +begin + if {self.}VMerge then return false; + return tr_pr_.CantSplit and page_ <> {self.}TSPage; +end; diff --git a/range/Advanced/TSPdfLineRange.tsf b/range/Advanced/TSPdfLineRange.tsf index e5ff25f..ccc0155 100644 --- a/range/Advanced/TSPdfLineRange.tsf +++ b/range/Advanced/TSPdfLineRange.tsf @@ -5,7 +5,7 @@ public function AddRange(range: TSPdfBasicRange); function SetAllRangeProp(pg: TSPage; sx: real; sy: real; ex: real; ey: real; w: real; fh: real; dh: real); function Align(jc: string); - function AdjustRangeOffset(x_offset: real; y_offset: real); + function AdjustRangeOffset(page: TSPage; x_offset: real; y_offset: real); private range_array_: array of TSPdfBasicRange; @@ -59,8 +59,9 @@ begin range.EndX += offset; end; -function TSPdfLineRange.AdjustRangeOffset(x_offset: real; y_offset: real); +function TSPdfLineRange.AdjustRangeOffset(page: TSPage; x_offset: real; y_offset: real); begin + if page <> {self.}TSPage then return; for _,range in range_array_ do begin if not ifnil(x_offset) then range.EndX += x_offset; diff --git a/range/Advanced/TSPdfParagraphRange.tsf b/range/Advanced/TSPdfParagraphRange.tsf index 6258bdf..4ba1206 100644 --- a/range/Advanced/TSPdfParagraphRange.tsf +++ b/range/Advanced/TSPdfParagraphRange.tsf @@ -9,7 +9,8 @@ public function FirstValidTSPage(): TSPage; function IsSamePage(): boolean; function GetLastPage(): TSPage; - function AdjustRangeOffset(x_offset: real; y_offset: real); + function AdjustRangeOffset(page: TSPage; x_offset: real; y_offset: real); + function GetLineRangeArr(): array of TSPdfLineRange; private function SetPPr(var ppr: PPr); @@ -662,8 +663,13 @@ begin return page_; end; -function TSPdfParagraphRange.AdjustRangeOffset(x_offset: real; y_offset: real); +function TSPdfParagraphRange.AdjustRangeOffset(page: TSPage; x_offset: real; y_offset: real); begin for _,line_range in line_range_array_ do - line_range.AdjustRangeOffset(x_offset, y_offset); + line_range.AdjustRangeOffset(page, x_offset, y_offset); +end; + +function TSPdfParagraphRange.GetLineRangeArr(): array of TSPdfLineRange; +begin + return line_range_array_; end; diff --git a/range/Advanced/TSPdfTableRange.tsf b/range/Advanced/TSPdfTableRange.tsf index 50fb081..2c80ec3 100644 --- a/range/Advanced/TSPdfTableRange.tsf +++ b/range/Advanced/TSPdfTableRange.tsf @@ -1,14 +1,16 @@ type TSPdfTableRange = class(TSPdfBasicRange) public function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: Components; table: Tbl); - function Calc(); function Do();override; + function Calc(); function FirstValidTSPage(): TSPage; function IsSamePage(): boolean; function GetLastPage(): TSPage; private function GetCellMatrix(grid_cols: array of GridColUnitDecorator); + function CreateTableMatrix(grid_cols: array of GridColUnitDecorator; trs: array of Tr); + function ComputeMatrixCells(); function ResetCoordinates(tbl_pr: TblPr; grid_cols: array of GridCol); function SetTblPr(tbl_pr: TblPr); function SetTblPrByStyleId(var tbl_pr: TblPr; style_id: string); @@ -23,7 +25,7 @@ private [weakref]docx_components_ware_: Components; [weakref]table_: Tbl; [weakref]page_: TSPage; - range_array_: tableArray; + cell_range_array_: tableArray; end; function TSPdfTableRange.Create(docx_to_pdf: TSDocxToPdf; pg: PdfPage; components: Components; table: Tbl); @@ -32,7 +34,7 @@ begin page_ := pg; docx_components_ware_ := Components; table_ := table; - range_array_ := array(); + cell_range_array_ := array(); {self.}TSPage := page_; end; @@ -50,9 +52,9 @@ begin {self.}GetCellMatrix(grid_cols); end; -function TSPdfTableRange.Do(); +function TSPdfTableRange.Do();override; begin - for _,row in range_array_ do + for _,row in cell_range_array_ do for _,range in row do if ifObj(range) then range.Do(); end; @@ -61,9 +63,19 @@ function TSPdfTableRange.GetCellMatrix(grid_cols: array of GridColUnitDecorator) begin trs := table_.Trs(); // 先构建一个矩阵 + {self.}CreateTableMatrix(grid_cols, trs); + // 遍历矩阵后进行计算合并 + {self.}ComputeMatrixCells(); +end; + +function TSPdfTableRange.CreateTableMatrix(grid_cols: array of GridColUnitDecorator; trs: array of Tr); +begin vmerge_arr := array(); for i,tr in trs do begin + {self.}SetTrPr(tr.TrPr); + tr_pr := new TrPrUnitDecorator(tr.TrPr); + tc_h := tr_pr.TrHeight.Val; tc_x := {self.}EndX; tcs := tr.Tcs(); pos := 0; @@ -74,13 +86,13 @@ begin vmerge := tc.TcPr.XmlChildVMerge.Val ? tc.TcPr.XmlChildVMerge.Val : tc.TcPr.VMerge; if vmerge = "restart" then begin - if ifarray(vmerge_arr[pos]) then range_array_[vmerge_arr[pos][0]][pos].VMerge := vmerge_arr[pos][1]; + if ifarray(vmerge_arr[pos]) then cell_range_array_[vmerge_arr[pos][0]][pos].VMerge := vmerge_arr[pos][1]; vmerge_arr[pos] := array(i, 0); end else if vmerge then begin vmerge_arr[pos][1]++; - range_array_[i][pos] := 0; + cell_range_array_[i][pos] := 0; tc_x += grid_cols[pos].W; grid_span := new GridSpanUnitDecorator(tc.TcPr.GridSpan); pos++; @@ -90,14 +102,15 @@ begin end else if ifarray(vmerge_arr[pos]) then begin - range_array_[vmerge_arr[pos][0]][pos].VMerge := vmerge_arr[pos][1]; + cell_range_array_[vmerge_arr[pos][0]][pos].VMerge := vmerge_arr[pos][1]; vmerge_arr[pos] := nil; end - cell_range := new TSPdfCellRange(docx_to_pdf_, page_, docx_components_ware_, tc, table_.TblPr); + cell_range := new TSPdfCellRange(self, docx_to_pdf_, page_, docx_components_ware_, tc, table_.TblPr, tr.TrPr); cell_range.StartX := tc_x; cell_range.Width := grid_cols[pos].W; cell_range.LowerBound := {self.}LowerBound; - range_array_[i][pos] := cell_range; + cell_range.FixedHeight := tc_h; + cell_range_array_[i][pos] := cell_range; grid_span := new GridSpanUnitDecorator(tc.TcPr.GridSpan); pos++; for k:=grid_span.Val-1 downto 1 do @@ -106,82 +119,96 @@ begin end end - // for i,arr in range_array_ do + // for i,arr in cell_range_array_ do // begin // println("i = {}, len = {}, arr = {}", i, length(arr), arr); // end + return; +end; - // 遍历矩阵后进行计算合并 +function TSPdfTableRange.ComputeMatrixCells(); +begin + i := 0; vmerge_arr := array(); row_height := array(); - for i,arr in range_array_ do + while i < length(cell_range_array_)-1 do begin - tr := trs[i]; - {self.}SetTrPr(tr.TrPr); - tr_pr := new TrPrUnitDecorator(tr.TrPr); - tc_h := tr_pr.TrHeight.Val; tc_y := {self.}EndY; max_height := 0; - flag := nil; - first_page := nil; - for j,range in arr do + recompute_flag := false; + vmerge_flag_arr := array(); + for j,range in cell_range_array_[i] do begin if range = 0 then begin vmerge_arr[j][1]--; - if vmerge_arr[j][1] = 0 then flag := j; + if vmerge_arr[j][1] = 0 then vmerge_flag_arr[length(vmerge_flag_arr)] := j; continue; end - if not ifObj(range) then continue; range.StartY := tc_y; - range.FixedHeight := tc_h; range.SetTSPage(page_); range.Calc(); - if range.VMerge then - vmerge_arr[j] := array(i, range.VMerge); + if range.IsReComputeByCantSplit() then + begin + // 调整上一行的下边界 + arr := cell_range_array_[i - 1]; + if ifarray then + begin + for k,range in arr do + begin + if range = 0 then + begin + pos := i - 2; + while pos > 0 do + begin + r := cell_range_array_[pos][k]; + if r = 0 then continue; + r.LowerBound := tc_y; + break; + end + end + else begin + range.LowerBound := tc_y; + end + end + end + page_ := docx_to_pdf_.GetNextPage(page_); + [x, y] := docx_to_pdf_.CalculateTextCoordinates(); + {self.}EndY := y; + println("y = {}", y); + recompute_flag := true; + break; + end + if range.VMerge then vmerge_arr[j] := array(i, range.VMerge); if not range.VMerge and range.DynamicHeight > max_height then max_height := range.DynamicHeight; - if ifnil(first_page) then first_page := range.FirstValidTSPage(); - if first_page <> range.FirstValidTSPage() then page_flag := true; end - - // TODO:跨页断行 - if tr_pr.CantSplit then - begin - end - else begin - end - - if tc_h > max_height then max_height := tc_h; + if recompute_flag then continue; + if range.FixedHeight > max_height then max_height := tc_h; row_height[i] := max_height; - if not ifnil(flag) then + for _,col_index in vmerge_flag_arr do begin total_height := max_height; - ind := vmerge_arr[flag][0]; - r := range_array_[ind][flag]; + row_index := vmerge_arr[col_index][0]; + r := cell_range_array_[row_index][col_index]; // 统计总高度 - while ind <= i-1 do - begin - total_height += row_height[ind]; - ind++; - end + while row_index <= i-1 do + total_height += row_height[row_index++]; r_height := total_height; if r.DynamicHeight > r_height then r_height := r.DynamicHeight; - surplus := r_height - ({self.}EndY - {self.}LowerBound); - r.AlignHeight(r_height, surplus); - r.SetVAlign(tc.TcPr.VAlign.Val); + r.AlignHeight(r_height); + r.SetVAlign(); max_height := r_height - total_height + max_height; end - surplus := max_height - ({self.}EndY - {self.}LowerBound); - for j,range in range_array_[i] do + for j,range in cell_range_array_[i] do begin if not ifObj(range) or range.VMerge then continue; - range.AlignHeight(max_height, surplus); - range.SetVAlign(tc.TcPr.VAlign.Val); + range.AlignHeight(max_height); + range.SetVAlign(); {self.}EndY := range.EndY; page_ := range.GetLastPage(); end + i++; end - end; function TSPdfTableRange.SetTblStylePr(var tc_pr: TcPr; type: string); @@ -273,7 +300,7 @@ end; function TSPdfTableRange.FirstValidTSPage(): TSPage; begin - range := range_array_[0][0]; + range := cell_range_array_[0][0]; return ifObj(range) ? range.TSPage : page_; end;