update
This commit is contained in:
parent
5c93255461
commit
a118ff6c26
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,23 @@
|
||||||
|
unit DTPColorToolKit;
|
||||||
|
interface
|
||||||
|
function HexToRGB(hex);
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
function HexToRGB(hex);
|
||||||
|
begin
|
||||||
|
hex_string := ifnumber(hex) ? format("%x", hex) : hex;
|
||||||
|
if length(hex_string) = 7 then
|
||||||
|
begin
|
||||||
|
if hex_string[1] <> "#" then raise "Invalid hexadecimal parameter.";
|
||||||
|
hex_string := hex_string[1:];
|
||||||
|
end
|
||||||
|
if length(hex_string) <> 6 then raise "Invalid hexadecimal parameter";
|
||||||
|
r := eval(&"return 0x" + hex_string[1:2]);
|
||||||
|
g := eval(&"return 0x" + hex_string[3:4]);
|
||||||
|
b := eval(&"return 0x" + hex_string[5:6]);
|
||||||
|
return array(r, g, b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,719 @@
|
||||||
|
unit DTPModules;
|
||||||
|
interface
|
||||||
|
uses TSPdfEnumerations, DocxMLAdapter, SharedMLAdapter;
|
||||||
|
|
||||||
|
type DocxComponentsModule = class(DocxComponents)
|
||||||
|
public
|
||||||
|
function Create();
|
||||||
|
function GetStyles(): Styles;
|
||||||
|
function GetStylesAdapter(): StylesAdapter;
|
||||||
|
function GetDocumentRelsAdapter(): RelationShipsAdapter;
|
||||||
|
function GetNumberingModule(): NumberingModule;
|
||||||
|
function GetTblStylePrByType(style_id: string; type: string): TblStylePr;
|
||||||
|
function GetFtr(target: string): Ftr;
|
||||||
|
function GetHdr(target: string): Hdr;
|
||||||
|
function GetFtrRelsAdapter(target: string): RelationShipsAdapter;
|
||||||
|
function GetHdrRelsAdapter(target: string): RelationShipsAdapter;
|
||||||
|
function GetFootnotesAdapter(): FootnotesAdapter;
|
||||||
|
private
|
||||||
|
styles_deserialize_flag_: boolean;
|
||||||
|
styles_adapter_: StylesAdapter;
|
||||||
|
document_rels_adapter_: RelationShipsAdapter;
|
||||||
|
numbering_module_: NumberingModule;
|
||||||
|
tbl_style_pr_hash_: array of TblStylePr;
|
||||||
|
ftr_hash_: array of Ftr;
|
||||||
|
hdr_hash_: array of Hdr;
|
||||||
|
hdr_rel_hash_: array of RelationShipsAdapter;
|
||||||
|
ftr_rel_hash_: array of RelationShipsAdapter;
|
||||||
|
footnotes_adapter_: FootnotesAdapter;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type FontModule = class
|
||||||
|
public
|
||||||
|
function Create(pdf: PdfFile);
|
||||||
|
|
||||||
|
function GetAsciiFont(name: string; bold: boolean; italic: boolean): PdfFont;
|
||||||
|
function GetCNSFont(name: string; bold: boolean; italic: boolean): PdfFont;
|
||||||
|
function GetSymbolFont(): PdfFont;
|
||||||
|
function GetZapfDingbatsFont(): PdfFont;
|
||||||
|
function UseExternalFont();
|
||||||
|
function SetSubstitutionRules(source: string; target: string);
|
||||||
|
function SetDefaultSz(value: real);
|
||||||
|
function GetDefaultSz(): real;
|
||||||
|
|
||||||
|
private
|
||||||
|
function GetExternalFont(name:string; bold: boolean; italic: boolean): PdfFont;
|
||||||
|
function GetBuiltInCNSFont(name:string; bold: boolean; italic: boolean): PdfFont;
|
||||||
|
function GetBuiltInAsciiFont(name:string; bold: boolean; italic: boolean): PdfFont;
|
||||||
|
|
||||||
|
private
|
||||||
|
[weakref]pdf_: PdfFile;
|
||||||
|
|
||||||
|
use_built_in_font_: boolean; // 是否使用内置字体
|
||||||
|
substitution_rules_: array of string; // 替换规则
|
||||||
|
external_reference_: array of string;
|
||||||
|
default_sz_: real;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type NoteModule = class
|
||||||
|
public
|
||||||
|
function Create(sect_module: SectModule);
|
||||||
|
function GetFootnoteOrderNumber(): string;
|
||||||
|
function GetFootnoteIndex(): string;
|
||||||
|
function AddFootnote();
|
||||||
|
|
||||||
|
private
|
||||||
|
function CalculateNumber(num_fmt: string; num: integer): string;
|
||||||
|
function ChineseCountingThousand(n: integer): string;
|
||||||
|
|
||||||
|
private
|
||||||
|
footnote_reference_hash_: hash;
|
||||||
|
footnote_index_: integer;
|
||||||
|
[weakref]sect_module_: SectModule;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type NumberingModule = class
|
||||||
|
public
|
||||||
|
function Create(number: NumberingAdapter);
|
||||||
|
function GetNumberLvl(ppr: PPr);
|
||||||
|
|
||||||
|
private
|
||||||
|
function CalculateNumber(num_fmt: string; num: integer): string;
|
||||||
|
function ChineseCountingThousand(n: integer): string;
|
||||||
|
|
||||||
|
private
|
||||||
|
numbering_adapter_: NumberingAdapter;
|
||||||
|
num_hash_: hash;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type SectModule = class
|
||||||
|
public
|
||||||
|
function Create();
|
||||||
|
function Destroy();
|
||||||
|
function Do();
|
||||||
|
function AddElement(element: tslobj);
|
||||||
|
|
||||||
|
public
|
||||||
|
Elements: array of tslobj;
|
||||||
|
SectPr: SectPrUnitDecorator;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type Toc = class
|
||||||
|
public
|
||||||
|
function Create(ppr: PPrUnitDecorator; rect: array of real; page: Page; x: real; y: real; font: PdfFont);
|
||||||
|
function LinkAnnot(dst: PdfDestination);
|
||||||
|
function AddPageNumber(page: Page);
|
||||||
|
|
||||||
|
private
|
||||||
|
[weakref]page_: Page;
|
||||||
|
ppr_: PPrUnitDecorator;
|
||||||
|
rect_: array of real;
|
||||||
|
font_: PdfFont;
|
||||||
|
x_;
|
||||||
|
y_;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type TocModule = class
|
||||||
|
public
|
||||||
|
function Create();
|
||||||
|
function UpdateDocxNumPages();
|
||||||
|
function LinkToToc(anchor: string; pg: Page; left: real; top: real);
|
||||||
|
function AddToc(anchor: string; toc: Toc);
|
||||||
|
|
||||||
|
function AddDocxPage(anchor: string; r: R);
|
||||||
|
|
||||||
|
private
|
||||||
|
toc_hash_: hash;
|
||||||
|
toc_unmatched_hash_: hash;
|
||||||
|
|
||||||
|
update_docx_num_pages_: boolean; // 开放给docx文件是否更新docx文件的页码
|
||||||
|
docx_page_hash_: hash;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// 坐标
|
||||||
|
type Point = class
|
||||||
|
public
|
||||||
|
function Create();
|
||||||
|
|
||||||
|
public
|
||||||
|
X: real;
|
||||||
|
Y: real;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Page延迟建立,存基本信息即可
|
||||||
|
type Page = class
|
||||||
|
public
|
||||||
|
function Create(pdf_file: PdfFile);
|
||||||
|
function OriginalTextCoordinates(): array of real;
|
||||||
|
function PrintGrid();
|
||||||
|
|
||||||
|
property PdfPage read ReadPdfPage;
|
||||||
|
function ReadPdfPage(): PdfPage;
|
||||||
|
|
||||||
|
public
|
||||||
|
Index: integer;
|
||||||
|
Number: integer;
|
||||||
|
SectPr: SectPrUnitDecorator;
|
||||||
|
BaseSize: real;
|
||||||
|
TextPoint: Point; // 正文坐标
|
||||||
|
FtrPoint: Point; // 页脚坐标
|
||||||
|
HdrPoint: Point; // 页眉坐标
|
||||||
|
|
||||||
|
private
|
||||||
|
[weakref]pdf_file_: PdfFile;
|
||||||
|
pdf_page_: PdfPage;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type PageManagerModule = class
|
||||||
|
public
|
||||||
|
function Create(pdf_file: PdfFile);
|
||||||
|
function Operator[](index: uinteger): Page;
|
||||||
|
function NewPage(): Page;
|
||||||
|
function NextPage(page: Page): Page;
|
||||||
|
function Count(): integer;
|
||||||
|
|
||||||
|
private
|
||||||
|
[weakref]pdf_file_: PdfFile;
|
||||||
|
page_array_: array of Page;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
// DocxComponentsModule
|
||||||
|
function DocxComponentsModule.Create();
|
||||||
|
begin
|
||||||
|
class(DocxComponents).Create();
|
||||||
|
tbl_style_pr_hash_ := array();
|
||||||
|
ftr_hash_ := array();
|
||||||
|
hdr_hash_ := array();
|
||||||
|
hdr_rel_hash_ := array();
|
||||||
|
ftr_rel_hash_ := array();
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DocxComponentsModule.GetStyles(): Styles;
|
||||||
|
begin
|
||||||
|
if styles_deserialize_flag_ then return {self.}Styles;
|
||||||
|
{self.}Styles.Deserialize();
|
||||||
|
styles_deserialize_flag_ := true;
|
||||||
|
return {self.}Styles;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DocxComponentsModule.GetStylesAdapter(): StylesAdapter;
|
||||||
|
begin
|
||||||
|
if styles_adapter_ then return styles_adapter_;
|
||||||
|
styles_adapter_ := new StylesAdapter({self.}GetStyles());
|
||||||
|
return styles_adapter_;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DocxComponentsModule.GetDocumentRelsAdapter(): RelationShipsAdapter;
|
||||||
|
begin
|
||||||
|
if document_rels_adapter_ then return document_rels_adapter_;
|
||||||
|
{self.}DocumentRels.Deserialize();
|
||||||
|
document_rels_adapter_ := new RelationShipsAdapter({self.}DocumentRels);
|
||||||
|
return document_rels_adapter_;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DocxComponentsModule.GetNumberingModule(): NumberingModule;
|
||||||
|
begin
|
||||||
|
if numbering_module_ then return numbering_module_;
|
||||||
|
if not {self.}Numbering then return nil;
|
||||||
|
{self.}Numbering.Deserialize();
|
||||||
|
numbering_module_ := new NumberingModule({self.}Numbering);
|
||||||
|
return numbering_module_;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DocxComponentsModule.GetTblStylePrByType(style_id: string; type: string): TblStylePr;
|
||||||
|
begin
|
||||||
|
if tbl_style_pr_hash_[style_id][type] then return tbl_style_pr_hash_[style_id][type];
|
||||||
|
styles_adapter := {self.}GetStylesAdapter();
|
||||||
|
style := styles_adapter.GetStyleByStyleId(style_id);
|
||||||
|
style := new StyleAdapter(style);
|
||||||
|
tbl_style_pr := style.GetTblStylePrByType(type);
|
||||||
|
tbl_style_pr_hash_[style_id][type] := tbl_style_pr;
|
||||||
|
return tbl_style_pr;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DocxComponentsModule.GetFtr(target: string): Ftr;
|
||||||
|
begin
|
||||||
|
if ftr_hash_[target] then return ftr_hash_[target];
|
||||||
|
index := replaceStr(replaceStr(target, "footer", ""), ".xml", "");
|
||||||
|
obj := {self.}Footers(strtoint(index));
|
||||||
|
obj.Deserialize();
|
||||||
|
ftr_hash_[target] := obj;
|
||||||
|
return obj;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DocxComponentsModule.GetHdr(target: string): Hdr;
|
||||||
|
begin
|
||||||
|
if hdr_hash_[target] then return hdr_hash_[target];
|
||||||
|
index := replaceStr(replaceStr(target, "header", ""), ".xml", "");
|
||||||
|
obj := {self.}Headers(strtoint(index));
|
||||||
|
obj.Deserialize();
|
||||||
|
hdr_hash_[target] := obj;
|
||||||
|
return obj;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DocxComponentsModule.GetHdrRelsAdapter(target: string): RelationShipsAdapter;
|
||||||
|
begin
|
||||||
|
if hdr_rel_hash_[target] then return hdr_rel_hash_[target];
|
||||||
|
index := replaceStr(replaceStr(target, "header", ""), ".xml", "");
|
||||||
|
obj := {self.}HeaderRels(strtoint(index));
|
||||||
|
obj.Deserialize();
|
||||||
|
rels_adapter := new RelationShipsAdapter(obj);
|
||||||
|
hdr_rel_hash_[target] := rels_adapter;
|
||||||
|
return rels_adapter;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DocxComponentsModule.GetFtrRelsAdapter(target: string): RelationShipsAdapter;
|
||||||
|
begin
|
||||||
|
if ftr_rel_hash_[target] then return ftr_rel_hash_[target];
|
||||||
|
index := replaceStr(replaceStr(target, "footer", ""), ".xml", "");
|
||||||
|
obj := {self.}FooterRels(strtoint(index));
|
||||||
|
obj.Deserialize();
|
||||||
|
rels_adapter := new RelationShipsAdapter(obj);
|
||||||
|
ftr_rel_hash_[target] := rels_adapter;
|
||||||
|
return rels_adapter;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DocxComponentsModule.GetFootnotesAdapter(): FootnotesAdapter;
|
||||||
|
begin
|
||||||
|
if footnotes_adapter_ then return footnotes_adapter_;
|
||||||
|
obj := {self.}Footnotes;
|
||||||
|
obj.Deserialize();
|
||||||
|
footnotes_adapter_ := new FootnotesAdapter(obj);
|
||||||
|
return footnotes_adapter_;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// FontModule
|
||||||
|
function FontModule.Create(pdf: PdfFile);
|
||||||
|
begin
|
||||||
|
pdf_ := pdf;
|
||||||
|
use_built_in_font_ := true;
|
||||||
|
substitution_rules_ := array("宋体": "SimSun",
|
||||||
|
"黑体": "SimHei",
|
||||||
|
"Courier New": "Courier",
|
||||||
|
"Helvetica": "Helvetica",
|
||||||
|
"Times New Roman": "Times-Roman",
|
||||||
|
);
|
||||||
|
external_reference_ := array();
|
||||||
|
default_sz_ := 10.5;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FontModule.SetDefaultSz(value: real);
|
||||||
|
begin
|
||||||
|
default_sz_ := value;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FontModule.GetDefaultSz();
|
||||||
|
begin
|
||||||
|
return default_sz_;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FontModule.UseExternalFont();
|
||||||
|
begin
|
||||||
|
use_built_in_font_ := false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FontModule.GetExternalFont(name:string; bold: boolean; italic: boolean);
|
||||||
|
begin
|
||||||
|
if ifnil(name) or name = '' then name := "等线";
|
||||||
|
if not ifnil(external_font_cache_[name]) then return external_font_cache_[name];
|
||||||
|
value := external_reference_[name];
|
||||||
|
if ifnil(value) then return nil;
|
||||||
|
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 return nil;
|
||||||
|
font := pdf_.GetFont(font_name, "UTF-8");
|
||||||
|
external_font_cache_[name] := font;
|
||||||
|
return font;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FontModule.GetCNSFont(name: string; bold: boolean; italic: boolean): PdfFont;
|
||||||
|
begin
|
||||||
|
return use_built_in_font_ ? {self.}GetBuiltInCNSFont(name, bold, italic) : {self.}GetExternalFont(name, bold, italic);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FontModule.GetBuiltInCNSFont(name: string; bold: boolean; italic: boolean): PdfFont;
|
||||||
|
begin
|
||||||
|
font_name := substitution_rules_[name];
|
||||||
|
if ifnil(font_name) then font_name := "SimSun";
|
||||||
|
if bold and italic then
|
||||||
|
font_name += ",BoldItalic";
|
||||||
|
else if bold then
|
||||||
|
font_name += ",Bold";
|
||||||
|
else if italic then
|
||||||
|
font_name += ",Italic";
|
||||||
|
return pdf_.GetFont(font_name, "GBK-EUC-H");
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FontModule.GetAsciiFont(name: string; bold: boolean; italic: boolean): PdfFont;
|
||||||
|
begin
|
||||||
|
return use_built_in_font_ ? {self.}GetBuiltInAsciiFont(name, bold, italic) : {self.}GetExternalFont(name, bold, italic);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FontModule.GetBuiltInAsciiFont(name:string; bold: boolean; italic: boolean): PdfFont;
|
||||||
|
begin
|
||||||
|
font_name := substitution_rules_[name];
|
||||||
|
if ifnil(font_name) then font_name := "Times-Roman";
|
||||||
|
if font_name = "Courier" or font_name = "Helvetica" then
|
||||||
|
begin
|
||||||
|
if bold and italic then
|
||||||
|
font_name += "-BoldOblique";
|
||||||
|
else if bold then
|
||||||
|
font_name += "-Bold";
|
||||||
|
else if italic then
|
||||||
|
font_name += "-Oblique";
|
||||||
|
end
|
||||||
|
else if font_name = "Times-Roman" then
|
||||||
|
begin
|
||||||
|
if bold and italic then
|
||||||
|
font_name := "Times-BoldItalic";
|
||||||
|
else if bold then
|
||||||
|
font_name += "Times-Bold";
|
||||||
|
else if italic then
|
||||||
|
font_name += "Times-Italic";
|
||||||
|
end
|
||||||
|
return pdf_.GetFont(font_name, "");
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FontModule.SetSubstitutionRules(source: string; target: string);
|
||||||
|
begin
|
||||||
|
substitution_rules_[source] := target;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FontModule.GetSymbolFont(): PdfFont;
|
||||||
|
begin
|
||||||
|
return pdf_.GetFont("Symbol", "");
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FontModule.GetZapfDingbatsFont(): PdfFont;
|
||||||
|
begin
|
||||||
|
return pdf_.GetFont("ZapfDingbats", "");
|
||||||
|
end;
|
||||||
|
|
||||||
|
// NoteModule
|
||||||
|
function NoteModule.Create(sect_module: SectModule);
|
||||||
|
begin
|
||||||
|
sect_module_ := sect_module;
|
||||||
|
footnote_reference_hash_ := array();
|
||||||
|
footnote_index_ := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function NoteModule.GetFootnoteOrderNumber();
|
||||||
|
begin
|
||||||
|
num_fmt := sect_module_.SectPr.FootnotePr.NumFmt.Val;
|
||||||
|
if ifnil(num_fmt) then num_fmt := "decimal";
|
||||||
|
return CalculateNumber(num_fmt, ++footnote_index_);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function NoteModule.GetFootnoteIndex(): string;
|
||||||
|
begin
|
||||||
|
return inttostr(footnote_index_);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function NoteModule.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 NoteModule.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;
|
||||||
|
|
||||||
|
// SectModule
|
||||||
|
function SectModule.Create();
|
||||||
|
begin
|
||||||
|
{self.}Elements := array();
|
||||||
|
{self.}SectPr := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SectModule.AddElement(element: tslobj);
|
||||||
|
begin
|
||||||
|
{self.}Elements[length({self.}Elements)] := element;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// NumberingModule
|
||||||
|
function NumberingModule.Create(number: NumberingAdapter);
|
||||||
|
begin
|
||||||
|
numbering_adapter_ := new NumberingAdapter(number);
|
||||||
|
num_hash_ := array();
|
||||||
|
end;
|
||||||
|
|
||||||
|
function NumberingModule.GetNumberLvl(ppr: PPr);
|
||||||
|
begin
|
||||||
|
num_id := ppr.NumPr.NumId.Val;
|
||||||
|
if ifnil(num_id) then return array("", nil);
|
||||||
|
ilvl := ppr.NumPr.Ilvl.Val;
|
||||||
|
pstyle := ppr.PStyle.Val;
|
||||||
|
num := numbering_adapter_.GetNumByNumId(num_id);
|
||||||
|
if ifnil(num) then return array("", nil);
|
||||||
|
abstract_id := num.AbstractNumId.Val;
|
||||||
|
abstract_num := numbering_adapter_.GetAbstractNumByAbstractNumId(abstract_id);
|
||||||
|
lvls := abstract_num.Lvls();
|
||||||
|
if ifnil(ilvl) then ilvl := "0";
|
||||||
|
for k,v in lvls do
|
||||||
|
begin
|
||||||
|
if ilvl and v.Ilvl = ilvl then
|
||||||
|
begin
|
||||||
|
lvl_text := v.LvlText.Val;
|
||||||
|
if not ifarray(num_hash_[num_id]) then num_hash_[num_id] := array(0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
|
ilvl_int := strtoint(ilvl);
|
||||||
|
for i:=0 to ilvl_int do
|
||||||
|
begin
|
||||||
|
source_str := "%" $ (i + 1);
|
||||||
|
n := num_hash_[num_id][i];
|
||||||
|
if i = ilvl_int then
|
||||||
|
begin
|
||||||
|
n := num_hash_[num_id][i] + 1;
|
||||||
|
for j:=i+1 to length(num_hash_[num_id])-1 do
|
||||||
|
num_hash_[num_id][j] := 0;
|
||||||
|
end
|
||||||
|
n := i = ilvl_int ? num_hash_[num_id][i] + 1 : num_hash_[num_id][i];
|
||||||
|
dest_str := {self.}CalculateNumber(v.NumFmt.Val, n);
|
||||||
|
lvl_text := replaceStr(lvl_text, source_str, dest_str);
|
||||||
|
end
|
||||||
|
num_hash_[num_id][ilvl_int]++;
|
||||||
|
if v.Suff.Val = "space" then lvl_text += " ";
|
||||||
|
return array(lvl_text, v);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return array("", nil);
|
||||||
|
end
|
||||||
|
|
||||||
|
function NumberingModule.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 NumberingModule.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;
|
||||||
|
|
||||||
|
// Page
|
||||||
|
function Page.Create(pdf_file: PdfFile);
|
||||||
|
begin
|
||||||
|
pdf_file_ := pdf_file;
|
||||||
|
{self.}TextPoint := new Point();
|
||||||
|
{self.}FtrPoint := new Point();
|
||||||
|
{self.}HdrPoint := new Point();
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Page.OriginalTextCoordinates(): array of real;
|
||||||
|
begin
|
||||||
|
x := {self.}SectPr.PgMar.Left;
|
||||||
|
y := min({self.}SectPr.PgSz.H - max({self.}SectPr.PgMar.Top, {self.}SectPr.PgMar.Header), {self.}HdrPoint.Y);
|
||||||
|
return array(x, y);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Page.ReadPdfPage(): PdfPage;
|
||||||
|
begin
|
||||||
|
if ifnil(pdf_page_) then
|
||||||
|
begin
|
||||||
|
pdf_page_ := pdf_file_.AddPage();
|
||||||
|
pdf_page_.SetWidth({self.}SectPr.PgSz.W);
|
||||||
|
pdf_page_.SetHeight({self.}SectPr.PgSz.H);
|
||||||
|
|
||||||
|
if sysparams["_PDF_PAGE_GRID_DEBUG_"] then
|
||||||
|
{self.}PrintGrid();
|
||||||
|
|
||||||
|
end
|
||||||
|
return pdf_page_;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Page.PrintGrid();
|
||||||
|
begin
|
||||||
|
i := 0;
|
||||||
|
while true do
|
||||||
|
begin
|
||||||
|
y := {self.}TextPoint.Y - i * {self.}SectPr.DocGrid.LinePitch;
|
||||||
|
if y <= {self.}SectPr.PgMar.Bottom then break;
|
||||||
|
pdf_page_.SetLineWidth(0.05);
|
||||||
|
pdf_page_.SetGrayStroke(0.75);
|
||||||
|
pdf_page_.MoveTo({self.}SectPr.PgMar.Left, y);
|
||||||
|
pdf_page_.LineTo({self.}SectPr.PgSz.W- {self.}SectPr.PgMar.Right, y);
|
||||||
|
pdf_page_.Stroke();
|
||||||
|
i++;
|
||||||
|
end
|
||||||
|
|
||||||
|
x1 := {self.}SectPr.PgMar.Left;
|
||||||
|
y1 := {self.}SectPr.PgSz.H - {self.}SectPr.PgMar.Top;
|
||||||
|
x2 := {self.}SectPr.PgSz.W - {self.}SectPr.PgMar.Right;
|
||||||
|
y2 := y1;
|
||||||
|
x3 := x1;
|
||||||
|
y3 := {self.}SectPr.PgMar.Bottom;
|
||||||
|
x4 := x2;
|
||||||
|
y4 := y3;
|
||||||
|
pdf_page_.SetLineWidth(0.05);
|
||||||
|
pdf_page_.SetGrayStroke(0.5);
|
||||||
|
pdf_page_.MoveTo(x1, y1);
|
||||||
|
pdf_page_.LineTo(x2, y2);
|
||||||
|
pdf_page_.Stroke();
|
||||||
|
pdf_page_.MoveTo(x1, y1);
|
||||||
|
pdf_page_.LineTo(x3, y3);
|
||||||
|
pdf_page_.Stroke();
|
||||||
|
pdf_page_.MoveTo(x2, y2);
|
||||||
|
pdf_page_.LineTo(x4, y4);
|
||||||
|
pdf_page_.Stroke();
|
||||||
|
pdf_page_.MoveTo(x3, y3);
|
||||||
|
pdf_page_.LineTo(x4, y4);
|
||||||
|
pdf_page_.Stroke();
|
||||||
|
end;
|
||||||
|
|
||||||
|
// PageManagerModule
|
||||||
|
function PageManagerModule.Create(pdf_file: PdfFile);
|
||||||
|
begin
|
||||||
|
pdf_file_ := pdf_file;
|
||||||
|
page_array_ := array();
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Operator PageManagerModule.[](index: uinteger): Page;
|
||||||
|
begin
|
||||||
|
return page_array_[index];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function PageManagerModule.NewPage(): Page;
|
||||||
|
begin
|
||||||
|
len := length(page_array_);
|
||||||
|
page := new Page(pdf_file_);
|
||||||
|
page.Index := len;
|
||||||
|
page_array_[len] := page;
|
||||||
|
return page;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function PageManagerModule.Count(): integer;
|
||||||
|
begin
|
||||||
|
return length(page_array_);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// TocModule
|
||||||
|
function TocModule.Create();
|
||||||
|
begin
|
||||||
|
toc_hash_ := array();
|
||||||
|
toc_unmatched_hash_ := array();
|
||||||
|
|
||||||
|
update_docx_num_pages_ := false;
|
||||||
|
docx_page_hash_ := array();
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TocModule.UpdateDocxNumPages();
|
||||||
|
begin
|
||||||
|
update_docx_num_pages_ := true;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TocModule.LinkToToc(anchor: string; pg: Page; left: real; top: real);
|
||||||
|
begin
|
||||||
|
arr := toc_hash_[anchor];
|
||||||
|
if ifnil(arr) then
|
||||||
|
begin
|
||||||
|
toc_unmatched_hash_[anchor] := array(pg, left, top);
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
dst := pg.PdfPage.CreateDestination();
|
||||||
|
dst.SetXYZ(left, top, 1);
|
||||||
|
for _,toc in arr do
|
||||||
|
toc.LinkAnnot(dst);
|
||||||
|
toc.AddPageNumber(pg);
|
||||||
|
|
||||||
|
if update_docx_num_pages_ then
|
||||||
|
begin
|
||||||
|
r := docx_page_hash_[anchor];
|
||||||
|
r.T.Text := pg.Number;
|
||||||
|
r.Serialize();
|
||||||
|
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);
|
||||||
|
begin
|
||||||
|
docx_page_hash_[anchor] := r;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Toc
|
||||||
|
function Toc.Create(ppr: PPrUnitDecorator; rect: array of real; pg: Page; x: real; y: real; font: PdfFont);
|
||||||
|
begin
|
||||||
|
ppr_ := ppr;
|
||||||
|
rect_ := rect;
|
||||||
|
page_ := pg;
|
||||||
|
x_ := x;
|
||||||
|
y_ := y;
|
||||||
|
font_ := font;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Toc.LinkAnnot(dst: PdfDestination);
|
||||||
|
begin
|
||||||
|
annot := page_.PdfPage.CreateLinkAnnot(rect_, dst);
|
||||||
|
annot.LinkAnnotSetHighlightMode(TSPdfEnumerations.ANNOT_NO_HIGHTLIGHT);
|
||||||
|
annot.LinkAnnotSetBorderStyle(0, 0, 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Toc.AddPageNumber(pg: Page);
|
||||||
|
begin
|
||||||
|
number := tostring(pg.Number);
|
||||||
|
page_.PdfPage.SetFontAndSize(font_, ppr_.RPr.Sz.Val);
|
||||||
|
number_sz := page_.PdfPage.TextWidth(number);
|
||||||
|
x := rect_[2] - number_sz;
|
||||||
|
page_.PdfPage.BeginText();
|
||||||
|
page_.PdfPage.TextOut(x, y_, number);
|
||||||
|
page_.PdfPage.EndText();
|
||||||
|
|
||||||
|
page_.PdfPage.SetRGBStroke(0, 0, 0);
|
||||||
|
page_.PdfPage.SetDash(array(0.5, 2), 2, 0);
|
||||||
|
page_.PdfPage.SetLineWidth(0.5);
|
||||||
|
page_.PdfPage.SetLineCap(TSPdfEnumerations.ROUND_END);
|
||||||
|
page_.PdfPage.MoveTo(x_+1, y_);
|
||||||
|
page_.PdfPage.LineTo(x-0.5, y_);
|
||||||
|
page_.PdfPage.Stroke();
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
@ -0,0 +1,245 @@
|
||||||
|
unit DTPPrimitiveRanges;
|
||||||
|
interface
|
||||||
|
uses DTPColorToolKit, DTPUtils;
|
||||||
|
|
||||||
|
type TextRange = class(BasicRange)
|
||||||
|
public
|
||||||
|
function Create();
|
||||||
|
function Do();override;
|
||||||
|
|
||||||
|
public
|
||||||
|
RPr: RPr;
|
||||||
|
Text: string;
|
||||||
|
Font: PdfFont;
|
||||||
|
Type: integer; // 0:默认,1: 数字,2:英文,3:中文,4:中文标点
|
||||||
|
end;
|
||||||
|
|
||||||
|
type BordersRange = class(BasicRange)
|
||||||
|
public
|
||||||
|
function Create();
|
||||||
|
function Do();override;
|
||||||
|
public
|
||||||
|
TcPr: TcPr;
|
||||||
|
Left: boolean;
|
||||||
|
Top: boolean;
|
||||||
|
Right: boolean;
|
||||||
|
Bottom: boolean;
|
||||||
|
|
||||||
|
private
|
||||||
|
function SetDash(val: string);
|
||||||
|
function DrawLine(border: Border; x1: real; y1: real; x2: real; y2: real);
|
||||||
|
end;
|
||||||
|
|
||||||
|
type ImageRange = class(BasicRange)
|
||||||
|
public
|
||||||
|
function Create();
|
||||||
|
function Do();override;
|
||||||
|
|
||||||
|
public
|
||||||
|
Image: PdfImage;
|
||||||
|
Type: string;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
type LineRange = class(BasicRange)
|
||||||
|
public
|
||||||
|
function Create();
|
||||||
|
function Do();override;
|
||||||
|
|
||||||
|
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]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.}Page := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// ImageRange
|
||||||
|
function ImageRange.Create();
|
||||||
|
begin
|
||||||
|
class(BasicRange).Create();
|
||||||
|
{self.}Image := nil;
|
||||||
|
{self.}Type := "";
|
||||||
|
end;
|
||||||
|
|
||||||
|
function ImageRange.Do();override;
|
||||||
|
begin
|
||||||
|
// println("image = {}, type = {}, x = {}, y = {}, w = {}, h = {}", {self.}image, {self.}Type, {self.}endx, {self.}endy, {self.}width, {self.}DynamicHeight);
|
||||||
|
if {self.}Type = "emf" then
|
||||||
|
{self.}Page.PdfPage.DrawEmf({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
|
||||||
|
else if {self.}Type = "wmf" then
|
||||||
|
{self.}Page.PdfPage.DrawWmf({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
|
||||||
|
else
|
||||||
|
{self.}Page.PdfPage.DrawImage({self.}Image, {self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
|
||||||
|
|
||||||
|
if sysparams["_PDF_IMAGE_DEBUG_"] then
|
||||||
|
begin
|
||||||
|
{self.}Page.PdfPage.SetLineWidth(0.1);
|
||||||
|
{self.}Page.PdfPage.SetRGBStroke(0.8, 0.8, 0);
|
||||||
|
{self.}Page.PdfPage.Rectangle({self.}EndX, {self.}EndY, {self.}Width, {self.}DynamicHeight);
|
||||||
|
{self.}Page.PdfPage.Stroke();
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
// BordersRange
|
||||||
|
function BordersRange.Create();
|
||||||
|
begin
|
||||||
|
class(BasicRange).Create();
|
||||||
|
{self.}TcPr := nil;
|
||||||
|
{self.}Left := false;
|
||||||
|
{self.}Top := false;
|
||||||
|
{self.}Right := false;
|
||||||
|
{self.}Bottom := false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function BordersRange.Do();override;
|
||||||
|
begin
|
||||||
|
// println("Left = {}, Top = {}, Right = {}, Bottom = {}, Tl2Br = {}, Tr2Bl = {}", Left, Top, Right, Bottom, Tl2Br, Tr2Bl);
|
||||||
|
borders := {self.}TcPr.TcBorders;
|
||||||
|
if {self.}TcPr.Shd.Fill and {self.}TcPr.Shd.Fill <> "auto" then
|
||||||
|
begin
|
||||||
|
[r, g, b] := DTPColorToolKit.HexToRGB({self.}TcPr.Shd.Fill);
|
||||||
|
{self.}Page.PdfPage.SetRGBFill(r/255, g/255, b/255);
|
||||||
|
x := {self.}EndX;
|
||||||
|
y := {self.}EndY - {self.}DynamicHeight;
|
||||||
|
w := {self.}Width;
|
||||||
|
h := {self.}DynamicHeight;
|
||||||
|
tmp := borders.Left.Sz ? borders.Left.Sz / 2 : 0.25;
|
||||||
|
x += tmp;
|
||||||
|
w -= tmp;
|
||||||
|
w -= borders.Right.Sz ? borders.Right.Sz / 2 : 0.25;
|
||||||
|
tmp := borders.Bottom.Sz ? borders.Bottom.Sz / 2 : 0.25;
|
||||||
|
y += tmp;
|
||||||
|
h -= tmp;
|
||||||
|
h -= borders.Top.Sz ? borders.Top.Sz / 2 : 0.25;
|
||||||
|
|
||||||
|
{self.}Page.PdfPage.Rectangle(x, y, w, h);
|
||||||
|
{self.}Page.PdfPage.Fill();
|
||||||
|
{self.}Page.PdfPage.SetRGBFill(0, 0, 0);
|
||||||
|
{self.}Left := true;
|
||||||
|
end
|
||||||
|
if {self.}Left then
|
||||||
|
{self.}DrawLine(borders.Left, {self.}EndX, {self.}EndY, {self.}EndX, {self.}EndY - {self.}DynamicHeight);
|
||||||
|
if {self.}Top then
|
||||||
|
{self.}DrawLine(borders.Top, {self.}EndX, {self.}EndY, {self.}EndX + {self.}Width, {self.}EndY);
|
||||||
|
if {self.}Right then
|
||||||
|
{self.}DrawLine(borders.Right, {self.}EndX + {self.}Width, {self.}EndY, {self.}EndX + {self.}Width, {self.}EndY - {self.}DynamicHeight);
|
||||||
|
if {self.}Bottom then
|
||||||
|
{self.}DrawLine(borders.Bottom, {self.}EndX, {self.}EndY - {Self.}DynamicHeight, {self.}EndX + {self.}Width, {self.}EndY - {self.}DynamicHeight);
|
||||||
|
if borders.Tl2Br then
|
||||||
|
{self.}DrawLine(borders.Tl2Br, {self.}EndX, {self.}Y, {self.}EndX + {self.}Width, {self.}EndY - {self.}DynamicHeight);
|
||||||
|
if borders.Tr2Bl then
|
||||||
|
{self.}DrawLine(borders.Tr2Bl, {self.}EndX + {self.}Width, {self.}Y, {self.}EndX, {self.}EndY - {self.}DynamicHeight);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function BordersRange.SetDash(val: string);
|
||||||
|
begin
|
||||||
|
if val = "single" or ifnil(val) then
|
||||||
|
{self.}Page.PdfPage.SetDash(array(), 0, 0);
|
||||||
|
if val = "dashed" then
|
||||||
|
{self.}Page.PdfPage.SetDash(array(1), 1, 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function BordersRange.DrawLine(border: Border; x1: real; y1: real; x2: real; y2: real);
|
||||||
|
begin
|
||||||
|
[r, g, b] := array(0, 0, 0);
|
||||||
|
line_width := border.Sz ?: 0.5;
|
||||||
|
{self.}SetDash(border.Val);
|
||||||
|
if border.Color and border.Color <> "auto" then [r, g, b] := DTPColorToolKit.HexToRGB(border.Color);
|
||||||
|
{self.}Page.PdfPage.SetRGBStroke(r, g, b);
|
||||||
|
{self.}Page.PdfPage.SetLineWidth(line_width);
|
||||||
|
{self.}Page.PdfPage.MoveTo(x1, y1);
|
||||||
|
{self.}Page.PdfPage.LineTo(x2, y2);
|
||||||
|
{self.}Page.PdfPage.Stroke();
|
||||||
|
{self.}Page.PdfPage.SetRGBStroke(0, 0, 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// TextRange
|
||||||
|
function TextRange.Create();
|
||||||
|
begin
|
||||||
|
class(BasicRange).Create();
|
||||||
|
{self.}RPr := nil;
|
||||||
|
{self.}Text := "";
|
||||||
|
{self.}Font := nil;
|
||||||
|
{self.}Type := -1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TextRange.Do();override;
|
||||||
|
begin
|
||||||
|
// println("text = {}, endx = {}, endy = {}, width = {}, page = {}", ansiToUtf8(text), endx, endy, width, page);
|
||||||
|
// println("Text = {}, sz = {}, szcs = {}, rpr.I = {}, rpr.B = {}, color = {}", ansiToUtf8({self.}Text), {self.}RPr.Sz.Val, {self.}RPr.SzCs.Val, {self.}RPr.I, {self.}RPr.B, {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] := DTPColorToolKit.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.}Page.PdfPage.SetRGBFill(r / 255, g / 255, b / 255);
|
||||||
|
{self.}Page.PdfPage.SetFontAndSize({self.}Font, sz);
|
||||||
|
{self.}Page.PdfPage.BeginText();
|
||||||
|
{self.}Page.PdfPage.TextOut({self.}EndX, y, {self.}Text);
|
||||||
|
{self.}Page.PdfPage.EndText();
|
||||||
|
{self.}Page.PdfPage.SetRGBFill(0, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
|
if sysparams["_PDF_TEXT_DEBUG_"] then
|
||||||
|
begin
|
||||||
|
{self.}Page.PdfPage.SetLineWidth(0.1);
|
||||||
|
{self.}Page.PdfPage.SetRGBStroke(1.0, 0.5, 0.0);
|
||||||
|
{self.}Page.PdfPage.MoveTo(0, {self.}EndY);
|
||||||
|
{self.}Page.PdfPage.LineTo(600, {self.}EndY);
|
||||||
|
{self.}Page.PdfPage.Stroke();
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
// LineRange
|
||||||
|
function LineRange.Create();
|
||||||
|
begin
|
||||||
|
class(BasicRange).Create();
|
||||||
|
{self.}LineWidth := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function LineRange.Do();override;
|
||||||
|
begin
|
||||||
|
// println("endx = {}, endy = {}, width = {}", EndX, EndY, Width);
|
||||||
|
{self.}Page.PdfPage.SetLineWidth({self.}LineWidth);
|
||||||
|
{self.}Page.PdfPage.SetRGBStroke(0, 0, 0);
|
||||||
|
{self.}Page.PdfPage.MoveTo({self.}EndX, {self.}EndY);
|
||||||
|
{self.}Page.PdfPage.LineTo({self.}EndX + {self.}Width, {self.}EndY);
|
||||||
|
{self.}Page.PdfPage.Stroke();
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
@ -0,0 +1,248 @@
|
||||||
|
unit DTPUtils;
|
||||||
|
interface
|
||||||
|
uses DTPPrimitiveRanges;
|
||||||
|
|
||||||
|
function Utf8CharLengthFromByte(byte: char): integer;
|
||||||
|
function IsChineseChar(str: utf8_string): boolean;
|
||||||
|
function IsChinesePunctuation(str: utf8_string): boolean;
|
||||||
|
|
||||||
|
type Point = class
|
||||||
|
public
|
||||||
|
function Create();
|
||||||
|
|
||||||
|
public
|
||||||
|
X: real;
|
||||||
|
Y: real;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type Stack = class
|
||||||
|
public
|
||||||
|
function Create();
|
||||||
|
function Pop();
|
||||||
|
function Push(element: any);
|
||||||
|
function Empty(): boolean;
|
||||||
|
|
||||||
|
private
|
||||||
|
arr_: tableArray;
|
||||||
|
index_: integer;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type FldStruct = class
|
||||||
|
public
|
||||||
|
function Create();
|
||||||
|
public
|
||||||
|
FldLock: boolean;
|
||||||
|
MergeFormat: boolean;
|
||||||
|
Quote: boolean;
|
||||||
|
Separate: boolean;
|
||||||
|
PageArabicMergeFormat: boolean;
|
||||||
|
NumPages: boolean;
|
||||||
|
ArabicMergeFormat: boolean;
|
||||||
|
EndFld: boolean;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type FldType = class
|
||||||
|
public
|
||||||
|
function Create();
|
||||||
|
|
||||||
|
public
|
||||||
|
Page: boolean;
|
||||||
|
NumPages: boolean;
|
||||||
|
Quote: boolean;
|
||||||
|
PageRef: boolean;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type FldStruct2 = class
|
||||||
|
public
|
||||||
|
function Create();
|
||||||
|
|
||||||
|
public
|
||||||
|
Type: FldType;
|
||||||
|
Arabic: boolean;
|
||||||
|
MergeFormat: boolean;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type TrProperty = class
|
||||||
|
public
|
||||||
|
function Create();
|
||||||
|
|
||||||
|
public
|
||||||
|
TrPr: TrPrUnitDecorator;
|
||||||
|
Height: real;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type Region = class
|
||||||
|
public
|
||||||
|
function Create();
|
||||||
|
|
||||||
|
public
|
||||||
|
BordersRange: BordersRange;
|
||||||
|
RangeArr: array of BasicRange;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type SymbolMapper = class
|
||||||
|
class function SymbolChr(symbol: string): string;
|
||||||
|
class function ZapfDingbatsChr(str: string): string;
|
||||||
|
private
|
||||||
|
static symbol_chr_hash_: array of chr;
|
||||||
|
static zapfdingbats_chr_hash_: array of chr;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
function Utf8CharLengthFromByte(byte: char): integer;
|
||||||
|
begin
|
||||||
|
if (_and(ord(byte), 0b10000000)) = 0 then
|
||||||
|
return 1;
|
||||||
|
else if (_and(ord(byte), 0b11100000)) = 0b11000000 then
|
||||||
|
return 2;
|
||||||
|
else if (_and(ord(byte), 0b11110000)) = 0b11100000 then
|
||||||
|
return 3;
|
||||||
|
else if (_and(ord(byte), 0b11111000)) = 0b11110000 then
|
||||||
|
return 4;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function IsChineseChar(str: utf8_string): boolean;
|
||||||
|
begin
|
||||||
|
unicode_str := utf8ToUnicode(str);
|
||||||
|
codepoint := ord(unicode_str[1]);
|
||||||
|
return (codepoint >= 0x4E00 && codepoint <= 0x9FFF) or
|
||||||
|
(codepoint >= 0x3400 && codepoint <= 0x4DBF) or
|
||||||
|
(codepoint >= 0x20000 && codepoint <= 0x2A6DF);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function IsChinesePunctuation(str: utf8_string): boolean;
|
||||||
|
begin
|
||||||
|
unicode_str := utf8ToUnicode(str);
|
||||||
|
codepoint := ord(unicode_str[1]);
|
||||||
|
return (codepoint >= 0x3000 && codepoint <= 0x303F) or
|
||||||
|
(codepoint >= 0xFF00 && codepoint <= 0xFFEF) or
|
||||||
|
(codepoint = 0x2018 || codepoint = 0x2019) or
|
||||||
|
(codepoint = 0x201C || codepoint = 0x201D) or
|
||||||
|
(codepoint = 0x2026 || codepoint = 0x2027);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Point
|
||||||
|
function Point.Create();
|
||||||
|
begin
|
||||||
|
{self.}X := 0;
|
||||||
|
{self.}Y := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Stack
|
||||||
|
function Stack.Create();
|
||||||
|
begin
|
||||||
|
arr_ := array();
|
||||||
|
index_ := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Stack.Pop();
|
||||||
|
begin
|
||||||
|
if index_ = 0 then return nil;
|
||||||
|
index_--;
|
||||||
|
ret := arr_[index_];
|
||||||
|
arr_[index_] := nil;
|
||||||
|
return ret;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Stack.Push(element: any);
|
||||||
|
begin
|
||||||
|
arr_[index_++] := element;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Stack.Empty(): boolean;
|
||||||
|
begin
|
||||||
|
return index_ = 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// FldStruct
|
||||||
|
function FldStruct.Create();
|
||||||
|
begin
|
||||||
|
FldLock := false;
|
||||||
|
MergeFormat := false;
|
||||||
|
Quote := false;
|
||||||
|
Separate := false;
|
||||||
|
PageArabicMergeFormat := false;
|
||||||
|
NumPages := false;
|
||||||
|
ArabicMergeFormat := false;
|
||||||
|
EndFld := false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// FldType
|
||||||
|
function FldType.Create();
|
||||||
|
begin
|
||||||
|
{self.}Page := false;
|
||||||
|
{self.}NumPages := false;
|
||||||
|
{self.}Quote := false;
|
||||||
|
{self.}PageRef := false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// FldStruct
|
||||||
|
function FldStruct2.Create();
|
||||||
|
begin
|
||||||
|
{self.}Type := new FldType();
|
||||||
|
{self.}Arabic := false;
|
||||||
|
{self.}MergeFormat := false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// TrProperty
|
||||||
|
function TrProperty.Create();
|
||||||
|
begin
|
||||||
|
{self.}TrPr := nil;
|
||||||
|
{self.}Height := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Region
|
||||||
|
function Region.Create();
|
||||||
|
begin
|
||||||
|
BordersRange := new DTPPrimitiveRanges.BordersRange();
|
||||||
|
RangeArr := array();
|
||||||
|
end
|
||||||
|
|
||||||
|
// SymbolMapper
|
||||||
|
class function SymbolMapper.SymbolChr(symbol: string);
|
||||||
|
begin
|
||||||
|
if ifnil(symbol_chr_hash_) then
|
||||||
|
begin
|
||||||
|
symbol_chr_hash_ := array(
|
||||||
|
"−": chr(0x2D),
|
||||||
|
"α": chr(0x61),
|
||||||
|
"β": chr(0x62),
|
||||||
|
"ε": chr(0x65),
|
||||||
|
"γ": chr(0x67),
|
||||||
|
"θ": chr(0x71),
|
||||||
|
"{": chr(0x7B),
|
||||||
|
"}": chr(0x7D),
|
||||||
|
"∞": chr(0xA5),
|
||||||
|
"f": chr(0xA6),
|
||||||
|
"±": chr(0xB1),
|
||||||
|
"∂": chr(0xB6),
|
||||||
|
"∏": chr(0xD5),
|
||||||
|
"〈": chr(0xE1),
|
||||||
|
"∑": chr(0xE5),
|
||||||
|
"〉": chr(0xF1),
|
||||||
|
"Į": chr(0xF2),
|
||||||
|
// "": chr(0x),
|
||||||
|
);
|
||||||
|
end
|
||||||
|
return symbol_chr_hash_[symbol];
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function SymbolMapper.ZapfDingbatsChr(str: string): string;
|
||||||
|
begin
|
||||||
|
if ifnil(zapfdingbats_chr_hash_) then
|
||||||
|
begin
|
||||||
|
zapfdingbats_chr_hash_ := array(
|
||||||
|
"": chr(118),
|
||||||
|
"": chr(110),
|
||||||
|
"": chr(108),
|
||||||
|
"": chr(117),
|
||||||
|
"": chr(108),
|
||||||
|
"o": chr(109),
|
||||||
|
"": chr(110),
|
||||||
|
);
|
||||||
|
end
|
||||||
|
return zapfdingbats_chr_hash_[symbol];
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
Loading…
Reference in New Issue