PdfConverter/range/Advanced/TSPdfTableRange.tsf

352 lines
11 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 TSPdfTableRange = class(TSPdfBasicRange)
public
function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: Components; table: Tbl);
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);
function SetTrPr(var tr_pr: TrPr);
function SetTrPrByStyleId(var tr_pr: TrPr; style_id: string);
function SetTcPr(var tc_pr: TcPr);
function SetTcPrByStyleId(var tc_pr: TcPr; style_id: string);
function SetTblStylePr(var tc_pr: TcPr; type: string);
private
[weakref]docx_to_pdf_: TSDocxToPdf;
[weakref]docx_components_ware_: Components;
[weakref]table_: Tbl;
[weakref]page_: TSPage;
tbl_pr_unit_decorator_: TblPrUnitDecorator;
cell_range_array_: tableArray;
tr_array_: array of TSTrProperty;
end;
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;
table_ := table;
cell_range_array_ := array();
tr_array_ := array();
{self.}TSPage := page_;
end;
function TSPdfTableRange.Calc();
begin
{self.}SetTblPr(table_.TblPr);
tbl_pr_unit_decorator_ := new TblPrUnitDecorator(table_.TblPr);
grid_cols := table_.TblGrid.GridCols();
for i:=0 to length(grid_cols)-1 do
grid_cols[i] := new GridColUnitDecorator(grid_cols[i]);
{self.}ResetCoordinates(tbl_pr_unit_decorator_, grid_cols);
{self.}EndX := {self.}StartX;
{self.}EndY := {self.}StartY;
// 如果是根据内容自适应应该计算并调整grid_cols的值
{self.}GetCellMatrix(grid_cols);
end;
function TSPdfTableRange.Do();override;
begin
for _,row in cell_range_array_ do
begin
flag := nil;
for __,range in row do
begin
if ifnil(flag) and ifObj(range) then flag := range.IfRemoveEmptyRectangle();
if not ifObj(range) or flag <> range.IfRemoveEmptyRectangle() then
begin
flag := false;
break;
end
end
for __,range in row do
begin
if ifObj(range) then
begin
range.RemoveFlag := flag;
range.Do();
end
end
end
end;
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;
trp := new TSTrProperty();
trp.TrPr := tr_pr;
tr_array_[i] := trp;
for j,tc in tcs do
begin
{self.}SetTcPr(tc.TcPr);
if i = 0 then {self.}SetTblStylePr(tc.TcPr, "firstRow");
else if (i + 1) % 2 = 0 then {self.}SetTblStylePr(tc.TcPr, "band1Horz");
else {self.}SetTblStylePr(tc.TcPr, "band2Horz");
vmerge := tc.TcPr.XmlChildVMerge.Val ? tc.TcPr.XmlChildVMerge.Val : tc.TcPr.VMerge;
if vmerge = "restart" then
begin
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]++;
cell_range_array_[i][pos] := 0;
tc_x += grid_cols[pos].W;
grid_span := new GridSpanUnitDecorator(tc.TcPr.GridSpan);
pos++;
for k:=grid_span.Val-1 downto 1 do
tc_x += grid_cols[pos++].W;
continue;
end
else if ifarray(vmerge_arr[pos]) then
begin
cell_range_array_[vmerge_arr[pos][0]][pos].VMerge := vmerge_arr[pos][1];
vmerge_arr[pos] := nil;
end
cell_range := new TSPdfCellRange(self, docx_to_pdf_, page_, docx_components_ware_, tc, tbl_pr_unit_decorator_, trp);
cell_range.StartX := tc_x;
cell_range.Width := grid_cols[pos].W;
cell_range.LowerBound := {self.}LowerBound;
cell_range.FixedHeight := tc_h;
cell_range.Row := i;
cell_range.Col := j;
cell_range_array_[i][pos] := cell_range;
grid_span := new GridSpanUnitDecorator(tc.TcPr.GridSpan);
pos++;
for k:=grid_span.Val-1 downto 1 do
cell_range.Width += grid_cols[pos++].W;
tc_x += cell_range.Width;
end
end
for pos,arr in vmerge_arr do
if ifarray(arr) then
cell_range_array_[arr[0]][pos].VMerge := arr[1];
// for i,arr in cell_range_array_ do
// begin
// println("i = {}, tr = {}", i, tr_array_[i]);
// println("i = {}, len = {}, arr = {}", i, length(arr), arr);
// end
return;
end;
function TSPdfTableRange.ComputeMatrixCells();
begin
i := 0;
vmerge_arr := array();
row_height := array();
while i < length(cell_range_array_) do
begin
tc_y := {self.}EndY;
max_height := 0;
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 vmerge_flag_arr[length(vmerge_flag_arr)] := j;
continue;
end
range.StartY := tc_y;
range.SetTSPage(page_);
range.Calc();
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;
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;
end
if recompute_flag then continue;
row_height[i] := max_height;
for _,col_index in vmerge_flag_arr do
begin
total_height := max_height;
row_index := vmerge_arr[col_index][0];
r := cell_range_array_[row_index][col_index];
// 统计总高度
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;
r.AlignHeight(r_height);
r.SetVAlign();
max_height := r_height - total_height + max_height;
end
for j,range in cell_range_array_[i] do
begin
if not ifObj(range) or range.VMerge then continue;
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);
begin
{self.}SetTcPr(tc_pr);
tbl_style_pr := docx_components_ware_.GetTblStylePrByType(tbl_pr_unit_decorator_.TblStyle.Val, type);
if tbl_style_pr then tc_pr.Copy(tbl_style_pr.TcPr);
end;
function TSPdfTableRange.ResetCoordinates(tbl_pr: TblPr; grid_cols: array of GridCol);
begin
total_width := 0;
for _,grid_col in grid_cols do
total_width += grid_col.W;
diff := total_width - {self.}Width;
case tbl_pr.Jc.Val of
"center":
begin
offset := diff/2;
{self.}StartX -= offset;
end
"right":
begin
{self.}StartX -= diff;
end
end;
{self.}Width := total_width;
end;
function TSPdfTableRange.SetTblPr(var tbl_pr: TblPr);
begin
new_tbl_pr := new TblPr();
{self.}SetTblPrByStyleId(new_tbl_pr, tbl_pr.TblStyle.Val);
new_tbl_pr.Copy(tbl_pr);
tbl_pr.Copy(new_tbl_pr);
end;
function TSPdfTableRange.SetTblPrByStyleId(var tbl_pr: TblPr; 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.}SetTblPrByStyleId(tbl_pr, based_on);
tbl_pr.Copy(style.TblPr);
end
end;
function TSPdfTableRange.SetTrPr(var tr_pr: TrPr);
begin
new_tr_pr := new TrPr();
{self.}SetTrPrByStyleId(new_tr_pr, tbl_pr_unit_decorator_.TblStyle.Val);
if ifObj(tr_pr) then
begin
new_tr_pr.Copy(tr_pr);
tr_pr.Copy(new_tr_pr);
end
end;
function TSPdfTableRange.SetTrPrByStyleId(var tr_pr: TrPr; 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.}SetTrPrByStyleId(tr_pr, based_on);
tr_pr.Copy(style.TrPr);
end
end;
function TSPdfTableRange.SetTcPr(var tc_pr: TcPr);
begin
new_tc_pr := new TcPr();
{self.}SetTcPrByStyleId(new_tc_pr, tbl_pr_unit_decorator_.TblStyle.Val);
if ifObj(tc_pr) then
begin
new_tc_pr.Copy(tc_pr);
tc_pr.Copy(new_tc_pr);
end
end;
function TSPdfTableRange.SetTcPrByStyleId(var tc_pr: TcPr; 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.}SetTcPrByStyleId(tc_pr, based_on);
tc_pr.Copy(style.TcPr);
end
end;
function TSPdfTableRange.FirstValidTSPage(): TSPage;
begin
range := cell_range_array_[0][0];
return ifObj(range) ? range.TSPage : page_;
end;
function TSPdfTableRange.IsSamePage(): boolean;
begin
return page_ = {self.}TSPage;
end;
function TSPdfTableRange.GetLastPage(): TSPage;
begin
return page_;
end;