From 2e0aadd3d0f959302fd1ecb3b3872e18074c74b3 Mon Sep 17 00:00:00 2001 From: csh Date: Thu, 3 Apr 2025 17:52:39 +0800 Subject: [PATCH] refactor --- TSDocxToPdf.tsf | 40 +- internal/DTPAdvancedRanges.tsf | 728 +++++++++++++++++------------- internal/DTPAdvancedRanges_bk.tsf | 8 +- internal/DTPModules.tsf | 25 +- internal/DTPPrimitiveRanges.tsf | 75 +-- 5 files changed, 505 insertions(+), 371 deletions(-) diff --git a/TSDocxToPdf.tsf b/TSDocxToPdf.tsf index 83cc4fb..7b7fe39 100644 --- a/TSDocxToPdf.tsf +++ b/TSDocxToPdf.tsf @@ -127,9 +127,12 @@ begin else begin for _,element in elements do begin - // if _ = 100 then break; - // if _ = 17 then - // println("_ = {}, paraid = {}, xml_file_ = {}, error = {}", _, element.ParaId, xml_file_, pdf_.GetError()); + // if _ = 4 then break; + // if _ = 31 then + // if element.LocalName = "p" then + // println("_ = {}, paraid = {}, xml_file_ = {}, error = {}", _, element.ParaId, xml_file_, pdf_.GetError()); + // println("_ = {}", _); + if element.LocalName = "p" then {self.}TransformP(element); else if element.LocalName = "tbl" then {self.}TransformTbl(element); else if element.LocalName = "sdt" then {self.}TransformSdt(element); @@ -273,16 +276,16 @@ begin ftr_range := new FtrRange(self, ftr); ftr_range.Width := w; ftr_range.Parent := self; - ftr_range.StartX := current_page_.SectPr.PgMar.Left; - ftr_range.StartY := current_page_.SectPr.PgSz.H; - ftr_range.StartPage := current_page_; ftr_range.LowerBound := 0; - if ftr_range.Calc() then + flag := ftr_range.Calc(); + y_offset := current_page_.SectPr.PgSz.H - ftr_range.DynamicHeight - current_page_.SectPr.PgMar.Footer; + ftr_range.Offset(current_page_.SectPr.PgMar.Left, y_offset, current_page_); + if flag then ftr_range.Do(); else realtime_range_array_[length(realtime_range_array_)] := ftr_range; - current_page_.FtrPoint.Y := ftr_range.EndY; + current_page_.FtrPoint.Y := ftr_range.StartY; // 向下偏移后的起始位置=正文的下边界 end; function TSDocxToPdf.SetHdr(type: string); @@ -303,11 +306,10 @@ begin hdr_range := new HdrRange(self, hdr); hdr_range.Width := w; hdr_range.Parent := self; - hdr_range.StartX := current_page_.SectPr.PgMar.Left; - hdr_range.StartY := current_page_.SectPr.PgSz.H - current_page_.SectPr.PgMar.Header; - hdr_range.StartPage := current_page_; hdr_range.LowerBound := 0; - if hdr_range.Calc() then + flag := hdr_range.Calc(); + hdr_range.Offset(current_page_.SectPr.PgMar.Left, current_page_.SectPr.PgSz.H - current_page_.SectPr.PgMar.Header, current_page_); + if flag then hdr_range.Do(); else realtime_range_array_[length(realtime_range_array_)] := hdr_range; @@ -349,13 +351,10 @@ begin range := new PRange(self, p); range.Width := w; range.Parent := self; + range.LowerBound := current_page_.LowerBound; fg := range.Calc(); {self.}RangesSpacing(range); - range.StartX := current_page_.TextPoint.X; - range.StartY := current_page_.TextPoint.Y; - range.StartPage := current_page_; - range.LowerBound := current_page_.LowerBound; - range.Run(); + range.Offset(current_page_.TextPoint.X, current_page_.TextPoint.Y, current_page_); if fg then range.Do(); else @@ -369,13 +368,10 @@ begin range := new TblRange(self, tbl); range.Width := w; range.Parent := self; + range.LowerBound := current_page_.LowerBound; fg := range.Calc(); {self.}RangesSpacing(range); - range.StartX := current_page_.TextPoint.X; - range.StartY := current_page_.TextPoint.Y; - range.StartPage := current_page_; - range.LowerBound := current_page_.LowerBound; - range.Run(); + range.Offset(current_page_.TextPoint.X, current_page_.TextPoint.Y, current_page_); range.Do(); current_page_.TextPoint.Y := range.EndY; end; diff --git a/internal/DTPAdvancedRanges.tsf b/internal/DTPAdvancedRanges.tsf index a2482f0..f4843b8 100644 --- a/internal/DTPAdvancedRanges.tsf +++ b/internal/DTPAdvancedRanges.tsf @@ -2,7 +2,21 @@ unit DTPAdvancedRanges; interface uses DTPPrimitiveRanges, DTPUtils, DTPModules, SharedML, DocxML, DrawingMLUnitDecorator, DocxMLUnitDecorator, TSPdfEnumerations; -type TocRange = class(BasicRange) +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(); @@ -12,18 +26,19 @@ public public TextRange: TextRange; BaseLine: real; // 目录...基线 - [weakref]StartRange: BasicRange; - [weakref]EndRange: BasicRange; + [weakref]StartRange: AdvancedRange; + [weakref]EndRange: AdvancedRange; private rect_: array of real; end; -type HdrRange = class(BasicRange) +type HdrRange = class(AdvancedRange) public function Create(docx_to_pdf: TSDocxToPdf; hdr: Hdr); - function Calc(): boolean; function Do();override; + function Calc(): boolean;override; + function Offset(x: real; y: real; page: Page);virtual; function ProcessRealtimeArray(); private @@ -35,11 +50,12 @@ private range_array_: array of Range; end; -type FtrRange = class(BasicRange) +type FtrRange = class(AdvancedRange) public function Create(docx_to_pdf: TSDocxToPdf; ftr: Ftr); - function Calc(): boolean; function Do();override; + function Calc(): boolean;override; + function Offset(x: real; y: real; page: Page);virtual; function ProcessRealtimeArray(); private @@ -49,20 +65,17 @@ private [weakref]docx_to_pdf_: TSDocxToPdf; ftr_: Ftr; range_array_: array of Range; - y_offset_: real; end; -type PLineRange = class(BasicRange) +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 AdjustPosition(); - function Offset(x: real; y: real); function Align(val: string); function AlignRightBound(right_bound: real); - function Arrange(); function RangeArr(): array of BasicRange; public @@ -73,17 +86,16 @@ private range_array_: array of BasicRange; end; -type PRange = class(BasicRange) +type PRange = class(AdvancedRange) public function Create(docx_to_pdf: TSDocxToPdf; p: P); function Init(); function Do();override; - function Calc(): boolean; - function Run(); + function Calc(): boolean;override; + function Offset(x: real; y: real; page: Page);override; function DeterminePosition(); function ProcessRealtimeArray(); function IsFirstLineOnNextPage(): boolean; - function Offset(x: real; y: real); function PLineRanges(): array of PLineRange; property PPrUnitDecorator read ppr_unit_decorator_; @@ -92,6 +104,8 @@ 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(); @@ -141,13 +155,14 @@ private realtime_numpages_array_: hash; end; -type TcRange = class(BasicRange) +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 Calc(); - function Run(); function GetTblStyleId(): string; function GetPrType(): string; function ContentNextPage(): boolean; @@ -160,7 +175,7 @@ public public Row: integer; Col: integer; - OffsetX: real; + SpacingBottom: real; private function GetLowerBound(pg: Page): real; @@ -178,12 +193,12 @@ private end; -type TblRange = class(BasicRange) +type TblRange = class(AdvancedRange) public function Create(docx_to_pdf: TSDocxToPdf; tbl: Tbl); function Do();override; - function Calc(); - function Run(); + function Calc(): boolean;override; + function Offset(x: real; y: real; page: Page);override; property TblPr read tbl_pr_unit_decorator_; property Rows read rows_; @@ -211,7 +226,7 @@ private tr_pr_array_: array of TrProperty; end; -type OMathParaRange = class(BasicRange) +type OMathParaRange = class(AdvancedRange) public function Create(docx_to_pdf: TSDocxToPdf; o_math_para: OMathPara); function Do();override; @@ -224,7 +239,7 @@ private o_math_range_: OMathRange; end; -type OMathRange = class(BasicRange) +type OMathRange = class(AdvancedRange) public function Create(docx_to_pdf: TSDocxToPdf; element: OpenXmlElement); function Do();override; @@ -235,7 +250,7 @@ public property Sz read sz_ write sz_; private - function MR(r: R; sz: real; x: real; y: real); + function MR(r: R; x: real; y: real); private [weakref]docx_to_pdf_: TSDocxToPdf; @@ -244,24 +259,53 @@ private range_array_: array of BasicRange; end; -type OMathFRange = class(BasicRange) +type OMathRRange = class(AdvancedRange) +public + function Create(docx_to_pdf: TSDocxToPdf; r: R); + function Do();override; + function Run(); + function Calc(); + + property Sz read sz_ write sz_; + +private + [weakref]docx_to_pdf_: TSDocxToPdf; + r_: R; + range_array_: array of BasicRange; + sz_: real; +end; + +type OMathFRange = class(AdvancedRange) public function Create(docx_to_pdf: TSDocxToPdf; f: F); function Do();override; function Calc(); function Run(); + property Sz read sz_ write sz_; + private [weakref]docx_to_pdf_: TSDocxToPdf; f_: F; range_array_: array of BasicRange; + sz_: real; end; implementation -function TocRange.Create(); +function AdvancedRange.Create(); begin class(BasicRange).Create(); + {self.}LowerBound := 0.0; + {self.}StartPage := nil; + {self.}StartX := 0.0; + {self.}StartY := 0.0; + range_array_ := array(); +end; + +function TocRange.Create(); +begin + class(AdvancedRange).Create(); {self.}TextRange := nil; {self.}BaseLine := 0; end; @@ -303,7 +347,7 @@ begin {self.}EndPage := pline_range.EndPage; if {self.}StartRange then begin - rect_ := array({self.}StartRange.StartX, pline_range.EndY, pline_range.StartX + pline_range.Width, pline_range.StartY); + 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); @@ -316,19 +360,38 @@ end; function HdrRange.Create(docx_to_pdf: TSDocxToPdf; hdr: Hdr); begin - class(BasicRange).Create(); + class(AdvancedRange).Create(); docx_to_pdf_ := docx_to_pdf; hdr_ := hdr; range_array_ := array(); end; -function HdrRange.Calc(); +function HdrRange.Do();override; begin + for _,range in range_array_ do + range.Do(); +end; + +function HdrRange.Calc(): boolean;override; +begin + {self.}DynamicHeight := 0; + return {self.}Traverse(hdr_); +end; + +function HdrRange.Offset(x: real; y: real; page: Page);virtual; +begin + {self.}StartX := x + XOffset; + {self.}StartY := y + YOffset; + {self.}StartPage := page; {self.}EndX := {self.}StartX; {self.}EndY := {self.}StartY; {self.}EndPage := {self.}StartPage; - {self.}DynamicHeight := 0; - return {self.}Traverse(hdr_); + 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); @@ -344,13 +407,7 @@ begin range.Parent := self; fg := range.Calc(); if not fg then flag := fg; - range.StartX := {self.}EndX; - range.StartY := {self.}EndY; - range.StartPage := {self.}EndPage; - range.LowerBound := {self.}LowerBound; - range.Run(); range_array_[length(range_array_)] := range; - {self.}EndY := range.EndY; {self.}DynamicHeight += range.DynamicHeight; end else if element.LocalName = "sdt" then @@ -361,12 +418,6 @@ begin return flag; end; -function HdrRange.Do();override; -begin - for _,range in range_array_ do - range.Do(); -end; - function HdrRange.ProcessRealtimeArray(); begin for _,range in range_array_ do @@ -375,34 +426,39 @@ 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(); - y_offset_ := 0; +end; + +function FtrRange.Do();override; +begin + for _,range in range_array_ do + range.Do(); end; function FtrRange.Calc(); begin + {self.}DynamicHeight := 0; + return {self.}Traverse(ftr_); +end; + +function FtrRange.Offset(x: real; y: real; page: Page);virtual; +begin + sy := page.SectPr.PgMar.Footer + {self.}DynamicHeight; + {self.}StartX := x + XOffset; + {self.}StartY := sy + YOffset; + {self.}StartPage := page; {self.}EndX := {self.}StartX; {self.}EndY := {self.}StartY; {self.}EndPage := {self.}StartPage; - {self.}DynamicHeight := 0; - flag := {self.}Traverse(ftr_); for _,range in range_array_ do begin - range.StartX := {self.}EndX; - range.StartY := {self.}EndY; - range.StartPage := {self.}EndPage; range.LowerBound := {self.}LowerBound; - range.Run(); + range.Offset({self.}StartX, {self.}EndY, {self.}EndPage); {self.}EndY := range.EndY; - {self.}DynamicHeight += range.DynamicHeight; end - y_offset_ := {self.}EndY - {self.}EndPage.FtrPoint.Y; - for _,range in range_array_ do - range.Offset(0, -y_offset_); - {self.}EndY := {self.}EndPage.FtrPoint.Y + {self.}DynamicHeight; - return flag; end; function FtrRange.Traverse(obj: OpenXmlElement); @@ -411,7 +467,6 @@ begin elements := obj.Elements(); for _,element in elements do begin - // println("LocalName = {}", element.LocalName); if element.LocalName = "p" then begin range := new PRange(docx_to_pdf_, element); @@ -420,6 +475,7 @@ begin 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 @@ -429,24 +485,17 @@ begin return flag; end; -function FtrRange.Do();override; -begin - for _,range in range_array_ do - range.Do(); -end; - function FtrRange.ProcessRealtimeArray(); begin for _,range in range_array_ do begin range.ProcessRealtimeArray(); - range.Offset(0, -y_offset_); end end; function PLineRange.Create(); begin - class(BasicRange).Create(); + class(AdvancedRange).Create(); {self.}TextMaxSize := 0; {self.}LineSpace := 0; range_array_ := array(); @@ -458,11 +507,27 @@ begin range.Do(); end; +function PLineRange.Offset(x: real; y: real; page: Page);override; +begin + {self.}StartX := x; + {self.}StartY := y; + {self.}StartPage := page; + {self.}EndX := x + {self.}XOffset; + {self.}EndY := y - {self.}DynamicHeight; // 没用上YOffset + {self.}EndPage := page; + y_offset := {self.}LineSpace >= {self.}DynamicHeight ? ({self.}LineSpace - {self.}TextMaxSize) / 2 + {self.}TextMaxSize - {self.}TextMaxSize / 5 : {self.}DynamicHeight; + y := {self.}StartY - y_offset; + for _,range in range_array_ do + range.Offset(x, y, page); // 公式不是y值,需要处理公式 +end; + function PLineRange.CanFitInLine(range: BasicRange): boolean; begin if range.Width > {self.}Width then return false; // 单一宽度比行宽还宽 - if {self.}EndX + 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 {self.}XOffset + range.Width < {self.}Width + 1e-6 then return false; // 未超过行宽 + if range is class(TextRange) and + range.Type = 4 and + not ({self.}Parent.Parent is class(TcRange)) then return false; // 中文标点不换行 return true; end; @@ -471,33 +536,6 @@ begin range_array_[length(range_array_)] := range; end; -function PLineRange.Offset(x: real; y: real); -begin - {self.}EndX += x; - {self.}EndY += y; - {self.}BaseSize += y; - for _,range in range_array_ do - begin - range.EndX += x; - range.EndY += y; - end; -end; - -function PLineRange.AdjustPosition(); -begin - {self.}EndX += {self.}StartX; - {self.}EndY := {self.}StartY - {self.}DynamicHeight; - {self.}EndPage := {self.}StartPage; - y_offset := {self.}LineSpace >= {self.}DynamicHeight ? ({self.}LineSpace - {self.}TextMaxSize) / 2 + {self.}TextMaxSize - {self.}TextMaxSize / 5 : {self.}DynamicHeight; - y := {self.}StartY - y_offset; - for _,range in range_array_ do - begin - range.EndPage := {self.}EndPage; - range.EndX += {self.}StartX; - range.EndY := y; - end -end; - function PLineRange.Align(val: string); begin offset := 0; @@ -532,7 +570,7 @@ end; function PRange.Create(docx_to_pdf: TSDocxToPdf; p: P); begin - class(BasicRange).Create(); + class(AdvancedRange).Create(); docx_to_pdf_ := docx_to_pdf; p_ := p; end; @@ -575,9 +613,13 @@ begin // 处理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(); +function PRange.Calc(): boolean;override; begin // ppr.rpr是无效的,应该以ppr.pStyle为准 {self.}SetPPPr(p_); @@ -647,6 +689,34 @@ begin return length(realtime_numpages_array_) ? false : true; end; +function PRange.Offset(x: real; y: real; page: Page);override; +begin + // println("PRange::x = {}, y = {}, page = {}", x, y, page); + {self.}StartX := x + {self.}XOffset; + {self.}StartY := y + {self.}YOffset; // 段落的YOffset实际为0 + {self.}StartPage := page; + {self.}EndX := {self.}StartX; + {self.}EndY := {self.}StartY; + {self.}EndPage := {self.}StartPage; + right_bound_ := {self.}StartX + {self.}Width; + + // 检查是否需要实时计算页码 + if length(realtime_page_array_) > 0 then + begin + pg := {self.}StartPage; + for _,range in realtime_page_array_ do + begin + pg.PdfPage.SetFontAndSize(range.Font, range.RPr.Sz.Val); + range.Text := tostring(pg.Number); + range.Width := pg.PdfPage.TextWidth(range.Text); + range.Type := 1; + end + realtime_page_array_ := array(); + {self.}RangesToLines(); + end + {self.}DeterminePosition(); +end; + function PRange.RBr(r: R); begin br_type_ := r.Br.Type; @@ -860,7 +930,6 @@ end; function PRange.OMathPara(o_math_para: OMathPara); begin - return; math_range := new OMathParaRange(docx_to_pdf_, o_math_para); math_range.Width := {self.}Width; math_range.Parent := self; @@ -961,7 +1030,6 @@ end; function PRange.RangesToLines(); begin - line_range_array_ := array(); {self.}UpdateTextRangeWidth(); {self.}BasicRangesToPLineRange(); {self.}HyperlinkToToc(); @@ -969,49 +1037,68 @@ end; function PRange.BasicRangesToPLineRange(); begin - pline_range := new PLineRange(); - pline_range.Parent := self; - pline_range.Width := {self.}Width; - pline_range.EndX := 0; + line_range_array_ := array(); + {self.}DynamicHeight := 0; + {self.}DynamicHeight += ppr_unit_decorator_.Spacing.Before; + // 段落的x偏移是缩进 + {self.}XOffset := ppr_unit_decorator_.Ind.LeftChars ? ppr_unit_decorator_.Ind.LeftChars * ppr_unit_decorator_.RPr.Sz.Val : ppr_unit_decorator_.Ind.Left; + {self.}YOffset := 0; + + pline_range := {self.}NewPLineRange(); + pline_range.XOffset := ppr_unit_decorator_.Ind.FirstLine; // 首行有间距.用offsetx作为位置计算 i := 0; anchor := nil; while i < length(body_range_array_) do begin range := body_range_array_[i]; - if i = 0 then - pline_range.EndX += ppr_unit_decorator_.Ind.FirstLine; if_newline := pline_range.CanFitInLine(range); if if_newline then begin - pline_range.LineSpace := {self.}GetParagraphLineSpace(pline_range.TextMaxSize, ppr_unit_decorator_.Spacing.Line, ppr_unit_decorator_.Spacing.LineRule); - pline_range.DynamicHeight := max(pline_range.LineSpace, pline_range.DynamicHeight); - pline_range.Index := length(line_range_array_); - line_range_array_[length(line_range_array_)] := pline_range; - - pline_range := new PLineRange(); - pline_range.Parent := self; - pline_range.Width := {self.}Width; - pline_range.EndX := 0; + {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.EndX := pline_range.EndX + range.StartX; // range.StartX是偏移值 + range.XOffset := pline_range.XOffset; range.Parent := pline_range; pline_range.AddRange(range); - pline_range.EndX += range.Width; + pline_range.XOffset += range.Width; i++; if i = length(body_range_array_) then begin - pline_range.LineSpace := {self.}GetParagraphLineSpace(pline_range.TextMaxSize, ppr_unit_decorator_.Spacing.Line, ppr_unit_decorator_.Spacing.LineRule); - pline_range.DynamicHeight := max(pline_range.LineSpace, pline_range.DynamicHeight); - pline_range.Index := length(line_range_array_); - line_range_array_[length(line_range_array_)] := pline_range; + {self.}AddPLineRange(pline_range); + {self.}DynamicHeight += pline_range.DynamicHeight; end end + + if length(line_range_array_) = 0 then + begin + line_space := {self.}GetParagraphLineSpace(ppr_unit_decorator_.RPr.Sz.Val, ppr_unit_decorator_.Spacing.Line, ppr_unit_decorator_.Spacing.LineRule); + {self.}DynamicHeight += line_space; + end + {self.}DynamicHeight += ppr_unit_decorator_.Spacing.After; + // println("line_range_array_ = {}", line_range_array_); end; +function PRange.NewPLineRange(): PLineRange; +begin + pline_range := new PLineRange(); + pline_range.Parent := self; + pline_range.Width := {self.}Width; + return pline_range; +end; + +function PRange.AddPLineRange(pline_range: PLineRange); +begin + pline_range.LineSpace := {self.}GetParagraphLineSpace(pline_range.TextMaxSize, ppr_unit_decorator_.Spacing.Line, ppr_unit_decorator_.Spacing.LineRule); + pline_range.DynamicHeight := max(pline_range.LineSpace, pline_range.DynamicHeight); + pline_range.Index := length(line_range_array_); + line_range_array_[length(line_range_array_)] := pline_range; +end; + function PRange.UpdateTextRangeWidth(); begin if length(realtime_page_array_) > 0 or length(realtime_numpages_array_) > 0 then return; @@ -1020,13 +1107,13 @@ begin while i < length(body_range_array_) do begin tail_range := body_range_array_[i]; - if not tail_range is class(TextRange) then + if not (tail_range is class(TextRange)) then begin head_range := body_range_array_[i+1]; i += 2; continue; end - if not last_range is class(TextRange) then + if not (tail_range is class(TextRange)) then begin head_range := tail_range; i++; @@ -1044,49 +1131,17 @@ begin end end; -function PRange.Run(); -begin - // 检查是否需要实时计算页码 - 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.DeterminePosition(); begin - x := {self.}StartX; - y := {self.}StartY; - right_bound_ := x + {self.}Width; - {self.}StartX := x; - {self.}StartY := y; - ppr := ppr_unit_decorator_; - sz := ppr.RPr.SzCs.Val ? ppr.RPr.SzCs.Val : ppr.RPr.Sz.Val ? ppr.RPr.Sz.Val : docx_to_pdf_.Font.GetDefaultSz(); - {self.}StartX += ppr.Ind.LeftChars ? ppr.Ind.LeftChars * sz : ppr.Ind.Left; - - {self.}EndX := {self.}StartX; - {self.}EndY := {self.}StartY; - {self.}EndPage := {self.}StartPage; - // 检查是否有分页,分一栏 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; - {self.}CheckAndAddPage({self.}EndY, ppr_unit_decorator_.Spacing.Before); - {self.}EndY -= ppr_unit_decorator_.Spacing.Before; - {self.}DynamicHeight := ppr_unit_decorator_.Spacing.Before; + // 段前距只有不换页情况才计算 + if not {self.}CheckAndAddPage({self.}EndY, ppr_unit_decorator_.Spacing.Before) then + {self.}EndY -= ppr_unit_decorator_.Spacing.Before; // 检查是否有段前分页 if ppr_unit_decorator_.PageBreakBefore then @@ -1094,13 +1149,11 @@ begin for _,line_range in line_range_array_ do begin - {self.}CheckAndAddPage({self.}EndY, line_range.DynamicHeight); - line_range.StartX := {self.}EndX; - line_range.StartY := {self.}EndY; - line_range.StartPage := {self.}EndPage; - line_range.AdjustPosition(); + y := {self.}EndY; + if {self.}CheckAndAddPage(y, line_range.DynamicHeight) then // 行不够时候调整上一页LowerBound + docx_to_pdf_.PageManager[{self.}EndPage.Index - 1].LowerBound := y; + line_range.Offset({self.}EndX, {self.}EndY, {self.}EndPage); line_range.Align(ppr_unit_decorator_.Jc.Val); - {self.}DynamicHeight += line_range.DynamicHeight; {self.}EndY := line_range.EndY; end if not {self.}Parent is class(TcRange) then @@ -1109,15 +1162,13 @@ begin if length(line_range_array_) = 0 then // 空段落 begin line_space := {self.}GetParagraphLineSpace(ppr_unit_decorator_.RPr.Sz.Val, ppr_unit_decorator_.Spacing.Line, ppr_unit_decorator_.Spacing.LineRule); - {self.}DynamicHeight += line_space; - {self.}EndY -= {self.}DynamicHeight; + {self.}EndY -= line_space; end {self.}DoDrawingAnchor(); {self.}DoAlternateContentAnchor(); {self.}DoToc(); - {self.}DynamicHeight += ppr_unit_decorator_.Spacing.After; {self.}EndY -= ppr_unit_decorator_.Spacing.After; end; @@ -1179,13 +1230,10 @@ 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.StartPage := {self.}EndPage; - range.StartX := x; - range.StartY := y; - range.LowerBound := 0; - range.Run(); + range.Offset(x, y, {self.}EndPage); range.Do(); y := range.EndY; end @@ -1212,14 +1260,6 @@ begin return ifnil(lrange) ? false : lrange.EndPage <> {self.}StartPage; end; -function PRange.Offset(x: real; y: real); -begin - {self.}EndX += x; - {self.}EndY += y; - for _,line_range in line_range_array_ do - line_range.Offset(x, y); -end; - function PRange.AlignRightBound(); begin len := length(line_range_array_); @@ -1235,7 +1275,6 @@ begin lb := lb > {self.}EndPage.LowerBound ? lb : {self.}EndPage.LowerBound; if y - offset < lb then begin - {self.}DynamicHeight += y - lb; {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]; @@ -1494,7 +1533,7 @@ end; function TcRange.Create(docx_to_pdf: TSDocxToPdf; tc: Tc; trp: TrProperty); begin - class(BasicRange).Create(); + class(AdvancedRange).Create(); docx_to_pdf_ := docx_to_pdf; tc_ := tc; trp_ := trp; @@ -1521,9 +1560,10 @@ begin end end; -function TcRange.Calc(); +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 @@ -1535,16 +1575,26 @@ begin range.Parent := self; range.Calc(); range_array_[length(range_array_)] := range; + {self.}DynamicHeight += range.DynamicHeight; end end + {self.}DynamicHeight += {self.}Parent.TblPr.TblCellMar.Bottom.W + {self.}Parent.TblPr.TblCellMar.Top.W; + + // 同步行高 + if not tc_.TcPr.VMerge and {self.}DynamicHeight > trp_.Height then + trp_.Height := {self.}DynamicHeight; + return true; end; -function TcRange.Run(); +function TcRange.Offset(x: real; y: real; page: Page);override; begin + // println("TcRange::x = {}, y = {}, page = {}", x, y, page); + {self.}StartX := x + {self.}XOffset; + {self.}StartY := y + {self.}YOffset; + {self.}StartPage := page; {self.}EndX := {self.}StartX; {self.}EndY := {self.}StartY; {self.}EndPage := {self.}StartPage; - {self.}DynamicHeight := 0; content_next_page_ := false; cell_x := {self.}EndX + {self.}Parent.TblPr.TblCellMar.Left.W; @@ -1552,11 +1602,8 @@ begin cell_h := {self.}FixedHeight; for _,range in range_array_ do begin - range.StartX := cell_x; - range.StartY := cell_y; range.LowerBound := {self.}LowerBound; - range.StartPage := {self.}EndPage; - range.Run(); + range.Offset(cell_x, cell_y, {self.}EndPage); if _ = 0 and range.IsFirstLineOnNextPage() then begin content_next_page_ := true; @@ -1564,14 +1611,8 @@ begin end cell_y := range.EndY; {self.}EndPage := range.EndPage; - {self.}DynamicHeight += range.DynamicHeight; end {self.}EndY := cell_y - {self.}Parent.TblPr.TblCellMar.Bottom.W; - {self.}DynamicHeight += {self.}Parent.TblPr.TblCellMar.Bottom.W + {self.}Parent.TblPr.TblCellMar.Top.W; - - // 同步行高 - if not tc_.TcPr.VMerge and {self.}DynamicHeight > trp_.Height then - trp_.Height := {self.}DynamicHeight; end; function TcRange.SetTop(); @@ -1616,6 +1657,13 @@ begin 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 @@ -1683,7 +1731,7 @@ begin begin offset /= 2; for _,range in arr do - range.Offset(0, -offset); + range.Offset(range.StartX, range.StartY - offset, range.StartPage); end end; end; @@ -1798,7 +1846,7 @@ end; function TblRange.Create(docx_to_pdf: TSDocxToPdf; tbl: Tbl); begin - class(BasicRange).Create(); + class(AdvancedRange).Create(); docx_to_pdf_ := docx_to_pdf; tbl_ := tbl; end; @@ -1866,7 +1914,7 @@ begin tc_range.Width := grid_cols[pos].W; tc_range.FixedHeight := tr_pr.TrHeight.Val; tc_range.Parent := self; - tc_range.OffsetX := tc_x; + tc_range.XOffset := tc_x; tc_range.Row := i; tc_range.Col := pos; tc_range_matrix_[i][pos] := tc_range; @@ -1883,10 +1931,15 @@ begin // for i,arr in tc_range_matrix_ do // println("i = {}, arr = {}", i, arr); // println("\n"); + return true; end; -function TblRange.Run(); +function TblRange.Offset(x: real; y: real; page: Page);override; begin + // println("TblRange::x = {}, y = {}, page = {}", x, y, page); + {self.}StartX := x + {self.}XOffset; + {self.}StartY := y + {self.}YOffset; // table的offset实际都为0 + {self.}StartPage := page; {self.}ResetCoordinates(tbl_pr_unit_decorator_, grid_cols_); {self.}EndX := {self.}StartX; {self.}EndY := {self.}StartY; @@ -1897,29 +1950,25 @@ begin vmerge_info := array(); while i < rows_ do begin - // println("i = {}", i); - // if i = 11 then return; - // if i = 10 then - // println(">>>>>>>>>>>>>>>>"); 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 - range.StartX := {self.}EndX + range.OffsetX; - range.StartY := tc_y; - range.StartPage := {self.}EndPage; - range.LowerBound := {self.}LowerBound; if top then range.SetTop(); range.Calc(); - range.Run(); + 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; @@ -2064,33 +2113,41 @@ end; function OMathParaRange.Create(docx_to_pdf: TSDocxToPdf; o_math_para: OMathPara); begin - class(BasicRange).Create(); + class(AdvancedRange).Create(); docx_to_pdf_ := docx_to_pdf; o_math_para_ := o_math_para; end; function OMathParaRange.Do();override; begin + o_math_range_.Do(); end; function OMathParaRange.Run();override; begin + o_math_range_.StartX := {self.}StartX; + o_math_range_.StartY := {self.}StartY; + o_math_range_.EndX := {self.}StartX; + o_math_range_.EndY := {self.}StartY; + o_math_range_.StartPage := {self.}StartPage; + o_math_range_.EndPage := {self.}StartPage; + o_math_range_.Run(); end; function OMathParaRange.Calc(); begin - o_math_ := new OMathRange(docx_to_pdf_, o_math_para_.OMath); - o_math_.Width := {self.}Width; - o_math_.Parent := self; - o_math_.StartX := 0; - o_math_.StartY := 0; - o_math_.SetMathSize(); - o_math_.Calc(); + o_math_range_ := new OMathRange(docx_to_pdf_, o_math_para_.OMath); + o_math_range_.Width := {self.}Width; + o_math_range_.Parent := self; + o_math_range_.StartX := 0; + o_math_range_.StartY := 0; + o_math_range_.SetMathSize(); + o_math_range_.Calc(); end; function OMathRange.Create(docx_to_pdf: TSDocxToPdf; element: OpenXmlElement); begin - class(BasicRange).Create(); + class(AdvancedRange).Create(); docx_to_pdf_ := docx_to_pdf; element_ := element; sz_ := 0; @@ -2098,37 +2155,65 @@ end; function OMathRange.Do();override; begin + for _,range in range_array_ do + range.Do(); +end; + +function OMathRange.Run();override; +begin + {self.}EndX := {self.}StartX; + {self.}EndY := {self.}StartY; + {self.}EndPage := {self.}StartPage; + for _,range in range_array_ do + begin + range.StartX := {self.}StartX; + range.StartY := {self.}StartY; + range.StartPage := {self.}StartPage; + range.Run(); + end end; function OMathRange.Calc(); begin range_array_ := array(); - elements := element_.Elements(); {self.}EndX := {self.}StartX; {self.}EndY := {self.}StartY; + min_y := {self.}StartY; + max_y := {self.}StartY; + elements := element_.Elements(); for _,element in elements do begin range := nil; if element.LocalName = "r" then - range := {self.}MR(element, sz_, {self.}EndX, {self.}EndY); + range := new OMathRRange(docx_to_pdf_, element); else if element.LocalName = "f" then - range := {self.}MF(element, sz_, {self.}EndX, {self.}EndY); - else if element.LocalName = "rad" then - range := {self.}MRad(element, sz_, {self.}EndX, {self.}EndY); - else if element.LocalName = "nary" then - range := {self.}MNary(element, sz_, {self.}EndX, {self.}EndY); - else if element.LocalName = "sSup" then - range := {self.}MSSup(element, sz_, {self.}EndX, {self.}EndY); + range := new OMathFRange(docx_to_pdf_, element); + // else if element.LocalName = "rad" then + // range := new OMathRadRange(docx_to_pdf_, element); + // else if element.LocalName = "nary" then + // range := new OMathNaryRange(docx_to_pdf_, element); + // else if element.LocalName = "sSup" then + // range := new OMathSSupRange(docx_to_pdf_, element); if not ifObj(range) then begin echo format("Math do not support <%s>\n", element.ElementName); continue; end + range.Parent := self; + range.StartX := {self.}EndX; + range.StartY := {self.}EndY; + range.Sz := sz_; + range.Calc(); + + if min_y > range.EndY then min_y := range.EndY; + if max_y < range.EndY + range.DynamicHeight then max_y := range.EndY + range.DynamicHeight; + {self.}EndX := range.EndX; {self.}EndY := range.EndY; range_array_[length(range_array_)] := range; end + {self.}DynamicHeight := max_y - min_y; end; function OMathRange.SetMathSize(); @@ -2150,20 +2235,104 @@ begin styles := docx_to_pdf_.DocxComponents.GetStyles(); default_rpr := styles.DocDefaults.RPrDefault.RPr(); if rpr then default_rpr.Copy(rpr); - sz_ := default_rpr.Sz.Val; + sz_ := strtofloat(default_rpr.Sz.Val); end; -function OMathRange.MR(r: R; sz: real; x: real; y: real): PLineRange; +function OMathFRange.Create(docx_to_pdf: TSDocxToPdf; f: F); begin - if not r.T then return; - line_range := new PLineRange(); - line_range.Parent := self; - line_range.EndX := x; - line_range.EndY := y - sz; - line_range.Width := 0; - line_range.TextMaxSize := sz; - line_range.DynamicHeight := sz; - text := r.T.Text; + class(AdvancedRange).Create(); + docx_to_pdf_ := docx_to_pdf; + f_ := f; + range_array_ := array(); +end; + +function OMathFRange.Do();override; +begin + for _,range in range_array_ do + range.Do(); +end; + +function OMathFRange.Run(); +begin + {self.}EndX := {self.}StartX; + {self.}EndY := {self.}StartY; + {self.}EndPage := {self.}StartPage; + for _,range in range_array_ do + begin + range.StartX := {self.}StartX; + range.StartY := {self.}StartY; + range.StartPage := {self.}StartPage; + range.Run(); + end +end; + +function OMathFRange.Calc(); +begin + {self.}EndX := {self.}StartX; + {self.}EndY := {self.}StartY; + + // 分子 + num_range := new OMathRange(docx_to_pdf_, f_.Num); + num_range.Sz := sz_; + num_range.StartX := {self.}EndX; + num_range.StartY := {self.}EndY; + num_range.Calc(); // 需要得到高宽 + + // 分母 + den_range := new OMathRange(docx_to_pdf_, f_.Den); + den_range.Sz := sz_; + den_range.StartX := {self.}EndX; + den_range.StartY := num_range.EndY - 0.418 * sz; + den_range.Calc(); // 需要得到高宽 + + max_len := max(den_range.Width, num_range.Width); + bar := max_len / 0.9; + line_range := new LineRange(); + line_range.StartX := {self.}EndX - (bar - max_len) / 2; + line_range.StartY := + 0.928 * sz; + line_range.EndX := line_range.StartX; + line_range.EndY := line_range.StartY; + line_range.Width := bar; + line_range.LineWidth := 0.04 * sz; + + range_array_ union= array(den_range, num_range); + // range_array_ union= array(den_range, num_range, line_range); +end; + +function OMathRRange.Create(docx_to_pdf: TSDocxToPdf; r: R); +begin + class(AdvancedRange).Create(); + docx_to_pdf_ := docx_to_pdf; + r_ := r; + range_array_ := array(); +end; + +function OMathRRange.Do();override; +begin + for _,range in range_array_ do + range.Do(); +end; + +function OMathRRange.Run(); +begin + {self.}EndX := {self.}StartX; + {self.}EndPage := {self.}StartPage; + {self.}DynamicHeight := sz_; + {self.}EndY := {self.}StartY - sz_; + for _,range in range_array_ do + begin + range.EndX += {self.}StartX; + range.EndY := range.StartY + {self.}EndY - sz_; + range.EndPage := {self.}EndPage; + end; +end; + +function OMathRRange.Calc(); +begin + if not r_.T then return; + x := {self.}StartX; + y := {self.}StartY; + text := r_.T.Text; pos := 1; while pos <= length(text) do begin @@ -2182,99 +2351,46 @@ begin else if char = 0x44 or char = 0x46 then text_range.Type := 5; word := a_word; - font_name := rpr.RFonts.EastAsia ?: rpr.RFonts.Ascii; - font_obj := docx_to_pdf_.Font.GetCNSFont(font_name, rpr.B, rpr.I); + font_obj := docx_to_pdf_.Font.GetCNSFont("SimSun", false, true); end else if DTPUtils.IsChineseChar(a_word) then begin text_range.Type := 3; word := utf8ToAnsi(a_word); - font_name := rpr.RFonts.EastAsia ?: rpr.RFonts.Ascii; - font_obj := docx_to_pdf_.Font.GetCNSFont(font_name, rpr.B, rpr.I); + font_obj := docx_to_pdf_.Font.GetCNSFont("SimSun", false, true); end else if DTPUtils.IsChinesePunctuation(a_word) then begin text_range.Type := 4; word := utf8ToAnsi(a_word); - font_name := rpr.RFonts.EastAsia ?: rpr.RFonts.Ascii; - font_obj := docx_to_pdf_.Font.GetCNSFont(font_name, rpr.B, rpr.I); + font_obj := docx_to_pdf_.Font.GetCNSFont("SimSun", false, true); end else begin - word := utf8ToAnsi(a_word); - if word = "?" then + word := class(SymbolMapper).SymbolChr(a_word); + if ifnil(word) then begin - word := class(SymbolMapper).ZapfDingbatsChr(a_word); - if ifnil(word) then word := "u"; - font_obj := docx_to_pdf_.Font.GetZapfDingbatsFont(); - end - else begin - font_name := rpr.RFonts.EastAsia ?: rpr.RFonts.Ascii; - font_obj := docx_to_pdf_.Font.GetCNSFont(font_name, rpr.B, rpr.I); + echo format("error symbol {{%s}}.\n", a_word); + word := chr(0x20); end + font_obj := docx_to_pdf_.Font.GetSymbolFont(); end + rpr := new RPr(); + rpr.Sz.Val := sz_; first_page := docx_to_pdf_.PageManager[0]; pdf_page := first_page.PdfPage; - pdf_page.SetFontAndSize(font_obj, rpr.Sz.Val); - rpr := new RPr(); - rpr.Sz.Val := sz; + pdf_page.SetFontAndSize(font_obj, sz); text_range.RPr := rpr; text_range.Text := word; text_range.Font := font_obj; text_range.Width := pdf_page.TextWidth(word); - text_range.Parent := line_range; + text_range.Parent := self; text_range.DynamicHeight := rpr.Sz.Val; - text_range.EndX := line_range.EndX; - text_range.EndY := line_range.EndY; - line_range.EndX += text_range.Width; - line_range.Width += text_range.Width; + text_range.EndX := x; + text_range.EndY := y; + x += text_range.Width; pos += num; - line_range.AddRange(text_range); + range_array_[length(range_array_)] := text_range; end - return line_range; end; -function OMathFRange.Create(docx_to_pdf: TSDocxToPdf; f: F); -begin - class(BasicRange).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.Calc(); -begin - {self.}EndX := {self.}StartX; - {self.}EndY := {self.}StartY; - - den_range := new OMathRange(docx_to_pdf_, f.Den); - den_range.Sz := sz_; - den_range.StartX := {self.}EndX; - den_range.StartY := {self.}EndY; - den_range.Calc(); // 需要得到高宽 - - num_range := new OMathRange(docx_to_pdf_, f.Num); - num_range.Sz := sz_; - num_range.StartX := {self.}EndX; - num_range.StartY := {self.}EndY + 1.418 * sz; - num_range.Calc(); // 需要得到高宽 - - max_len := max(den_range.Width, num_range.Width); - bar := max_len / 0.9; - line_range := new LineRange(); - line_range.StartX := x - (bar - max_len) / 2; - line_range.StartY := y + 0.928 * sz; - line_range.EndX := line_range. - line_range.Width := bar; - line_range.LineWidth := 0.04 * sz; - - range_array_ union= array(den_range, num_range, line_range); -end; - - end. diff --git a/internal/DTPAdvancedRanges_bk.tsf b/internal/DTPAdvancedRanges_bk.tsf index cc92516..961b489 100644 --- a/internal/DTPAdvancedRanges_bk.tsf +++ b/internal/DTPAdvancedRanges_bk.tsf @@ -354,7 +354,11 @@ begin end else begin word := class(SymbolMapper).SymbolChr(a_word); - if ifnil(word) then raise format("error symbol {{%s}}", a_word); + if ifnil(word) then + begin + echo format("error symbol {{%s}}", a_word); + word := chr(0x20); + end font_obj := docx_to_pdf_.Font.GetSymbolFont(); end rpr := new RPr(); @@ -1048,7 +1052,7 @@ begin end; // CellRange -function CellRange.Create(docx_to_pdf: TSDocxToPdf; pg: Page; components: TSDocxComponentsModule; tc: Tc; tbl_pr: TblPr; trp: TSTrProperty); +function CellRange.Create(docx_to_pdf: TSDocxToPdf; pg: Page; components: DocxComponentsModule; tc: Tc; tbl_pr: TblPr; trp: TSTrProperty); begin docx_to_pdf_ := docx_to_pdf; last_page_ := pg; diff --git a/internal/DTPModules.tsf b/internal/DTPModules.tsf index f87b8fd..f5b888a 100644 --- a/internal/DTPModules.tsf +++ b/internal/DTPModules.tsf @@ -105,8 +105,9 @@ public function UpdateDocxNumPages(); function CalculateRect(anchor: string); - function LinkToToc(anchor: string; range: BasicRange); - function AddToc(anchor: string; toc: Toc); + function LinkToToc(anchor: string; range: BasicRange);overload; + function LinkToToc(anchor: string);overload; + function AddToc(anchor: string; toc: Toc);overload; function AddDocxPage(anchor: string; r: R); @@ -689,10 +690,10 @@ begin toc.CalculateRect(); end; -function TocModule.LinkToToc(anchor: string; range: BasicRange); +function TocModule.LinkToToc(anchor: string; range: BasicRange);overload; begin arr := toc_hash_[anchor]; - if ifnil(arr) then + if ifnil(arr) then // 未匹配到链接,说明链接可能在后面 begin toc_unmatched_hash_[anchor] := range; return; @@ -712,16 +713,20 @@ begin end end; +function TocModule.LinkToToc(anchor: string);overload; +begin + range := toc_unmatched_hash_[anchor]; + if range then + begin + {self.}LinkToToc(anchor, range); + toc_unmatched_hash_[anchor] := nil; + end +end; + function TocModule.AddToc(anchor: string; toc: Toc); begin if ifarray(toc_hash_[anchor]) then toc_hash_[anchor] union= array(toc); else toc_hash_[anchor] := array(toc); - if toc_unmatched_hash_[anchor] then - begin - toc := toc_unmatched_hash_[anchor]; - {self.}LinkToToc(anchor, toc[0], toc[1], toc[2]); - toc_unmatched_hash_[anchor] := nil; - end end; function TocModule.AddDocxPage(anchor: string; r: R); diff --git a/internal/DTPPrimitiveRanges.tsf b/internal/DTPPrimitiveRanges.tsf index 94eff13..a70b5e7 100644 --- a/internal/DTPPrimitiveRanges.tsf +++ b/internal/DTPPrimitiveRanges.tsf @@ -2,13 +2,34 @@ unit DTPPrimitiveRanges; interface uses DTPColorToolKit, DTPUtils; +type BasicRange = class +public + function Create(); + function Do();virtual; + function Offset(x: real; y: real; page: Page);virtual; + +public + [weakref]Parent: tslobj; + [weakref]EndPage: Page; // 结束page + XOffset: real; + YOffset: real; // XOffset, YOffset是相对(0,0)的偏移位置 + EndX: real; + EndY: real; // range的结束坐标(x,y) + Width: real; + DynamicHeight: real; + FixedHeight: real; + + // StartX: real; + // StartY: real; // range的起始坐标(x,y) +end; + type TextRange = class(BasicRange) public function Create(); function Do();override; public - RPr: RPr; + RPr: RPrUnitDecorator; Text: string; Font: PdfFont; Type: integer; // 0:默认,1: 数字,2:英文,3:中文,4:中文标点,5:,.英文逗号和点 @@ -19,8 +40,9 @@ public function Create(); function Do();override; function DoFill(); + public - TcPr: TcPr; + TcPr: TcPrUnitDecorator; Left: boolean; Top: boolean; Right: boolean; @@ -39,7 +61,6 @@ public public Image: PdfImage; Type: string; - end; type LineRange = class(BasicRange) @@ -51,39 +72,30 @@ public LineWidth: real; end; -type BasicRange = class -public - function Create(); - function Do();virtual; - -public - StartX: real; - StartY: real; // range的起始坐标(x,y) - EndX: real; - EndY: real; // range的结束坐标(x,y) - Width: real; - FixedHeight: real; - DynamicHeight: real; - LowerBound: real; - [weakref]Parent: tslobj; - [weakref]StartPage: Page; // 起始page - [weakref]EndPage: Page; // 结束page -end; - implementation // BasicRange function BasicRange.Create(); begin - {self.}StartX := 0; - {self.}StartY := 0; - {self.}EndX := 0; - {self.}EndY := 0; - {self.}Width := 0; - {self.}DynamicHeight := 0; - {self.}LowerBound := 0; - {self.}FixedHeight := 0; + {self.}Parent := nil; {self.}EndPage := nil; + {self.}XOffset := 0.0; + {self.}YOffset := 0.0; + {self.}EndX := 0.0; + {self.}EndY := 0.0; + {self.}Width := 0.0; + {self.}DynamicHeight := 0.0; + {self.}FixedHeight := 0.0; + + // {self.}StartX := 0; + // {self.}StartY := 0; +end; + +function BasicRange.Offset(x: real; y: real; page: Page);virtual; +begin + {self.}EndX := {self.}XOffset + x; + {self.}EndY := {self.}YOffset + y; + {self.}EndPage := page; end; // ImageRange @@ -127,7 +139,8 @@ end; function BordersRange.DoFill(); begin borders := {self.}TcPr.TcBorders; - if {self.}TcPr.Shd.Fill and {self.}TcPr.Shd.Fill <> "auto" then + // println("TcPr.Shd.Val = {}", TcPr.Shd.Val); + if {self.}TcPr.Shd.Val <> "clear" and {self.}TcPr.Shd.Fill and {self.}TcPr.Shd.Fill <> "auto" then begin [r, g, b] := DTPColorToolKit.HexToRGB({self.}TcPr.Shd.Fill); {self.}EndPage.PdfPage.SetRGBFill(r/255, g/255, b/255);