1. 支持分栏

2. 支持简单的单个脚注
This commit is contained in:
csh 2024-12-13 17:19:52 +08:00
parent a677e5a843
commit 4c002f803f
8 changed files with 359 additions and 68 deletions

View File

@ -10,9 +10,13 @@ public
function GetCurrentTextPoint(): Point;
function GetCurrentHdrPoint(): Point;
function GetCurrentFtrPoint(): Point;
function GetCurrentNoteWare(): TSNoteWare;
function GetCachePath(image_path: string): string;
function GetNextPage(page: TSPage): TSPage;
function GetCurrentXmlFile(): string;
function AddTSPageWare(flag: boolean): TSPage;
function AddTSPage(flag: boolean): TSPage;
function LinkToToc(anchor: string; page: TSPage; left: real; top: real);
function AddToc(anchor: string; toc: TSToc);
@ -21,6 +25,8 @@ public
function CalculateTextCoordinates(): array of real;
function GetSymbol(symbol: string);
function AddDocxPage(pg: TSPage; r: R);
function CalcParams(): real;
function AddColIndex();
function UpdateDocxPageNumpages();
function SaveDocxFile();overload;
@ -36,6 +42,7 @@ private
function InitSectWare();
function InitSymbol();
function AllocateElementsToSectWare();
function ClassifyCols(var point: Point; cols: Cols);
function SetHdr(type: string);
function SetFtr(type: string);
@ -49,22 +56,26 @@ private
pdf_: PdfFile;
docx_components_ware_: TSDocxComponentsWare; // TSDocxComponentsWare
cache_path_: string; // 临时目录,用来存放临时文件
sect_ware_array_: array of TSSectWare; // 页面布局组件数组
font_ware_: TSFontWare; // 字体部件
sect_ware_array_: array of TSSectWare; // 页面布局部件数组
current_sect_ware_: TSSectWare;
current_sect_pr_adapter_: SectPrAdapter;
symbol_: tableArray;
current_page_: TSPage;
page_array_: array of TSPage;
sect_ware_: TSSectWare;
sect_pr_adapter_: SectPrAdapter;
toc_array_: tableArray;
toc_unmacthed_array_: tableArray;
range_page_number_array_: tableArray;
text_point_: Point; // 定位坐标点
hdr_point_: Point; // 页眉坐标
ftr_point_: Point; // 页脚坐标
even_and_odd_flag_: boolean;
xml_file_: string;
symbol_: tableArray;
xml_file_: string;
even_and_odd_flag_: boolean;
note_ware_: TSNoteWare; // 脚注/尾注
// 回写docx
docx_page_arr_: tableArray;
update_docx_pages_: boolean;
end;
@ -82,12 +93,13 @@ end;
function TSDocxToPdf.Create(alias: string; file: string);
begin
pdf_ := new PdfFile();
font_ware_ := new TSFontWare(pdf_);
{self.}InitPdfEncoder();
{self.}InitDocxComponents(alias, file);
{self.}InitCachePath(file);
{self.}InitSectWare();
{self.}InitSymbol();
font_ware_ := new TSFontWare(pdf_);
current_page_ := nil;
page_array_ := array();
toc_array_ := array();
@ -96,12 +108,14 @@ begin
text_point_ := new Point();
hdr_point_ := new Point();
ftr_point_ := new Point();
xml_file_ := "document.xml";
xml_file_ := "document.xml";
settings := docx_components_ware_.Settings;
settings.XmlChildEvenAndOddHeaders.Deserialize();
even_and_odd_flag_ := settings.EvenAndOddHeaders ? true : false;
note_ware_ := nil;
// 回写docx
docx_page_arr_ := array();
update_docx_pages_ := false;
end;
@ -116,28 +130,55 @@ begin
return pdf_.SaveToFile(alias, file);
end;
function TSDocxToPdf.CalcParams(): real;
begin
cols := current_sect_ware_.SectPr.Cols.Cols();
// println("cols = {}", cols);
w := 0;
if cols then
begin
for i:=0 to col_index_ do
begin
w := cols[i].W;
if i > 0 then text_point_.X += (cols[i-1].W + cols[i-1].Space);
end
end
else
w := current_sect_ware_.SectPr.PgSz.W - current_sect_ware_.SectPr.PgMar.Right - current_sect_ware_.SectPr.PgMar.Left;
return w;
end;
function TSDocxToPdf.Transform();
begin
for _,sect_ware in sect_ware_array_ do
begin
if sect_ware_ <> sect_ware then
if current_sect_ware_ <> sect_ware then
begin
sect_ware_ := sect_ware;
sect_pr_adapter_ := new SectPrAdapter(sect_ware_.SectPr.GetObject());
current_sect_ware_ := sect_ware;
current_sect_pr_adapter_ := new SectPrAdapter(current_sect_ware_.SectPr.GetObject());
{self.}AddTSPage(true);
xml_file_ := "document.xml";
end
w := sect_ware_.SectPr.PgSz.W - sect_ware_.SectPr.PgMar.Right - sect_ware_.SectPr.PgMar.Left;
lb := sect_ware_.SectPr.PgMar.Bottom;
// 分栏
elements := sect_ware.Elements();
for _,element in elements do
cols := current_sect_ware_.SectPr.Cols;
if cols.Num > 1 then
begin
// if _ = 8 then break;
// if _ = 3 then
// println("_ = {}, xml_file_ = {}", _, xml_file_);
if element.LocalName = "p" then {self.}TransformP(text_point_, element, w, lb);
else if element.LocalName = "tbl" then {self.}TransformTbl(text_point_, element, w, lb);
else if element.LocalName = "sdt" then {self.}TransformSdt(text_point_, element, w, lb);
columns := {self.}ClassifyCols(text_point_, cols);
end
else begin
w := current_sect_ware_.SectPr.PgSz.W - current_sect_ware_.SectPr.PgMar.Right - current_sect_ware_.SectPr.PgMar.Left;
lb := current_sect_ware_.SectPr.PgMar.Bottom;
for _,element in elements do
begin
// if _ = 8 then break;
// if _ = 3 then
// println("_ = {}, xml_file_ = {}", _, xml_file_);
if element.LocalName = "p" then {self.}TransformP(text_point_, element, w, lb);
else if element.LocalName = "tbl" then {self.}TransformTbl(text_point_, element, w, lb);
else if element.LocalName = "sdt" then {self.}TransformSdt(text_point_, element, w, lb);
end
end
end
{self.}ProcessNumpages();
@ -160,7 +201,7 @@ end;
function TSDocxToPdf.GetCurrentSectWare(): TSSectWare;
begin
return sect_ware_;
return current_sect_ware_;
end;
function TSDocxToPdf.GetCachePath(image_path: string): string;
@ -194,7 +235,7 @@ function TSDocxToPdf.InitDocxComponents(alias: string; file: string);
begin
namespace "DOCX";
docx_components_ware_ := new TSDocxComponentsWare();
[err, msg] := docx_components_ware_.OpenFile(alias, file, nil);
[err, msg] := docx_components_ware_.Open(alias, file, nil);
if err then raise "Open file error.";
end;
@ -209,9 +250,11 @@ end;
function TSDocxToPdf.InitSectWare();
begin
sect_ware_array_ := array();
current_sect_ware_ := nil;
current_sect_pr_adapter_ := nil;
document := docx_components_ware_.Document;
document.Deserialize();
sect_ware_array_ := array();
{self.}AllocateElementsToSectWare();
end;
@ -236,6 +279,7 @@ begin
begin
sect := new SectPrUnitDecorator(sect);
sect.PgSz.Orient := sect.PgSz.Orient ? "portrait" : "landscape";
sect.Type.Val := sect.Type.Val ?: "nextPage";
ware.SectPr := sect;
ware.Do();
end
@ -243,7 +287,7 @@ begin
begin
element := elements[i];
ware.AddElement(element);
if element.LocalName = "p" and ifObj(element.PPr.SectPr.XmlNode) then
if element.LocalName = "p" and ifObj(element.PPr.SectPr) then
begin
##fp(ware, element.PPr.SectPr);
sect_ware_array_[length(sect_ware_array_)] := ware;
@ -260,21 +304,22 @@ end;
function TSDocxToPdf.AddTSPage(flag: boolean = false): TSPage;
begin
if current_sect_ware_.SectPr.Type.Val = "continuous" and length(page_array_) <> 0 then return;
page := pdf_.AddPage();
page.SetWidth(sect_ware_.SectPr.PgSz.W);
page.SetHeight(sect_ware_.SectPr.PgSz.H);
// println("W = {}, H = {}", sect_ware_.SectPr.PgSz.W, sect_ware_.SectPr.PgSz.H);
page.SetWidth(current_sect_ware_.SectPr.PgSz.W);
page.SetHeight(current_sect_ware_.SectPr.PgSz.H);
// println("W = {}, H = {}", current_sect_ware_.SectPr.PgSz.W, current_sect_ware_.SectPr.PgSz.H);
len := length(page_array_);
current_page_ := new TSPage();
current_page_.Index := len;
current_page_.PdfPage := page;
current_page_.Number := flag ? ifnil(sect_ware_.SectPr.PgNumType.Start) ? 1 : sect_ware_.SectPr.PgNumType.Start : page_array_[len-1].Number + 1;
current_page_.Number := flag ? ifnil(current_sect_ware_.SectPr.PgNumType.Start) ? 1 : current_sect_ware_.SectPr.PgNumType.Start : page_array_[len-1].Number + 1;
// println("len = {}, Number = {}", len, current_page_.Number);
page_array_[len] := current_page_;
// 页眉页脚
if sect_ware_.SectPr.TitlePg and current_page_.Index = 0 then
if current_sect_ware_.SectPr.TitlePg and current_page_.Index = 0 then
type_name := "first";
else if not even_and_odd_flag_ then
type_name := "default";
@ -294,28 +339,28 @@ begin
text_point_.Y := y;
if sysparams["_PDF_PAGE_GRID_DEBUG_"] then
{self.}PrintGrid(page, sect_ware_);
{self.}PrintGrid(page, current_sect_ware_);
return current_page_;
end;
function TSDocxToPdf.CalculateTextCoordinates(): array of real;
begin
x := sect_ware_.SectPr.PgMar.Left;
y := min(sect_ware_.SectPr.PgSz.H - max(sect_ware_.SectPr.PgMar.Top, sect_ware_.SectPr.PgMar.Header), hdr_point_.Y);
x := current_sect_ware_.SectPr.PgMar.Left;
y := min(current_sect_ware_.SectPr.PgSz.H - max(current_sect_ware_.SectPr.PgMar.Top, current_sect_ware_.SectPr.PgMar.Header), hdr_point_.Y);
return array(x, y);
end;
function TSDocxToPdf.SetFtr(type: string);
begin
ftr_point_.X := sect_ware_.SectPr.PgMar.Left;
ftr_point_.Y := sect_ware_.SectPr.PgMar.Bottom;
footer_reference := sect_pr_adapter_.GetFooterReferenceByType(type);
ftr_point_.X := current_sect_ware_.SectPr.PgMar.Left;
ftr_point_.Y := current_sect_ware_.SectPr.PgMar.Bottom;
footer_reference := current_sect_pr_adapter_.GetFooterReferenceByType(type);
if ifObj(footer_reference) then
begin
rels_adapter := docx_components_ware_.GetDocumentRelsAdapter();
rel := rels_adapter.GetRelationshipById(footer_reference.Id);
w := sect_ware_.SectPr.PgSz.W - sect_ware_.SectPr.PgMar.Right - sect_ware_.SectPr.PgMar.Left;
w := current_sect_ware_.SectPr.PgSz.W - current_sect_ware_.SectPr.PgMar.Right - current_sect_ware_.SectPr.PgMar.Left;
lb := 0;
obj := docx_components_ware_.GetFtr(rel.Target);
xml_file_ := rel.Target;
@ -329,14 +374,14 @@ end;
function TSDocxToPdf.SetHdr(type: string);
begin
hdr_point_.X := sect_ware_.SectPr.PgMar.Left;
hdr_point_.Y := sect_ware_.SectPr.PgSz.H - sect_ware_.SectPr.PgMar.Header;
header_reference := sect_pr_adapter_.GetHeaderReferenceByType(type);
hdr_point_.X := current_sect_ware_.SectPr.PgMar.Left;
hdr_point_.Y := current_sect_ware_.SectPr.PgSz.H - current_sect_ware_.SectPr.PgMar.Header;
header_reference := current_sect_pr_adapter_.GetHeaderReferenceByType(type);
if ifObj(header_reference) then
begin
rels_adapter := docx_components_ware_.GetDocumentRelsAdapter();
rel := rels_adapter.GetRelationshipById(header_reference.Id);
w := sect_ware_.SectPr.PgSz.W - sect_ware_.SectPr.PgMar.Right - sect_ware_.SectPr.PgMar.Left;
w := current_sect_ware_.SectPr.PgSz.W - current_sect_ware_.SectPr.PgMar.Right - current_sect_ware_.SectPr.PgMar.Left;
lb := 0;
obj := docx_components_ware_.GetHdr(rel.Target);
xml_file_ := rel.Target;
@ -495,3 +540,78 @@ begin
return docx_components_ware_.SaveAs(alias, file);
end;
function TSDocxToPdf.GetCurrentNoteWare(): TSNoteWare;
begin
if ifnil(note_ware_) then note_ware_ := new TSNoteWare(current_sect_ware_);
return note_ware_;
end;
function TSDocxToPdf.ClassifyCols(var point: Point; cols: Cols);
begin
bk_page := current_page_;
columns := array();
x := point.X;
y := point.Y;
w := current_sect_ware_.SectPr.PgSz.W - current_sect_ware_.SectPr.PgMar.Right - current_sect_ware_.SectPr.PgMar.Left;
lb := current_sect_ware_.SectPr.PgMar.Bottom;
w_array := array();
ccols := cols.Cols();
for i:=0 to cols.Num-1 do
begin
rw := 0;
if cols.EqualWidth = "0" then
begin
rw := ccols[i].W;
if i > 0 then x += ccols[i-1].W + ccols[i-1].Space;
end
else begin
rw := w / 3;
x := point.X + i * rw + i * cols.Space;
end
range := new TSPdfColumnRange(self, current_page_, docx_components_ware_);
range.StartX := x;
range.StartY := y;
range.Width := rw;
range.LowerBound := lb;
columns[length(columns)] := range;
end
i := 0;
elements := current_sect_ware_.Elements();
range := columns[0];
for _,element in elements do
begin
if element.LocalName = "p" then
begin
p := new P();
sub_elements := element.Elements();
for _,sub in sub_elements do
begin
p.AppendChild(sub);
if sub.LocalName = "r" and sub.Br.Type = "column" then
begin
range.AddElement(p);
p := new P();
p.PPr.Copy(element.PPr);
range := columns[++i];
end
end
range.AddElement(p);
end
else begin
range.AddElement(element);
end
end
pg := nil;
max_y := nil;
for _,column in columns do
begin
column.Do();
page := column.GetLastPage();
if ifnil(pg) then pg := page;
if ifnil(max_y) then max_y := range.EndY;
if page.Index > pg.Index then max_y := range.EndY;
else if page.Index = pg.Index and max_y > range.EndY then max_y := range.EndY;
end
current_page_ := bk_page;
point.Y := max_y;
end;

