对range进行重构

This commit is contained in:
csh 2024-07-04 11:20:10 +08:00
parent 999a7ef2d0
commit 51dc8596be
13 changed files with 562 additions and 422 deletions

View File

@ -242,25 +242,23 @@ function TSDocxToPdf.TransformParagraph(sect_ware: TSSectWare; paragraph: P);
begin
w := sect_ware.SectPr.PgSz.W - sect_ware.SectPr.PgMar.Right - sect_ware.SectPr.PgMar.Left;
range := new TSPdfParagraphRange(self, current_page_, docx_components_, sect_ware, paragraph);
range.X := point_.X;
range.Y := point_.Y;
range.W := w;
range.H := 0;
range.StartX := point_.X;
range.StartY := point_.Y;
range.Width := w;
range.Calc();
range.Do();
point_.Y := range.Y;
point_.Y := range.EndY;
end;
function TSDocxToPdf.TransformTable(sect_ware: TSSectWare; table: Tbl);
begin
w := sect_ware.SectPr.PgSz.W - sect_ware.SectPr.PgMar.Right - sect_ware.SectPr.PgMar.Left;
range := new TSPdfTableRange(self, current_page_, docx_components_, sect_ware, table);
range.X := point_.X;
range.Y := point_.Y;
range.W := w;
range.H := 0;
range.StartX := point_.X;
range.StartY := point_.Y;
range.Width := w;
range.Calc();
range.Do();
point_.Y := range.Y;
point_.Y := range.EndY;
end;

View File

@ -0,0 +1,147 @@
type TSPdfCellRange = class(TSPdfBasicRange)
public
function Create(docx_to_pdf: TSDocxToPdf; pg: PdfPage; components: Components; sect_ware: TSSectWare; tc: Tc; tbl_pr: TblPr);
function Calc();
function AlignHeight(surplus: real);
function GetLastPage();
function Do();override;
private
docx_to_pdf_: TSDocxToPdf;
page_: PdfPage;
docx_components_: Components;
sect_ware_: TSSectWare;
tc_: Tc;
tbl_pr_: TblPr;
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(docx_to_pdf: TSDocxToPdf; pg: PdfPage; components: Components; sect_ware: TSSectWare; tc: Tc; tbl_pr: TblPr);
begin
docx_to_pdf_ := docx_to_pdf;
page_ := pg;
docx_components_ := components;
sect_ware_ := sect_ware;
tc_ := tc;
tbl_pr_ := tbl_pr;
region_array_ := array();
self.Page := page_;
end;
function TSPdfCellRange.Calc();
begin
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.Page := page_;
region_array_[length(region_array_)] := region;
self.EndX := self.StartX;
self.EndY := self.StartY;
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_, sect_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_, sect_ware_, element);
end
if ifObj(range) then
begin
range.StartX := cell_x;
range.StartY := cell_y;
range.Width := cell_w;
range.FixedHeight := cell_h;
range.Calc();
region.RangeArr[length(region.RangeArr)] := range;
self.DynamicHeight += range.DynamicHeight;
cell_y -= range.DynamicHeight;
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
region.RectangleRange.Do();
for _,range in region.RangeArr do
range.Do();
end
end;
function TSPdfCellRange.AlignHeight(surplus: real);
begin
region := region_array_[0];
if surplus < 1e-6 then
begin
if region.RectangleRange.FixedHeight then region.RectangleRange.DynamicHeight := region.RectangleRange.FixedHeight;
self.EndY := self.StartY - region.RectangleRange.DynamicHeight;
return;
end
region.RectangleRange.DynamicHeight := self.StartY - sect_ware_.SectPr.PgMar.Bottom;
arr := region.RangeArr;
region.RangeArr := array();
span := sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Top - sect_ware_.SectPr.PgMar.Bottom;
hash := array(region.RectangleRange.Page: region);
while surplus > span do
begin
page_ := docx_to_pdf_.GetNextPage(page_);
region := new Region();
region.RectangleRange.EndX := self.StartX;
region.RectangleRange.EndY := self.StartY;
region.RectangleRange.Width := self.Width;
region.RectangleRange.DynamicHeight := span;
region.Page := page_;
region_array_[length(region_array_)] := region;
surplus -= span;
hash[region.RectangleRange.Page] := 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 := sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Top;
region.RectangleRange.Width := self.Width;
region.RectangleRange.DynamicHeight := surplus;
region.RectangleRange.Page := page_;
region_array_[length(region_array_)] := region;
hash[region.RectangleRange.Page] := region;
self.EndY := region.RectangleRange.EndY - surplus;
end
for _,range in arr do
begin
region := hash[range.Page];
region.RangeArr[length(region.RangeArr)] := range;
end
end;
function TSPdfCellRange.GetLastPage();
begin
return page_;
end;

