PdfConverter/range/Advanced/TSPdfCellRange.tsf

229 lines
7.3 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; tr_pr: TrPr);
function Calc();
function Do();override;
function SetTSPage(page: TSPage);
function GetLastPage();
function AlignHeight(height: real);
function IsSamePage(): boolean;
function FirstValidTSPage(): TSPage;
function SetVAlign();
function IsReComputeByCantSplit(): boolean;
function IfRemoveEmptyRectangle(): boolean;
public
VMerge;
RemoveFlag;
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;
type Region = class
function Create();
begin
RectangleRange := new TSPdfRectangleRange();
RangeArr := array();
end
RectangleRange: TSPdfRectangleRange;
RangeArr: array of TSPdfAbstractRange;
end;
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;
end;
function TSPdfCellRange.Calc();
begin
region_array_ := array();
region := new Region();
region.RectangleRange.EndX := {self.}StartX;
region.RectangleRange.EndY := {self.}StartY;
region.RectangleRange.Width := {self.}Width;
region.RectangleRange.FixedHeight := {self.}FixedHeight;
region.RectangleRange.TSPage := page_;
region.RectangleRange.TcPr := tc_.TcPr;
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_, 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_, 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;
page_ := range.GetLastPage();
end
end
{self.}EndY := cell_y;
{self.}DynamicHeight += tbl_pr_.TblCellMar.Top.W + tbl_pr_.TblCellMar.Bottom.W;
end;
function TSPdfCellRange.Do();override;
begin
for _,region in region_array_ do
begin
if _ = 0 and {self.}RemoveFlag then continue;
region.RectangleRange.Do();
for _,range in region.RangeArr do
range.Do();
end
end;
function TSPdfCellRange.SetTSPage(page: TSPage);
begin
page_ := page;
{self.}TSPage := page;
end;
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 {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();
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_);
region := new Region();
region.RectangleRange.EndX := {self.}StartX;
region.RectangleRange.EndY := y;
region.RectangleRange.Width := {self.}Width;
region.RectangleRange.DynamicHeight := span;
region.RectangleRange.TSPage := page_;
region.RectangleRange.TcPr := tc_.TcPr;
region_array_[length(region_array_)] := region;
surplus -= span;
hash[region.RectangleRange.TSPage.Index] := region;
end
if surplus > 1e-6 then
begin
page_ := docx_to_pdf_.GetNextPage(page_);
region := new Region();
region.RectangleRange.EndX := {self.}StartX;
region.RectangleRange.EndY := y;
region.RectangleRange.Width := {self.}Width;
region.RectangleRange.DynamicHeight := surplus;
region.RectangleRange.TSPage := page_;
region.RectangleRange.TcPr := tc_.TcPr;
region_array_[length(region_array_)] := region;
hash[region.RectangleRange.TSPage.Index] := region;
{self.}EndY := region.RectangleRange.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 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.RectangleRange.EndY - region.RectangleRange.DynamicHeight) - tbl_pr_.TblCellMar.Bottom.W;
case val of
"center":
begin
offset /= 2;
for _,range in arr do
range.AdjustRangeOffset(region.RectangleRange.TSPage, nil, -offset);
end
end;
end;
function TSPdfCellRange.IsSamePage(): boolean;
begin
return page_ = {self.}TSPage;
end;
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;
function TSPdfCellRange.IfRemoveEmptyRectangle(): boolean;
begin
if length(region_array_) < 2 then return false;
return length(region_array_[0].RangeArr) ? false : true;
end;