View File

@ -0,0 +1,64 @@
type TSPdfColumnRange = class(TSPdfBasicRange)
public
function Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare);
function AddElement(ele: Element);
function Elements(): array of Element;
function GetLastPage(): TSPage;
function Do();override;
private
[weakref]docx_to_pdf_: TSDocxToPdf;
[weakref]docx_components_ware_: TSDocxComponentsWare;
[weakref]page_: TSPage;
elements_: array of Elements;
paragraph_: P;
last_y_: real;
end;
function TSPdfColumnRange.Create(docx_to_pdf: TSDocxToPdf; pg: TSPage; components: TSDocxComponentsWare);
begin
docx_to_pdf_ := docx_to_pdf;
page_ := pg;
docx_components_ware_ := components;
elements_ := array();
last_y_ := 0;
end;
function TSPdfColumnRange.AddElement(ele: Element);
begin
elements_[length(elements_)] := ele;
end;
function TSPdfColumnRange.Elements(): array of Element;
begin
return elements_;
end;
function TSPdfColumnRange.Do();override;
begin
x := {self.}StartX;
y := {self.}StartY;
for _,element in elements_ do
begin
range := nil;
if element.LocalName = "p" then
range := new TSPdfParagraphRange(docx_to_pdf_, page_, docx_components_ware_, element);
else if element.LocalName = "tbl" then
range := new TSPdfTableRange(docx_to_pdf_, page_, docx_components_ware_, element);
if ifnil(range) then continue;
range.StartX := x;
range.StartY := y;
range.Width := {self.}Width;
range.LowerBound := {self.}LowerBound;
range.Calc();
range.Do();
y := range.EndY;
page_ := range.GetLastPage();
end
{self.}EndY := y;
end;
function TSPdfColumnRange.GetLastPage(): TSPage;
begin
return page_;
end;