View File

@ -0,0 +1,59 @@
type TSPdfLineRange = class(TSPdfBasicRange)
public
function Create(pg: PdfPage);
function Do();override;
function AddRange(range: TSPdfBasicRange);
function SetAllRangeProp(pg: PdfPage; sx: real; sy: real; ex: real; ey: real; w: real; fh: real; dh: real);
function Align(jc: string);
private
range_array_: array of TSPdfBasicRange;
end;
function TSPdfLineRange.Create(pg: PdfPage);
begin
self.Page := pg;
range_array_ := array();
end;
function TSPdfLineRange.AddRange(range: TSPdfBasicRange);
begin
range_array_[length(range_array_)] := range;
end;
function TSPdfLineRange.Do();override;
begin
for _,range in range_array_ do
range.Do();
end;
function TSPdfLineRange.SetAllRangeProp(pg: PdfPage; sx: real; sy: real; ex: real; ey: real; w: real; fh: real; dh: real);
begin
for _,range in range_array_ do
begin
if not ifnil(pg) then range.Page := pg;
if not ifnil(sx) then range.StartX := sx;
if not ifnil(sy) then range.StartY := sy;
if not ifnil(ex) then range.EndX := ex;
if not ifnil(ey) then range.EndY := ey;
if not ifnil(w) then range.Width := w;
if not ifnil(fh) then range.FixedHeight := fh;
if not ifnil(dh) then range.DynamicHeight := dh;
end
end;
function TSPdfLineRange.Align(jc: string);
begin
offset := 0;
first := range_array_[0];
last := range_array_[length(range_array_)-1];
case jc of
"center":
offset := (self.Width - last.EndX + first.EndX - last.Width) / 2;
"right":
offset := self.Width - last.EndX + first.EndX - last.Width;
end;
if offset <= 0 then return;
for _,range in range_array_ do
range.EndX += offset;
end;

View File

