type TSPdfCellRange = class(TSPdfBasicRange) public function Create(table_range: TSPdfTableRange; docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; tc: Tc; tbl_pr: TblPr; trp: TSTrProperty); function Calc(); function Do();override; function SetTSPage(page: TSPage); function GetLastPage(); function AlignHeight(height: real); function SetVAlign(); function IsReComputeByCantSplit(): boolean; function IfRemoveEmptyRectangle(): boolean; function SetTop(); property Tc read tc_; private function GetCellPrType(): string; function SetBorderRange(range: TSPdfBordersRange); public RemoveFlag: boolean; Row: integer; Col: integer; VMerge: integer; [weakref]TSTrPr: TSTrProperty; private [weakref]parent_: TSPdfTableRange; [weakref]docx_to_pdf_: TSDocxToPdf; [weakref]last_page_: TSPage; [weakref]docx_components_ware_: TSDocxComponentsWare; [weakref]tc_: Tc; [weakref]tbl_pr_: TblPr; tc_pr_unit_decorator_: TcPrUnitDecorator; region_array_: array of Region; // 单元格可能跨页,所以可能存在多个 top_: boolean; end; type Region = class function Create(); begin BordersRange := new TSPdfBordersRange(); RangeArr := array(); end BordersRange: TSPdfBordersRange; RangeArr: array of TSPdfBasicRange; end; function TSPdfCellRange.Create(table_range: TSPdfTableRange; docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; tc: Tc; tbl_pr: TblPr; trp: TSTrProperty); begin parent_ := table_range; docx_to_pdf_ := docx_to_pdf; last_page_ := pg; docx_components_ware_ := components; tc_ := tc; tbl_pr_ := tbl_pr; region_array_ := array(); top_ := false; tc_pr_unit_decorator_ := new TcPrUnitDecorator(tc_.TcPr); {self.}TSTrPr := trp; {self.}Tc := tc; {self.}VMerge := 1; {self.}TSPage := last_page_; end; function TSPdfCellRange.Calc(); begin region_array_ := array(); region := new Region(); region.BordersRange.EndX := {self.}StartX; region.BordersRange.EndY := {self.}StartY; region.BordersRange.Width := {self.}Width; region.BordersRange.FixedHeight := {self.}FixedHeight; region.BordersRange.TSPage := last_page_; region.BordersRange.TcPr := tc_pr_unit_decorator_; {self.}SetBorderRange(region.BordersRange); region_array_[length(region_array_)] := region; {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; cell_h := {self.}FixedHeight; elements := tc_.Elements(); for _,element in elements do begin range := nil; if element.LocalName = "p" then begin range := new TSPdfParagraphRange(docx_to_pdf_, last_page_, docx_components_ware_, element); range.SetTblStyleIdAndType(tbl_pr_.TblStyle.Val, {self.}GetCellPrType()); end else if element.LocalName = "tbl" then begin range := new TSPdfTableRange(docx_to_pdf_, last_page_, docx_components_ware_, element); continue; // TODO:表中表存在不可靠问题 end if ifObj(range) then begin range.StartX := cell_x; 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; cell_y := range.EndY; last_page_ := range.GetLastPage(); end end {self.}EndY := cell_y - tbl_pr_.TblCellMar.Bottom.W; {self.}DynamicHeight += tbl_pr_.TblCellMar.Top.W + tbl_pr_.TblCellMar.Bottom.W; if {self.}EndY < {self.}LowerBound and not range.Empty() then begin last_page_ := docx_to_pdf_.GetNextPage(last_page_); if ifnil(last_page_) then last_page_ := docx_to_pdf_.AddTSPage(); point := docx_to_pdf_.GetCurrentTextPoint(); {self.}StartY := point.Y; {self.}Calc(); end if {self.}TSTrPr.TrPr.TrHeight.HRule <> "exact" and {self.}DynamicHeight > {self.}FixedHeight then begin region.BordersRange.FixedHeight := {self.}DynamicHeight; {self.}FixedHeight := {self.}DynamicHeight; end if not {self.}Tc.TcPr.VMerge and {self.}DynamicHeight > {self.}TSTrPr.Height then {self.}TSTrPr.Height := {self.}DynamicHeight; end; function TSPdfCellRange.Do();override; begin for _,region in region_array_ do begin if _ = 0 and {self.}RemoveFlag then continue; // println("Row = {}, Col = {}", {self.}Row, {self.}Col); region.BordersRange.Do(); for _,range in region.RangeArr do range.Do(); end end; function TSPdfCellRange.SetTSPage(page: TSPage); begin last_page_ := page; {self.}TSPage := page; end; function TSPdfCellRange.AlignHeight(height: real); begin region := region_array_[0]; y_lowerbound := {self.}StartY - {self.}LowerBound; surplus := height - y_lowerbound; if surplus < 1e-6 then begin region.BordersRange.DynamicHeight := height; {self.}SetBorderRange(region.BordersRange); {self.}EndY := {self.}StartY - region.BordersRange.DynamicHeight; return; end region.BordersRange.DynamicHeight := y_lowerbound; arr := region.RangeArr; region.RangeArr := array(); hash := array(region.BordersRange.TSPage.Index: region); last_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 last_page_ := docx_to_pdf_.GetNextPage(last_page_); region := new Region(); region.BordersRange.EndX := {self.}StartX; region.BordersRange.EndY := y; region.BordersRange.Width := {self.}Width; region.BordersRange.DynamicHeight := span; region.BordersRange.TSPage := last_page_; region.BordersRange.TcPr := tc_pr_unit_decorator_; region.BordersRange.Top := true; region.BordersRange.Bottom := true; {self.}SetBorderRange(region.BordersRange); region_array_[length(region_array_)] := region; surplus -= span; hash[region.BordersRange.TSPage.Index] := region; end if surplus > 1e-6 then begin last_page_ := docx_to_pdf_.GetNextPage(last_page_); region := new Region(); region.BordersRange.EndX := {self.}StartX; region.BordersRange.EndY := y; region.BordersRange.Width := {self.}Width; region.BordersRange.DynamicHeight := surplus; region.BordersRange.TSPage := last_page_; region.BordersRange.TcPr := tc_pr_unit_decorator_; region.BordersRange.Top := true; {self.}SetBorderRange(region.BordersRange); region_array_[length(region_array_)] := region; hash[region.BordersRange.TSPage.Index] := region; {self.}EndY := region.BordersRange.EndY - surplus; end for _,range in arr do begin 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; function TSPdfCellRange.GetLastPage(); begin return last_page_; end; function TSPdfCellRange.SetVAlign(); begin val := tc_.TcPr.VAlign.Val; region := region_array_[0]; arr := region.RangeArr; if length(arr) = 0 then return; last_y := arr[length(arr)-1].EndY; offset := last_y - (region.BordersRange.EndY - region.BordersRange.DynamicHeight) - tbl_pr_.TblCellMar.Bottom.W; case val of "center": begin offset /= 2; for _,range in arr do range.AdjustRangeOffset(region.BordersRange.TSPage, nil, -offset); end end; end; function TSPdfCellRange.IsReComputeByCantSplit(): boolean; begin if {self.}Tc.TcPr.VMerge then return false; return {self.}TSTrPr.TrPr.CantSplit and last_page_ <> {self.}TSPage; end; function TSPdfCellRange.IfRemoveEmptyRectangle(): boolean; begin if length(region_array_) < 2 then return false; return length(region_array_[0].RangeArr) ? false : true; end; function TSPdfCellRange.GetCellPrType(): string; begin if {self.}Row = 0 then return "firstRow"; else if ({self.}Row + 1) % 2 = 0 then return "band1Horz"; else return "band2Horz"; end; function TSPdfCellRange.SetBorderRange(range: TSPdfBordersRange); begin if top_ then range.Top := true; if ifObj(tbl_pr_.TblBorders) then begin if {self.}Row = 0 then begin if tbl_pr_.TblBorders.Top then begin if not tc_pr_unit_decorator_.TcBorders.Top then tc_pr_unit_decorator_.TcBorders.Top.Copy(tbl_pr_.TblBorders.Top); range.Top := true; end if tbl_pr_.TblBorders.InsideH and {self.}VMerge <> parent_.Rows()-1 then begin if not tc_pr_unit_decorator_.TcBorders.Bottom then tc_pr_unit_decorator_.TcBorders.Bottom.Copy(tbl_pr_.TblBorders.InsideH); range.Bottom := true; end if tbl_pr_.TblBorders.InsideV and {self.}Col <> parent_.Cols()-1 then begin if not tc_pr_unit_decorator_.TcBorders.Right then tc_pr_unit_decorator_.TcBorders.Right.Copy(tbl_pr_.TblBorders.InsideV); range.Right := true; end if tbl_pr_.TblBorders.Bottom and {self.}VMerge = parent_.Rows()-1 then begin if not tc_pr_unit_decorator_.TcBorders.Bottom then tc_pr_unit_decorator_.TcBorders.Bottom.Copy(tbl_pr_.TblBorders.Bottom); range.Bottom := true; end end else if {self.}Row = parent_.Rows()-1 then begin if tbl_pr_.TblBorders.Bottom then begin if not tc_pr_unit_decorator_.TcBorders.Bottom then tc_pr_unit_decorator_.TcBorders.Bottom.Copy(tbl_pr_.TblBorders.Bottom); range.Bottom := true; end if tbl_pr_.TblBorders.InsideV and {self.}Col <> parent_.Cols()-1 then begin if not tc_pr_unit_decorator_.TcBorders.Right then tc_pr_unit_decorator_.TcBorders.Right.Copy(tbl_pr_.TblBorders.InsideV); range.Right := true; end end else begin if tbl_pr_.TblBorders.Bottom and {self.}VMerge = parent_.Rows()-1 then begin if not tc_pr_unit_decorator_.TcBorders.Bottom then tc_pr_unit_decorator_.TcBorders.Bottom.Copy(tbl_pr_.TblBorders.Bottom); range.Bottom := true; end if tbl_pr_.TblBorders.InsideH and {self.}VMerge <> parent_.Rows()-1 then begin if not tc_pr_unit_decorator_.TcBorders.Bottom then tc_pr_unit_decorator_.TcBorders.Bottom.Copy(tbl_pr_.TblBorders.InsideH); range.Bottom := true; end if tbl_pr_.TblBorders.InsideV and {self.}Col <> parent_.Cols()-1 then begin if not tc_pr_unit_decorator_.TcBorders.Right then tc_pr_unit_decorator_.TcBorders.Right.Copy(tbl_pr_.TblBorders.InsideV); range.Right := true; end end if {self.}Col = 0 then begin if tbl_pr_.TblBorders.Left then begin if not tc_pr_unit_decorator_.TcBorders.Left then tc_pr_unit_decorator_.TcBorders.Left.Copy(tbl_pr_.TblBorders.Left); range.Left := true; end end if {self.}Col = parent_.Cols()-1 then begin if tbl_pr_.TblBorders.Right then begin if not tc_pr_unit_decorator_.TcBorders.Right then tc_pr_unit_decorator_.TcBorders.Right.Copy(tbl_pr_.TblBorders.Right); range.Right := true; end end end else begin range.Left := {self.}Col = 0; range.Top := {self.}Row = 0; range.Right := true; range.Bottom := true; end end; function TSPdfCellRange.SetTop(); begin top_ := true; end;