View File

@ -7,6 +7,7 @@ public
function Align(jc: string);
function AdjustRangeOffset(page: TSPage; x_offset: real; y_offset: real);
function AlignRightBound(right_bound: real);
function Offset(x_offset: real; y_offset; real);
private
range_array_: array of TSPdfBasicRange;
@ -81,3 +82,12 @@ begin
range_array_[i].EndX += avg * i;
end
end;
function TSPdfLineRange.Offset(x_offset: real; y_offset; real);
begin
for _,range in range_array_ do
begin
range.EndX += x_offset;
range.EndY -= y_offset;
end
end;

View File

@ -10,6 +10,7 @@ public
function AdjustRangeOffset(page: TSPage; x_offset: real; y_offset: real);
function GetLineRangeArr(): array of TSPdfLineRange;
function Empty(): boolean;
function Offset(x: real; y: real);
private
function SetPPr(var ppr: PPr);
@ -31,6 +32,7 @@ private
function RFootnoteReference(r: R);
function RObject(r: R);
function RFldChar(r: R; stack: Stack);
function RFootnoteRef(r: R);
function SetLinesAlignment();
function ResetCoordinates();
function NewLineRange(): TSPdfLineRange;
@ -39,6 +41,7 @@ private
function HyperlinkToTextRange(hyperlink: Hyperlink; ppr: PPrUnitDecorator);
function GetXYCordinates(): array of real;
function AlignRightBound();
function Init();
private
[weakref]docx_to_pdf_: TSDocxToPdf;
@ -125,14 +128,10 @@ begin
{self.}TSPage := page_;
end;
function TSPdfParagraphRange.Calc(): tableArray;
function TSPdfParagraphRange.Init();
begin
// ppr.rpr是无效的应该以ppr.pStyle为准
range_array_ := array();
right_bound_ := {self.}StartX + {self.}Width;
if ifnil(paragraph_.XmlChildPPr) then paragraph_.XmlChildPPr := new PPr();
{self.}SetPPr(paragraph_.PPr);
ppr_unit_decorator_ := new PPrUnitDecorator(paragraph_.PPr);
if not ppr_unit_decorator_.RPr.Sz.Val then ppr_unit_decorator_.RPr.Sz.Val := docx_to_pdf_.Font.GetDefaultSz();
{self.}ResetCoordinates();
{self.}EndX := {self.}StartX;
{self.}EndY := {self.}StartY;
@ -140,9 +139,18 @@ begin
{self.}EndY -= ppr_unit_decorator_.Spacing.Before;
{self.}DynamicHeight += ppr_unit_decorator_.Spacing.Before;
{self.}SetLvlText();
end;
function TSPdfParagraphRange.Calc(): tableArray;
begin
// ppr.rpr是无效的应该以ppr.pStyle为准
if ifnil(paragraph_.XmlChildPPr) then paragraph_.XmlChildPPr := new PPr();
{self.}SetPPr(paragraph_.PPr);
ppr_unit_decorator_ := new PPrUnitDecorator(paragraph_.PPr);
if not ppr_unit_decorator_.RPr.Sz.Val then ppr_unit_decorator_.RPr.Sz.Val := docx_to_pdf_.Font.GetDefaultSz();
if paragraph_.PPr.PageBreakBefore then
{self.}CheckAndAddPage({self.}LowerBound, 1);
{self.}Init();
elements := paragraph_.Elements();
empty_flag := true;
@ -170,12 +178,13 @@ begin
end
if element.Br.Type = "page" then
// {self.}EndY := {self.}LowerBound;
{self.}CheckAndAddPage({self.}LowerBound, 1);
{self.}EndY := {self.}LowerBound;
// {self.}CheckAndAddPage({self.}LowerBound, 1);
else if ifObj(element.Drawing) then {self.}RDrawing(element);
else if ifObj(element.AlternateContent) then {self.}RAlternateContent(element);
else if ifObj(element.FootnoteReference) then {self.}RFootnoteReference(element);
else if ifObj(element.Object) then {self.}RObject(element);
else if element.FootnoteRef then {self.}RFootnoteRef(element);
else {self.}RToTextRange(element, bookmark_name);
end
else if element.LocalName = "fldSimple" then
@ -540,7 +549,7 @@ end;
function TSPdfParagraphRange.RDrawing(r: R);
begin
if ifObj(r.Drawing._Inline.XmlNode) then
if ifObj(r.Drawing._Inline) then
begin
id := r.Drawing._Inline.Graphic.GraphicData.Pic.BlipFill.Blip.Embed;
[image_type, image] := {self.}GetImageData(id);
@ -555,7 +564,7 @@ begin
image_range.DynamicHeight := xfrm.Ext.CY;
range_array_[length(range_array_)] := image_range;
end
else if ifObj(r.Drawing.Anchor.XmlNode) then
else if ifObj(r.Drawing.Anchor) then
begin
anchor := r.Drawing.Anchor;
id := anchor.Graphic.GraphicData.Pic.BlipFill.Blip.Embed;
@ -619,8 +628,29 @@ begin
footnote := footnotes_adapter.GetFootnoteById(id);
sect_ware := docx_to_pdf_.GetCurrentSectWare();
w := sect_ware.SectPr.PgSz.W - sect_ware.SectPr.PgMar.Right - sect_ware.SectPr.PgMar.Left;
lb := 0;
lb := {self.}LowerBound;
[x, y] := docx_to_pdf_.CalculateTextCoordinates();
elements := footnote.Elements();
for _,element in elements do
begin
if element.LocalName = "p" then
begin
range := new TSPdfParagraphRange(docx_to_pdf_, page_, docx_components_ware_, element);
range.StartX := x;
range.StartY := y;
range.Width := w;
range.LowerBound := {self.}LowerBound;
range.Calc();
range.Offset(0, y - range.DynamicHeight - {self.}LowerBound);
range.Do();
{self.}LowerBound += range.DynamicHeight;
rpr := new RPrUnitDecorator(r.RPr);
text := docx_to_pdf_.GetCurrentNoteWare().GetIndex();
if ifString(text) then {self.}SplitTextToTextRange(text, rpr, nil);
return;
// break;
end
end
// range := new TSPdfParagraphRange(self, page_, docx_components_ware_, );
end;
@ -914,3 +944,17 @@ function TSPdfParagraphRange.Empty(): boolean;
begin
return empty_;
end;
function TSPdfParagraphRange.Offset(x: real; y: real);
begin
for _,line_range in line_range_array_ do
line_range.Offset(x, y);
end;
function TSPdfParagraphRange.RFootnoteRef(r: R);
begin
note_ware := docx_to_pdf_.GetCurrentNoteWare();
rpr := new RPrUnitDecorator(r.RPr);
text := note_ware.GetFootnoteOrderNumber();
if ifString(text) then {self.}SplitTextToTextRange(text, rpr, nil);
end;