@ -1,6 +1,6 @@
type TSPdfParagraphRange = class(TSPdfAbstractRange)
type TSPdfParagraphRange = class(TSPdfBasicRange)
public
function Create(docx_to_pdf: TSDocxToPdf; page: PdfPage; components: Components; sect_ware: TSSectWare; paragraph: P);
function Create(docx_to_pdf: TSDocxToPdf; pg: PdfPage; components: Components; sect_ware: TSSectWare; paragraph: P);
function Calc();
function Do();override;
function SetExtraStyleId(style_id: string);
@ -21,6 +21,7 @@ private
function RToDrawingRange(r: R; ppr: PPr);
function SetLinesAlignment(ppr: PPr);
function ResetCoordinates(ppr);
function NewLineRange(): TSPdfLineRange;
private
docx_to_pdf_: TSDocxToPdf;
@ -28,23 +29,22 @@ private
sect_ware_: TSSectWare;
paragraph_: P;
extra_style_id_: string;
range_array_: array of TSPdfAbstractRange;
page_: PdfPage;
point_: TSPoint;
lines_range_array_: tableArray;
range_array_: array of TSPdfBasicRange;
line_range_array_: array of TSPdfLineRange;
end;
function TSPdfParagraphRange.Create(docx_to_pdf: TSDocxToPdf; page: PdfPage; components: Components; sect_ware: TSSectWare; paragraph: P);
function TSPdfParagraphRange.Create(docx_to_pdf: TSDocxToPdf; pg: PdfPage; components: Components; sect_ware: TSSectWare; paragraph: P);
begin
docx_to_pdf_ := docx_to_pdf;
page_ := page;
page_ := pg;
docx_components_ := Components;
sect_ware_ := sect_ware;
paragraph_ := paragraph;
extra_style_id_ := "";
range_array_ := array();
point_ := new TSPoint(); // 动态记录段落的坐标位置
lines_range_array_ := array();
line_range_array_ := array();
self.Page := page_;
end;
function TSPdfParagraphRange.Calc(): tableArray;
@ -53,16 +53,17 @@ begin
self.SetLvlText();
ppr := new PPrUnitDecorator(paragraph_.PPr);
self.ResetCoordinates(ppr);
point_.X := self.X;
point_.Y := self.Y;
self.CheckAndAddPage(point_.Y, ppr.Spacing.Before);
point_.Y -= ppr.Spacing.Before;
self.EndX := self.StartX;
self.EndY := self.StartY;
self.CheckAndAddPage(self.EndY, ppr.Spacing.Before);
self.EndY -= ppr.Spacing.Before;
self.DynamicHeight += ppr.Spacing.Before;
rs := paragraph_.Rs();
if length(rs) = 0 then
begin
line_space := self.GetParagraphLineSpace(ppr.RPr.Sz.Val, ppr.Spacing.Line);
if not self.H then self.H := ppr.Spacing.After + line_space;
point_.Y -= self.H;
self.DynamicHeight += ppr.Spacing.After + line_space;
self.EndY -= self.DynamicHeight;
end
else begin
for _, r in rs do
@ -79,9 +80,8 @@ end;
function TSPdfParagraphRange.Do();
begin
for _,line_range in lines_range_array_ do
for _,range in line_range do
range.Do();
for _,line_range in line_range_array_ do
line_range.Do();
end;
function TSPdfParagraphRange.SetExtraStyleId(style_id: string);
@ -89,94 +89,80 @@ begin
extra_style_id_ := style_id;
end;
function TSPdfParagraphRange.NewLineRange(): TSPdfLineRange;
begin
line_range := new TSPdfLineRange(page_);
line_range.StartX := self.EndX;
line_range.StartY := self.EndY;
line_range.Width := self.Width;
return line_range;
end;
function TSPdfParagraphRange.RangesToLines(ppr: PPr);
begin
lines_range_array_ := array();
line_range := self.NewLineRange();
i := 0;
max_size := 0;
max_y := 0;
line_range := array();
total_height := 0;
while i <= length(range_array_)-1 do
begin
range := range_array_[i];
if i = 0 then point_.X += ppr.Ind.FirstLine;
if i = 0 then self.EndX += ppr.Ind.FirstLine;
if range is class(TSPdfTextRange) and range.RPr.Sz.Val > max_size then
max_size := range.RPr.Sz.Val;
if range.H > max_y then max_y := range.H;
if range.DynamicHeight > max_y then max_y := range.DynamicHeight;
line_space := self.GetParagraphLineSpace(max_size, ppr.Spacing.Line);
diff := point_.Y - sect_ware_.SectPr.PgMar.Bottom;
if self.CheckAndAddPage(point_.Y, max(line_space, range.H)) then
total_height += diff;
if_newline := point_.X + range.W - self.X > self.W + 1e-6;
if if_newline and range.W < self.W then
diff := self.EndY - sect_ware_.SectPr.PgMar.Bottom;
if self.CheckAndAddPage(self.EndY, max(line_space, range.DynamicHeight)) then
self.DynamicHeight += diff;
if_newline := self.EndX + range.Width - self.StartX > self.Width + 1e-6;
if if_newline and range.Width < self.Width then
begin
offset := line_space > max_y ? (line_space - max_size) / 2 + max_size - max_size / 5 : max_y;
for _,item in line_range do
begin
item.Page := page_;
item.Y := point_.Y - offset;
end
lines_range_array_[length(lines_range_array_)] := line_range;
line_range := array();
max_value := max(line_space, max_y);
line_range.Page := page_;
line_range.EndY := self.EndY - max_value;
line_range.DynamicHeight := max_value;
line_range.SetAllRangeProp(pg: page_, ey: self.EndY - offset);
line_range_array_[length(line_range_array_)] := line_range;
line_range := self.NewLineRange();
max_size := 0;
max_y := 0;
total_height += max_value;
point_.Y -= max_value;
point_.X := self.X;
self.DynamicHeight += max_value;
self.EndY -= max_value;
self.EndX := self.StartX;
// w:hanging
sz := range.RPr.SzCs.Val ? range.RPr.SzCs.Val : range.RPr.Sz.Val ? range.RPr.Sz.Val : docx_to_pdf_.Font.GetDefaultSz();
point_.X -= ppr.Ind.HangingChars ? ppr.Ind.HangingChars * sz : ppr.Ind.Hanging;
self.EndX -= ppr.Ind.HangingChars ? ppr.Ind.HangingChars * sz : ppr.Ind.Hanging;
continue;
end
range.X := point_.X - range.X;
point_.X += range.W;
line_range[length(line_range)] := range;
range.EndX := self.EndX - range.StartX;
self.EndX += range.Width;
line_range.AddRange(range);
i++;
if i = length(range_array_) then
begin
offset := line_space > max_y ? (line_space - max_size) / 2 + max_size - max_size / 5 : max_y;
for _,item in line_range do
begin
item.Page := page_;
item.Y := point_.Y - offset;
end
lines_range_array_[length(lines_range_array_)] := line_range;
max_value := max(line_space, max_y) + ppr.Spacing.After;
total_height += max_value;
point_.Y -= max_value;
line_range.Page := page_;
line_range.EndY := self.EndY - max_value;
line_range.DynamicHeight := max_value;
line_range.SetAllRangeProp(pg: page_, ey: self.EndY - offset);
line_range_array_[length(line_range_array_)] := line_range;
self.DynamicHeight += max_value;
self.EndY -= max_value;
end
end
self.SetLinesAlignment(ppr);
if not self.H then self.H := total_height;
self.Y := point_.Y;
end;
function TSPdfParagraphRange.SetLinesAlignment(ppr: PPr);
begin
if length(lines_range_array_) = 0 then return;
idx := length(lines_range_array_)-1;
line := lines_range_array_[idx];
offset := 0;
case ppr.Jc.Val of
"center":
begin
first := line[0];
last := line[length(line)-1];
offset := (self.W - last.X + first.X - last.W) / 2;
end
"right":
begin
first := line[0];
last := line[length(line)-1];
offset := self.W - last.X + first.X - last.W;
end
end;
if offset < 0 then return;
if offset then
for i:=0 to length(line)-1 do
line[i].X += offset;
if length(line_range_array_) = 0 then return;
idx := length(line_range_array_)-1;
line_range := line_range_array_[idx];
line_range.Align(ppr.Jc.Val);
end;
function TSPdfParagraphRange.CheckAndAddPage(y: real; offset: real): boolean;
@ -186,7 +172,7 @@ begin
page_ := docx_to_pdf_.GetNextPage(page_);
if ifnil(page_) then page_ := docx_to_pdf_.AddPage(sect_ware_);
point := docx_to_pdf_.GetCurrentPoint();
point_.Y := point.Y;
self.EndY := point.Y;
return true;
end
return false;
@ -229,10 +215,7 @@ begin
text_range.RPr := rpr;
text_range.Text := word;
text_range.Font := font_obj;
text_range.W := word_width;
text_range.H := 0;
text_range.X := 0;
text_range.Y := 0;
text_range.Width := word_width;
range_array_[length(range_array_)] := text_range;
end
end;
@ -257,10 +240,10 @@ begin
end;
image_range := new TSPdfImageRange();
image_range.Image := image;
image_range.X := xfrm.Off.X;
image_range.Y := xfrm.Off.Y;
image_range.W := xfrm.Ext.CX;
image_range.H := xfrm.Ext.CY;
image_range.StartX := xfrm.Off.X;
image_range.StartY := xfrm.Off.Y;
image_range.Width := xfrm.Ext.CX;
image_range.DynamicHeight := xfrm.Ext.CY;
fileDelete("", image_path);
range_array_[length(range_array_)] := image_range;
end;
@ -360,7 +343,7 @@ function TSPdfParagraphRange.ResetCoordinates(ppr);
begin
// 根据段落的间距确定新的坐标
sz := ppr.RPr.SzCs.Val ? ppr.RPr.SzCs.Val : ppr.RPr.Sz.Val ? ppr.RPr.Sz.Val : docx_to_pdf_.Font.GetDefaultSz();
self.X += ppr.Ind.LeftChars ? ppr.Ind.LeftChars * sz : ppr.Ind.Left;
self.W -= ppr.Ind.LeftChars ? ppr.Ind.LeftChars * sz : ppr.Ind.Left;
self.W -= ppr.Ind.RightChars ? ppr.Ind.RightChars * sz : ppr.Ind.Right;
self.StartX += ppr.Ind.LeftChars ? ppr.Ind.LeftChars * sz : ppr.Ind.Left;
self.Width -= ppr.Ind.LeftChars ? ppr.Ind.LeftChars * sz : ppr.Ind.Left;
self.Width -= ppr.Ind.RightChars ? ppr.Ind.RightChars * sz : ppr.Ind.Right;
end;

