PdfConverter/range/Advanced/TSPdfCellRange.tsf

361 lines
12 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;