View File

@ -24,10 +24,17 @@ begin
// println("Text = {}, sz = {}, szcs = {}, rpr.I = {}, color = {}", ansiToUtf8({self.}Text), {self.}RPr.Sz.Val, {self.}RPr.SzCs.Val, {self.}RPr.I, {self.}RPr.Color.Val);
[r, g, b] := array(0, 0, 0);
if {self.}RPr.Color.Val and {self.}RPr.Color.Val <> "auto" then [r, g, b] := TSColorToolKit.HexToRGB({self.}RPr.Color.Val);
y := {self.}EndY;
sz := {self.}RPr.Sz.Val;
if {self.}RPr.VertAlign.Val = "superscript" then
begin
y += sz / 3;
sz := sz * 2 / 3;
end
{self.}TSPage.PdfPage.SetRGBFill(r / 255, g / 255, b / 255);
{self.}TSPage.PdfPage.SetFontAndSize({self.}Font, {self.}RPr.Sz.Val);
{self.}TSPage.PdfPage.SetFontAndSize({self.}Font, sz);
{self.}TSPage.PdfPage.BeginText();
{self.}TSPage.PdfPage.TextOut({self.}EndX, {self.}EndY, {self.}Text);
{self.}TSPage.PdfPage.TextOut({self.}EndX, y, {self.}Text);
{self.}TSPage.PdfPage.EndText();
{self.}TSPage.PdfPage.SetRGBFill(0, 0, 0);