View File

@ -0,0 +1,187 @@
type TSPdfTableRange = class(TSPdfBasicRange)
public
function Create(docx_to_pdf: TSDocxToPdf; pg: PdfPage; components: Components; sect_ware: TSSectWare; paragraph: P);
function Calc();
function Do();override;
private
function ProcessTrData(grid_cols: array of GridCol; tr: Tr; tbl_pr: TblPr): array of TSPdfAbstractRange;
function ResetCoordinates(tbl_pr: TblPr; grid_cols: array of GridCol);
function CheckAndAddPage(y: real; offset: real): boolean;
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);
private
docx_to_pdf_: TSDocxToPdf;
docx_components_: Components;
sect_ware_: TSSectWare;
table_: Tbl;
range_array_: tableArray;
page_: PdfPage;
point_: TSPoint;
end;
function TSPdfTableRange.Create(docx_to_pdf: TSDocxToPdf; pg: PdfPage; components: Components; sect_ware: TSSectWare; table: Tbl);
begin
docx_to_pdf_ := docx_to_pdf;
page_ := pg;
docx_components_ := Components;
sect_ware_ := sect_ware;
table_ := table;
range_array_ := array();
self.Page := page_;
end;
function TSPdfTableRange.Calc();
begin
self.SetTblPr(table_.TblPr);
tbl_pr := 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, grid_cols);
self.EndX := self.StartX;
self.EndY := self.StartY;
// 如果是根据内容自适应应该计算并调整grid_cols的值
trs := table_.Trs();
for i,tr in trs do
range_array_[i] := self.ProcessTrData(grid_cols, tr, tbl_pr);
end;
function TSPdfTableRange.Do();
begin
for _,row in range_array_ do
for _,range in row do
range.Do();
end;
function TSPdfTableRange.CheckAndAddPage(y: real; offset: real): boolean;
begin
if y - offset < sect_ware_.SectPr.PgMar.Bottom then
begin
page_ := docx_to_pdf_.GetNextPage(page_);
if ifnil(page_) then page_ := docx_to_pdf_.AddPage(sect_ware_);
point := docx_to_pdf_.GetCurrentPoint();
self.EndY := point.Y;
return true;
end
return false;
end;
function TSPdfTableRange.ProcessTrData(grid_cols: array of GridCol; tr: Tr; tbl_pr: TblPr): array of TSPdfAbstractRange;
begin
self.SetTrPr(tr.TrPr);
tr_pr := new TrPrUnitDecorator(tr.TrPr);
height := tr_pr.TrHeight.Val;
tc_x := self.EndX;
tc_y := self.EndY;
tc_h := height;
max_height := 0;
cell_range_array := array();
tcs := tr.Tcs();
for i,tc in tcs do
begin
cell_range := new TSPdfCellRange(docx_to_pdf_, page_, docx_components_, sect_ware_, tc, tbl_pr);
cell_range.StartX := tc_x;
cell_range.StartY := tc_y;
cell_range.Width := grid_cols[i].W;
cell_range.FixedHeight := tc_h;
cell_range.Calc();
tc_x += grid_cols[i].W;
if cell_range.DynamicHeight > max_height then max_height := cell_range.DynamicHeight;
cell_range_array[length(cell_range_array)] := cell_range;
end
if tc_h > max_height then max_height := tc_h;
surplus := max_height - (self.EndY - sect_ware_.SectPr.PgMar.Bottom);
for _,range in cell_range_array do
begin
range.AlignHeight(surplus);
self.EndY := range.EndY; // 理论上每个range.EndY都是一个值
page_ := range.GetLastPage();
end
return cell_range_array;
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 := class(TSPdfSingletonKit).GetComponent(docx_components_, "styles_adapter");
style := styles.StyleId(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, table_.TblPr.TblStyle.Val);
new_tr_pr.Copy(tr_pr);
tr_pr.Copy(new_tr_pr);
end;
function TSPdfTableRange.SetTrPrByStyleId(var tr_pr: TrPr; style_id: string);
begin
styles := class(TSPdfSingletonKit).GetComponent(docx_components_, "styles_adapter");
style := styles.StyleId(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, table_.TblPr.TblStyle.Val);
new_tc_pr.Copy(tc_pr);
tc_pr.Copy(new_tc_pr);
end;
function TSPdfTableRange.SetTcPrByStyleId(var tc_pr: TcPr; style_id: string);
begin
styles := class(TSPdfSingletonKit).GetComponent(docx_components_, "styles_adapter");
style := styles.StyleId(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;

View File

@ -1,10 +0,0 @@
type TSPdfAbstractRange = class
public
function Do();virtual;
public
X: real;
Y: real; // range的起始坐标(x,y)
W: real; // range的宽度
H: real; // range的高度
end;

View File

@ -1,21 +0,0 @@
type TSPdfImageRange = class(TSPdfAbstractRange)
public
function Do();override;
public
Page: PdfPage;
Image: PdfImage;
end;
function TSPdfImageRange.Do();
begin
// println("image = {}, x = {}, y = {}, w = {}, h = {}", image, x, y, w, h);
self.Page.DrawImage(self.Image, self.X, self.Y, self.W, self.H);
if sysparams["_PDF_IMAGE_DEBUG_"] then
begin
self.Page.SetLineWidth(0.1);
self.Page.SetRGBStroke(0.8, 0.8, 0);
self.Page.Rectangle(X, Y, W, H);
self.Page.Stroke();
end
end;

View File

@ -1,16 +0,0 @@
type TSPdfRectRange = class(TSPdfAbstractRange)
public
function Do();override;
public
Page: PdfPage;
end;
function TSPdfRectRange.Do();override;
begin
// self.Page.SetRGBStroke(1.0, 0.0, 0.0);
self.Page.SetGrayStroke(0.5);
self.Page.SetLineWidth(0.5);
self.Page.Rectangle(self.X, self.Y - self.H, self.W, self.H);
self.Page.Stroke();
self.Page.SetGrayStroke(0);
end;

View File

@ -1,273 +0,0 @@
type TSPdfTableRange = class(TSPdfAbstractRange)
public
function Create(docx_to_pdf: TSDocxToPdf; page: PdfPage; components: Components; sect_ware: TSSectWare; paragraph: P);
function Calc();
function Do();override;
private
function ProcessTrData(grid_cols: array of GridCol; tr: Tr; tbl_pr: TblPr): array of TSPdfAbstractRange;
function ResetCoordinates(tbl_pr: TblPr; grid_cols: array of GridCol);
function CheckAndAddPage(y: real; offset: real): boolean;
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);
private
docx_to_pdf_: TSDocxToPdf;
docx_components_: Components;
sect_ware_: TSSectWare;
table_: Tbl;
range_array_: tableArray;
page_: PdfPage;
point_: TSPoint;
end;
function TSPdfTableRange.Create(docx_to_pdf: TSDocxToPdf; page: PdfPage; components: Components; sect_ware: TSSectWare; table: Tbl);
begin
docx_to_pdf_ := docx_to_pdf;
page_ := page;
docx_components_ := Components;
sect_ware_ := sect_ware;
table_ := table;
range_array_ := array();
point_ := new TSPoint(); // 动态记录段落的坐标位置
end;
function TSPdfTableRange.Calc();
begin
self.SetTblPr(table_.TblPr);
tbl_pr := 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, grid_cols);
point_.X := self.X;
point_.Y := self.Y;
// 如果是根据内容自适应应该计算并调整grid_cols的值
trs := table_.Trs();
for i,tr in trs do
range_array_[i] := self.ProcessTrData(grid_cols, tr, tbl_pr);
end;
function TSPdfTableRange.Do();
begin
for _,row in range_array_ do
for _,range in row do
range.Do();
end;
function TSPdfTableRange.CheckAndAddPage(y: real; offset: real): boolean;
begin
if y - offset < sect_ware_.SectPr.PgMar.Bottom then
begin
page_ := docx_to_pdf_.GetNextPage(page_);
if ifnil(page_) then page_ := docx_to_pdf_.AddPage(sect_ware_);
point := docx_to_pdf_.GetCurrentPoint();
point_.Y := point.Y;
return true;
end
return false;
end;
function TSPdfTableRange.ProcessTrData(grid_cols: array of GridCol; tr: Tr; tbl_pr: TblPr): array of TSPdfAbstractRange;
begin
self.SetTrPr(tr.TrPr);
tr_pr := new TrPrUnitDecorator(tr.TrPr);
height := tr_pr.TrHeight.Val;
tcs := tr.Tcs();
tc_x := point_.X;
tc_y := point_.Y;
tc_h := height;
max_height := tc_h;
rows_range_array := array();
for i,tc in tcs do
begin
tc_w := grid_cols[i].W;
elements := tc.Elements();
rect_range := new TSPdfRectRange();
rect_range.X := tc_x;
rect_range.Y := tc_y;
rect_range.W := tc_w;
rect_range.H := tc_h;
rect_range.Page := page_;
rows_range_array[length(rows_range_array)] := rect_range;
cell_x := tc_x + tbl_pr.TblCellMar.Left.W;
cell_y := tc_y - tbl_pr.TblCellMar.Top.W;
cell_w := tc_w - tbl_pr.TblCellMar.Right.W - tbl_pr.TblCellMar.Left.W;
cell_total_h := 0;
for _,element in elements do
begin
range := nil;
if element.LocalName = "p" then
begin
range := new TSPdfParagraphRange(docx_to_pdf_, page_, docx_components_, sect_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_, sect_ware_, element);
end
if ifObj(range) then
begin
range.X := cell_x;
range.Y := cell_y;
range.W := cell_w;
range.H := tc_h;
range.Calc();
rows_range_array[length(rows_range_array)] := range;
cell_total_h += range.H;
cell_y -= range.H;
end
end
tc_x += tc_w;
if cell_total_h > max_height then max_height := cell_total_h;
end
// 判定是否跨页
total_height := max_height + tbl_pr.TblCellMar.Top.W + tbl_pr.TblCellMar.Bottom.W;
surplus := total_height - (point_.Y - sect_ware_.SectPr.PgMar.Bottom);
if not self.H and surplus > 0 then
begin
for _,range in rows_range_array do
range.H := point_.Y - sect_ware_.SectPr.PgMar.Bottom;
span := sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Top - sect_ware_.SectPr.PgMar.Bottom;
quotient := surplus div span;
remainder := surplus % span;
page := page_;
tc_y := point_.Y;
i := 0;
while i < quotient do
begin
tc_x := point_.X;
tc_y := sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Top;
tc_h := tc_y - sect_ware_.SectPr.PgMar.Bottom;
page := docx_to_pdf_.GetNextPage(page);
for j:=0 to length(tcs)-1 do
begin
tc_w := grid_cols[i].W;
rect_range := new TSPdfRectRange();
rect_range.X := tc_x;
rect_range.Y := tc_y;
rect_range.W := tc_w;
rect_range.H := tc_h;
rect_range.Page := page;
tc_x += tc_w;
rows_range_array[length(rows_range_array)] := rect_range;
end
i++;
end
if remainder then
begin
tc_x := point_.X;
tc_y := sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Top;
tc_h := remainder;
page := docx_to_pdf_.GetNextPage(page);
for j:=0 to length(tcs)-1 do
begin
tc_w := grid_cols[i].W;
rect_range := new TSPdfRectRange();
rect_range.X := tc_x;
rect_range.Y := tc_y;
rect_range.W := tc_w;
rect_range.H := tc_h;
rect_range.Page := page;
tc_x += tc_w;
rows_range_array[length(rows_range_array)] := rect_range;
end
end
point_.Y := tc_y - remainder;
self.Y := point_.Y;
page_ := page;
end
else begin
tc_h := tc_h ? tc_h : max_height;
for _,range in rows_range_array do
range.H := tc_h;
point_.Y -= tc_h;
self.Y := point_.Y;
end
return rows_range_array;
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.W;
case tbl_pr.jc.Val of
"center":
begin
offset := diff/2;
self.X -= offset;
end
"right":
begin
self.X -= diff;
end
end;
self.W := 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 := class(TSPdfSingletonKit).GetComponent(docx_components_, "styles_adapter");
style := styles.StyleId(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, table_.TblPr.TblStyle.Val);
new_tr_pr.Copy(tr_pr);
tr_pr.Copy(new_tr_pr);
end;
function TSPdfTableRange.SetTrPrByStyleId(var tr_pr: TrPr; style_id: string);
begin
styles := class(TSPdfSingletonKit).GetComponent(docx_components_, "styles_adapter");
style := styles.StyleId(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, table_.TblPr.TblStyle.Val);
new_tc_pr.Copy(tc_pr);
tc_pr.Copy(new_tc_pr);
end;
function TSPdfTableRange.SetTcPrByStyleId(var tc_pr: TcPr; style_id: string);
begin
styles := class(TSPdfSingletonKit).GetComponent(docx_components_, "styles_adapter");
style := styles.StyleId(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;

View File

@ -0,0 +1,27 @@
type TSPdfBasicRange = class
public
function Create();
function Do();virtual;
public
StartX: real;
StartY: real; // range的起始坐标(x,y)
EndX: real;
EndY: real; // range的结束坐标(x,y)
Width: real;
FixedHeight: real;
DynamicHeight: real;
Page: PdfPage;
end;
function TSPdfBasicRange.Create();
begin
self.StartX := 0;
self.StartY := 0;
self.EndX := 0;
self.EndY := 0;
self.Width := 0;
self.FixedHeight := 0;
self.DynamicHeight := 0;
self.Page := nil;
end;

View File

@ -0,0 +1,28 @@
type TSPdfImageRange = class(TSPdfBasicRange)
public
function Create();
function Do();override;
public
Image: PdfImage;
end;
function TSPdfImageRange.Create();
begin
class(TSPdfBasicRange).Create();
self.Image := nil;
end;
function TSPdfImageRange.Do();
begin
// println("image = {}, x = {}, y = {}, w = {}, h = {}", self.image, self.endx, self.endy, self.width, self.DynamicHeight);
self.Page.DrawImage(self.Image, self.EndX, self.EndY, self.Width, self.DynamicHeight);
if sysparams["_PDF_IMAGE_DEBUG_"] then
begin
self.Page.SetLineWidth(0.1);
self.Page.SetRGBStroke(0.8, 0.8, 0);
self.Page.Rectangle(self.EndX, self.EndY, self.Width, self.DynamicHeight);
self.Page.Stroke();
end
end;

View File

@ -0,0 +1,22 @@
type TSPdfRectangleRange = class(TSPdfBasicRange)
public
function Create();
function Do();override;
end;
function TSPdfRectangleRange.Create();
begin
class(TSPdfBasicRange).Create();
end;
function TSPdfRectangleRange.Do();override;
begin
// self.Page.SetRGBStroke(1.0, 0.0, 0.0);
// println("page = {}, endx = {}, endy = {}, DynamicHeight = {}, Width = {}", self.Page, self.EndX, self.EndY, self.DynamicHeight, self.Width);
self.Page.SetGrayStroke(0.5);
self.Page.SetLineWidth(0.5);
self.Page.Rectangle(self.EndX, self.EndY - self.DynamicHeight, self.Width, self.DynamicHeight);
self.Page.Stroke();
self.Page.SetGrayStroke(0);
end;

View File

@ -1,23 +1,32 @@
type TSPdfTextRange = class(TSPdfAbstractRange)
type TSPdfTextRange = class(TSPdfBasicRange)
uses TSColorToolKit;
public
function Create();
function Do();override;
public
RPr: RPr;
Text: string;
Font: PdfFont;
Page: PdfPage;
end;
function TSPdfTextRange.Create();
begin
class(TSPdfBasicRange).Create();
self.RPr := nil;
self.Text := "";
self.Font := nil;
end;
function TSPdfTextRange.Do();
begin
// println("text = {}, x = {}, y = {}, w = {}, sz = {}", ansiToUtf8(text), x, y, w);
// println("text = {}, endx = {}, endy = {}, width = {}, page = {}", ansiToUtf8(text), endx, endy, width, page);
[r, g, b] := array(0, 0, 0);
if self.RPr.Color.Val then [r, g, b] := TSColorToolKit.HexToRGB(self.RPr.Color.Val);
self.Page.SetRGBFill(r / 255, g / 255, b / 255);
self.Page.SetFontAndSize(self.Font, self.RPr.Sz.Val);
self.Page.BeginText();
self.Page.TextOut(self.X, self.Y, self.Text);
self.Page.TextOut(self.EndX, self.EndY, self.Text);
self.Page.EndText();
self.Page.SetRGBFill(0, 0, 0);
@ -26,8 +35,8 @@ if sysparams["_PDF_TEXT_DEBUG_"] then
begin
self.Page.SetLineWidth(0.1);
self.Page.SetRGBStroke(1.0, 0.5, 0.0);
self.Page.MoveTo(0, self.Y);
self.Page.LineTo(600, self.Y);
self.Page.MoveTo(0, self.EndY);
self.Page.LineTo(600, self.EndY);
self.Page.Stroke();
end
end;