2397 lines
79 KiB
Plaintext
2397 lines
79 KiB
Plaintext
unit DTPAdvancedRanges;
|
||
interface
|
||
uses DTPPrimitiveRanges, DTPUtils, DTPModules, SharedML, DocxML, DrawingMLUnitDecorator, DocxMLUnitDecorator, TSPdfEnumerations;
|
||
|
||
type AdvancedRange = class(BasicRange)
|
||
public
|
||
function Create();
|
||
function Do();virtual;
|
||
function Calc(): boolean;virtual;
|
||
function Offset(x: real; y: real; page: Page);virtual;
|
||
|
||
public
|
||
LowerBound: real;
|
||
StartPage: Page;
|
||
StartX: real;
|
||
StartY: real;
|
||
end;
|
||
|
||
type TocRange = class(AdvancedRange)
|
||
public
|
||
function Create();
|
||
function CalculateRect();
|
||
function LinkAnnot(dst: PdfDestination);
|
||
function AddPageNumber(pg: Page);
|
||
|
||
public
|
||
TextRange: TextRange;
|
||
BaseLine: real; // 目录...基线
|
||
[weakref]StartRange: AdvancedRange;
|
||
[weakref]EndRange: AdvancedRange;
|
||
|
||
private
|
||
rect_: array of real;
|
||
end;
|
||
|
||
type HdrRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; hdr: Hdr);
|
||
function Do();override;
|
||
function Calc(): boolean;override;
|
||
function Offset(x: real; y: real; page: Page);virtual;
|
||
function ProcessRealtimeArray();
|
||
|
||
private
|
||
function Traverse(obj: OpenXmlElement);
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
hdr_: Hdr;
|
||
range_array_: array of Range;
|
||
end;
|
||
|
||
type FtrRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; ftr: Ftr);
|
||
function Do();override;
|
||
function Calc(): boolean;override;
|
||
function Offset(x: real; y: real; page: Page);virtual;
|
||
function ProcessRealtimeArray();
|
||
|
||
private
|
||
function Traverse(obj: OpenXmlElement);
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
ftr_: Ftr;
|
||
range_array_: array of Range;
|
||
end;
|
||
|
||
type PLineRange = class(AdvancedRange)
|
||
public
|
||
function Create();
|
||
function Do();override;
|
||
function Offset(x: real; y: real; page: Page);override;
|
||
function CanFitInLine(range: BasicRange): boolean;
|
||
function AddRange(range: BasicRange);
|
||
function Align(val: string);
|
||
function AlignRightBound(right_bound: real);
|
||
function RangeArr(): array of BasicRange;
|
||
|
||
public
|
||
TextMaxSize: real; // 行的文字最大size
|
||
LineSpace: real; // 行间距
|
||
Index: integer;
|
||
private
|
||
range_array_: array of BasicRange;
|
||
end;
|
||
|
||
type PRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; p: P);
|
||
function Init();
|
||
function Do();override;
|
||
function Calc(): boolean;override;
|
||
function Offset(x: real; y: real; page: Page);override;
|
||
function DeterminePosition();
|
||
function ProcessRealtimeArray();
|
||
function IsFirstLineOnNextPage(): boolean;
|
||
function PLineRanges(): array of PLineRange;
|
||
|
||
property PPrUnitDecorator read ppr_unit_decorator_;
|
||
|
||
private
|
||
function RangesToLines();
|
||
function BasicRangesToPLineRange();
|
||
function UpdateTextRangeWidth();
|
||
function NewPLineRange(): PLineRange;
|
||
function AddPLineRange(pline_range: PLineRange);
|
||
function CheckAndAddPage(y: real; offset: real): boolean;
|
||
function AlignRightBound();
|
||
function HyperlinkToToc();
|
||
function DoDrawingAnchor();
|
||
function DoAlternateContentAnchor();
|
||
function DoToc();
|
||
|
||
function SetPPPr(var p: P);
|
||
function SetPPrByStyleId(var ppr: PPr; style_id: string);
|
||
function SetRRPr(var r: R; ppr_unit_decorator: PPrUnitDecorator);
|
||
function SetRPrByStyleId(var rpr: RPr; style_id: string);
|
||
function SetRPrByTblStyleId(var rpr: RPr; style_id: string);
|
||
function SetLvlText();
|
||
function GetXYCordinates(): array of real;
|
||
function GetImageFileType(data: binary): string;
|
||
function GetImageData(id: string): PdfImage;
|
||
function GetParagraphLineSpace(size: real; line: integer; line_rule: string): real;
|
||
function SplitTextToTextRange(range_arr: array of BasicRange; text: string; rpr: RPrUnitDecorator; anchor: string);
|
||
|
||
function RBr(r: R);
|
||
function RFootnoteReference(r: R);
|
||
function RT(r: R; anchor: string);
|
||
function RDrawing(r: R);
|
||
function RFldChar(r: R; stack: Stack);
|
||
function RAlternateContent(r: R);
|
||
function FldSimple(fld_simple: fldSimple);
|
||
function Hyperlink(hyperlink: Hyperlink);
|
||
function OMathPara(o_math_para: OMathPara);
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
p_: P;
|
||
ppr_unit_decorator_: PPrUnitDecorator;
|
||
body_range_array_: array of BasicRange; // 正文range
|
||
bullet_range_array_: array of BasicRange; // 项目符号的range
|
||
line_range_array_: array of PLineRange; // 行range
|
||
drawing_anchor_array_: array of Anchor; // 浮动对象节点,比如浮动型图片r.Drawing.Anchor
|
||
alternate_content_array_: array of AlternateContent; // 文本框
|
||
right_bound_: real; // 右对齐边界
|
||
br_type_: string;
|
||
bookmark_hash_: hash;
|
||
hyperlink_hash_: hash;
|
||
footnote_reference_hash_: hash; // 脚注
|
||
|
||
// 存放一些需要实时计算的值,比如页码
|
||
realtime_page_array_: hash;
|
||
realtime_numpages_array_: hash;
|
||
end;
|
||
|
||
type TcRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; tc: Tc; trp: TrProperty);
|
||
function Do();override;
|
||
function Calc(): boolean;override;
|
||
function Offset(x: real; y: real; page: Page);override;
|
||
|
||
function DoBordersRangeFill();
|
||
function GetTblStyleId(): string;
|
||
function GetPrType(): string;
|
||
function ContentNextPage(): boolean;
|
||
function AlignHeight(height: real);
|
||
function SetVAlign();
|
||
function SetTop();
|
||
|
||
property Tc Read tc_;
|
||
|
||
public
|
||
Row: integer;
|
||
Col: integer;
|
||
SpacingBottom: real;
|
||
|
||
private
|
||
function GetLowerBound(pg: Page): real;
|
||
function SetBorderRange(range: BordersRange);
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
tc_: Tc;
|
||
trp_: TrProperty;
|
||
tc_pr_unit_decorator_: TcPrUnitDecorator;
|
||
content_next_page_: boolean;
|
||
range_array_: array of BasicRange;
|
||
region_array_: array of Region;
|
||
top_: boolean;
|
||
end;
|
||
|
||
|
||
type TblRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; tbl: Tbl);
|
||
function Do();override;
|
||
function Calc(): boolean;override;
|
||
function Offset(x: real; y: real; page: Page);override;
|
||
|
||
property TblPr read tbl_pr_unit_decorator_;
|
||
property Rows read rows_;
|
||
property Cols read cols_;
|
||
|
||
private
|
||
function CreateTableMatrix(grid_cols: array of GridColUnitDecorator; trs: array of Tr);
|
||
function ResetCoordinates(tbl_pr: TblPr; grid_cols: array of GridCol);
|
||
function SetTblTblPr(var table: Tbl);
|
||
function SetTblPrByStyleId(var tbl_pr: TblPr; style_id: string);
|
||
function SetTrTrPr(var tr_pr: TrPr);
|
||
function SetTrPrByStyleId(var tr_pr: TrPr; style_id: string);
|
||
function SetTcTcPr(var tc: Tc);
|
||
function SetTcPrByStyleId(var tc_pr: TcPr; style_id: string);
|
||
function OverrideTcPrByTblStylePrType(var tc_pr: TcPr; type: string);
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
tbl_: Tbl;
|
||
tbl_pr_unit_decorator_: TblPrUnitDecorator;
|
||
grid_cols_: array of GridColUnitDecorator;
|
||
rows_: integer;
|
||
cols_: integer;
|
||
tc_range_matrix_: array of TcRange;
|
||
tr_pr_array_: array of TrProperty;
|
||
end;
|
||
|
||
type OMathParaRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; o_math_para: OMathPara);
|
||
function Do();override;
|
||
function Run();
|
||
function Calc();
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
o_math_para_: OMathPara;
|
||
o_math_range_: OMathRange;
|
||
end;
|
||
|
||
type OMathRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; element: OpenXmlElement);
|
||
function Do();override;
|
||
function Run();
|
||
function Calc();
|
||
function SetMathSize();
|
||
|
||
property Sz read sz_ write sz_;
|
||
|
||
private
|
||
function MR(r: R; x: real; y: real);
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
element_: OMath;
|
||
sz_: real;
|
||
range_array_: array of BasicRange;
|
||
end;
|
||
|
||
type OMathRRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; r: R);
|
||
function Do();override;
|
||
function Run();
|
||
function Calc();
|
||
|
||
property Sz read sz_ write sz_;
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
r_: R;
|
||
range_array_: array of BasicRange;
|
||
sz_: real;
|
||
end;
|
||
|
||
type OMathFRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; f: F);
|
||
function Do();override;
|
||
function Calc();
|
||
function Run();
|
||
|
||
property Sz read sz_ write sz_;
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
f_: F;
|
||
range_array_: array of BasicRange;
|
||
sz_: real;
|
||
end;
|
||
|
||
implementation
|
||
|
||
function AdvancedRange.Create();
|
||
begin
|
||
class(BasicRange).Create();
|
||
{self.}LowerBound := 0.0;
|
||
{self.}StartPage := nil;
|
||
{self.}StartX := 0.0;
|
||
{self.}StartY := 0.0;
|
||
range_array_ := array();
|
||
end;
|
||
|
||
function TocRange.Create();
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
{self.}TextRange := nil;
|
||
{self.}BaseLine := 0;
|
||
end;
|
||
|
||
function TocRange.LinkAnnot(dst: PdfDestination);
|
||
begin
|
||
annot := {self.}EndPage.PdfPage.CreateLinkAnnot(rect_, dst);
|
||
annot.LinkAnnotSetHighlightMode(TSPdfEnumerations.ANNOT_NO_HIGHTLIGHT);
|
||
annot.LinkAnnotSetBorderStyle(0, 0, 0);
|
||
end;
|
||
|
||
function TocRange.AddPageNumber(pg: Page);
|
||
begin
|
||
number_str := tostring(pg.Number);
|
||
{self.}EndPage.PdfPage.SetFontAndSize({self.}TextRange.Font, {self.}TextRange.RPr.Sz.Val);
|
||
number_sz := {self.}EndPage.PdfPage.TextWidth(number_str);
|
||
x := rect_[2] - number_sz;
|
||
y := {self.}BaseLine;
|
||
{self.}TextRange.EndPage := {self.}EndPage;
|
||
{self.}TextRange.Text := number_str;
|
||
{self.}TextRange.EndX := x;
|
||
{self.}TextRange.EndY := y;
|
||
{self.}TextRange.Do();
|
||
|
||
// 目录......
|
||
sx := {self.}EndX;
|
||
{self.}EndPage.PdfPage.SetRGBStroke(0, 0, 0);
|
||
{self.}EndPage.PdfPage.SetDash(array(0.5, 2), 2, 0);
|
||
{self.}EndPage.PdfPage.SetLineWidth(0.5);
|
||
{self.}EndPage.PdfPage.SetLineCap(TSPdfEnumerations.ROUND_END);
|
||
{self.}EndPage.PdfPage.MoveTo(sx, y);
|
||
{self.}EndPage.PdfPage.LineTo(x-0.5, y);
|
||
{self.}EndPage.PdfPage.Stroke();
|
||
end;
|
||
|
||
function TocRange.CalculateRect();
|
||
begin
|
||
pline_range := {self.}Parent;
|
||
{self.}EndPage := pline_range.EndPage;
|
||
if {self.}StartRange then
|
||
begin
|
||
rect_ := array({self.}StartRange.EndX, pline_range.EndY, pline_range.StartX + pline_range.Width, pline_range.StartY);
|
||
end
|
||
else begin
|
||
rect_ := array(pline_range.StartX, pline_range.EndY, pline_range.StartX + pline_range.Width, pline_range.StartY);
|
||
end
|
||
offset := pline_range.LineSpace >= pline_range.DynamicHeight ? (pline_range.LineSpace - pline_range.TextMaxSize) / 2 + pline_range.TextMaxSize - pline_range.TextMaxSize / 5 : pline_range.DynamicHeight;
|
||
y := pline_range.StartY - offset;
|
||
{self.}BaseLine := y;
|
||
{self.}EndX := ifObj({self.}EndRange) ? {self.}EndRange.EndX + {self.}EndRange.Width + 1 : {self.}Parent.StartX;
|
||
end;
|
||
|
||
function HdrRange.Create(docx_to_pdf: TSDocxToPdf; hdr: Hdr);
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
hdr_ := hdr;
|
||
range_array_ := array();
|
||
end;
|
||
|
||
function HdrRange.Do();override;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.Do();
|
||
end;
|
||
|
||
function HdrRange.Calc(): boolean;override;
|
||
begin
|
||
{self.}DynamicHeight := 0;
|
||
return {self.}Traverse(hdr_);
|
||
end;
|
||
|
||
function HdrRange.Offset(x: real; y: real; page: Page);virtual;
|
||
begin
|
||
{self.}StartX := x + XOffset;
|
||
{self.}StartY := y + YOffset;
|
||
{self.}StartPage := page;
|
||
{self.}EndX := {self.}StartX;
|
||
{self.}EndY := {self.}StartY;
|
||
{self.}EndPage := {self.}StartPage;
|
||
for _,range in range_array_ do
|
||
begin
|
||
range.LowerBound := {self.}LowerBound;
|
||
range.Offset({self.}EndX, {self,}EndY, {self.}EndPage);
|
||
{self.}EndY := range.EndY;
|
||
end
|
||
end;
|
||
|
||
function HdrRange.Traverse(obj: OpenXmlElement);
|
||
begin
|
||
flag := true;
|
||
elements := obj.Elements();
|
||
for _,element in elements do
|
||
begin
|
||
if element.LocalName = "p" then
|
||
begin
|
||
range := new PRange(docx_to_pdf_, element);
|
||
range.Width := {self.}Width;
|
||
range.Parent := self;
|
||
fg := range.Calc();
|
||
if not fg then flag := fg;
|
||
range_array_[length(range_array_)] := range;
|
||
{self.}DynamicHeight += range.DynamicHeight;
|
||
end
|
||
else if element.LocalName = "sdt" then
|
||
begin
|
||
{self.}Traverse(element.SdtContent);
|
||
end
|
||
end
|
||
return flag;
|
||
end;
|
||
|
||
function HdrRange.ProcessRealtimeArray();
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.ProcessRealtimeArray();
|
||
end;
|
||
|
||
function FtrRange.Create(docx_to_pdf: TSDocxToPdf; ftr: Ftr);
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
ftr_ := ftr;
|
||
range_array_ := array();
|
||
end;
|
||
|
||
function FtrRange.Do();override;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.Do();
|
||
end;
|
||
|
||
function FtrRange.Calc();
|
||
begin
|
||
{self.}DynamicHeight := 0;
|
||
return {self.}Traverse(ftr_);
|
||
end;
|
||
|
||
function FtrRange.Offset(x: real; y: real; page: Page);virtual;
|
||
begin
|
||
sy := page.SectPr.PgMar.Footer + {self.}DynamicHeight;
|
||
{self.}StartX := x + XOffset;
|
||
{self.}StartY := sy + YOffset;
|
||
{self.}StartPage := page;
|
||
{self.}EndX := {self.}StartX;
|
||
{self.}EndY := {self.}StartY;
|
||
{self.}EndPage := {self.}StartPage;
|
||
for _,range in range_array_ do
|
||
begin
|
||
range.LowerBound := {self.}LowerBound;
|
||
range.Offset({self.}StartX, {self.}EndY, {self.}EndPage);
|
||
{self.}EndY := range.EndY;
|
||
end
|
||
end;
|
||
|
||
function FtrRange.Traverse(obj: OpenXmlElement);
|
||
begin
|
||
flag := true;
|
||
elements := obj.Elements();
|
||
for _,element in elements do
|
||
begin
|
||
if element.LocalName = "p" then
|
||
begin
|
||
range := new PRange(docx_to_pdf_, element);
|
||
range.Width := {self.}Width;
|
||
range.Parent := self;
|
||
fg := range.Calc();
|
||
if not fg then flag := fg;
|
||
range_array_[length(range_array_)] := range;
|
||
{self.}DynamicHeight += range.DynamicHeight;
|
||
end
|
||
else if element.LocalName = "sdt" then
|
||
begin
|
||
flag := {self.}Traverse(element.SdtContent);
|
||
end
|
||
end
|
||
return flag;
|
||
end;
|
||
|
||
function FtrRange.ProcessRealtimeArray();
|
||
begin
|
||
for _,range in range_array_ do
|
||
begin
|
||
range.ProcessRealtimeArray();
|
||
end
|
||
end;
|
||
|
||
function PLineRange.Create();
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
{self.}TextMaxSize := 0;
|
||
{self.}LineSpace := 0;
|
||
range_array_ := array();
|
||
end
|
||
|
||
function PLineRange.Do();override;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.Do();
|
||
end;
|
||
|
||
function PLineRange.Offset(x: real; y: real; page: Page);override;
|
||
begin
|
||
{self.}StartX := x;
|
||
{self.}StartY := y;
|
||
{self.}StartPage := page;
|
||
{self.}EndX := x + {self.}XOffset;
|
||
{self.}EndY := y - {self.}DynamicHeight; // 没用上YOffset
|
||
{self.}EndPage := page;
|
||
y_offset := {self.}LineSpace >= {self.}DynamicHeight ? ({self.}LineSpace - {self.}TextMaxSize) / 2 + {self.}TextMaxSize - {self.}TextMaxSize / 5 : {self.}DynamicHeight;
|
||
y := {self.}StartY - y_offset;
|
||
for _,range in range_array_ do
|
||
range.Offset(x, y, page); // 公式不是y值,需要处理公式
|
||
end;
|
||
|
||
function PLineRange.CanFitInLine(range: BasicRange): boolean;
|
||
begin
|
||
if range.Width > {self.}Width then return false; // 单一宽度比行宽还宽
|
||
if {self.}XOffset + range.Width < {self.}Width + 1e-6 then return false; // 未超过行宽
|
||
if range is class(TextRange) and
|
||
range.Type = 4 and
|
||
not ({self.}Parent.Parent is class(TcRange)) then return false; // 中文标点不换行
|
||
return true;
|
||
end;
|
||
|
||
function PLineRange.AddRange(range: BasicRange);
|
||
begin
|
||
range_array_[length(range_array_)] := range;
|
||
end;
|
||
|
||
function PLineRange.Align(val: string);
|
||
begin
|
||
offset := 0;
|
||
last := range_array_[length(range_array_)-1];
|
||
case val of
|
||
"center":
|
||
offset := ({self.}Width + {self.}StartX - {self.}EndX) / 2;
|
||
"right":
|
||
offset := {self.}Width + {self.}StartX - {self.}EndX;
|
||
end;
|
||
if offset <= 0 then return;
|
||
for _,range in range_array_ do
|
||
range.EndX += offset;
|
||
end;
|
||
|
||
function PLineRange.AlignRightBound(right_bound: real);
|
||
begin
|
||
last := range_array_[length(range_array_)-1];
|
||
diff := right_bound - (last.EndX + last.Width);
|
||
if diff > 1e-6 then
|
||
begin
|
||
avg := diff / (length(range_array_) - 1);
|
||
for i:=1 to length(range_array_)-1 do
|
||
range_array_[i].EndX += avg * i;
|
||
end
|
||
end;
|
||
|
||
function PLineRange.RangeArr(): array of BasicRange;
|
||
begin
|
||
return range_array_;
|
||
end;
|
||
|
||
function PRange.Create(docx_to_pdf: TSDocxToPdf; p: P);
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
p_ := p;
|
||
end;
|
||
|
||
function PRange.Init();
|
||
begin
|
||
br_type_ := "";
|
||
body_range_array_ := array();
|
||
bullet_range_array_ := array();
|
||
line_range_array_ := array();
|
||
drawing_anchor_array_ := array();
|
||
alternate_content_array_ := array();
|
||
bookmark_hash_ := array();
|
||
hyperlink_hash_ := array();
|
||
footnote_reference_hash_ := array();
|
||
realtime_page_array_ := array();
|
||
realtime_numpages_array_ := array();
|
||
// 根据段落的间距确定新的坐标
|
||
ppr := ppr_unit_decorator_;
|
||
sz := ppr.RPr.SzCs.Val ? : ppr.RPr.Sz.Val;
|
||
{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
|
||
|
||
function PRange.Do();override;
|
||
begin
|
||
for _,line_range in line_range_array_ do
|
||
line_range.Do();
|
||
|
||
// 段落边框
|
||
if length(line_range_array_) > 0 and ppr_unit_decorator_.PBdr.Bottom.Val = "single" then
|
||
begin
|
||
{self.}EndPage.PdfPage.SetLineWidth(0.5);
|
||
{self.}EndPage.PdfPage.SetGrayStroke(0.25);
|
||
{self.}EndPage.PdfPage.MoveTo({self.}StartX, {self.}EndY);
|
||
{self.}EndPage.PdfPage.LineTo({self.}StartX + {self.}Width, {self.}EndY);
|
||
{self.}EndPage.PdfPage.Stroke();
|
||
end
|
||
|
||
// 处理bookmark
|
||
for anchor,arr in bookmark_hash_ do
|
||
if arr[0] then docx_to_pdf_.Toc.LinkToToc(anchor, arr[0]);
|
||
|
||
// 检查是否有hyperlink要链接
|
||
for anchor,_ in hyperlink_hash_ do
|
||
docx_to_pdf_.Toc.LinkToToc(anchor);
|
||
end;
|
||
|
||
function PRange.Calc(): boolean;override;
|
||
begin
|
||
// ppr.rpr是无效的,应该以ppr.pStyle为准
|
||
{self.}SetPPPr(p_);
|
||
ppr_unit_decorator_ := new DocxMLUnitDecorator.PPrUnitDecorator(p_.PPr);
|
||
if not ppr_unit_decorator_.RPr.Sz.Val then ppr_unit_decorator_.RPr.Sz.Val := docx_to_pdf_.Font.GetDefaultSz();
|
||
{self.}Init();
|
||
{self.}SetLvlText();
|
||
|
||
bookmark_name := "";
|
||
elements := p_.Elements();
|
||
fld_stack := new DTPUtils.Stack();
|
||
for _, element in elements do
|
||
begin
|
||
if element.LocalName = "pPr" then continue;
|
||
else if element.LocalName = "bookmarkStart" then
|
||
begin
|
||
bookmark_name := element.Name;
|
||
bookmark_hash_[bookmark_name] := array();
|
||
end
|
||
else if element.LocalName = "bookmarkEnd" then
|
||
begin
|
||
bookmark_name := "";
|
||
end
|
||
else if element.LocalName = "r" then
|
||
begin
|
||
{self.}SetRRPr(element, ppr_unit_decorator_);
|
||
if element.FldChar.FldCharType = "begin" then
|
||
begin
|
||
fld_struct := new DTPUtils.FldStruct();
|
||
fld_stack.Push(fld_struct);
|
||
continue;
|
||
end
|
||
if not fld_stack.Empty() then
|
||
begin
|
||
{self.}RFldChar(element, fld_stack);
|
||
continue;
|
||
end
|
||
if element.T then {self.}RT(element, bookmark_name);
|
||
else if element.Br then {self.}RBr(element);
|
||
else if element.Drawing then {self.}RDrawing(element);
|
||
else if element.AlternateContent then {self.}RAlternateContent(element);
|
||
else if element.FootnoteReference then {self.}RFootnoteReference(element);
|
||
end
|
||
else if element.LocalName = "fldSimple" then
|
||
begin
|
||
{self.}FldSimple(element);
|
||
end
|
||
else if element.LocalName = "hyperlink" then
|
||
begin
|
||
{self.}Hyperlink(element);
|
||
end
|
||
else if element.LocalName = "oMathPara" then
|
||
begin
|
||
{self.}OMathPara(element);
|
||
end
|
||
else if element.LocalName = "oMath" then
|
||
begin
|
||
o_math_para := new OMathPara();
|
||
o_math_para.XmlChildOMath := element;
|
||
// o_math_para.OMath.Copy(element);
|
||
{self.}OMathPara(o_math_para);
|
||
end
|
||
end
|
||
{self.}RangesToLines();
|
||
|
||
// 需要实时计算总页码的情况是需要最后处理的
|
||
return length(realtime_numpages_array_) ? false : true;
|
||
end;
|
||
|
||
function PRange.Offset(x: real; y: real; page: Page);override;
|
||
begin
|
||
// println("PRange::x = {}, y = {}, page = {}", x, y, page);
|
||
{self.}StartX := x + {self.}XOffset;
|
||
{self.}StartY := y + {self.}YOffset; // 段落的YOffset实际为0
|
||
{self.}StartPage := page;
|
||
{self.}EndX := {self.}StartX;
|
||
{self.}EndY := {self.}StartY;
|
||
{self.}EndPage := {self.}StartPage;
|
||
right_bound_ := {self.}StartX + {self.}Width;
|
||
|
||
// 检查是否需要实时计算页码
|
||
if length(realtime_page_array_) > 0 then
|
||
begin
|
||
pg := {self.}StartPage;
|
||
for _,range in realtime_page_array_ do
|
||
begin
|
||
pg.PdfPage.SetFontAndSize(range.Font, range.RPr.Sz.Val);
|
||
range.Text := tostring(pg.Number);
|
||
range.Width := pg.PdfPage.TextWidth(range.Text);
|
||
range.Type := 1;
|
||
end
|
||
realtime_page_array_ := array();
|
||
{self.}RangesToLines();
|
||
end
|
||
{self.}DeterminePosition();
|
||
end;
|
||
|
||
function PRange.RBr(r: R);
|
||
begin
|
||
br_type_ := r.Br.Type;
|
||
end;
|
||
|
||
function PRange.RFootnoteReference(r: R);
|
||
begin
|
||
return;
|
||
docx_to_pdf_.Note.AddFootnoteId(r.FootnoteReference.Id);
|
||
rpr := new RPrUnitDecorator(r.RPr);
|
||
if not rpr.Sz.Val then rpr.Sz.Val := rpr.SzCs.Val ? rpr.SzCs.Val : docx_to_pdf_.Font.GetDefaultSz();
|
||
font_name := rpr.RFonts.Ascii ?: rpr.RFonts.EastAsia;
|
||
font_obj := docx_to_pdf_.Font.GetCNSFont(font_name, rpr.B, rpr.I);
|
||
text := new TextRange();
|
||
text.RPr := rpr;
|
||
text.Font := font_obj;
|
||
text.Text := docx_to_pdf_.Note.GetFootnoteOrderNumber();
|
||
text.Width := docx_to_pdf_.PageManager[0].PdfPage.TextWidth(text.Text);
|
||
body_range_array_[length(body_range_array_)] := text;
|
||
footnote_reference_hash_[text] := id;
|
||
end;
|
||
|
||
function PRange.RDrawing(r: R);
|
||
begin
|
||
if r.Drawing.Anchor then
|
||
begin
|
||
anchor := r.Drawing.Anchor;
|
||
drawing_anchor_array_[length(drawing_anchor_array_)] := anchor;
|
||
end
|
||
else if r.Drawing._Inline then
|
||
begin
|
||
id := r.Drawing._Inline.Graphic.GraphicData.Pic.BlipFill.Blip.Embed;
|
||
[image_type, image] := {self.}GetImageData(id);
|
||
if not image then return;
|
||
xfrm := new XfrmUnitDecorator(r.Drawing._Inline.Graphic.GraphicData.Pic.SpPr.Xfrm);
|
||
image_range := new ImageRange();
|
||
image_range.Image := image;
|
||
image_range.Type := image_type;
|
||
image_range.Width := xfrm.Ext.CX;
|
||
image_range.DynamicHeight := xfrm.Ext.CY;
|
||
body_range_array_[length(body_range_array_)] := image_range;
|
||
end
|
||
end;
|
||
|
||
function PRange.RFldChar(r: R; stack: Stack);
|
||
begin
|
||
fld_struct := stack.Pop();
|
||
if r.FldChar.FldCharType = "separate" then
|
||
begin
|
||
fld_struct.Status := 1;
|
||
stack.Push(fld_struct);
|
||
return;
|
||
end
|
||
// else if r.FldChar.FldCharType = "end" then
|
||
// fld_struct.Status = 2;
|
||
if fld_struct.Status = 2 then return;
|
||
|
||
if r.InstrText.Text then
|
||
begin
|
||
fields := str2array(r.InstrText.Text, " ");
|
||
for _,field in fields do
|
||
begin
|
||
fld := trim(field);
|
||
if fld = "NUMPAGES" then
|
||
fld_struct.Type.NumPages := true;
|
||
else if fld = "PAGE" then
|
||
fld_struct.Type.Page := true;
|
||
else if fld = "QUOTE" then
|
||
fld_struct.Type.Quote := true;
|
||
else if fld = "PAGEREF" then
|
||
fld_struct.Type.PageRef := true;
|
||
else if fld = "Arabic" then
|
||
fld_struct.Arabic := true;
|
||
else if fld = "MERGEFORMAT" then
|
||
fld_struct.MergeFormat := true;
|
||
end
|
||
end
|
||
if fld_struct.Status = 1 then
|
||
begin
|
||
if fld_struct.Type.Page then
|
||
begin
|
||
rpr := new RPrUnitDecorator(r.RPr);
|
||
if not rpr.Sz.Val then rpr.Sz.Val := rpr.SzCs.Val ? rpr.SzCs.Val : docx_to_pdf_.Font.GetDefaultSz();
|
||
font_name := rpr.RFonts.EastAsia ? rpr.RFonts.EastAsia : rpr.RFonts.Ascii;
|
||
font_obj := docx_to_pdf_.Font.GetCNSFont(font_name, rpr.B, rpr.I);
|
||
text := new TextRange();
|
||
text.RPr := rpr;
|
||
// text.Type := 1;
|
||
text.Font := font_obj;
|
||
text.DynamicHeight := rpr.Sz.Val;
|
||
text.Width := 1.5 * RPr.Sz.Val; // 预留三个数字的宽度
|
||
realtime_page_array_[length(realtime_page_array_)] := text;
|
||
body_range_array_[length(body_range_array_)] := text;
|
||
end
|
||
else if fld_struct.Type.NumPages then
|
||
begin
|
||
rpr := new RPrUnitDecorator(r.RPr);
|
||
if not rpr.Sz.Val then rpr.Sz.Val := rpr.SzCs.Val ? rpr.SzCs.Val : docx_to_pdf_.Font.GetDefaultSz();
|
||
font_name := rpr.RFonts.EastAsia ? rpr.RFonts.EastAsia : rpr.RFonts.Ascii;
|
||
font_obj := docx_to_pdf_.Font.GetCNSFont(font_name, rpr.B, rpr.I);
|
||
text := new TextRange();
|
||
text.RPr := rpr;
|
||
// text.Type := 1;
|
||
text.Font := font_obj;
|
||
text.DynamicHeight := rpr.Sz.Val;
|
||
text.Width := 1.5 * RPr.Sz.Val; // 预留三个数字的宽度
|
||
realtime_numpages_array_[length(realtime_numpages_array_)] := text;
|
||
body_range_array_[length(body_range_array_)] := text;
|
||
end
|
||
fld_struct.Status := 2;
|
||
end
|
||
if fld_struct.Status <> 2 then stack.Push(fld_struct);
|
||
|
||
end;
|
||
|
||
function PRange.RAlternateContent(r: R);
|
||
begin
|
||
anchor := r.AlternateContent.Choice.Drawing.Anchor;
|
||
alternate_content_array_[length(alternate_content_array_)] := anchor;
|
||
end;
|
||
|
||
function PRange.FldSimple(fld_simple: fldSimple);
|
||
begin
|
||
if fld_simple.Instr then
|
||
begin
|
||
fields := str2array(fld_simple.Instr, " ");
|
||
fld_struct := new DTPUtils.FldStruct();
|
||
for _,field in fields do
|
||
begin
|
||
fld := trim(field);
|
||
if fld = "NUMPAGES" then
|
||
fld_struct.Type.NumPages := true;
|
||
else if fld = "Arabic" then
|
||
fld_struct.Arabic := true;
|
||
else if fld = "MERGEFORMAT" then
|
||
fld_struct.MergeFormat := true;
|
||
end
|
||
end
|
||
r := fld_simple.Rs(0);
|
||
{self.}SetRRPr(r, ppr_unit_decorator_);
|
||
if fld_struct.Type.NumPages then
|
||
begin
|
||
if fld_struct.Arabic then
|
||
begin
|
||
rpr := new RPrUnitDecorator(r.RPr);
|
||
if not rpr.Sz.Val then rpr.Sz.Val := rpr.SzCs.Val ? rpr.SzCs.Val : docx_to_pdf_.Font.GetDefaultSz();
|
||
font_name := rpr.RFonts.EastAsia ? rpr.RFonts.EastAsia : rpr.RFonts.Ascii;
|
||
font_obj := docx_to_pdf_.Font.GetCNSFont(font_name, rpr.B, rpr.I);
|
||
text := new TextRange();
|
||
text.RPr := rpr;
|
||
// text.Type := 1;
|
||
text.Font := font_obj;
|
||
text.DynamicHeight := rpr.Sz.Val;
|
||
text.Width := 1.5 * RPr.Sz.Val; // 预留三个数字的宽度
|
||
realtime_numpages_array_[length(realtime_numpages_array_)] := text;
|
||
body_range_array_[length(body_range_array_)] := text;
|
||
end
|
||
end
|
||
end;
|
||
|
||
function PRange.Hyperlink(hyperlink: Hyperlink);
|
||
begin
|
||
i := length(body_range_array_);
|
||
rs := hyperlink.Rs();
|
||
fld_stack := new DTPUtils.Stack();
|
||
for _,r in rs do
|
||
begin
|
||
if r.FldChar.FldCharType = "begin" then
|
||
begin
|
||
fld_struct := new DTPUtils.FldStruct();
|
||
fld_stack.Push(fld_struct);
|
||
end
|
||
else if r.FldChar.FldCharType = "end" then
|
||
begin
|
||
fld_stack.Pop();
|
||
end
|
||
else if r.FldChar.FldCharType = "separate" then
|
||
begin
|
||
separate := true;
|
||
end
|
||
else if separate then
|
||
begin
|
||
docx_to_pdf_.Toc.AddDocxPage(hyperlink.Anchor, r);
|
||
|
||
rpr := new RPrUnitDecorator(r.RPr);
|
||
if not rpr.Sz.Val then rpr.Sz.Val := rpr.SzCs.Val ? rpr.SzCs.Val : docx_to_pdf_.Font.GetDefaultSz();
|
||
font_name := rpr.RFonts.EastAsia ? rpr.RFonts.EastAsia : rpr.RFonts.Ascii;
|
||
font_obj := docx_to_pdf_.Font.GetCNSFont(font_name, rpr.B, rpr.I);
|
||
text := new TextRange();
|
||
text.RPr := rpr;
|
||
text.Font := font_obj;
|
||
text.DynamicHeight := rpr.Sz.Val;
|
||
text.Width := 1.5 * RPr.Sz.Val; // 预留三个数字的宽度
|
||
end
|
||
if not fld_stack.Empty() then continue;
|
||
if r.T then
|
||
begin
|
||
{self.}SetRRPr(r, ppr_unit_decorator_);
|
||
r.RPr.Color.Val := nil;
|
||
{self.}RT(r);
|
||
end
|
||
end
|
||
arr := array();
|
||
while i < length(body_range_array_) do
|
||
begin
|
||
arr[length(arr)] := body_range_array_[i];
|
||
i++;
|
||
end
|
||
hyperlink_hash_[hyperlink.Anchor] := array(text, arr);
|
||
end;
|
||
|
||
function PRange.OMathPara(o_math_para: OMathPara);
|
||
begin
|
||
math_range := new OMathParaRange(docx_to_pdf_, o_math_para);
|
||
math_range.Width := {self.}Width;
|
||
math_range.Parent := self;
|
||
math_range.Calc();
|
||
body_range_array_[length(body_range_array_)] := math_range;
|
||
end;
|
||
|
||
function PRange.HyperlinkToToc();
|
||
begin
|
||
ppr_ := ppr_unit_decorator_;
|
||
for anchor, arr in hyperlink_hash_ do
|
||
begin
|
||
text := arr[0];
|
||
r_arr := arr[1];
|
||
range0 := r_arr[0];
|
||
range1 := r_arr[length(r_arr)-1];
|
||
if range0.Parent.Index = range1.Parent.Index then // 同一行
|
||
begin
|
||
if range1.Parent.EndX + text.Width < {self.}Width then // 页码不需要换行
|
||
begin
|
||
toc := new TocRange();
|
||
toc.Parent := range0.Parent;
|
||
toc.TextRange := text;
|
||
toc.StartRange := range0;
|
||
toc.EndRange := range1;
|
||
docx_to_pdf_.Toc.AddToc(anchor, toc);
|
||
end
|
||
else begin // 需要新增一行
|
||
pline_range := new PLineRange();
|
||
pline_range.Parent := self;
|
||
pline_range.Width := {self.}Width;
|
||
pline_range.EndX := 0;
|
||
pline_range.DynamicHeight := range1.Parent.DynamicHeight;
|
||
pline_range.LineSpace := range1.Parent.LineRule;
|
||
index := range1.Parent.Index + 1;
|
||
for i:=length(line_range_array_) downto index do
|
||
begin
|
||
line_range := line_range_array_[i];
|
||
line_range.Index++;
|
||
line_range_array_[i+1] := line_range;
|
||
end
|
||
line_range_array_[index] := pline_range;
|
||
toc := new TocRange();
|
||
toc.Parent := pline_range;
|
||
toc.TextRange := text;
|
||
docx_to_pdf_.Toc.AddToc(anchor, toc);
|
||
end
|
||
end
|
||
else begin
|
||
for i:=range0.Parent.Index to range1.Parent.Index do
|
||
begin
|
||
if i = range1.Parent.Index then
|
||
begin
|
||
if range1.Parent.EndX + text.Width < {self.}Width then // 页码不需要换行
|
||
begin
|
||
toc := new TocRange();
|
||
toc.Parent := range1.Parent;
|
||
toc.TextRange := text;
|
||
toc.EndRange := range1;
|
||
docx_to_pdf_.Toc.AddToc(anchor, toc);
|
||
end
|
||
else begin // 需要新增一行
|
||
pline_range := new PLineRange();
|
||
pline_range.Parent := self;
|
||
pline_range.Width := {self.}Width;
|
||
pline_range.EndX := 0;
|
||
pline_range.DynamicHeight := range1.Parent.DynamicHeight;
|
||
pline_range.LineSpace := range1.Parent.LineRule;
|
||
index := range1.Parent.Index + 1;
|
||
for i:=length(line_range_array_) downto index do
|
||
begin
|
||
line_range := line_range_array_[i];
|
||
line_range.Index++;
|
||
line_range_array_[i+1] := line_range;
|
||
end
|
||
line_range_array_[index] := pline_range;
|
||
toc := new TocRange();
|
||
toc.Parent := pline_range;
|
||
toc.TextRange := text;
|
||
docx_to_pdf_.Toc.AddToc(anchor, toc);
|
||
end
|
||
end
|
||
else begin
|
||
toc := new TocRange();
|
||
toc.Parent := line_range_array_[i];
|
||
toc.TextRange := text;
|
||
docx_to_pdf_.Toc.AddToc(anchor, toc);
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end;
|
||
|
||
function PRange.PLineRanges(): array of PLineRange;
|
||
begin
|
||
return line_range_array_;
|
||
end;
|
||
|
||
function PRange.RangesToLines();
|
||
begin
|
||
{self.}UpdateTextRangeWidth();
|
||
{self.}BasicRangesToPLineRange();
|
||
{self.}HyperlinkToToc();
|
||
end;
|
||
|
||
function PRange.BasicRangesToPLineRange();
|
||
begin
|
||
line_range_array_ := array();
|
||
{self.}DynamicHeight := 0;
|
||
{self.}DynamicHeight += ppr_unit_decorator_.Spacing.Before;
|
||
// 段落的x偏移是缩进
|
||
{self.}XOffset := ppr_unit_decorator_.Ind.LeftChars ? ppr_unit_decorator_.Ind.LeftChars * ppr_unit_decorator_.RPr.Sz.Val : ppr_unit_decorator_.Ind.Left;
|
||
{self.}YOffset := 0;
|
||
|
||
pline_range := {self.}NewPLineRange();
|
||
pline_range.XOffset := ppr_unit_decorator_.Ind.FirstLine; // 首行有间距.用offsetx作为位置计算
|
||
i := 0;
|
||
anchor := nil;
|
||
while i < length(body_range_array_) do
|
||
begin
|
||
range := body_range_array_[i];
|
||
if_newline := pline_range.CanFitInLine(range);
|
||
if if_newline then
|
||
begin
|
||
{self.}AddPLineRange(pline_range);
|
||
{self.}DynamicHeight += pline_range.DynamicHeight;
|
||
pline_range := {self.}NewPLineRange();
|
||
end
|
||
if range is class(TextRange) and range.RPr.Sz.Val > pline_range.TextMaxSize then
|
||
pline_range.TextMaxSize := range.RPr.Sz.Val;
|
||
if range.DynamicHeight > pline_range.DynamicHeight then pline_range.DynamicHeight := range.DynamicHeight;
|
||
range.XOffset := pline_range.XOffset;
|
||
range.Parent := pline_range;
|
||
pline_range.AddRange(range);
|
||
pline_range.XOffset += range.Width;
|
||
i++;
|
||
if i = length(body_range_array_) then
|
||
begin
|
||
{self.}AddPLineRange(pline_range);
|
||
{self.}DynamicHeight += pline_range.DynamicHeight;
|
||
end
|
||
end
|
||
|
||
if length(line_range_array_) = 0 then
|
||
begin
|
||
line_space := {self.}GetParagraphLineSpace(ppr_unit_decorator_.RPr.Sz.Val, ppr_unit_decorator_.Spacing.Line, ppr_unit_decorator_.Spacing.LineRule);
|
||
{self.}DynamicHeight += line_space;
|
||
end
|
||
{self.}DynamicHeight += ppr_unit_decorator_.Spacing.After;
|
||
|
||
// println("line_range_array_ = {}", line_range_array_);
|
||
end;
|
||
|
||
function PRange.NewPLineRange(): PLineRange;
|
||
begin
|
||
pline_range := new PLineRange();
|
||
pline_range.Parent := self;
|
||
pline_range.Width := {self.}Width;
|
||
return pline_range;
|
||
end;
|
||
|
||
function PRange.AddPLineRange(pline_range: PLineRange);
|
||
begin
|
||
pline_range.LineSpace := {self.}GetParagraphLineSpace(pline_range.TextMaxSize, ppr_unit_decorator_.Spacing.Line, ppr_unit_decorator_.Spacing.LineRule);
|
||
pline_range.DynamicHeight := max(pline_range.LineSpace, pline_range.DynamicHeight);
|
||
pline_range.Index := length(line_range_array_);
|
||
line_range_array_[length(line_range_array_)] := pline_range;
|
||
end;
|
||
|
||
function PRange.UpdateTextRangeWidth();
|
||
begin
|
||
if length(realtime_page_array_) > 0 or length(realtime_numpages_array_) > 0 then return;
|
||
head_range := body_range_array_[0];
|
||
i := 1;
|
||
while i < length(body_range_array_) do
|
||
begin
|
||
tail_range := body_range_array_[i];
|
||
if not (tail_range is class(TextRange)) then
|
||
begin
|
||
head_range := body_range_array_[i+1];
|
||
i += 2;
|
||
continue;
|
||
end
|
||
if not (tail_range is class(TextRange)) then
|
||
begin
|
||
head_range := tail_range;
|
||
i++;
|
||
continue;
|
||
end
|
||
if head_range then
|
||
begin
|
||
if head_range.Type in array(1, 2) and tail_range.Type = 3 then
|
||
head_range.Width += head_range.Width / 2;
|
||
else if head_range.Type = 3 and tail_range.Type in array(1, 2) then
|
||
head_range.Width += tail_range.Width / 2;
|
||
end
|
||
head_range := tail_range;
|
||
i++;
|
||
end
|
||
end;
|
||
|
||
function PRange.DeterminePosition();
|
||
begin
|
||
// 检查是否有分页,分一栏
|
||
if br_type_ = "page" then
|
||
{self.}EndY := {self.}LowerBound;
|
||
else if br_type_ = "column" and (ifnil(docx_to_pdf_.CurrentSect.SectPr.Cols.Num) or docx_to_pdf_.CurrentSect.SectPr.Cols.Num <= 1) then
|
||
{self.}EndY := {self.}LowerBound;
|
||
|
||
// 段前距只有不换页情况才计算
|
||
if not {self.}CheckAndAddPage({self.}EndY, ppr_unit_decorator_.Spacing.Before) then
|
||
{self.}EndY -= ppr_unit_decorator_.Spacing.Before;
|
||
|
||
// 检查是否有段前分页
|
||
if ppr_unit_decorator_.PageBreakBefore then
|
||
{self.}CheckAndAddPage({self.}LowerBound, 1);
|
||
|
||
for _,line_range in line_range_array_ do
|
||
begin
|
||
y := {self.}EndY;
|
||
if {self.}CheckAndAddPage(y, line_range.DynamicHeight) then // 行不够时候调整上一页LowerBound
|
||
docx_to_pdf_.PageManager[{self.}EndPage.Index - 1].LowerBound := y;
|
||
line_range.Offset({self.}EndX, {self.}EndY, {self.}EndPage);
|
||
line_range.Align(ppr_unit_decorator_.Jc.Val);
|
||
{self.}EndY := line_range.EndY;
|
||
end
|
||
if not {self.}Parent is class(TcRange) then
|
||
{self.}AlignRightBound();
|
||
|
||
if length(line_range_array_) = 0 then // 空段落
|
||
begin
|
||
line_space := {self.}GetParagraphLineSpace(ppr_unit_decorator_.RPr.Sz.Val, ppr_unit_decorator_.Spacing.Line, ppr_unit_decorator_.Spacing.LineRule);
|
||
{self.}EndY -= line_space;
|
||
end
|
||
|
||
{self.}DoDrawingAnchor();
|
||
{self.}DoAlternateContentAnchor();
|
||
{self.}DoToc();
|
||
|
||
{self.}EndY -= ppr_unit_decorator_.Spacing.After;
|
||
end;
|
||
|
||
function PRange.DoToc();
|
||
begin
|
||
for anchor,_ in hyperlink_hash_ do
|
||
docx_to_pdf_.Toc.CalculateRect(anchor);
|
||
end;
|
||
|
||
function PRange.DoDrawingAnchor();
|
||
begin
|
||
for _,anchor in drawing_anchor_array_ do
|
||
begin
|
||
id := anchor.Graphic.GraphicData.Pic.BlipFill.Blip.Embed;
|
||
[image_type, image] := {self.}GetImageData(id);
|
||
if not image then return;
|
||
xfrm := new XfrmUnitDecorator(anchor.Graphic.GraphicData.Pic.SpPr.Xfrm);
|
||
position_h := new PositionHUnitDecorator(anchor.PositionH);
|
||
position_v := new PositionVUnitDecorator(anchor.PositionV);
|
||
[x, y] := {self.}GetXYCordinates();
|
||
if position_h.RelativeFrom = "paragraph" then
|
||
x := {self.}StartY;
|
||
if position_v.RelativeFrom = "paragraph" then
|
||
y := {self.}StartY;
|
||
image_range := new ImageRange();
|
||
image_range.Image := image;
|
||
image_range.Type := image_type;
|
||
image_range.EndX := x + position_h.PosOffset.Text;
|
||
image_range.EndY := y - position_v.PosOffset.Text - xfrm.Ext.CY;
|
||
image_range.Width := xfrm.Ext.CX;
|
||
image_range.DynamicHeight := xfrm.Ext.CY;
|
||
image_range.EndPage := {self.}EndPage;
|
||
image_range.Do();
|
||
end
|
||
end;
|
||
|
||
function PRange.DoAlternateContentAnchor();
|
||
begin
|
||
for _,anchor in alternate_content_array_ do
|
||
begin
|
||
wsp := anchor.Graphic.GraphicData.Wsp;
|
||
[x, y] := {self.}GetXYCordinates();
|
||
xfrm := new XfrmUnitDecorator(wsp.SpPr.Xfrm);
|
||
position_h := new PositionHUnitDecorator(anchor.PositionH);
|
||
position_v := new PositionVUnitDecorator(anchor.PositionV);
|
||
if position_h.RelativeFrom = "paragraph" then
|
||
x := {self.}StartY;
|
||
if position_v.RelativeFrom = "paragraph" then
|
||
y := {self.}StartY;
|
||
x += position_h.PosOffset.Text;
|
||
y -= position_v.PosOffset.Text;
|
||
w := xfrm.Ext.CX;
|
||
body_pr := new BodyPrUnitDecorator(wsp.BodyPr);
|
||
x += body_pr.LIns;
|
||
w -= (body_pr.LIns + body_pr.RIns);
|
||
ps := wsp.Txbx.TxbxContent.Ps();
|
||
for _,p in ps do
|
||
begin
|
||
range := new PRange(docx_to_pdf_, p);
|
||
range.Width := w;
|
||
range.Parent := self;
|
||
range.LowerBound := 0;
|
||
fg := range.Calc();
|
||
if not fg then flag := fg;
|
||
range.Offset(x, y, {self.}EndPage);
|
||
range.Do();
|
||
y := range.EndY;
|
||
end
|
||
end
|
||
end;
|
||
|
||
function PRange.ProcessRealtimeArray();
|
||
begin
|
||
for _,range in realtime_numpages_array_ do
|
||
begin
|
||
range.Text := tostring(docx_to_pdf_.PageManager[docx_to_pdf_.PageManager.Count-1].Number);
|
||
first_page := docx_to_pdf_.PageManager[0];
|
||
range.Width := first_page.PdfPage.TextWidth(range.Text);
|
||
range.Type := 1;
|
||
end
|
||
realtime_numpages_array_ := array();
|
||
{self.}RangesToLines();
|
||
{self.}DeterminePosition();
|
||
end;
|
||
|
||
function PRange.IsFirstLineOnNextPage(): boolean;
|
||
begin
|
||
lrange := line_range_array_[0];
|
||
return ifnil(lrange) ? false : lrange.EndPage <> {self.}StartPage;
|
||
end;
|
||
|
||
function PRange.AlignRightBound();
|
||
begin
|
||
len := length(line_range_array_);
|
||
if len = 1 then return;
|
||
for i:=0 to len-2 do
|
||
line_range_array_[i].AlignRightBound(right_bound_);
|
||
end;
|
||
|
||
function PRange.CheckAndAddPage(y: real; offset: real): boolean;
|
||
begin
|
||
lb := {self.}LowerBound;
|
||
if lb > 0 then
|
||
lb := lb > {self.}EndPage.LowerBound ? lb : {self.}EndPage.LowerBound;
|
||
if y - offset < lb then
|
||
begin
|
||
{self.}EndPage := docx_to_pdf_.PageManager[{self.}EndPage.Index + 1];
|
||
if ifnil({self.}EndPage) then {self.}EndPage := docx_to_pdf_.AddPage();
|
||
{self.}EndY := {self.}EndPage.OriginalTextCoordinates()[1];
|
||
return true;
|
||
end
|
||
return false;
|
||
end;
|
||
|
||
function PRange.RT(r: R; anchor: string);
|
||
begin
|
||
rpr := new DocxMLUnitDecorator.RPrUnitDecorator(r.RPr);
|
||
text := r.T.Text;
|
||
if text then {self.}SplitTextToTextRange(body_range_array_, text, rpr, anchor);
|
||
end;
|
||
|
||
function PRange.SplitTextToTextRange(range_arr: array of BasicRange; text: string; rpr: RPrUnitDecorator; anchor: string);
|
||
begin
|
||
pos := 1;
|
||
if not rpr.Sz.Val then rpr.Sz.Val := rpr.SzCs.Val ? rpr.SzCs.Val : docx_to_pdf_.Font.GetDefaultSz();
|
||
while pos <= length(text) do
|
||
begin
|
||
text_range := new TextRange();
|
||
num := DTPUtils.Utf8CharLengthFromByte(text[pos]);
|
||
a_word := text[pos : pos+num-1];
|
||
if num = 1 then
|
||
begin
|
||
char := ord(a_word);
|
||
if char >= 0x30 and char <= 0x39 then
|
||
text_range.Type := 1;
|
||
else if char >= 0x41 and char <= 0x5A then
|
||
text_range.Type := 2;
|
||
else if char >= 0x61 and char <= 0x7A then
|
||
text_range.Type := 2;
|
||
else if char = 0x44 or char = 0x46 then
|
||
text_range.Type := 5;
|
||
word := a_word;
|
||
font_name := rpr.RFonts.EastAsia ?: rpr.RFonts.Ascii;
|
||
font_obj := docx_to_pdf_.Font.GetCNSFont(font_name, rpr.B, rpr.I);
|
||
// font_name := rpr.RFonts.Ascii ?: rpr.RFonts.EastAsia;
|
||
// font_obj := docx_to_pdf_.Font.GetAsciiFont(font_name, rpr.B, rpr.I);
|
||
end
|
||
else if DTPUtils.IsChineseChar(a_word) then
|
||
begin
|
||
text_range.Type := 3;
|
||
word := utf8ToAnsi(a_word);
|
||
font_name := rpr.RFonts.EastAsia ?: rpr.RFonts.Ascii;
|
||
font_obj := docx_to_pdf_.Font.GetCNSFont(font_name, rpr.B, rpr.I);
|
||
end
|
||
else if DTPUtils.IsChinesePunctuation(a_word) then
|
||
begin
|
||
text_range.Type := 4;
|
||
word := utf8ToAnsi(a_word);
|
||
font_name := rpr.RFonts.EastAsia ?: rpr.RFonts.Ascii;
|
||
font_obj := docx_to_pdf_.Font.GetCNSFont(font_name, rpr.B, rpr.I);
|
||
end
|
||
else begin
|
||
word := utf8ToAnsi(a_word);
|
||
if word = "?" then
|
||
begin
|
||
word := class(SymbolMapper).ZapfDingbatsChr(a_word);
|
||
if ifnil(word) then word := "u";
|
||
font_obj := docx_to_pdf_.Font.GetZapfDingbatsFont();
|
||
end
|
||
else begin
|
||
font_name := rpr.RFonts.EastAsia ?: rpr.RFonts.Ascii;
|
||
font_obj := docx_to_pdf_.Font.GetCNSFont(font_name, rpr.B, rpr.I);
|
||
end
|
||
end
|
||
first_page := docx_to_pdf_.PageManager[0];
|
||
pdf_page := first_page.PdfPage;
|
||
pdf_page.SetFontAndSize(font_obj, rpr.Sz.Val);
|
||
text_range.RPr := rpr;
|
||
text_range.Text := word;
|
||
text_range.Font := font_obj;
|
||
text_range.Width := pdf_page.TextWidth(word);
|
||
text_range.DynamicHeight := rpr.Sz.Val;
|
||
pos += num;
|
||
range_arr[length(range_arr)] := text_range;
|
||
|
||
if ifarray(bookmark_hash_[anchor]) then bookmark_hash_[anchor] union= array(text_range);
|
||
end
|
||
end;
|
||
|
||
function PRange.SetPPPr(var p: P);
|
||
begin
|
||
new_ppr := new PPr();
|
||
styles := docx_to_pdf_.DocxComponents.GetStyles();
|
||
new_ppr.Copy(styles.DocDefaults.PPrDefault.PPr);
|
||
new_ppr.RPr.Copy(styles.DocDefaults.RPrDefault.RPr);
|
||
if {self.}Parent is class(TcRange) then
|
||
{self.}SetPPrByStyleId(new_ppr, {self.}Parent.GetTblStyleId());
|
||
{self.}SetPPrByStyleId(new_ppr, p.PPr.PStyle.Val);
|
||
new_ppr.Copy(p.PPr);
|
||
p.PPr.Copy(new_ppr);
|
||
end;
|
||
|
||
function PRange.SetPPrByStyleId(var ppr: PPr; style_id: string);
|
||
begin
|
||
styles := docx_to_pdf_.DocxComponents.GetStylesAdapter();
|
||
style := styles.GetStyleByStyleId(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 PRange.SetRRPr(var r: R; ppr_unit_decorator: PPrUnitDecorator);
|
||
begin
|
||
new_rpr := new RPr();
|
||
styles := docx_to_pdf_.DocxComponents.GetStyles();
|
||
new_rpr.Copy(styles.DocDefaults.RPrDefault.RPr);
|
||
if {self.}Parent is class(TcRange) then
|
||
{self.}SetRPrByTblStyleId(new_rpr, {self.}Parent.GetTblStyleId());
|
||
{self.}SetRPrByStyleId(new_rpr, ppr_unit_decorator.PStyle.Val);
|
||
{self.}SetRPrByStyleId(new_rpr, r.RPr.RStyle.Val);
|
||
new_rpr.Copy(r.RPr);
|
||
r.RPr.Copy(new_rpr);
|
||
end;
|
||
|
||
function PRange.SetRPrByTblStyleId(var rpr: RPr; style_id: string);
|
||
begin
|
||
styles := docx_to_pdf_.DocxComponents.GetStylesAdapter();
|
||
style := styles.GetStyleByStyleId(style_id);
|
||
if ifObj(style) then
|
||
begin
|
||
based_on := style.BasedOn.Val;
|
||
{self.}SetRPrByTblStyleId(rpr, based_on);
|
||
rpr.Copy(style.RPr);
|
||
end
|
||
if {self.}Parent is class(TcRange) then
|
||
begin
|
||
pr_type := {self.}Parent.GetPrType();
|
||
tbl_style_pr := docx_to_pdf_.DocxComponents.GetTblStylePrByType(style_id, pr_type);
|
||
if tbl_style_pr then rpr.Copy(tbl_style_pr.RPr);
|
||
end
|
||
end;
|
||
|
||
function PRange.SetRPrByStyleId(var rpr: RPr; style_id: string);
|
||
begin
|
||
styles := docx_to_pdf_.DocxComponents.GetStylesAdapter();
|
||
style := styles.GetStyleByStyleId(style_id);
|
||
if ifObj(style) then
|
||
begin
|
||
based_on := style.BasedOn.Val;
|
||
{self.}SetRPrByStyleId(rpr, based_on);
|
||
rpr.Copy(style.RPr);
|
||
end
|
||
end;
|
||
|
||
function PRange.SetLvlText();
|
||
begin
|
||
numbering_module := docx_to_pdf_.DocxComponents.GetNumberingModule();
|
||
if not ifObj(numbering_module) then return;
|
||
[lvl_text, lvl] := numbering_module.GetNumberLvl(p_.PPr);
|
||
if lvl_text = "" and ifnil(lvl) then return;
|
||
{self.}SetRRPr(lvl, ppr_unit_decorator_);
|
||
rpr := new RPrUnitDecorator(lvl.RPr);
|
||
// {self.}SplitTextToTextRange(bullet_range_array_, lvl_text, rpr);
|
||
{self.}SplitTextToTextRange(body_range_array_, lvl_text, rpr);
|
||
end;
|
||
|
||
function PRange.GetXYCordinates(): array of real;
|
||
begin
|
||
xml_file := docx_to_pdf_.GetCurrentXmlFile();
|
||
if xml_file = "document.xml" then
|
||
begin
|
||
[x, y] := {self.}EndPage.OriginalTextCoordinates();
|
||
end
|
||
else begin
|
||
x := {self.}EndPage.SectPr.PgMar.Left;
|
||
if ansiContainsStr(xml_file, "footer") then
|
||
y := {self.}EndPage.SectPr.PgMar.Bottom;
|
||
else if ansiContainsStr(xml_file, "header") then
|
||
y := {self.}EndPage.SectPr.PgSz.H - {self.}EndPage.SectPr.PgMar.Header;
|
||
end
|
||
return array(x, y);
|
||
end;
|
||
|
||
function PRange.GetImageData(id: string): PdfImage;
|
||
begin
|
||
xml_file := docx_to_pdf_.GetCurrentXmlFile();
|
||
if {self.}Parent is class(HdrRange) then
|
||
rels_adapter := docx_to_pdf_.DocxComponents.GetHdrRelsAdapter(xml_file);
|
||
else if {self.}Parent is class(FtrRange) then
|
||
rels_adapter := docx_to_pdf_.DocxComponents.GetFtrRelsAdapter(xml_file);
|
||
else
|
||
rels_adapter := docx_to_pdf_.DocxComponents.GetDocumentRelsAdapter();
|
||
rel := rels_adapter.GetRelationshipById(id);
|
||
image_path := "word/" + rel.Target;
|
||
image := docx_to_pdf_.DocxComponents.Zip().Get(image_path);
|
||
data := image.Data();
|
||
image_path := docx_to_pdf_.GetCachePath(image_path);
|
||
writeFile(rwBinary(), "", image_path, 0, length(data), data);
|
||
image := nil;
|
||
image_type := GetImageFileType(data);
|
||
case image_type of
|
||
"png":
|
||
image := docx_to_pdf_.PdfFile().LoadPngImageFromFile("", image_path);
|
||
"jpg":
|
||
image := docx_to_pdf_.PdfFile().LoadJpegImageFromFile("", image_path);
|
||
"emf":
|
||
image := docx_to_pdf_.PdfFile().LoadEmfImageFromFile("", image_path);
|
||
"wmf":
|
||
image := docx_to_pdf_.PdfFile().LoadWmfImageFromFile("", image_path);
|
||
end;
|
||
fileDelete("", image_path);
|
||
return array(image_type, image);
|
||
end;
|
||
|
||
function PRange.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)),
|
||
('name': 'emf', 'position': 40, 'value': array(0x20, 0x45, 0x4d, 0x46)),
|
||
('name': 'wmf', 'position': 0, 'value': array(0xd7, 0xcd, 0xc6, 0x9a)),
|
||
);
|
||
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 PRange.GetParagraphLineSpace(size: real; line: integer; line_rule: string): real;
|
||
begin
|
||
if not line then line := 240;
|
||
if line_rule = "exact" or line_rule = "atLeast" then
|
||
begin
|
||
lines := line / 240;
|
||
return size + lines;
|
||
end
|
||
else begin
|
||
lines := roundto(line / 240, -1);
|
||
multi := ceil(size / docx_to_pdf_.CurrentSect.BaseSize);
|
||
if (not ifnil(ppr_unit_decorator_.SnapToGrid) and not ppr_unit_decorator_.SnapToGrid) or
|
||
((ifnil(ppr_unit_decorator_.SnapToGrid) or ppr_unit_decorator_.SnapToGrid) and lines > multi) then
|
||
multi *= lines;
|
||
return docx_to_pdf_.CurrentSect.SectPr.DocGrid.LinePitch * multi;
|
||
end
|
||
end;
|
||
|
||
function TcRange.Create(docx_to_pdf: TSDocxToPdf; tc: Tc; trp: TrProperty);
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
tc_ := tc;
|
||
trp_ := trp;
|
||
tc_pr_unit_decorator_ := new TcPrUnitDecorator(tc_.TcPr);
|
||
content_next_page_ := false;
|
||
top_ := false;
|
||
end;
|
||
|
||
function TcRange.Do();
|
||
begin
|
||
for _,region in region_array_ do
|
||
begin
|
||
region.BordersRange.Do();
|
||
for __,range in region.RangeArr do
|
||
range.Do();
|
||
end
|
||
end;
|
||
|
||
function TcRange.DoBordersRangeFill();
|
||
begin
|
||
for _,region in region_array_ do
|
||
begin
|
||
region.BordersRange.DoFill();
|
||
end
|
||
end;
|
||
|
||
function TcRange.Calc(): boolean;override;
|
||
begin
|
||
range_array_ := array();
|
||
{self.}DynamicHeight := 0;
|
||
cell_w := {self.}Width - {self.}Parent.TblPr.TblCellMar.Right.W - {self.}Parent.TblPr.TblCellMar.Left.W;
|
||
elements := tc_.Elements();
|
||
for _,element in elements do
|
||
begin
|
||
if element.LocalName = "p" then
|
||
begin
|
||
range := new PRange(docx_to_pdf_, element);
|
||
range.Width := cell_w;
|
||
range.Parent := self;
|
||
range.Calc();
|
||
range_array_[length(range_array_)] := range;
|
||
{self.}DynamicHeight += range.DynamicHeight;
|
||
end
|
||
end
|
||
{self.}DynamicHeight += {self.}Parent.TblPr.TblCellMar.Bottom.W + {self.}Parent.TblPr.TblCellMar.Top.W;
|
||
|
||
// 同步行高
|
||
if not tc_.TcPr.VMerge and {self.}DynamicHeight > trp_.Height then
|
||
trp_.Height := {self.}DynamicHeight;
|
||
return true;
|
||
end;
|
||
|
||
function TcRange.Offset(x: real; y: real; page: Page);override;
|
||
begin
|
||
// println("TcRange::x = {}, y = {}, page = {}", x, y, page);
|
||
{self.}StartX := x + {self.}XOffset;
|
||
{self.}StartY := y + {self.}YOffset;
|
||
{self.}StartPage := page;
|
||
{self.}EndX := {self.}StartX;
|
||
{self.}EndY := {self.}StartY;
|
||
{self.}EndPage := {self.}StartPage;
|
||
content_next_page_ := false;
|
||
|
||
cell_x := {self.}EndX + {self.}Parent.TblPr.TblCellMar.Left.W;
|
||
cell_y := {self.}EndY - {self.}Parent.TblPr.TblCellMar.Top.W;
|
||
cell_h := {self.}FixedHeight;
|
||
for _,range in range_array_ do
|
||
begin
|
||
range.LowerBound := {self.}LowerBound;
|
||
range.Offset(cell_x, cell_y, {self.}EndPage);
|
||
if _ = 0 and range.IsFirstLineOnNextPage() then
|
||
begin
|
||
content_next_page_ := true;
|
||
break;
|
||
end
|
||
cell_y := range.EndY;
|
||
{self.}EndPage := range.EndPage;
|
||
end
|
||
{self.}EndY := cell_y - {self.}Parent.TblPr.TblCellMar.Bottom.W;
|
||
end;
|
||
|
||
function TcRange.SetTop();
|
||
begin
|
||
top_ := true;
|
||
end;
|
||
|
||
function TcRange.ContentNextPage(): boolean;
|
||
begin
|
||
return content_next_page_;
|
||
end;
|
||
|
||
function TcRange.AlignHeight(height: real);
|
||
begin
|
||
region_array_ := array();
|
||
region := new DTPUtils.Region();
|
||
region.BordersRange.Width := {self.}Width;
|
||
region.BordersRange.FixedHeight := {self.}FixedHeight;
|
||
region.BordersRange.TcPr := tc_pr_unit_decorator_;
|
||
{self.}SetBorderRange(region.BordersRange);
|
||
region_array_[length(region_array_)] := region;
|
||
|
||
pg := {self.}StartPage;
|
||
y := {self.}StartY;
|
||
page_remaining_height := y - {self.}GetLowerBound(pg);
|
||
surplus := height - page_remaining_height;
|
||
if surplus < 1e-6 then // 一页就够
|
||
begin
|
||
region.BordersRange.EndX := {self.}StartX;
|
||
region.BordersRange.EndY := {self.}StartY;
|
||
region.BordersRange.EndPage := pg;
|
||
region.BordersRange.DynamicHeight := height;
|
||
region.RangeArr union= range_array_;
|
||
{self.}EndY := {self.}StartY - height;
|
||
end
|
||
else begin
|
||
page_hash := array();
|
||
region.BordersRange.EndX := {self.}StartX;
|
||
region.BordersRange.EndY := {self.}StartY;
|
||
region.BordersRange.EndPage := pg;
|
||
region.BordersRange.DynamicHeight := page_remaining_height;
|
||
page_hash[pg.Index] := region;
|
||
// surplus -= page_remaining_height;
|
||
pg := docx_to_pdf_.PageManager[{self.}pg.Index + 1];
|
||
if ifnil(pg) then // 受间距影响,实际上文字没有进入下一页
|
||
begin
|
||
region.RangeArr union= range_array_;
|
||
{self.}EndY := {self.}StartY - page_remaining_height;
|
||
return;
|
||
end
|
||
|
||
y := pg.OriginalTextCoordinates()[1];
|
||
page_remaining_height := y - {self.}GetLowerBound(pg);
|
||
while surplus > page_remaining_height do
|
||
begin
|
||
region := new DTPUtils.Region();
|
||
region.BordersRange.Width := {self.}Width;
|
||
region.BordersRange.EndX := {self.}StartX;
|
||
region.BordersRange.EndY := y;
|
||
region.BordersRange.EndPage := pg;
|
||
region.BordersRange.DynamicHeight := page_remaining_height;
|
||
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;
|
||
page_hash[pg.Index] := region;
|
||
surplus -= page_remaining_height;
|
||
pg := docx_to_pdf_.PageManager[{self.}pg.Index + 1];
|
||
y := pg.OriginalTextCoordinates()[1];
|
||
page_remaining_height := y - {self.}GetLowerBound(pg);
|
||
end
|
||
if surplus > 1e-6 then
|
||
begin
|
||
region := new DTPUtils.Region();
|
||
region.BordersRange.Width := {self.}Width;
|
||
region.BordersRange.EndX := {self.}StartX;
|
||
region.BordersRange.EndY := y;
|
||
region.BordersRange.EndPage := pg;
|
||
region.BordersRange.DynamicHeight := surplus;
|
||
region.BordersRange.TcPr := tc_pr_unit_decorator_;
|
||
region.BordersRange.Top := true;
|
||
page_hash[pg.Index] := region;
|
||
{self.}SetBorderRange(region.BordersRange);
|
||
region_array_[length(region_array_)] := region;
|
||
{self.}EndY := y - surplus;
|
||
end
|
||
|
||
// 对应page分散到对应region
|
||
ranges := array();
|
||
for _,range in range_array_ do
|
||
ranges union= range.PLineRanges();
|
||
for _,range in ranges do
|
||
begin
|
||
region := page_hash[range.EndPage.Index];
|
||
region.RangeArr[length(region.RangeArr)] := range;
|
||
end
|
||
end
|
||
end;
|
||
|
||
function TcRange.GetLowerBound(pg: Page): real;
|
||
begin
|
||
return {self.}LowerBound = 0 ? pg.LowerBound : max({self.}LowerBound, pg.LowerBound);
|
||
end;
|
||
|
||
function TcRange.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) - {self.}Parent.TblPr.TblCellMar.Bottom.W;
|
||
case val of
|
||
"center":
|
||
begin
|
||
offset /= 2;
|
||
for _,range in arr do
|
||
range.Offset(range.StartX, range.StartY - offset, range.StartPage);
|
||
end
|
||
end;
|
||
end;
|
||
|
||
function TcRange.SetBorderRange(range: BordersRange);
|
||
begin
|
||
tbl_pr := {self.}Parent.TblPr;
|
||
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 <> {self.}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 <> {self.}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 = {self.}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 = {self.}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 <> {self.}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 = {self.}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 <> {self.}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 <> {self.}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 = {self.}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
|
||
if top_ then range.Top := true;
|
||
end;
|
||
|
||
function TcRange.GetTblStyleId(): string;
|
||
begin
|
||
return {self.}Parent.TblPr.TblStyle.Val;
|
||
end;
|
||
|
||
function TcRange.GetPrType(): string;
|
||
begin
|
||
if {self.}Row = 0 then return "firstRow";
|
||
else if ({self.}Row + 1) % 2 = 0 then return "band1Horz";
|
||
else return "band2Horz";
|
||
end;
|
||
|
||
function TblRange.Create(docx_to_pdf: TSDocxToPdf; tbl: Tbl);
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
tbl_ := tbl;
|
||
end;
|
||
|
||
function TblRange.Do();
|
||
begin
|
||
for _,r in tc_range_matrix_ do
|
||
for __,range in r do
|
||
if ifObj(range) then
|
||
range.DoBordersRangeFill();
|
||
for _,r in tc_range_matrix_ do
|
||
for __,range in r do
|
||
if ifObj(range) then
|
||
range.Do();
|
||
end;
|
||
|
||
function TblRange.Calc();
|
||
begin
|
||
{self.}SetTblTblPr(tbl_);
|
||
tbl_pr_unit_decorator_ := new TblPrUnitDecorator(tbl_.TblPr);
|
||
tbl_grid_unit_decorator := new TblGridUnitDecorator(tbl_.TblGrid);
|
||
grid_cols_ := tbl_grid_unit_decorator.GridCols();
|
||
// 如果是根据内容自适应,应该计算并调整grid_cols的值
|
||
trs := tbl_.Trs();
|
||
rows_ := length(trs);
|
||
cols_ := length(grid_cols_);
|
||
tr_pr_array_ := array();
|
||
tc_range_matrix_ := nils(rows_, cols_);
|
||
// 先构建一个矩阵
|
||
{self.}CreateTableMatrix(grid_cols_, trs);
|
||
end;
|
||
|
||
function TblRange.CreateTableMatrix(grid_cols: array of GridColUnitDecorator; trs: array of Tr);
|
||
begin
|
||
for i,tr in trs do
|
||
begin
|
||
{self.}SetTrTrPr(tr);
|
||
tr_pr := new TrPrUnitDecorator(tr.TrPr);
|
||
tc_x := 0;
|
||
trp := new DTPUtils.TrProperty();
|
||
trp.TrPr := tr_pr;
|
||
tr_pr_array_[i] := trp;
|
||
tcs := tr.Tcs();
|
||
pos := 0;
|
||
for j,tc in tcs do
|
||
begin
|
||
{self.}SetTcTcPr(tc);
|
||
if i = 0 then {self.}OverrideTcPrByTblStylePrType(tc.TcPr, "firstRow");
|
||
else if i = length(trs)-1 then {self.}OverrideTcPrByTblStylePrType(tc.TcPr, "lastRow")
|
||
else if (i + 1) % 2 = 0 then {self.}OverrideTcPrByTblStylePrType(tc.TcPr, "band1Horz");
|
||
else {self.}OverrideTcPrByTblStylePrType(tc.TcPr, "band2Horz");
|
||
|
||
grid_span := new GridSpanUnitDecorator(tc.TcPr.GridSpan);
|
||
if tc.TcPr.VMerge and tc.TcPr.VMerge <> "restart" then
|
||
begin
|
||
tc_x += grid_cols[pos++].W;
|
||
for k:=grid_span.Val-1 downto 1 do
|
||
begin
|
||
tc_range_matrix_[i][pos] := 0;
|
||
tc_x += grid_cols[pos++].W;
|
||
end
|
||
continue;
|
||
end
|
||
tc_range := new TcRange(docx_to_pdf_, tc, trp);
|
||
tc_range.Width := grid_cols[pos].W;
|
||
tc_range.FixedHeight := tr_pr.TrHeight.Val;
|
||
tc_range.Parent := self;
|
||
tc_range.XOffset := tc_x;
|
||
tc_range.Row := i;
|
||
tc_range.Col := pos;
|
||
tc_range_matrix_[i][pos] := tc_range;
|
||
pos++;
|
||
// 水平合并的单元格,占位需要和垂直的区分
|
||
for k:=grid_span.Val-1 downto 1 do
|
||
begin
|
||
tc_range_matrix_[i][pos] := 0; // 水平合并占位0
|
||
tc_range.Width += grid_cols[pos++].W;
|
||
end
|
||
tc_x += tc_range.Width;
|
||
end
|
||
end
|
||
// for i,arr in tc_range_matrix_ do
|
||
// println("i = {}, arr = {}", i, arr);
|
||
// println("\n");
|
||
return true;
|
||
end;
|
||
|
||
function TblRange.Offset(x: real; y: real; page: Page);override;
|
||
begin
|
||
// println("TblRange::x = {}, y = {}, page = {}", x, y, page);
|
||
{self.}StartX := x + {self.}XOffset;
|
||
{self.}StartY := y + {self.}YOffset; // table的offset实际都为0
|
||
{self.}StartPage := page;
|
||
{self.}ResetCoordinates(tbl_pr_unit_decorator_, grid_cols_);
|
||
{self.}EndX := {self.}StartX;
|
||
{self.}EndY := {self.}StartY;
|
||
{self.}EndPage := {self.}StartPage;
|
||
i := 0;
|
||
merge_arr := array();
|
||
vmerge_height := array();
|
||
vmerge_info := array();
|
||
while i < rows_ do
|
||
begin
|
||
j := 0;
|
||
tc_y := {self.}EndY;
|
||
top := recompute_flag;
|
||
recompute_flag := false;
|
||
while j < cols_ do
|
||
begin
|
||
// if i = 13 then
|
||
// println(">>>>>>>>>>>>>>>");
|
||
range := tc_range_matrix_[i][j];
|
||
if not ifObj(range) then
|
||
begin
|
||
j++;
|
||
continue;
|
||
end
|
||
if top then range.SetTop();
|
||
range.Calc();
|
||
range.LowerBound := {self.}LowerBound;
|
||
range.Offset({self.}EndX, {self.}tc_y, {self.}EndPage);
|
||
// println("i = {}, j = {}, height = {}, sy = {}, LowerBound = {}", i, j, range.DynamicHeight, range.StartY, range.LowerBound);
|
||
if range.ContentNextPage() then // 单元格新页开始,调整上一页的下边界,并重新计算
|
||
begin
|
||
top := true;
|
||
recompute_flag := true;
|
||
{self.}EndPage.LowerBound := tc_y;
|
||
{self.}EndPage := docx_to_pdf_.PageManager[{self.}EndPage.Index + 1];
|
||
[x, y] := {self.}EndPage.OriginalTextCoordinates();
|
||
{self.}EndY := y;
|
||
break;
|
||
end
|
||
if range.Tc.TcPr.VMerge then
|
||
begin
|
||
b_merge_index := i;
|
||
e_merge_index := i + 1;
|
||
while ifnil(tc_range_matrix_[e_merge_index+1][j]) and e_merge_index < rows_-1 do
|
||
e_merge_index++;
|
||
merge_arr[e_merge_index][j] := b_merge_index;
|
||
if ifnil(vmerge_height[e_merge_index]) or range.DynamicHeight > vmerge_height[e_merge_index] then
|
||
vmerge_height[e_merge_index] := range.DynamicHeight;
|
||
vmerge_info[e_merge_index] := b_merge_index;
|
||
end
|
||
j++;
|
||
end
|
||
if recompute_flag then continue;
|
||
top := false;
|
||
i_height := 0;
|
||
for k,v in merge_arr[i] do
|
||
begin
|
||
i_height := tr_pr_array_[i].Height;
|
||
r := tc_range_matrix_[v][k];
|
||
total_height := 0;
|
||
for index:=v to i-1 do
|
||
total_height += tr_pr_array_[index].Height;
|
||
h := vmerge_height[i];
|
||
if h > total_height + i_height then
|
||
i_height := h - total_height;
|
||
else
|
||
h := total_height + i_height;
|
||
r.AlignHeight(h);
|
||
r.SetVAlign();
|
||
end
|
||
if i_height then tr_pr_array_[i].Height := i_height;
|
||
for _,range in tc_range_matrix_[i] do
|
||
begin
|
||
if not ifObj(range) or range.Tc.TcPr.VMerge then continue;
|
||
range.AlignHeight(tr_pr_array_[i].Height);
|
||
range.SetVAlign();
|
||
{self.}EndY := range.EndY;
|
||
if {self.}EndPage.Index < range.EndPage.Index then
|
||
{self.}EndPage := range.EndPage;
|
||
end
|
||
i++;
|
||
end
|
||
end;
|
||
|
||
function TblRange.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 TblRange.OverrideTcPrByTblStylePrType(var tc_pr: TcPr; type: string);
|
||
begin
|
||
// tc_pr应该是经过外层copy的
|
||
tbl_style_pr := docx_to_pdf_.DocxComponents.GetTblStylePrByType(tbl_pr_unit_decorator_.TblStyle.Val, type);
|
||
if tbl_style_pr then tc_pr.Copy(tbl_style_pr.TcPr);
|
||
end;
|
||
|
||
function TblRange.SetTblTblPr(var tbl: Tbl);
|
||
begin
|
||
new_tbl_pr := new TblPr();
|
||
{self.}SetTblPrByStyleId(new_tbl_pr, tbl.TblPr.TblStyle.Val);
|
||
new_tbl_pr.Copy(tbl.TblPr);
|
||
tbl.TblPr.Copy(new_tbl_pr);
|
||
end;
|
||
|
||
function TblRange.SetTblPrByStyleId(var tbl_pr: TblPr; style_id: string);
|
||
begin
|
||
styles := docx_to_pdf_.DocxComponents.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 TblRange.SetTrTrPr(var tr: Tr);
|
||
begin
|
||
new_tr_pr := new TrPr();
|
||
{self.}SetTrPrByStyleId(new_tr_pr, tbl_pr_unit_decorator_.TblStyle.Val);
|
||
new_tr_pr.Copy(tr.TrPr);
|
||
tr.TrPr.Copy(new_tr_pr);
|
||
end;
|
||
|
||
function TblRange.SetTrPrByStyleId(var tr_pr: TrPr; style_id: string);
|
||
begin
|
||
styles := docx_to_pdf_.DocxComponents.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 TblRange.SetTcTcPr(var tc: Tc);
|
||
begin
|
||
new_tc_pr := new TcPr();
|
||
{self.}SetTcPrByStyleId(new_tc_pr, tbl_pr_unit_decorator_.TblStyle.Val);
|
||
new_tc_pr.Copy(tc.TcPr);
|
||
tc.TcPr.Copy(new_tc_pr);
|
||
end;
|
||
|
||
function TblRange.SetTcPrByStyleId(var tc_pr: TcPr; style_id: string);
|
||
begin
|
||
styles := docx_to_pdf_.DocxComponents.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 OMathParaRange.Create(docx_to_pdf: TSDocxToPdf; o_math_para: OMathPara);
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
o_math_para_ := o_math_para;
|
||
end;
|
||
|
||
function OMathParaRange.Do();override;
|
||
begin
|
||
o_math_range_.Do();
|
||
end;
|
||
|
||
function OMathParaRange.Run();override;
|
||
begin
|
||
o_math_range_.StartX := {self.}StartX;
|
||
o_math_range_.StartY := {self.}StartY;
|
||
o_math_range_.EndX := {self.}StartX;
|
||
o_math_range_.EndY := {self.}StartY;
|
||
o_math_range_.StartPage := {self.}StartPage;
|
||
o_math_range_.EndPage := {self.}StartPage;
|
||
o_math_range_.Run();
|
||
end;
|
||
|
||
function OMathParaRange.Calc();
|
||
begin
|
||
o_math_range_ := new OMathRange(docx_to_pdf_, o_math_para_.OMath);
|
||
o_math_range_.Width := {self.}Width;
|
||
o_math_range_.Parent := self;
|
||
o_math_range_.StartX := 0;
|
||
o_math_range_.StartY := 0;
|
||
o_math_range_.SetMathSize();
|
||
o_math_range_.Calc();
|
||
end;
|
||
|
||
function OMathRange.Create(docx_to_pdf: TSDocxToPdf; element: OpenXmlElement);
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
element_ := element;
|
||
sz_ := 0;
|
||
end;
|
||
|
||
function OMathRange.Do();override;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.Do();
|
||
end;
|
||
|
||
function OMathRange.Run();override;
|
||
begin
|
||
{self.}EndX := {self.}StartX;
|
||
{self.}EndY := {self.}StartY;
|
||
{self.}EndPage := {self.}StartPage;
|
||
for _,range in range_array_ do
|
||
begin
|
||
range.StartX := {self.}StartX;
|
||
range.StartY := {self.}StartY;
|
||
range.StartPage := {self.}StartPage;
|
||
range.Run();
|
||
end
|
||
end;
|
||
|
||
function OMathRange.Calc();
|
||
begin
|
||
range_array_ := array();
|
||
{self.}EndX := {self.}StartX;
|
||
{self.}EndY := {self.}StartY;
|
||
min_y := {self.}StartY;
|
||
max_y := {self.}StartY;
|
||
elements := element_.Elements();
|
||
for _,element in elements do
|
||
begin
|
||
range := nil;
|
||
if element.LocalName = "r" then
|
||
range := new OMathRRange(docx_to_pdf_, element);
|
||
else if element.LocalName = "f" then
|
||
range := new OMathFRange(docx_to_pdf_, element);
|
||
// else if element.LocalName = "rad" then
|
||
// range := new OMathRadRange(docx_to_pdf_, element);
|
||
// else if element.LocalName = "nary" then
|
||
// range := new OMathNaryRange(docx_to_pdf_, element);
|
||
// else if element.LocalName = "sSup" then
|
||
// range := new OMathSSupRange(docx_to_pdf_, element);
|
||
|
||
if not ifObj(range) then
|
||
begin
|
||
echo format("Math do not support <%s>\n", element.ElementName);
|
||
continue;
|
||
end
|
||
range.Parent := self;
|
||
range.StartX := {self.}EndX;
|
||
range.StartY := {self.}EndY;
|
||
range.Sz := sz_;
|
||
range.Calc();
|
||
|
||
if min_y > range.EndY then min_y := range.EndY;
|
||
if max_y < range.EndY + range.DynamicHeight then max_y := range.EndY + range.DynamicHeight;
|
||
|
||
{self.}EndX := range.EndX;
|
||
{self.}EndY := range.EndY;
|
||
range_array_[length(range_array_)] := range;
|
||
end
|
||
{self.}DynamicHeight := max_y - min_y;
|
||
end;
|
||
|
||
function OMathRange.SetMathSize();
|
||
begin
|
||
elements := element_.Elements();
|
||
element := elements[0];
|
||
rpr := nil;
|
||
if element.LocalName = "r" then
|
||
rpr := element.RPr;
|
||
else if element.LocalName = "f" then
|
||
rpr := element.FPr.CtrlPr.RPr;
|
||
else if element.LocalName = "nary" then
|
||
rpr := element.NaryPr.CtrlPr.RPr;
|
||
else if element.LocalName = "rad" then
|
||
rpr := element.RadPr.CtrlPr.RPr;
|
||
else if element.LocalName = "sSup" then
|
||
rpr := element.SSupPr.CtrlPr.RPr;
|
||
|
||
styles := docx_to_pdf_.DocxComponents.GetStyles();
|
||
default_rpr := styles.DocDefaults.RPrDefault.RPr();
|
||
if rpr then default_rpr.Copy(rpr);
|
||
sz_ := strtofloat(default_rpr.Sz.Val);
|
||
end;
|
||
|
||
function OMathFRange.Create(docx_to_pdf: TSDocxToPdf; f: F);
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
f_ := f;
|
||
range_array_ := array();
|
||
end;
|
||
|
||
function OMathFRange.Do();override;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.Do();
|
||
end;
|
||
|
||
function OMathFRange.Run();
|
||
begin
|
||
{self.}EndX := {self.}StartX;
|
||
{self.}EndY := {self.}StartY;
|
||
{self.}EndPage := {self.}StartPage;
|
||
for _,range in range_array_ do
|
||
begin
|
||
range.StartX := {self.}StartX;
|
||
range.StartY := {self.}StartY;
|
||
range.StartPage := {self.}StartPage;
|
||
range.Run();
|
||
end
|
||
end;
|
||
|
||
function OMathFRange.Calc();
|
||
begin
|
||
{self.}EndX := {self.}StartX;
|
||
{self.}EndY := {self.}StartY;
|
||
|
||
// 分子
|
||
num_range := new OMathRange(docx_to_pdf_, f_.Num);
|
||
num_range.Sz := sz_;
|
||
num_range.StartX := {self.}EndX;
|
||
num_range.StartY := {self.}EndY;
|
||
num_range.Calc(); // 需要得到高宽
|
||
|
||
// 分母
|
||
den_range := new OMathRange(docx_to_pdf_, f_.Den);
|
||
den_range.Sz := sz_;
|
||
den_range.StartX := {self.}EndX;
|
||
den_range.StartY := num_range.EndY - 0.418 * sz;
|
||
den_range.Calc(); // 需要得到高宽
|
||
|
||
max_len := max(den_range.Width, num_range.Width);
|
||
bar := max_len / 0.9;
|
||
line_range := new LineRange();
|
||
line_range.StartX := {self.}EndX - (bar - max_len) / 2;
|
||
line_range.StartY := + 0.928 * sz;
|
||
line_range.EndX := line_range.StartX;
|
||
line_range.EndY := line_range.StartY;
|
||
line_range.Width := bar;
|
||
line_range.LineWidth := 0.04 * sz;
|
||
|
||
range_array_ union= array(den_range, num_range);
|
||
// range_array_ union= array(den_range, num_range, line_range);
|
||
end;
|
||
|
||
function OMathRRange.Create(docx_to_pdf: TSDocxToPdf; r: R);
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
r_ := r;
|
||
range_array_ := array();
|
||
end;
|
||
|
||
function OMathRRange.Do();override;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.Do();
|
||
end;
|
||
|
||
function OMathRRange.Run();
|
||
begin
|
||
{self.}EndX := {self.}StartX;
|
||
{self.}EndPage := {self.}StartPage;
|
||
{self.}DynamicHeight := sz_;
|
||
{self.}EndY := {self.}StartY - sz_;
|
||
for _,range in range_array_ do
|
||
begin
|
||
range.EndX += {self.}StartX;
|
||
range.EndY := range.StartY + {self.}EndY - sz_;
|
||
range.EndPage := {self.}EndPage;
|
||
end;
|
||
end;
|
||
|
||
function OMathRRange.Calc();
|
||
begin
|
||
if not r_.T then return;
|
||
x := {self.}StartX;
|
||
y := {self.}StartY;
|
||
text := r_.T.Text;
|
||
pos := 1;
|
||
while pos <= length(text) do
|
||
begin
|
||
text_range := new TextRange();
|
||
num := DTPUtils.Utf8CharLengthFromByte(text[pos]);
|
||
a_word := text[pos : pos+num-1];
|
||
if num = 1 then
|
||
begin
|
||
char := ord(a_word);
|
||
if char >= 0x30 and char <= 0x39 then
|
||
text_range.Type := 1;
|
||
else if char >= 0x41 and char <= 0x5A then
|
||
text_range.Type := 2;
|
||
else if char >= 0x61 and char <= 0x7A then
|
||
text_range.Type := 2;
|
||
else if char = 0x44 or char = 0x46 then
|
||
text_range.Type := 5;
|
||
word := a_word;
|
||
font_obj := docx_to_pdf_.Font.GetCNSFont("SimSun", false, true);
|
||
end
|
||
else if DTPUtils.IsChineseChar(a_word) then
|
||
begin
|
||
text_range.Type := 3;
|
||
word := utf8ToAnsi(a_word);
|
||
font_obj := docx_to_pdf_.Font.GetCNSFont("SimSun", false, true);
|
||
end
|
||
else if DTPUtils.IsChinesePunctuation(a_word) then
|
||
begin
|
||
text_range.Type := 4;
|
||
word := utf8ToAnsi(a_word);
|
||
font_obj := docx_to_pdf_.Font.GetCNSFont("SimSun", false, true);
|
||
end
|
||
else begin
|
||
word := class(SymbolMapper).SymbolChr(a_word);
|
||
if ifnil(word) then
|
||
begin
|
||
echo format("error symbol {{%s}}.\n", a_word);
|
||
word := chr(0x20);
|
||
end
|
||
font_obj := docx_to_pdf_.Font.GetSymbolFont();
|
||
end
|
||
rpr := new RPr();
|
||
rpr.Sz.Val := sz_;
|
||
first_page := docx_to_pdf_.PageManager[0];
|
||
pdf_page := first_page.PdfPage;
|
||
pdf_page.SetFontAndSize(font_obj, sz);
|
||
text_range.RPr := rpr;
|
||
text_range.Text := word;
|
||
text_range.Font := font_obj;
|
||
text_range.Width := pdf_page.TextWidth(word);
|
||
text_range.Parent := self;
|
||
text_range.DynamicHeight := rpr.Sz.Val;
|
||
text_range.EndX := x;
|
||
text_range.EndY := y;
|
||
x += text_range.Width;
|
||
pos += num;
|
||
range_array_[length(range_array_)] := text_range;
|
||
end
|
||
end;
|
||
|
||
end.
|