View File

@ -11,7 +11,6 @@ public
function GetFtrRelsAdapter(target: string): RelationShipsAdapter;
function GetHdrRelsAdapter(target: string): RelationShipsAdapter;
function GetFootnotesAdapter(): FootnotesAdapter;
private
styles_deserialize_flag_: boolean;
styles_adapter_: StylesAdapter;
@ -125,6 +124,6 @@ begin
if footnotes_adapter_ then return footnotes_adapter_;
obj := {self.}Footnotes;
obj.Deserialize();
footnotes_adapter_ := new FootnotesAdapter();
footnotes_adapter_ := new FootnotesAdapter(obj);
return footnotes_adapter_;
end;

View File

@ -1,7 +1,6 @@
type TSFontWare = class
public
function Create(pdf: PdfFile);
function GetFontByText(text: string; name: string; bold: boolean; italic: boolean): PdfFont;
function GetAsciiFont(name: string; bold: boolean; italic: boolean): PdfFont;
function GetCNSFont(name: string; bold: boolean; italic: boolean): PdfFont;
function GetSymbolFont(): PdfFont;
@ -18,7 +17,6 @@ private
private
[weakref]pdf_: PdfFile;
is_linux_: boolean; // 是否是linux
use_built_in_font_: boolean; // 是否使用内置字体
substitution_rules_: array of string; // 替换规则
external_reference_: array of string;
@ -60,27 +58,16 @@ begin
if not ifnil(external_font_cache_[name]) then return external_font_cache_[name];
value := external_reference_[name];
if ifnil(value) then return nil;
// if ifnil(value) then raise name + " is unsupported font.";
if value["ext"] = ".ttf" then
font_name := pdf_.LoadTTFontFromFile("", value["path"], true);
else if value["ext"] = ".ttc" then
font_name := pdf_.LoadTTFontFromFile2("", value["path"], 0, true);
// if not ifString(font_name) then raise "Load font error : " + format("%x", font_name);
if not ifString(font_name) then return nil;
font := pdf_.GetFont(font_name, "UTF-8");
external_font_cache_[name] := font;
return font;
end;
function TSFontWare.GetFontByText(text: string; name: string; bold: boolean; italic: boolean): PdfFont;
begin
len := length(text);
if len > 1 then
return {self.}GetCNSFont(name, bold, italic);
else
return {self.}GetAsciiFont(name, bold, italic);
end;
function TSFontWare.GetCNSFont(name: string; bold: boolean; italic: boolean): PdfFont;
begin
return use_built_in_font_ ? {self.}GetBuiltInCNSFont(name, bold, italic) : {self.}GetExternalFont(name, bold, italic);

