支持目录

This commit is contained in:
csh
2024-07-19 14:49:22 +08:00
parent cfc2d74ab8
commit d14de26d58
7 changed files with 237 additions and 73 deletions
+135 -43
View File
@@ -13,15 +13,18 @@ private
function SetLvlText();
function GetImageFileType(data: binary): string;
function GetParagraphLineSpace(size: real; line: integer): real;
function RangesToLines(ppr: PPr): tableArray;
function RangesToLines(ppr: PPrUnitDecorator): tableArray;
function CheckAndAddPage(y: real; offset: real): boolean;
function GetUtf8CharLength(byte: string): integer;
function RToTextRange(r: R; ppr: PPr);
function SplitTextToTextRange(text: string; rpr: RPr);
function RToDrawingRange(r: R; ppr: PPr);
function SetLinesAlignment(ppr: PPr);
function ResetCoordinates(ppr: PPr);
function RToTextRange(r: R; ppr: PPrUnitDecorator; link: string);
function SplitTextToTextRange(text: string; rpr: RPrUnitDecorator; link: string);
function RToDrawingRange(r: R; ppr: PPrUnitDecorator);
function SetLinesAlignment(ppr: PPrUnitDecorator);
function ResetCoordinates(ppr: PPrUnitDecorator);
function NewLineRange(): TSPdfLineRange;
function BookMarkLinkToc();
function HyperlinkToToc(ppr: PPrUnitDecorator);
function HyperlinkToTextRange(hyperlink: Hyperlink; ppr: PPrUnitDecorator);
private
[weakref]docx_to_pdf_: TSDocxToPdf;
@@ -32,6 +35,8 @@ private
extra_style_id_: string;
range_array_: array of TSPdfBasicRange;
line_range_array_: array of TSPdfLineRange;
hyperlink_array_: tableArray;
bookmark_array_: tableArray;
end;
function TSPdfParagraphRange.Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare; sect_ware: TSSectWare; paragraph: P);
@@ -44,11 +49,14 @@ begin
extra_style_id_ := "";
range_array_ := array();
line_range_array_ := array();
hyperlink_array_ := array();
bookmark_array_ := array();
{self.}TSPage := page_;
end;
function TSPdfParagraphRange.Calc(): tableArray;
begin
// ppr.rpr是无效的,应该以ppr.pStyle为准
{self.}SetPPr(paragraph_.PPr);
{self.}SetLvlText();
ppr := new PPrUnitDecorator(paragraph_.PPr);
@@ -58,37 +66,115 @@ begin
{self.}CheckAndAddPage({self.}EndY, ppr.Spacing.Before);
{self.}EndY -= ppr.Spacing.Before;
{self.}DynamicHeight += ppr.Spacing.Before;
rs := paragraph_.Rs();
if length(rs) = 0 then
elements := paragraph_.Elements();
empty_flag := true;
bookmark_id := '';
bookmark_name := '';
bookmark_flag := false;
for _,element in elements do
begin
if not ifObj(element.XmlNode) then continue;
if element.LocalName = "r" then
begin
empty_flag := false;
{self.}SetRPr(element.RPr, ppr);
if element.Br.Type = "page" then
{self.}CheckAndAddPage(sect_ware_.SectPr.PgMar.Bottom, 1);
else if ifObj(element.Drawing.XmlNode) then {self.}RToDrawingRange(element, ppr);
else {self.}RToTextRange(element, ppr, bookmark_name);
end
else if element.LocalName = "hyperlink" then
begin
empty_flag := false;
{self.}HyperlinkToTextRange(element, ppr);
end
else if element.LocalName = "bookmarkStart" then
begin
bookmark_id := element.Id;
bookmark_name := element.Name;
bookmark_array_[bookmark_name] := array();
end
else if element.LocalName = "bookmarkEnd" then
begin
bookmark_id := '';
bookmark_name := '';
end
end
if empty_flag then
begin
line_space := {self.}GetParagraphLineSpace(ppr.RPr.Sz.Val, ppr.Spacing.Line);
{self.}DynamicHeight += ppr.Spacing.After + line_space;
{self.}EndY -= {self.}DynamicHeight;
end
else begin
for _, r in rs do
begin
{self.}SetRPr(r.RPr, paragraph_.PPr);
if r.Br.Type = "page" then
{self.}CheckAndAddPage(sect_ware_.SectPr.PgMar.Bottom, 1);
else if ifObj(r.Drawing.XmlNode) then {self.}RToDrawingRange(r, ppr);
else {self.}RToTextRange(r, ppr);
end
end
{self.}RangesToLines(ppr);
// hyperlinks := paragraph_.Hyperlinks(); // TOC
// for _,hyperlink in hyperlinks do
// begin
// rs := hyperlink.Rs();
// for _,r in rs do
// begin
// if r.FldChar.FldCharType = "begin" then break;
// {self.}RToTextRange(r, ppr);
// end
// end
if hyperlink_array_ then {self.}HyperlinkToToc(ppr);
if bookmark_array_ then {self.}BookMarkLinkToc();
end;
function TSPdfParagraphRange.Do();
function TSPdfParagraphRange.BookMarkLinkToc();
begin
for name,arr in bookmark_array_ do
if arr[0] then docx_to_pdf_.LinkToToc(name, arr[0].TSPage);
end;
function TSPdfParagraphRange.HyperlinkToToc(ppr: PPrUnitDecorator);
begin
for anchor,arr in hyperlink_array_ do // 整理hyperlink发送到docx_to_pdf_
begin
pg := arr[0].TSPage;
left := {self.}StartX;
bottom := arr[0].EndY;
right := left + {self.}Width;
top := bottom + arr[0].RPr.Sz.Val;
x := arr[0].EndX + arr[0].Width;
y := arr[0].EndY;
for _,range in arr do
begin
if range.TSPage <> pg then // 说明目录文字换页
begin
rect := array(left, bottom, right, top);
toc := new TSToc(ppr, rect, pg, x, y);
docx_to_pdf_.AddToc(anchor, toc);
pg := range.TSPage;
left := range.EndX;
top := range.EndY + range.RPr.Sz.Val;
right := left;
bottom := range.EndY;
continue;
end
top := range.EndY + arr[0].RPr.Sz.Val;
x := range.EndX + range.Width;
end
rect := array(left, bottom, right, top);
font_name := ppr.RPr.RFonts.EastAsia ? ppr.RPr.RFonts.EastAsia : ppr.RPr.RFonts.Ascii;
font_obj := docx_to_pdf_.Font.GetFont(font_name, ppr.RPr.B, ppr.RPr.I);
toc := new TSToc(ppr, rect, pg, x, y, font_obj);
docx_to_pdf_.AddToc(anchor, toc);
end
end;
function TSPdfParagraphRange.HyperlinkToTextRange(hyperlink: Hyperlink; ppr: PPrUnitDecorator);
begin
i := length(range_array_);
rs := hyperlink.Rs();
for _,r in rs do
begin
if r.FldChar.FldCharType = "begin" then break;
r.RPr := new RPr();
{self.}SetRPr(r.RPr, ppr);
{self.}RToTextRange(r, ppr, hyperlink.Anchor);
end
arr := array();
while i < length(range_array_) do
begin
arr[length(arr)] := range_array_[i];
i++;
end
hyperlink_array_[hyperlink.Anchor] := arr;
end;
function TSPdfParagraphRange.Do();override;
begin
for _,line_range in line_range_array_ do
line_range.Do();
@@ -108,7 +194,7 @@ begin
return line_range;
end;
function TSPdfParagraphRange.RangesToLines(ppr: PPr);
function TSPdfParagraphRange.RangesToLines(ppr: PPrUnitDecorator);
begin
line_range := {self.}NewLineRange();
i := 0;
@@ -167,7 +253,7 @@ begin
{self.}SetLinesAlignment(ppr);
end;
function TSPdfParagraphRange.SetLinesAlignment(ppr: PPr);
function TSPdfParagraphRange.SetLinesAlignment(ppr: PPrUnitDecorator);
begin
if length(line_range_array_) = 0 then return;
idx := length(line_range_array_)-1;
@@ -200,14 +286,20 @@ begin
return 4;
end;
function TSPdfParagraphRange.RToTextRange(r: R; ppr: PPr);
function TSPdfParagraphRange.RToTextRange(r: R; ppr: PPrUnitDecorator; link: string);
begin
rpr := new RPrUnitDecorator(r.RPr);
text := r.T.Text;
if ifString(text) then {self.}SplitTextToTextRange(text, rpr);
if r.Anchor then
begin
{self.}HyperlinkToTextRange(r, ppr);
end
else begin
rpr := new RPrUnitDecorator(r.RPr);
text := r.T.Text;
if ifString(text) then {self.}SplitTextToTextRange(text, rpr, link);
end
end;
function TSPdfParagraphRange.SplitTextToTextRange(text: string; rpr: RPr);
function TSPdfParagraphRange.SplitTextToTextRange(text: string; rpr: RPrUnitDecorator; link: string);
begin
pos := 1;
while pos <= length(text) do
@@ -219,7 +311,6 @@ begin
font_name := rpr.RFonts.EastAsia ? rpr.RFonts.EastAsia : rpr.RFonts.Ascii;
font_obj := docx_to_pdf_.Font.GetFont(font_name, rpr.B, rpr.I);
if not rpr.Sz.Val then rpr.Sz.Val := rpr.SzCs.Val ? rpr.SzCs.Val : docx_to_pdf_.Font.GetDefaultSz();
// println("page_.PdfPage = {}, font_obj = {}, sz = {}", page_.PdfPage, font_obj, rpr.Sz.Val);
page_.PdfPage.SetFontAndSize(font_obj, rpr.Sz.Val);
word_width := page_.PdfPage.TextWidth(word);
text_range := new TSPdfTextRange();
@@ -228,10 +319,11 @@ begin
text_range.Font := font_obj;
text_range.Width := word_width;
range_array_[length(range_array_)] := text_range;
if ifarray(bookmark_array_[link]) then bookmark_array_[link] union= array(text_range);
end
end;
function TSPdfParagraphRange.RToDrawingRange(r: R; ppr: PPr);
function TSPdfParagraphRange.RToDrawingRange(r: R; ppr: PPrUnitDecorator);
begin
xfrm := new XfrmUnitDecorator(r.Drawing._Inline.Graphic.GraphicData.Pic.SpPr.Xfrm);
rels_adapter := docx_components_ware_.GetDocumentRelsAdapter();
@@ -318,11 +410,11 @@ end;
function TSPdfParagraphRange.SetRPr(var rpr; ppr: PPr);
begin
// rpr,先继承ppr,再继承样式,最后继承自己
new_rpr := new RPr();
style_id := rpr.RStyle.Val;
new_rpr.Copy(ppr.RPr);
{self.}SetRPrByStyleId(new_rpr, style_id);
styles := docx_components_ware_.GetStyles();
new_rpr.Copy(styles.DocDefaults.RPrDefault.RPr);
{self.}SetRPrByStyleId(new_rpr, ppr.PStyle.Val);
{self.}SetRPrByStyleId(new_rpr, rpr.RStyle.Val);
new_rpr.Copy(rpr);
rpr.Copy(new_rpr);
end;
@@ -350,7 +442,7 @@ begin
{self.}SplitTextToTextRange(lvl_text, rpr);
end;
function TSPdfParagraphRange.ResetCoordinates(ppr: PPr);
function TSPdfParagraphRange.ResetCoordinates(ppr: PPrUnitDecorator);
begin
// 根据段落的间距确定新的坐标
sz := ppr.RPr.SzCs.Val ? ppr.RPr.SzCs.Val : ppr.RPr.Sz.Val ? ppr.RPr.Sz.Val : docx_to_pdf_.Font.GetDefaultSz();
-15
View File
@@ -7,7 +7,6 @@ public
private
function ProcessTrData(grid_cols: array of GridCol; tr: Tr; tbl_pr: TblPr): array of TSPdfAbstractRange;
function ResetCoordinates(tbl_pr: TblPr; grid_cols: array of GridCol);
function CheckAndAddPage(y: real; offset: real): boolean;
function SetTblPr(tbl_pr: TblPr);
function SetTblPrByStyleId(var tbl_pr: TblPr; style_id: string);
function SetTrPr(var tr_pr: TrPr);
@@ -22,7 +21,6 @@ private
[weakref]table_: Tbl;
[weakref]page_: TSPage;
[weakref]range_array_: tableArray;
point_: TSPoint;
end;
function TSPdfTableRange.Create(docx_to_pdf: TSDocxToPdf; pg: PdfPage; components: Components; sect_ware: TSSectWare; table: Tbl);
@@ -60,19 +58,6 @@ begin
range.Do();
end;
function TSPdfTableRange.CheckAndAddPage(y: real; offset: real): boolean;
begin
if y - offset < sect_ware_.SectPr.PgMar.Bottom then
begin
page_ := docx_to_pdf_.GetNextPage(page_);
if ifnil(page_) then page_ := docx_to_pdf_.AddPage(sect_ware_);
point := docx_to_pdf_.GetCurrentPoint();
{self.}EndY := point.Y;
return true;
end
return false;
end;
function TSPdfTableRange.ProcessTrData(grid_cols: array of GridCol; tr: Tr; tbl_pr: TblPr): array of TSPdfAbstractRange;
begin
{self.}SetTrPr(tr.TrPr);
+3
View File
@@ -1,6 +1,9 @@
type TSPdfTocRange = class(TSPdfBasicRange)
public
function Create();
public
TSPage: TSPage;
end;
function TSPdfTocRange.Create();