3044 lines
96 KiB
Plaintext
3044 lines
96 KiB
Plaintext
unit DTPAdvancedRanges;
|
||
interface
|
||
uses DTPPrimitiveRanges, DTPUtils, DocxML, 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);override;
|
||
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);override;
|
||
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 P read p_;
|
||
|
||
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_: PPr);
|
||
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: RPr; 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 RObject(r: R);
|
||
function FldSimple(fld_simple: fldSimple);
|
||
function Hyperlink(hyperlink: Hyperlink);
|
||
function OMathPara(o_math_para: OMathPara);
|
||
function OMath(o_math: OMath);
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
p_: P;
|
||
ppr_: PPr;
|
||
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_: TcPr;
|
||
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_;
|
||
property Rows read rows_;
|
||
property Cols read cols_;
|
||
|
||
private
|
||
function CreateTableMatrix(grid_cols: array of GridCol; 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; type: string);
|
||
function SetTcPrByStyleId(var tc_pr: TcPr; style_id: string; type: string);
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
tbl_: Tbl;
|
||
tbl_pr_: TblPr;
|
||
grid_cols_: array of GridCol;
|
||
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 Calc();override;
|
||
function Offset(x: real; y: real; page: Page);override;
|
||
function AdjustOffset(x: real; y: real);override;
|
||
|
||
public
|
||
BaseHeight: real; // 基准高度
|
||
|
||
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 Calc();override;
|
||
function Offset(x: real; y: real; page: Page);override;
|
||
function AdjustOffset(x: real; y: real);override;
|
||
function SetMathSize();
|
||
|
||
public
|
||
BaseHeight: real; // 基准高度
|
||
BaseSz: real; // 基准字体大小
|
||
SingleLine: boolean; // 是否单行公式
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
element_: OMath;
|
||
range_array_: array of BasicRange;
|
||
end;
|
||
|
||
type OMathRRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; r: R);
|
||
function Do();override;
|
||
function Calc();override;
|
||
function Offset(x: real; y: real; page: Page);override;
|
||
function AdjustOffset(x: real; y: real);overload;
|
||
|
||
public
|
||
BaseHeight: real; // 基准高度
|
||
BaseSz: real; // 基准字体大小
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
r_: R;
|
||
range_array_: array of BasicRange;
|
||
end;
|
||
|
||
type OMathFRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; f: F);
|
||
function Do();override;
|
||
function Calc();override;
|
||
function Offset(x: real; y: real; page: Page);override;
|
||
function AdjustOffset(x: real; y: real);overload;
|
||
|
||
public
|
||
BaseHeight: real; // 基准高度
|
||
BaseSz: real; // 基准字体大小
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
f_: F;
|
||
range_array_: array of BasicRange;
|
||
end;
|
||
|
||
type OMathNaryRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; nary: Nary);
|
||
function Do();override;
|
||
function Calc();override;
|
||
function Offset(x: real; y: real; page: Page);override;
|
||
function AdjustOffset(x: real; y: real);overload;
|
||
|
||
public
|
||
BaseHeight: real; // 基准高度
|
||
BaseSz: real; // 基准字体大小
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
nary_: Nary;
|
||
range_array_: array of BasicRange;
|
||
end;
|
||
|
||
type OMathRadRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; rad: Rad);
|
||
function Do();override;
|
||
function Calc();override;
|
||
function Offset(x: real; y: real; page: Page);override;
|
||
function AdjustOffset(x: real; y: real);overload;
|
||
|
||
public
|
||
BaseHeight: real; // 基准高度
|
||
BaseSz: real; // 基准字体大小
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
rad_: rad;
|
||
range_array_: array of BasicRange;
|
||
end;
|
||
|
||
type OMathSSupRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; s_sup: SSup);
|
||
function Do();override;
|
||
function Calc();override;
|
||
function Offset(x: real; y: real; page: Page);override;
|
||
function AdjustOffset(x: real; y: real);overload;
|
||
|
||
public
|
||
BaseHeight: real; // 基准高度
|
||
BaseSz: real; // 基准字体大小
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
s_sup_: SSup;
|
||
range_array_: array of BasicRange;
|
||
end;
|
||
|
||
type OMathSSubRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; s_sub: SSub);
|
||
function Do();override;
|
||
function Calc();override;
|
||
function Offset(x: real; y: real; page: Page);override;
|
||
function AdjustOffset(x: real; y: real);overload;
|
||
|
||
public
|
||
BaseHeight: real; // 基准高度
|
||
BaseSz: real; // 基准字体大小
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
s_sub_: SSub;
|
||
range_array_: array of BasicRange;
|
||
end;
|
||
|
||
type OMathDRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; d: D);
|
||
function Do();override;
|
||
function Calc();override;
|
||
function Offset(x: real; y: real; page: Page);override;
|
||
function AdjustOffset(x: real; y: real);overload;
|
||
|
||
public
|
||
BaseHeight: real; // 基准高度
|
||
BaseSz: real; // 基准字体大小
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
d_: D;
|
||
range_array_: array of BasicRange;
|
||
end;
|
||
|
||
type OMathFuncRange = class(AdvancedRange)
|
||
public
|
||
function Create(docx_to_pdf: TSDocxToPdf; func: Func);
|
||
function Do();override;
|
||
function Calc();override;
|
||
function Offset(x: real; y: real; page: Page);override;
|
||
function AdjustOffset(x: real; y: real);overload;
|
||
|
||
public
|
||
BaseHeight: real; // 基准高度
|
||
BaseSz: real; // 基准字体大小
|
||
|
||
private
|
||
[weakref]docx_to_pdf_: TSDocxToPdf;
|
||
func_: Func;
|
||
range_array_: array of BasicRange;
|
||
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 AdvancedRange.Offset(x: real; y: real; page: Page);
|
||
begin
|
||
{self.}StartX := {self.}XOffset + x;
|
||
{self.}StartY := {self.}YOffset + y;
|
||
{self.}StartPage := page;
|
||
{self.}EndX := {self.}StartX;
|
||
{self.}EndY := {self.}StartY;
|
||
{self.}EndPage := {self.}StartPage;
|
||
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
|
||
class(AdvancedRange).Offset(x, y, page);
|
||
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
|
||
class(AdvancedRange).Offset(x, y, page);
|
||
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;
|
||
offset := {self.}LineSpace >= {self.}DynamicHeight ? ({self.}LineSpace - {self.}TextMaxSize) / 2 + {self.}TextMaxSize - {self.}TextMaxSize / 5 : {self.}DynamicHeight;
|
||
y_offset := {self.}StartY - offset;
|
||
for _,range in range_array_ do
|
||
begin
|
||
if range is class(OMathRange) then // 公式不是y值,需要处理公式
|
||
range.Offset(x, y, page);
|
||
// range.Offset(0, 841.9, page);
|
||
else
|
||
range.Offset(x, y_offset, page);
|
||
end
|
||
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; // 中文标点不换行
|
||
if range is class(OMathParaRange) 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_;
|
||
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_.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_);
|
||
if not p_.PPr.RPr.Sz.Val then p_.PPr.RPr.Sz.Val := docx_to_pdf_.Font.GetDefaultSz();
|
||
ppr_ := p_.PPr;
|
||
{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_);
|
||
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);
|
||
else if element.Object then {self.}RObject(element);
|
||
else if element.Anchor then {self.}Hyperlink(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
|
||
// 公式嵌入段落
|
||
{self.}OMath(element);
|
||
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);
|
||
class(AdvancedRange).Offset(x, y, page);
|
||
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);
|
||
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.IsApplied, rpr.I.IsApplied);
|
||
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 := 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;
|
||
image_range.RPr := r.RPr;
|
||
body_range_array_[length(body_range_array_)] := image_range;
|
||
end
|
||
end;
|
||
|
||
function PRange.RObject(r: R);
|
||
begin
|
||
id := r.Object.Shape.Imagedata.Id;
|
||
[image_type, image] := {self.}GetImageData(id);
|
||
if not image then return;
|
||
style := r.Object.Shape.Style;
|
||
style_arr := str2array(style, ";");
|
||
for _,str in style_arr do
|
||
begin
|
||
if startsStr("width:", str) then w := strtofloat(str[7:length(str)-2]);
|
||
else if startsStr("height:", str) then h := strtofloat(str[8:length(str)-2]);
|
||
end
|
||
image_range := new ImageRange();
|
||
image_range.Image := image;
|
||
image_range.Type := image_type;
|
||
image_range.Width := w;
|
||
image_range.DynamicHeight := h;
|
||
image_range.RPr := r.RPr;
|
||
body_range_array_[length(body_range_array_)] := image_range;
|
||
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
|
||
rpr := r.RPr;
|
||
if fld_struct.Type.Page then
|
||
begin
|
||
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.IsApplied, rpr.I.IsApplied);
|
||
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
|
||
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.IsApplied, rpr.I.IsApplied);
|
||
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
|
||
else if fld_struct.Type.Quote then
|
||
begin
|
||
if r.Drawing then {self.}RDrawing(r);
|
||
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_);
|
||
if fld_struct.Type.NumPages then
|
||
begin
|
||
if fld_struct.Arabic then
|
||
begin
|
||
rpr := 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.IsApplied, rpr.I.IsApplied);
|
||
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 := 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.IsApplied, rpr.I.IsApplied);
|
||
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_);
|
||
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_para_range := new OMathParaRange(docx_to_pdf_, o_math_para);
|
||
math_para_range.Width := 0;
|
||
math_para_range.Parent := self;
|
||
math_para_range.Calc();
|
||
body_range_array_[length(body_range_array_)] := math_para_range;
|
||
end;
|
||
|
||
function PRange.OMath(o_math: OMath);
|
||
begin
|
||
math_range := new OMathRange(docx_to_pdf_, o_math);
|
||
math_range.Width := 0;
|
||
math_range.Parent := self;
|
||
math_range.XOffset := 0;
|
||
math_range.YOffset := 0;
|
||
math_range.SetMathSize();
|
||
math_range.Calc();
|
||
math_range.AdjustOffset(0, -math_range.DynamicHeight);
|
||
body_range_array_[length(body_range_array_)] := math_range;
|
||
end;
|
||
|
||
function PRange.HyperlinkToToc();
|
||
begin
|
||
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_.Spacing.Before;
|
||
// 段落的x偏移是缩进
|
||
{self.}XOffset := ppr_.Ind.LeftChars ? ppr_.Ind.LeftChars * ppr_.RPr.Sz.Val : ppr_.Ind.Left;
|
||
{self.}YOffset := 0;
|
||
|
||
pline_range := {self.}NewPLineRange();
|
||
pline_range.XOffset := ppr_.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.AdjustOffset(pline_range.XOffset, 0);
|
||
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_.RPr.Sz.Val, ppr_.Spacing.Line, ppr_.Spacing.LineRule);
|
||
{self.}DynamicHeight += line_space;
|
||
end
|
||
{self.}DynamicHeight += ppr_.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_.Spacing.Line, ppr_.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;
|
||
i := 0;
|
||
head_range := nil;
|
||
tail_range := nil;
|
||
while i < length(body_range_array_)-1 do
|
||
begin
|
||
if not (head_range is class(TextRange)) then
|
||
begin
|
||
i++;
|
||
head_range := body_range_array_[i];
|
||
end
|
||
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_.Spacing.Before) then
|
||
{self.}EndY -= ppr_.Spacing.Before;
|
||
|
||
// 检查是否有段前分页
|
||
if ppr_.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_.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_.RPr.Sz.Val, ppr_.Spacing.Line, ppr_.Spacing.LineRule);
|
||
{self.}EndY -= line_space;
|
||
end
|
||
|
||
{self.}DoDrawingAnchor();
|
||
{self.}DoAlternateContentAnchor();
|
||
{self.}DoToc();
|
||
|
||
{self.}EndY -= ppr_.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 := anchor.Graphic.GraphicData.Pic.SpPr.Xfrm;
|
||
position_h := anchor.PositionH;
|
||
position_v := 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 := wsp.SpPr.Xfrm;
|
||
position_h := anchor.PositionH;
|
||
position_v := 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 := 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
|
||
text := r.T.Text;
|
||
if text then {self.}SplitTextToTextRange(body_range_array_, text, r.rpr, anchor);
|
||
end;
|
||
|
||
function PRange.SplitTextToTextRange(range_arr: array of BasicRange; text: string; rpr: RPr; 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.IsApplied, rpr.I.IsApplied);
|
||
// font_name := rpr.RFonts.Ascii ?: rpr.RFonts.EastAsia;
|
||
// font_obj := docx_to_pdf_.Font.GetAsciiFont(font_name, rpr.B.IsApplied, rpr.I.IsApplied);
|
||
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.IsApplied, rpr.I.IsApplied);
|
||
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.IsApplied, rpr.I.IsApplied);
|
||
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.IsApplied, rpr.I.IsApplied);
|
||
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
|
||
if not p.PPr then
|
||
begin
|
||
styles := docx_to_pdf_.DocxComponents.GetStyles();
|
||
p.PPr := styles.DocDefaults.PPrDefault.PPr;
|
||
end
|
||
else begin
|
||
if p.PPr.PStyle.Val then
|
||
{self.}SetPPrByStyleId(p.PPr, p.PPr.PStyle.Val);
|
||
else if {self.}Parent is class(TcRange) then
|
||
{self.}SetPPrByStyleId(p.PPr, {self.}Parent.GetTblStyleId());
|
||
end
|
||
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
|
||
ppr.SetFallback(style.PPr);
|
||
based_on := style.BasedOn.Val;
|
||
{self.}SetPPrByStyleId(ifnil(style.PPr) ? ppr : style.PPr, based_on);
|
||
end
|
||
end;
|
||
|
||
function PRange.SetRRPr(var r: R; ppr_: PPr);
|
||
begin
|
||
if ifnil(r.RPr) then
|
||
begin
|
||
styles := docx_to_pdf_.DocxComponents.GetStyles();
|
||
r.RPr := styles.DocDefaults.RPrDefault.RPr;
|
||
end
|
||
else begin
|
||
if r.RPr.RStyle.Val then
|
||
{self.}SetRPrByStyleId(r.RPr, r.RPr.RStyle.Val);
|
||
else if ppr_.PStyle.Val then
|
||
{self.}SetRPrByStyleId(r.RPr, ppr_.PStyle.Val);
|
||
else if {self.}Parent is class(TcRange) then
|
||
{self.}SetRPrByTblStyleId(r.RPr, {self.}Parent.GetTblStyleId());
|
||
end
|
||
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
|
||
pr_type := {self.}Parent.GetPrType();
|
||
tbl_style_pr := docx_to_pdf_.DocxComponents.GetTblStylePrByType(style_id, pr_type);
|
||
rpr.SetFallback(tbl_style_pr.RPr);
|
||
{self.}SetRPrByTblStyleId(ifnil(tbl_style_pr.RPr) ? rpr : tbl_style_pr.RPr, style.BasedOn.Val);
|
||
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
|
||
rpr.SetFallback(style.RPr);
|
||
based_on := style.BasedOn.Val;
|
||
{self.}SetRPrByStyleId(ifnil(style.RPr) ? rpr : style.RPr, based_on);
|
||
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_);
|
||
// {self.}SplitTextToTextRange(bullet_range_array_, lvl_text, rpr);
|
||
{self.}SplitTextToTextRange(body_range_array_, lvl_text, lvl.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_.SnapToGrid) and not ppr_.SnapToGrid) or
|
||
((ifnil(ppr_.SnapToGrid) or ppr_.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_ := 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.IsApplied 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);
|
||
class(AdvancedRange).Offset(x, y, page);
|
||
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_;
|
||
{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_;
|
||
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_;
|
||
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_.TcBorders.Top then
|
||
tc_pr_.TcBorders.Top.SetFallback(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_.TcBorders.Bottom then
|
||
tc_pr_.TcBorders.Bottom.SetFallback(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_.TcBorders.Right then
|
||
tc_pr_.TcBorders.Right.SetFallback(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_.TcBorders.Bottom then
|
||
tc_pr_.TcBorders.Bottom.SetFallback(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_.TcBorders.Bottom then
|
||
tc_pr_.TcBorders.Bottom.SetFallback(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_.TcBorders.Right then
|
||
tc_pr_.TcBorders.Right.SetFallback(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_.TcBorders.Bottom then
|
||
tc_pr_.TcBorders.Bottom.SetFallback(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_.TcBorders.Bottom then
|
||
tc_pr_.TcBorders.Bottom.SetFallback(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_.TcBorders.Right then
|
||
tc_pr_.TcBorders.Right.SetFallback(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_.TcBorders.Left then
|
||
tc_pr_.TcBorders.Left.SetFallback(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_.TcBorders.Right then
|
||
tc_pr_.TcBorders.Right.SetFallback(tbl_pr.TblBorders.Right);
|
||
range.Right := true;
|
||
end
|
||
end
|
||
end
|
||
else begin
|
||
range.Left := false;
|
||
range.Top := false;
|
||
range.Right := false;
|
||
range.Bottom := false;
|
||
end
|
||
if top_ and ifObj(tbl_pr.TblBorders) 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_:= tbl_.TblPr;
|
||
tbl_grid_:= tbl_.TblGrid;
|
||
grid_cols_ := tbl_grid_.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 GridCol; trs: array of Tr);
|
||
begin
|
||
for i,tr in trs do
|
||
begin
|
||
{self.}SetTrTrPr(tr);
|
||
tr_pr := 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
|
||
if i = 0 then {self.}SetTcTcPr(tc, "firstRow");
|
||
else if i = length(trs)-1 then {self.}SetTcTcPr(tc, "lastRow");
|
||
else if (i + 1) % 2 = 0 then {self.}SetTcTcPr(tc, "band1Horz");
|
||
else {self.}SetTcTcPr(tc, "band2Horz");
|
||
|
||
grid_span := tc.TcPr.GridSpan;
|
||
if tc.TcPr.VMerge.IsApplied and tc.TcPr.VMerge.Val <> "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_, 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.IsApplied 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.IsApplied 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.SetTblTblPr(var tbl: Tbl);
|
||
begin
|
||
if ifnil(tbl.TblPr) then
|
||
tbl.TblPr := new TblPr();
|
||
{self.}SetTblPrByStyleId(tbl.TblPr, tbl.TblPr.TblStyle.Val);
|
||
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
|
||
tbl_pr.SetFallback(style.TblPr);
|
||
based_on := style.BasedOn.Val;
|
||
{self.}SetTblPrByStyleId(ifnil(style.TblPr) ? tbl_pr : style.TblPr, based_on);
|
||
end
|
||
end;
|
||
|
||
function TblRange.SetTrTrPr(var tr: Tr);
|
||
begin
|
||
if ifnil(tr.TrPr) then
|
||
tr.TrPr := new TrPr();
|
||
{self.}SetTrPrByStyleId(tr.TrPr, tbl_pr_.TblStyle.Val);
|
||
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
|
||
tr_pr.SetFallback(style.TrPr);
|
||
based_on := style.BasedOn.Val;
|
||
{self.}SetTrPrByStyleId(ifnil(style.TrPr) ? tr_pr : style.TrPr, based_on);
|
||
end
|
||
end;
|
||
|
||
function TblRange.SetTcTcPr(var tc: Tc; type: string);
|
||
begin
|
||
if ifnil(tc.TcPr) then
|
||
tc.TcPr := new TcPr();
|
||
{self.}SetTcPrByStyleId(tc.TcPr, tbl_pr_.TblStyle.Val, type);
|
||
end;
|
||
|
||
function TblRange.SetTcPrByStyleId(var tc_pr: TcPr; style_id: string; type: string);
|
||
begin
|
||
if type then
|
||
begin
|
||
style := docx_to_pdf_.DocxComponents.GetTblStylePrByType(style_id, type);
|
||
if ifObj(style) then
|
||
tc_pr.SetFallback(style.TcPr);
|
||
end
|
||
else begin
|
||
styles := docx_to_pdf_.DocxComponents.GetStylesAdapter();
|
||
style := styles.GetStyleByStyleId(style_id);
|
||
if ifObj(style) then
|
||
begin
|
||
tc_pr.SetFallback(style.TcPr);
|
||
based_on := style.BasedOn.Val;
|
||
{self.}SetTcPrByStyleId(ifnil(style.TcPr) ? tc_pr : style.TcPr, based_on);
|
||
end
|
||
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.Offset(x: real; y: real; page: Page);override;
|
||
begin
|
||
class(AdvancedRange).Offset(x, y, page);
|
||
o_math_range_.Offset({self.}EndX, {self.}EndY, {self.}EndPage);
|
||
end;
|
||
|
||
function OMathParaRange.Calc();override;
|
||
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_.XOffset := 0;
|
||
o_math_range_.YOffset := 0;
|
||
o_math_range_.SingleLine := true;
|
||
o_math_range_.SetMathSize();
|
||
o_math_range_.Calc();
|
||
o_math_range_.AdjustOffset(0, -o_math_range_.DynamicHeight);
|
||
{self.}Width := o_math_range_.Width;
|
||
{self.}DynamicHeight := o_math_range_.DynamicHeight;
|
||
end;
|
||
|
||
function OMathParaRange.AdjustOffset(x: real; y: real);override;
|
||
begin
|
||
class(BasicRange).AdjustOffset(x, y);
|
||
o_math_range_.AdjustOffset(x, y);
|
||
end;
|
||
|
||
function OMathRange.Create(docx_to_pdf: TSDocxToPdf; element: OpenXmlElement);
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
element_ := element;
|
||
{self.}BaseHeight := 0;
|
||
{self.}BaseSz := 0;
|
||
{self.}SingleLine := false;
|
||
end;
|
||
|
||
function OMathRange.Do();override;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.Do();
|
||
end;
|
||
|
||
function OMathRange.Offset(x: real; y: real; page: Page);override;
|
||
begin
|
||
class(AdvancedRange).Offset(x, y, page);
|
||
for _,range in range_array_ do
|
||
range.Offset(x, y, page);
|
||
end;
|
||
|
||
function OMathRange.AdjustOffset(x: real; y: real);overload;
|
||
begin
|
||
class(BasicRange).AdjustOffset(x, y);
|
||
for _,range in range_array_ do
|
||
range.AdjustOffset(x, y);
|
||
end;
|
||
|
||
function OMathRange.Calc();override;
|
||
begin
|
||
range_array_ := array();
|
||
x := {self.}XOffset;
|
||
y := {self.}YOffset;
|
||
elements := element_.Elements();
|
||
up_h := 0;
|
||
for _,element in elements do
|
||
begin
|
||
range := nil;
|
||
if element.LocalName = "r" then
|
||
begin
|
||
range := new OMathRRange(docx_to_pdf_, element);
|
||
range.BaseSz := {self.}BaseSz;
|
||
end
|
||
else if element.LocalName = "f" then
|
||
begin
|
||
range := new OMathFRange(docx_to_pdf_, element);
|
||
range.BaseSz := {self.}SingleLine ? {self.}BaseSz : 0.7 * {self.}BaseSz;
|
||
end
|
||
else if element.LocalName = "rad" then
|
||
begin
|
||
range := new OMathRadRange(docx_to_pdf_, element);
|
||
range.BaseSz := {self.}BaseSz;
|
||
end
|
||
else if element.LocalName = "nary" then
|
||
begin
|
||
range := new OMathNaryRange(docx_to_pdf_, element);
|
||
range.BaseSz := {self.}BaseSz;
|
||
end
|
||
else if element.LocalName = "sSup" then
|
||
begin
|
||
range := new OMathSSupRange(docx_to_pdf_, element);
|
||
range.BaseSz := {self.}BaseSz;
|
||
end
|
||
else if element.LocalName = "sSub" then
|
||
begin
|
||
range := new OMathSSubRange(docx_to_pdf_, element);
|
||
range.BaseSz := {self.}BaseSz;
|
||
end
|
||
else if element.LocalName = "d" then
|
||
begin
|
||
range := new OMathDRange(docx_to_pdf_, element);
|
||
range.BaseSz := {self.}BaseSz;
|
||
end
|
||
else if element.LocalName = "func" then
|
||
begin
|
||
range := new OMathFuncRange(docx_to_pdf_, element);
|
||
range.BaseSz := {self.}BaseSz;
|
||
end
|
||
|
||
if not ifObj(range) then
|
||
begin
|
||
echo format("Math do not support <%s>\n", element.ElementName);
|
||
continue;
|
||
end
|
||
range.Parent := self;
|
||
range.XOffset := x;
|
||
range.YOffset := y;
|
||
range.Calc();
|
||
x += range.Width; // 下一个元素偏移位置
|
||
{self.}Width += range.Width;
|
||
|
||
if range.BaseHeight > {self.}BaseHeight then
|
||
{self.}BaseHeight := range.BaseHeight;
|
||
if range.DynamicHeight - range.BaseHeight > up_h then
|
||
up_h := range.DynamicHeight - range.BaseHeight;
|
||
// if range.DynamicHeight > {self.}DynamicHeight then
|
||
// {self.}DynamicHeight := range.DynamicHeight;
|
||
|
||
range_array_[length(range_array_)] := range;
|
||
end
|
||
{self.}DynamicHeight := {self.}BaseHeight + up_h;
|
||
for _,range in range_array_ do
|
||
range.AdjustOffset(0, {self.}BaseHeight - range.BaseHeight);
|
||
end;
|
||
|
||
function OMathRange.SetMathSize();
|
||
begin
|
||
elements := element_.Elements();
|
||
element := elements[0];
|
||
rpr := nil;
|
||
if element.LocalName = "r" then
|
||
rpr := element.RPr("w");
|
||
else if element.LocalName = "f" then
|
||
rpr := element.FPr.CtrlPr.RPr("w");
|
||
else if element.LocalName = "nary" then
|
||
rpr := element.NaryPr.CtrlPr.RPr("w");
|
||
else if element.LocalName = "rad" then
|
||
rpr := element.RadPr.CtrlPr.RPr("w");
|
||
else if element.LocalName = "sSup" then
|
||
rpr := element.SSupPr.CtrlPr.RPr("w");
|
||
|
||
styles := docx_to_pdf_.DocxComponents.GetStyles();
|
||
default_rpr := styles.DocDefaults.RPrDefault.RPr;
|
||
default_rpr.SetFallback(rpr);
|
||
{self.}BaseSz := strtofloat(default_rpr.Sz.Val) / 2;
|
||
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.Offset(x: real; y: real; page: Page);override;
|
||
begin
|
||
class(AdvancedRange).Offset(x, y, page);
|
||
for _,range in range_array_ do
|
||
range.Offset(x, y, page);
|
||
end;
|
||
|
||
function OMathFRange.Calc();override;
|
||
begin
|
||
x := {self.}XOffset;
|
||
y := {self.}YOffset;
|
||
|
||
// 分子分母单独计算高度,最后再合并
|
||
// 分母
|
||
den_range := new OMathRange(docx_to_pdf_, f_.Den);
|
||
den_range.BaseSz := {self.}BaseSz;
|
||
den_range.XOffset := x;
|
||
den_range.YOffset := y;
|
||
den_range.Calc(); // 需要得到高宽
|
||
|
||
// 分子
|
||
num_range := new OMathRange(docx_to_pdf_, f_.Num);
|
||
num_range.BaseSz := {self.}BaseSz;
|
||
num_range.XOffset := x;
|
||
num_range.YOffset := y;
|
||
num_range.Calc(); // 需要得到高宽
|
||
|
||
max_len := max(den_range.Width, num_range.Width);
|
||
|
||
xo := (max_len - num_range.Width) / 2;
|
||
num_range.AdjustOffset(xo, den_range.DynamicHeight + 0.3 * {self.}BaseSz);
|
||
xo := (max_len - den_range.Width) / 2;
|
||
den_Range.AdjustOffset(xo, 0);
|
||
|
||
// 线
|
||
line_range := new LineRange();
|
||
line_range.XOffset := {self.}XOffset;
|
||
line_range.YOffset := y + den_range.DynamicHeight;
|
||
line_range.Width := max_len;
|
||
line_range.LineWidth := 0.04 * {self.}BaseSz;
|
||
|
||
{self.}DynamicHeight := num_range.DynamicHeight + den_range.DynamicHeight + 0.3 * {self.}BaseSz;
|
||
{self.}Width := line_range.Width;
|
||
|
||
range_array_ union= array(den_range, num_range, line_range);
|
||
|
||
// 分式的基准在line处
|
||
{self.}BaseHeight := den_range.DynamicHeight;
|
||
end;
|
||
|
||
function OMathFRange.AdjustOffset(x: real; y: real);override;
|
||
begin
|
||
class(BasicRange).AdjustOffset(x, y);
|
||
for _,range in range_array_ do
|
||
range.AdjustOffset(x, y);
|
||
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.Offset(x: real; y: real; page: Page);
|
||
begin
|
||
class(AdvancedRange).Offset(x, y, page);
|
||
{self.}DynamicHeight := {self.}BaseSz;
|
||
for _,range in range_array_ do
|
||
range.Offset(x, y, page);
|
||
{self.}EndY := {self.}StartY - {self.}DynamicHeight;
|
||
end;
|
||
|
||
function OMathRRange.AdjustOffset(x: real; y: real);override;
|
||
begin
|
||
class(BasicRange).AdjustOffset(x, y);
|
||
for _,range in range_array_ do
|
||
range.AdjustOffset(x, y);
|
||
end;
|
||
|
||
function OMathRRange.Calc();
|
||
begin
|
||
{self.}DynamicHeight := {self.}BaseSz;
|
||
if not r_.T then return;
|
||
x := {self.}XOffset;
|
||
y := {self.}YOffset;
|
||
text := r_.T.Text;
|
||
pos := 1;
|
||
case r_.RPr.Sty.Val of
|
||
"p":
|
||
begin
|
||
b := false;
|
||
i := false;
|
||
end
|
||
"b":
|
||
begin
|
||
b := true;
|
||
i := false;
|
||
end
|
||
"i":
|
||
begin
|
||
b := false;
|
||
i := true;
|
||
end
|
||
"bi":
|
||
begin
|
||
b := true;
|
||
i := true;
|
||
end
|
||
else begin
|
||
b := false;
|
||
i := true;
|
||
end
|
||
end;
|
||
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("Times-Roman", b, i);
|
||
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", b, i);
|
||
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", b, i);
|
||
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 := {self.}BaseSz;
|
||
first_page := docx_to_pdf_.PageManager[0];
|
||
pdf_page := first_page.PdfPage;
|
||
pdf_page.SetFontAndSize(font_obj, {self.}BaseSz);
|
||
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.XOffset := x;
|
||
text_range.YOffset := y;
|
||
x += text_range.Width;
|
||
pos += num;
|
||
range_array_[length(range_array_)] := text_range;
|
||
{self.}Width += text_range.Width;
|
||
end
|
||
{self.}BaseHeight := {self.}BaseSz / 4;
|
||
end;
|
||
|
||
function OMathNaryRange.Create(docx_to_pdf: TSDocxToPdf; nary: Nary);
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
nary_ := nary;
|
||
range_array_ := array();
|
||
end;
|
||
|
||
function OMathNaryRange.Do();override;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.Do();
|
||
end;
|
||
|
||
function OMathNaryRange.Offset(x: real; y: real; page: Page);override;
|
||
begin
|
||
class(AdvancedRange).Offset(x, y, page);
|
||
for _,range in range_array_ do
|
||
range.Offset(x, y, page);
|
||
end;
|
||
|
||
function OMathNaryRange.AdjustOffset(x: real; y: real);overload;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.AdjustOffset(x, y);
|
||
end;
|
||
|
||
function OMathNaryRange.Calc();override;
|
||
begin
|
||
x := {self.}XOffset;
|
||
y := {self.}YOffset;
|
||
|
||
val := nary_.NaryPr.Chr.Val ?: "Į";
|
||
symbol := class(SymbolMapper).SymbolChr(val);
|
||
if ifnil(symbol) then
|
||
begin
|
||
echo format("error = %s", val);
|
||
return;
|
||
end
|
||
symbol_font := docx_to_pdf_.Font.GetSymbolFont();
|
||
first_page := docx_to_pdf_.PageManager[0];
|
||
pdf_page := first_page.PdfPage;
|
||
size := {self.}BaseSz;
|
||
pdf_page.SetFontAndSize(symbol_font, size);
|
||
symbol_range := new TextRange();
|
||
symbol_range.Text := symbol;
|
||
symbol_range.XOffset := x;
|
||
symbol_range.YOffset := y;
|
||
symbol_range.Width := pdf_page.TextWidth(symbol);
|
||
symbol_range.Font := symbol_font;
|
||
symbol_range.RPr := new DocxML.RPr();
|
||
symbol_range.RPr.Sz.Val := size;
|
||
symbol_range.DynamicHeight := size;
|
||
|
||
sub_range := new OMathRange(docx_to_pdf_, nary_.Sub);
|
||
sub_range.BaseSz := {self.}BaseSz / 2;
|
||
sub_range.XOffset := x;
|
||
sub_range.YOffset := y;
|
||
sub_range.Calc();
|
||
|
||
sup_range := new OMathRange(docx_to_pdf_, nary_.Sup);
|
||
sup_range.BaseSz := {self.}BaseSz / 2;
|
||
sup_range.XOffset := x;
|
||
sup_range.YOffset := y;
|
||
sup_range.Calc(); // 需要得到高宽
|
||
|
||
if nary_.NaryPr.LimLoc.Val = "subSup" then
|
||
begin
|
||
max_width := max(sub_range.Width, sup_range.Width) + symbol_range.Width;
|
||
sub_range.AdjustOffset(symbol_range.Width, -sub_range.DynamicHeight/2);
|
||
sup_range.AdjustOffset(symbol_range.Width, symbol_range.DynamicHeight - sup_range.DynamicHeight/2);
|
||
{self.}Width := max_width;
|
||
{self.}DynamicHeight := symbol_range.DynamicHeight + sub_range.DynamicHeight/2 + sup_range.DynamicHeight + {self.}BaseSz * 0.1;
|
||
end
|
||
// else if nary_.Nary.LimLoc.Val = "undOvr" then
|
||
else begin // undOvr
|
||
max_width := maxValue(array(sub_range.Width, sup_range.Width, symbol_range.Width));
|
||
sub_range.AdjustOffset((max_width - sub_range.Width)/2, 0);
|
||
symbol_range.AdjustOffset((max_width - symbol_range.Width)/2, sub_range.DynamicHeight);
|
||
sup_range.AdjustOffset((max_width - sup_range.Width)/2, symbol_range.DynamicHeight + sub_range.DynamicHeight);
|
||
{self.}Width := max_width;
|
||
{self.}DynamicHeight := sup_range.DynamicHeight + symbol_range.DynamicHeight + sub_range.DynamicHeight;
|
||
end
|
||
|
||
e_range := new OMathRange(docx_to_pdf_, nary_.E);
|
||
e_range.BaseSz := {self.}BaseSz;
|
||
e_range.XOffset := x + max_width;
|
||
e_range.YOffset := y + sub_range.DynamicHeight;
|
||
e_range.Calc();
|
||
|
||
range_array_ union= array(symbol_range, sub_range, sup_range, e_range);
|
||
|
||
{self.}Width += e_range.Width;
|
||
{self.}DynamicHeight := max({self.}DynamicHeight, e_range.DynamicHeight);
|
||
{self.}BaseHeight := symbol_range.DynamicHeight / 4 + sub_range.DynamicHeight;
|
||
end;
|
||
|
||
function OMathRadRange.Create(docx_to_pdf: TSDocxToPdf; rad: Rad);
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
rad_ := rad;
|
||
range_array_ := array();
|
||
end;
|
||
|
||
function OMathRadRange.Do();override;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.Do();
|
||
end;
|
||
|
||
function OMathRadRange.Offset(x: real; y: real; page: Page);override;
|
||
begin
|
||
class(AdvancedRange).Offset(x, y, page);
|
||
for _,range in range_array_ do
|
||
range.Offset(x, y, page);
|
||
end;
|
||
|
||
function OMathRadRange.AdjustOffset(x: real; y: real);overload;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.AdjustOffset(x, y);
|
||
end;
|
||
|
||
function OMathRadRange.Calc();override;
|
||
begin
|
||
x := {self.}XOffset;
|
||
y := {self.}YOffset;
|
||
|
||
deg_range := new OMathRange(docx_to_pdf_, rad_.Deg);
|
||
deg_range.BaseSz := {self.}BaseSz / 2;
|
||
deg_range.XOffset := x;
|
||
deg_range.YOffset := y;
|
||
deg_range.Calc();
|
||
|
||
e_range := new OMathRange(docx_to_pdf_, rad_.E);
|
||
e_range.BaseSz := {self.}BaseSz;
|
||
e_range.XOffset := x;
|
||
e_range.YOffset := y;
|
||
e_range.Calc(); // 需要得到高宽
|
||
|
||
symbol := chr(0xD6);
|
||
symbol_font := docx_to_pdf_.Font.GetSymbolFont();
|
||
first_page := docx_to_pdf_.PageManager[0];
|
||
pdf_page := first_page.PdfPage;
|
||
size := e_range.DynamicHeight;
|
||
pdf_page.SetFontAndSize(symbol_font, size);
|
||
symbol_range := new TextRange();
|
||
symbol_range.Text := symbol;
|
||
symbol_range.XOffset := x;
|
||
symbol_range.YOffset := y;
|
||
symbol_range.Width := pdf_page.TextWidth(symbol);
|
||
symbol_range.Font := symbol_font;
|
||
symbol_range.RPr := new DocxML.RPr();
|
||
symbol_range.RPr.Sz.Val := size;
|
||
symbol_range.DynamicHeight := size;
|
||
|
||
deg_range.AdjustOffset(0, -e_range.DynamicHeight / 2);
|
||
symbol_range.AdjustOffset(deg_range.Width, 0);
|
||
e_range.AdjustOffset(size*0.3 + deg_range.Width, 0);
|
||
|
||
line_range := new LineRange();
|
||
line_range.XOffset := symbol_range.XOffset + symbol_range.Width * 0.9;
|
||
line_range.YOffset := symbol_range.DynamicHeight * 0.9;
|
||
line_range.Width := e_range.Width;
|
||
line_range.LineWidth := 0.04 * size;
|
||
|
||
range_array_ union= array(symbol_range, deg_range, e_range, line_range);
|
||
|
||
{self.}Width := deg_range.Width + symbol_range.Width + e_range.Width + 0.3*size;
|
||
{self.}DynamicHeight := symbol_range.DynamicHeight;
|
||
|
||
{self.}BaseHeight := symbol_range.DynamicHeight / 2;
|
||
end;
|
||
|
||
function OMathSSupRange.Create(docx_to_pdf: TSDocxToPdf; s_sup: SSup);
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
s_sup_ := s_sup;
|
||
range_array_ := array();
|
||
end;
|
||
|
||
function OMathSSupRange.Do();override;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.Do();
|
||
end;
|
||
|
||
function OMathSSupRange.Offset(x: real; y: real; page: Page);override;
|
||
begin
|
||
class(AdvancedRange).Offset(x, y, page);
|
||
for _,range in range_array_ do
|
||
range.Offset(x, y, page);
|
||
end;
|
||
|
||
function OMathSSupRange.AdjustOffset(x: real; y: real);overload;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.AdjustOffset(x, y);
|
||
end;
|
||
|
||
function OMathSSupRange.Calc();override;
|
||
begin
|
||
x := {self.}XOffset;
|
||
y := {self.}YOffset;
|
||
|
||
e_range := new OMathRange(docx_to_pdf_, s_sup_.E);
|
||
e_range.BaseSz := {self.}BaseSz;
|
||
e_range.XOffset := x;
|
||
e_range.YOffset := y;
|
||
e_range.Calc(); // 需要得到高宽
|
||
|
||
sup_range := new OMathRange(docx_to_pdf_, s_sup_.Sup);
|
||
sup_range.BaseSz := {self.}BaseSz * 0.4;
|
||
sup_range.XOffset := x;
|
||
sup_range.YOffset := y;
|
||
sup_range.Calc();
|
||
sup_range.AdjustOffset(e_range.Width, e_range.DynamicHeight / 2);
|
||
|
||
range_array_ union= array(e_range, sup_range);
|
||
|
||
{self.}Width := e_range.Width + sup_range.Width;
|
||
h := sup_range.DynamicHeight + e_range.DynamicHeight / 2;
|
||
{self.}DynamicHeight := max(h, e_range.DynamicHeight);
|
||
{self.}BaseHeight := e_range.BaseHeight;
|
||
end;
|
||
|
||
function OMathSSubRange.Create(docx_to_pdf: TSDocxToPdf; s_sub: SSub);
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
s_sub_ := s_sub;
|
||
range_array_ := array();
|
||
end;
|
||
|
||
function OMathSSubRange.Do();override;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.Do();
|
||
end;
|
||
|
||
function OMathSSubRange.Offset(x: real; y: real; page: Page);override;
|
||
begin
|
||
class(AdvancedRange).Offset(x, y, page);
|
||
for _,range in range_array_ do
|
||
range.Offset(x, y, page);
|
||
end;
|
||
|
||
function OMathSSubRange.AdjustOffset(x: real; y: real);overload;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.AdjustOffset(x, y);
|
||
end;
|
||
|
||
function OMathSSubRange.Calc();override;
|
||
begin
|
||
x := {self.}XOffset;
|
||
y := {self.}YOffset;
|
||
|
||
e_range := new OMathRange(docx_to_pdf_, s_sub_.E);
|
||
e_range.BaseSz := {self.}BaseSz;
|
||
e_range.XOffset := x;
|
||
e_range.YOffset := y;
|
||
e_range.Calc(); // 需要得到高宽
|
||
|
||
sub_range := new OMathRange(docx_to_pdf_, s_sub_.Sub);
|
||
sub_range.BaseSz := {self.}BaseSz * 0.4;
|
||
sub_range.XOffset := x;
|
||
sub_range.YOffset := y;
|
||
sub_range.Calc();
|
||
sub_range.AdjustOffset(e_range.Width, -(sub_range.DynamicHeight - {self.}BaseSz * 0.4));
|
||
|
||
range_array_ union= array(e_range, sub_range);
|
||
|
||
{self.}Width += e_range.Width + sub_range.Width;
|
||
h := e_range.DynamicHeight + sub_range.DynamicHeight - {self.}BaseSz * 0.4;
|
||
{self.}DynamicHeight := max(h, e_range.DynamicHeight);
|
||
{self.}BaseHeight := e_range.BaseHeight;
|
||
end;
|
||
|
||
function OMathDRange.Create(docx_to_pdf: TSDocxToPdf; d: D);
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
d_ := d;
|
||
range_array_ := array();
|
||
end;
|
||
|
||
function OMathDRange.Do();override;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.Do();
|
||
end;
|
||
|
||
function OMathDRange.Offset(x: real; y: real; page: Page);override;
|
||
begin
|
||
class(AdvancedRange).Offset(x, y, page);
|
||
for _,range in range_array_ do
|
||
range.Offset(x, y, page);
|
||
end;
|
||
|
||
function OMathDRange.AdjustOffset(x: real; y: real);overload;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.AdjustOffset(x, y);
|
||
end;
|
||
|
||
function OMathDRange.Calc();override;
|
||
begin
|
||
x := {self.}XOffset;
|
||
y := {self.}YOffset;
|
||
|
||
e_range := new OMathRange(docx_to_pdf_, d_.E);
|
||
e_range.BaseSz := {self.}BaseSz;
|
||
e_range.XOffset := x;
|
||
e_range.YOffset := y;
|
||
e_range.Calc();
|
||
|
||
beg_chr := class(SymbolMapper).SymbolChr(d_.DPr.BegChr.Val) ?: chr(0x28); // (
|
||
end_chr := class(SymbolMapper).SymbolChr(d_.DPr.EndChr.Val) ?: chr(0x29); // )
|
||
|
||
max_h := e_range.DynamicHeight;
|
||
font_obj := docx_to_pdf_.Font.GetSymbolFont();
|
||
first_page := docx_to_pdf_.PageManager[0];
|
||
pdf_page := first_page.PdfPage;
|
||
pdf_page.SetFontAndSize(font_obj, max_h);
|
||
|
||
beg_range := new TextRange();
|
||
beg_range.Text := beg_chr;
|
||
beg_range.RPr := new RPr();
|
||
beg_range.RPr.Sz.Val := max_h;
|
||
beg_range.Font := font_obj;
|
||
beg_range.Width := pdf_page.TextWidth(beg_chr);
|
||
beg_range.Parent := self;
|
||
beg_range.DynamicHeight := max_h;
|
||
beg_range.XOffset := x;
|
||
beg_range.YOffset := y;
|
||
|
||
end_range := new TextRange();
|
||
end_range.Text := end_chr;
|
||
end_range.RPr := new RPr();
|
||
end_range.RPr.Sz.Val := max_h;
|
||
end_range.Font := font_obj;
|
||
end_range.Width := pdf_page.TextWidth(end_chr);
|
||
end_range.Parent := self;
|
||
end_range.DynamicHeight := max_h;
|
||
end_range.XOffset := x;
|
||
end_range.YOffset := y;
|
||
|
||
e_range.AdjustOffset(beg_range.Width, 0);
|
||
end_range.AdjustOffset(e_range.Width + beg_range.Width, 0);
|
||
|
||
range_array_ union= array(beg_range, e_range, end_range);
|
||
{self.}Width := beg_range.Width + e_range.Width + end_range.Width;
|
||
{self.}DynamicHeight := max_h;
|
||
{self.}BaseHeight := {self.}DynamicHeight / 2;
|
||
end;
|
||
|
||
function OMathFuncRange.Create(docx_to_pdf: TSDocxToPdf; func: Func);
|
||
begin
|
||
class(AdvancedRange).Create();
|
||
docx_to_pdf_ := docx_to_pdf;
|
||
func_ := func;
|
||
range_array_ := array();
|
||
end;
|
||
|
||
function OMathFuncRange.Do();override;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.Do();
|
||
end;
|
||
|
||
function OMathFuncRange.Offset(x: real; y: real; page: Page);override;
|
||
begin
|
||
class(AdvancedRange).Offset(x, y, page);
|
||
for _,range in range_array_ do
|
||
range.Offset(x, y, page);
|
||
end;
|
||
|
||
function OMathFuncRange.AdjustOffset(x: real; y: real);overload;
|
||
begin
|
||
for _,range in range_array_ do
|
||
range.AdjustOffset(x, y);
|
||
end;
|
||
|
||
function OMathFuncRange.Calc();override;
|
||
begin
|
||
x := {self.}XOffset;
|
||
y := {self.}YOffset;
|
||
|
||
f_name_range := new OMathRange(docx_to_pdf_, func_.FName);
|
||
f_name_range.BaseSz := {self.}BaseSz;
|
||
f_name_range.XOffset := x;
|
||
f_name_range.YOffset := y;
|
||
f_name_range.Calc(); // 需要得到高宽
|
||
|
||
e_range := new OMathRange(docx_to_pdf_, func_.E);
|
||
e_range.BaseSz := {self.}BaseSz;
|
||
e_range.XOffset := x;
|
||
e_range.YOffset := y;
|
||
e_range.Calc();
|
||
|
||
max_h := max(f_name_range.DynamicHeight, e_range.DynamicHeight);
|
||
|
||
e_range.AdjustOffset(f_name_range.Width, (max_h - e_range.DynamicHeight) / 2);
|
||
f_name_range.AdjustOffset(0, (max_h - f_name_range.DynamicHeight) / 2);
|
||
|
||
range_array_ union= array(f_name_range, e_range);
|
||
|
||
{self.}Width += f_name_range.Width + e_range.Width;
|
||
{self.}DynamicHeight := max(f_name_range.DynamicHeight, e_range.DynamicHeight);
|
||
{self.}BaseHeight := f_name_range.BaseHeight;
|
||
end;
|
||
|
||
end.
|