60
ware/TSNoteWare.tsf Normal file
View File

@ -0,0 +1,60 @@
type TSNoteWare = class
public
function Create(sect_ware: TSSectWare);
function GetFootnoteOrderNumber(): string;
function GetIndex(): string;
private
function CalculateNumber(num_fmt: string; num: integer): string;
function ChineseCountingThousand(n: integer): string;
private
[weakref]sect_ware_: TSSectWare;
index_: integer;
end;
function TSNoteWare.Create(sect_ware: TSSectWare);
begin
sect_ware_ := sect_ware;
index_ := 0;
end;
function TSNoteWare.GetFootnoteOrderNumber();
begin
num_fmt := sect_ware_.SectPr.FootnotePr.NumFmt.Val;
if ifnil(num_fmt) then num_fmt := "decimal";
return CalculateNumber(num_fmt, ++index_);
end;
function TSNoteWare.GetIndex(): string;
begin
return inttostr(index_);
end;
function TSNoteWare.CalculateNumber(num_fmt: string; num: integer): string;
begin
if num_fmt = "decimal" then
return format("%d", num);
else if num_fmt = "chineseCountingThousand" then
return {self.}ChineseCountingThousand(num);
else
return format("%d", num);
end;
function TSNoteWare.ChineseCountingThousand(n: integer): string;
begin
chinese_digits := array("零", "一", "二", "三", "四", "五", "六", "七", "八", "九");
chinese_units := array("", "十", "百", "千");
if n < 10 then return chinese_digits[n];
result := "";
num_str := inttostr(n);
len := length(num_str);
for i:=1 to len do
begin
digit_int := strtoint(num_str[i]);
if digit_int <> 0 then
result += chinese_digits[digit_int] + chinese_units[len - i];
end
if length(result) >= 6 and result[:6] = "一十" then result := result[4:];
return result;
end;