对range进行重构
This commit is contained in:
@@ -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;
|
||||
@@ -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;
|
||||
@@ -0,0 +1,349 @@
|
||||
type TSPdfParagraphRange = class(TSPdfBasicRange)
|
||||
public
|
||||
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);
|
||||
|
||||
private
|
||||
function SetPPr(var ppr: PPr);
|
||||
function SetPPrByStyleId(var ppr: PPr; style_id: string);
|
||||
function SetRPr(var rpr; ppr: PPr);
|
||||
function SetRPrByStyleId(var rpr: RPr; style_id: string);
|
||||
function SetLvlText();
|
||||
function GetImageFileType(data: binary): string;
|
||||
function GetParagraphLineSpace(size: real; line: integer): real;
|
||||
function RangesToLines(ppr: PPr): tableArray;
|
||||
function CheckAndAddPage(y: real; offset: real): boolean;
|
||||
function GetUtf8CharLength(byte: string): integer;
|
||||
function RToTextRange(r: R; ppr: PPr);
|
||||
function SplitTextToTextRange(text: string; rpr: RPr);
|
||||
function RToDrawingRange(r: R; ppr: PPr);
|
||||
function SetLinesAlignment(ppr: PPr);
|
||||
function ResetCoordinates(ppr);
|
||||
function NewLineRange(): TSPdfLineRange;
|
||||
|
||||
private
|
||||
docx_to_pdf_: TSDocxToPdf;
|
||||
docx_components_: Components;
|
||||
sect_ware_: TSSectWare;
|
||||
paragraph_: P;
|
||||
extra_style_id_: string;
|
||||
page_: PdfPage;
|
||||
range_array_: array of TSPdfBasicRange;
|
||||
line_range_array_: array of TSPdfLineRange;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.Create(docx_to_pdf: TSDocxToPdf; pg: PdfPage; components: Components; sect_ware: TSSectWare; paragraph: P);
|
||||
begin
|
||||
docx_to_pdf_ := docx_to_pdf;
|
||||
page_ := pg;
|
||||
docx_components_ := Components;
|
||||
sect_ware_ := sect_ware;
|
||||
paragraph_ := paragraph;
|
||||
extra_style_id_ := "";
|
||||
range_array_ := array();
|
||||
line_range_array_ := array();
|
||||
self.Page := page_;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.Calc(): tableArray;
|
||||
begin
|
||||
self.SetPPr(paragraph_.PPr);
|
||||
self.SetLvlText();
|
||||
ppr := new PPrUnitDecorator(paragraph_.PPr);
|
||||
self.ResetCoordinates(ppr);
|
||||
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);
|
||||
self.DynamicHeight += ppr.Spacing.After + line_space;
|
||||
self.EndY -= self.DynamicHeight;
|
||||
end
|
||||
else begin
|
||||
for _, r in rs do
|
||||
begin
|
||||
self.SetRPr(r.RPr, paragraph_.PPr);
|
||||
if r.Br.Type = "page" then
|
||||
self.CheckAndAddPage(sect_ware_.SectPr.PgMar.Bottom, 1);
|
||||
else if ifObj(r.Drawing.XmlNode) then self.RToDrawingRange(r, ppr);
|
||||
else self.RToTextRange(r, ppr);
|
||||
end
|
||||
end
|
||||
self.RangesToLines(ppr);
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.Do();
|
||||
begin
|
||||
for _,line_range in line_range_array_ do
|
||||
line_range.Do();
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.SetExtraStyleId(style_id: string);
|
||||
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
|
||||
line_range := self.NewLineRange();
|
||||
i := 0;
|
||||
max_size := 0;
|
||||
max_y := 0;
|
||||
while i <= length(range_array_)-1 do
|
||||
begin
|
||||
range := range_array_[i];
|
||||
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.DynamicHeight > max_y then max_y := range.DynamicHeight;
|
||||
line_space := self.GetParagraphLineSpace(max_size, ppr.Spacing.Line);
|
||||
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;
|
||||
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;
|
||||
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();
|
||||
self.EndX -= ppr.Ind.HangingChars ? ppr.Ind.HangingChars * sz : ppr.Ind.Hanging;
|
||||
continue;
|
||||
end
|
||||
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;
|
||||
max_value := max(line_space, max_y) + ppr.Spacing.After;
|
||||
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);
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.SetLinesAlignment(ppr: PPr);
|
||||
begin
|
||||
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;
|
||||
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 TSPdfParagraphRange.GetUtf8CharLength(byte: string): integer;
|
||||
begin
|
||||
if (_and(ord(byte), 0b10000000)) = 0 then
|
||||
return 1;
|
||||
else if (_and(ord(byte), 0b11100000)) = 0b11000000 then
|
||||
return 2;
|
||||
else if (_and(ord(byte), 0b11110000)) = 0b11100000 then
|
||||
return 3;
|
||||
else if (_and(ord(byte), 0b11111000)) = 0b11110000 then
|
||||
return 4;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.RToTextRange(r: R; ppr: PPr);
|
||||
begin
|
||||
rpr := new RPrUnitDecorator(r.RPr);
|
||||
text := r.T.Text;
|
||||
if ifString(text) then self.SplitTextToTextRange(text, rpr);
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.SplitTextToTextRange(text: string; rpr: RPr);
|
||||
begin
|
||||
pos := 1;
|
||||
while pos <= length(text) do
|
||||
begin
|
||||
num := self.GetUtf8CharLength(text[pos]);
|
||||
word := text[pos : pos+num-1];
|
||||
word := utf8ToAnsi(word);
|
||||
pos += num;
|
||||
font_name := rpr.RFonts.EastAsia ? rpr.RFonts.EastAsia : rpr.RFonts.Ascii;
|
||||
font_obj := docx_to_pdf_.Font.GetFont(font_name, rpr.B, rpr.I);
|
||||
if not rpr.Sz.Val then rpr.Sz.Val := rpr.SzCs.Val ? rpr.SzCs.Val : docx_to_pdf_.Font.GetDefaultSz();
|
||||
page_.SetFontAndSize(font_obj, rpr.Sz.Val);
|
||||
word_width := page_.TextWidth(word);
|
||||
text_range := new TSPdfTextRange();
|
||||
text_range.RPr := rpr;
|
||||
text_range.Text := word;
|
||||
text_range.Font := font_obj;
|
||||
text_range.Width := word_width;
|
||||
range_array_[length(range_array_)] := text_range;
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.RToDrawingRange(r: R; ppr: PPr);
|
||||
begin
|
||||
xfrm := new XfrmUnitDecorator(r.Drawing._Inline.Graphic.GraphicData.Pic.SpPr.Xfrm);
|
||||
rels_adapter := class(TSPdfSingletonKit).GetComponent(docx_components_, "document_rels_adapter");
|
||||
id := r.Drawing._Inline.Graphic.GraphicData.Pic.BlipFill.Blip.Embed;
|
||||
rel := rels_adapter.Id(id);
|
||||
image_path := "word/" + rel.Target;
|
||||
image := docx_components_.Zip().Get(image_path);
|
||||
data := image.Data();
|
||||
image_path := docx_to_pdf_.GetCachePath(image_path);
|
||||
writeFile(rwBinary(), "", image_path, 0, length(data)-1, data);
|
||||
image := nil;
|
||||
case self.GetImageFileType(data) of
|
||||
"png":
|
||||
image := docx_to_pdf_.GetPdf().LoadPngImageFromFile("", image_path);
|
||||
"jpg":
|
||||
image := docx_to_pdf_.GetPdf().LoadJpegImageFromFile("", image_path);
|
||||
end;
|
||||
image_range := new TSPdfImageRange();
|
||||
image_range.Image := image;
|
||||
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;
|
||||
|
||||
function TSPdfParagraphRange.GetImageFileType(data: binary): string;
|
||||
begin
|
||||
stream := new TMemoryStream();
|
||||
size := length(data);
|
||||
stream.Write(data[0:size-1], size);
|
||||
def := array(
|
||||
('name': 'png', 'position': 0, 'value': array(0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A)),
|
||||
('name': 'jpg', 'position': 0, 'value': array(0xFF, 0xD8)),
|
||||
);
|
||||
for i:=0 to length(def)-1 do
|
||||
begin
|
||||
value := def[i]['value'];
|
||||
stream.Seek(def[i]['position']);
|
||||
for j:=0 to length(value)-1 do
|
||||
begin
|
||||
r := 0;
|
||||
stream.Read(r, 1);
|
||||
if r <> value[j] then break;
|
||||
if j = length(value)-1 then return def[i]['name'];
|
||||
end
|
||||
end
|
||||
return '';
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.GetParagraphLineSpace(size: real; line: integer): real;
|
||||
begin
|
||||
if not line then line := 12;
|
||||
lines := roundto(line / 12, -1);
|
||||
multi := ceil(size / sect_ware_.BaseSize) * lines;
|
||||
return sect_ware_.SectPr.DocGrid.LinePitch * multi;
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.SetPPr(var ppr: PPr);
|
||||
begin
|
||||
new_ppr := new PPr();
|
||||
styles := class(TSPdfSingletonKit).GetComponent(docx_components_, "styles");
|
||||
new_ppr.Copy(styles.DocDefaults.PPrDefault.PPr);
|
||||
new_ppr.RPr.Copy(styles.DocDefaults.RPrDefault.RPr);
|
||||
self.SetPPrByStyleId(new_ppr, extra_style_id_);
|
||||
self.SetPPrByStyleId(new_ppr, ppr.PStyle.Val);
|
||||
new_ppr.Copy(ppr);
|
||||
ppr.Copy(new_ppr);
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.SetPPrByStyleId(var ppr: PPr; 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.SetPPrByStyleId(ppr, based_on);
|
||||
ppr.Copy(style.PPr);
|
||||
ppr.RPr.Copy(style.RPr);
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.SetRPr(var rpr; ppr: PPr);
|
||||
begin
|
||||
// rpr,先继承ppr,再继承样式,最后继承自己
|
||||
new_rpr := new RPr();
|
||||
style_id := rpr.RStyle.Val;
|
||||
new_rpr.Copy(ppr.RPr);
|
||||
self.SetRPrByStyleId(new_rpr, style_id);
|
||||
new_rpr.Copy(rpr);
|
||||
rpr.Copy(new_rpr);
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.SetRPrByStyleId(var rpr: RPr; 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.SetRPrByStyleId(rpr, based_on);
|
||||
rpr.Copy(style.RPr);
|
||||
end
|
||||
end;
|
||||
|
||||
function TSPdfParagraphRange.SetLvlText();
|
||||
begin
|
||||
numbering_ware := class(TSPdfSingletonKit).GetComponent(docx_components_, "numbering_ware");
|
||||
if not ifObj(numbering_ware) then return;
|
||||
[lvl_text, lvl] := numbering_ware.GetNumberLvl(paragraph_.PPr);
|
||||
if lvl_text = "" and ifnil(lvl) then return;
|
||||
self.SetRPr(lvl.RPr, paragraph_.PPr);
|
||||
rpr := new RPrUnitDecorator(lvl.RPr);
|
||||
self.SplitTextToTextRange(lvl_text, rpr);
|
||||
end;
|
||||
|
||||
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.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;
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user