mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 06:05:58 -06:00
PdfDraw now supports color emoji, Fix in Gtk DrawText, refactored font height adjustment in replacement fonts
This commit is contained in:
parent
adcd29c609
commit
f084e9a612
11 changed files with 235 additions and 99 deletions
|
|
@ -38,15 +38,15 @@ void FontSysData::Init(Font font, int angle)
|
|||
|
||||
cairo_matrix_init_scale(font_matrix, fh, fh);
|
||||
|
||||
if(font.IsItalic() && !(FTFace(font)->style_flags & FT_STYLE_FLAG_ITALIC)) {
|
||||
cairo_matrix_t sheer[1];
|
||||
cairo_matrix_init_identity(sheer);
|
||||
sheer->xy = -0.2;
|
||||
cairo_matrix_multiply(font_matrix, font_matrix, sheer);
|
||||
}
|
||||
|
||||
if(angle)
|
||||
cairo_matrix_rotate(font_matrix, -angle * M_2PI / 3600);
|
||||
cairo_matrix_rotate(font_matrix, -angle * M_PI / 1800);
|
||||
|
||||
if(font.IsItalic() && !(FTFace(font)->style_flags & FT_STYLE_FLAG_ITALIC)) { // Synthetic italic
|
||||
cairo_matrix_t shear[1];
|
||||
cairo_matrix_init_identity(shear);
|
||||
shear->xy = -0.165;
|
||||
cairo_matrix_multiply(font_matrix, shear, font_matrix);
|
||||
}
|
||||
|
||||
cairo_font_options_t *opt = cairo_font_options_create();
|
||||
scaled_font = cairo_scaled_font_create(font_face, font_matrix, ctm, opt);
|
||||
|
|
|
|||
|
|
@ -426,15 +426,22 @@ bool Replace(Font fnt, int chr, Font& rfnt)
|
|||
f.Face(fi);
|
||||
if(IsNormal_nc(f, chr)) {
|
||||
int a = fnt.GetAscent();
|
||||
int d = fnt.GetDescent();
|
||||
static WString apple_kbd = "⌘⌃⇧⌥"; // do not make these smaller it looks ugly...
|
||||
if(f.GetAscent() > a && apple_kbd.Find(chr) < 0) {
|
||||
LLOG("Original font: " << fnt << " " << fnt.GetAscent() << " " << f.GetDescent() <<
|
||||
", replacement " << f << " " << f.GetAscent() << " " << f.GetDescent());
|
||||
if((f.GetAscent() > a || f.GetDescent() > d) && apple_kbd.Find(chr) < 0) {
|
||||
static sFontMetricsReplacement cache[256];
|
||||
int q = CombineHash(fnt, f) & 255;
|
||||
if(cache[q].src != fnt || cache[q].dst != f) {
|
||||
cache[q].src = fnt;
|
||||
cache[q].dst = f;
|
||||
while(f.GetAscent() > a && f.GetHeight() > 1) {
|
||||
f.Height(max(1, f.GetHeight() - max(1, f.GetHeight() / 20)));
|
||||
double h = f.GetHeight();
|
||||
f.Height(min(h * a / max(1, f.GetAscent()), h * d / max(1, f.GetDescent())) + 1);
|
||||
while((f.GetAscent() > a || f.GetDescent() > d) && f.GetHeight() > 1) {
|
||||
f.Height(max(1, f.GetHeight() - 1/*max(1, f.GetHeight() / 20)*/));
|
||||
LLOG("Original font: " << fnt << " " << fnt.GetAscent() << " " << f.GetDescent() <<
|
||||
", downsized " << f << " " << f.GetAscent() << " " << f.GetDescent());
|
||||
}
|
||||
cache[q].mdst = f;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,9 +155,9 @@ CommonFontInfo GetFontInfoSys(Font font)
|
|||
else
|
||||
*fi.path = 0;
|
||||
|
||||
if(font.GetFaceInfo() & Font::COLORIMG) {
|
||||
if(font.GetFaceInfo() & Font::COLORIMG) { // Experimental estimate for cairo results
|
||||
fi.colorimg_cy = fi.ascent + fi.descent;
|
||||
int h = font.GetHeight();
|
||||
int h = 4 * font.GetHeight() / 3;
|
||||
fi.ascent = h * fi.ascent / fi.colorimg_cy;
|
||||
fi.descent = h - fi.ascent;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ struct Xform2D {
|
|||
static Xform2D Scale(double scale);
|
||||
static Xform2D Rotation(double fi);
|
||||
static Xform2D Sheer(double fi);
|
||||
static Xform2D SheerX(double fi);
|
||||
static Xform2D Map(Pointf s1, Pointf s2, Pointf s3); // maps 0,0 -> s3, 1,0 -> s1, 0,1 -> s2
|
||||
static Xform2D Map(Pointf s1, Pointf s2, Pointf s3, Pointf t1, Pointf t2, Pointf t3);
|
||||
|
||||
|
|
|
|||
|
|
@ -90,11 +90,17 @@ Xform2D Xform2D::Rotation(double fi)
|
|||
Xform2D Xform2D::Sheer(double fi)
|
||||
{
|
||||
Xform2D m;
|
||||
m.x.x = m.y.y = 1;
|
||||
m.x.y = atan(fi);
|
||||
return m;
|
||||
}
|
||||
|
||||
Xform2D Xform2D::SheerX(double fi)
|
||||
{
|
||||
Xform2D m;
|
||||
m.y.x = atan(fi);
|
||||
return m;
|
||||
}
|
||||
|
||||
Xform2D Xform2D::Identity()
|
||||
{
|
||||
Xform2D m;
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ PdfDraw::OutlineInfo PdfDraw::GetOutlineInfo(Font fnt)
|
|||
of.sitalic = of.standard_ttf = false;
|
||||
|
||||
TTFReader ttf;
|
||||
if(ttf.Open(fnt, false, true)) {
|
||||
if((fnt.GetFaceInfo() & Font::COLORIMG) == 0 && ttf.Open(fnt, false, true)) {
|
||||
of.standard_ttf = true;
|
||||
of.sitalic = fnt.IsItalic() && (ttf.head.macStyle & 2) == 0;
|
||||
of.sbold = fnt.IsBold() && (ttf.head.macStyle & 1) == 0;
|
||||
|
|
@ -310,70 +310,134 @@ PdfDraw::OutlineInfo PdfDraw::GetOutlineInfo(Font fnt)
|
|||
|
||||
enum { FONTHEIGHT_TTF = -9999 };
|
||||
|
||||
Image RenderGlyph(int cx, int x, Font font, int chr, int py, int pcy, Color fg, Color bg);
|
||||
|
||||
PdfDraw::CGlyph PdfDraw::ColorGlyph(Font fnt, int chr)
|
||||
{
|
||||
auto key = MakeTuple(fnt, chr);
|
||||
int q = color_glyph.Find(key);
|
||||
if(q >= 0)
|
||||
return color_glyph[q];
|
||||
|
||||
CGlyph cg;
|
||||
cg.sz = { fnt[chr], fnt.GetCy() };
|
||||
cg.x = 0;
|
||||
int l = fnt.GetLeftSpace(chr);
|
||||
if(l < 0) {
|
||||
cg.x = -l;
|
||||
cg.sz.cx -= l;
|
||||
}
|
||||
int r = fnt.GetRightSpace(chr);
|
||||
if(r < 0)
|
||||
cg.sz.cx -= r;
|
||||
|
||||
Image m[2];
|
||||
for(int i = 0; i < 2; i++)
|
||||
m[i] = RenderGlyph(cg.sz.cx, cg.x, fnt, chr, 0, cg.sz.cy, Blue(), i ? Black() : White());
|
||||
Image cm = RecreateAlpha(m[0], m[1]);
|
||||
cg.image = PdfImage(cm, cm.GetSize());
|
||||
color_glyph.Add(key, cg);
|
||||
return cg;
|
||||
}
|
||||
|
||||
void PdfDraw::DrawTextOp(int x, int y, int angle, const wchar *s, Font fnt,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
LLOG("DrawTextOp " << x << ", " << y << "angle: " << angle << ", text: " << s << ", font " << fnt);
|
||||
LLOG("DrawTextOp " << x << ", " << y << " angle: " << angle << ", text: " << s << ", font " << fnt);
|
||||
if(!n) return;
|
||||
int h = fnt.GetHeight();
|
||||
if(h == 0)
|
||||
fnt.Height(100);
|
||||
if(h < 0)
|
||||
fnt.Height(-h);
|
||||
Font ff = fnt;
|
||||
int fh = fnt.GetHeight();
|
||||
OutlineInfo of = GetOutlineInfo(fnt);
|
||||
if(of.standard_ttf)
|
||||
fnt.Height(FONTHEIGHT_TTF);
|
||||
String txt;
|
||||
PutrgColor(ink);
|
||||
PutRGColor(ink);
|
||||
double sina = 0, cosa = 1;
|
||||
if(angle)
|
||||
Draw::SinCos(angle, sina, cosa);
|
||||
int nbld = 0;
|
||||
int sbld = 1;
|
||||
if(of.sbold) {
|
||||
nbld = abs(ff.GetHeight()) / 30;
|
||||
sbld = min(5, nbld);
|
||||
}
|
||||
int posx = 0;
|
||||
for(int q = 0; q <= nbld; q += sbld) {
|
||||
page << "BT ";
|
||||
posx = q;
|
||||
M22 m;
|
||||
if(of.sitalic)
|
||||
m.c = 0.165;
|
||||
if(angle)
|
||||
m.Mul(cosa, sina, -sina, cosa);
|
||||
bool straight = true;
|
||||
OutlineInfo of = GetOutlineInfo(fnt);
|
||||
Xform2D m;
|
||||
if(of.sitalic) {
|
||||
m = m.SheerX(0.165);
|
||||
straight = false;
|
||||
}
|
||||
if(angle) {
|
||||
straight = false;
|
||||
m = Xform2D::Rotation(-angle * M_PI / 1800.0) * m;
|
||||
}
|
||||
|
||||
auto Fmt = [](double x) { return FormatF(x, 5); };
|
||||
|
||||
if(fnt.GetFaceInfo() & Font::COLORIMG) {
|
||||
int fi = -1;
|
||||
bool straight = (fabs(m.a - 1) <= 1e-8 && fabs(m.b) <= 1e-8 && fabs(m.c) <= 1e-8 && fabs(m.d - 1) <= 1e-8);
|
||||
Pointf prev(0, 0);
|
||||
for(int i = 0; i < n; i++) {
|
||||
Pointf next(Pt(x + posx * cosa + fround(ff.GetAscent() * sina)),
|
||||
Pt(pgsz.cy - (y - posx * sina) - fround(ff.GetAscent() * cosa)));
|
||||
CharPos fp = GetCharPos(fnt, s[i]);
|
||||
if(fi != fp.fi) {
|
||||
fi = fp.fi;
|
||||
PutFontHeight(fi, fh);
|
||||
}
|
||||
CGlyph cg = ColorGlyph(fnt, s[i]);
|
||||
page << "q ";
|
||||
if(straight)
|
||||
page << (next.x - prev.x) << ' ' << (next.y - prev.y) << " Td";
|
||||
else
|
||||
page << m.a << ' ' << m.b << ' ' << m.c << ' ' << m.d << ' ' << next.x << ' ' << next.y << " Tm";
|
||||
page << " <" << FormatIntHex(fp.ci, 2);
|
||||
page << "> Tj\n";
|
||||
posx += dx ? dx[i] : ff[s[i]];
|
||||
prev = next;
|
||||
}
|
||||
page << "ET\n";
|
||||
page << Ptf(cg.sz.cx) << " 0 0 " << Ptf(cg.sz.cy) << ' '
|
||||
<< Ptf(x + posx + cg.x) << ' ' << Ptf(pgsz.cy - y - cg.sz.cy);
|
||||
else {
|
||||
Xform2D mm = m * Xform2D::Scale(Pt(cg.sz.cx), Pt(cg.sz.cy));
|
||||
page << Fmt(mm.x.x) << ' ' << Fmt(mm.x.y) << ' ' << Fmt(mm.y.x) << ' ' << Fmt(mm.y.y)
|
||||
<< ' ' << Ptf(x + posx * cosa + cg.sz.cx * sina)
|
||||
<< ' ' << Ptf(pgsz.cy - (y - posx * sina) - cg.sz.cy * cosa);
|
||||
}
|
||||
page << " cm /Image" << cg.image + 1 << " Do Q\n";
|
||||
|
||||
if(q == 0 && url.GetCount()) { // For now, only 'zero angle' text can have links
|
||||
posx += dx ? dx[i] : fnt[s[i]];
|
||||
}
|
||||
if(url.GetCount()) { // For now, only 'zero angle' text can have links
|
||||
UrlInfo& u = page_url.At(offset.GetCount()).Add();
|
||||
u.rect = RectC(x, y, posx, ff.GetCy()).Offseted(current_offset);
|
||||
u.rect = RectC(x, y, posx, fnt.GetCy()).Offseted(current_offset);
|
||||
u.url = url;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int h = fnt.GetHeight();
|
||||
if(h == 0)
|
||||
fnt.Height(100);
|
||||
if(h < 0)
|
||||
fnt.Height(-h);
|
||||
Font ff = fnt;
|
||||
int fh = fnt.GetHeight();
|
||||
if(of.standard_ttf)
|
||||
fnt.Height(FONTHEIGHT_TTF);
|
||||
String txt;
|
||||
PutrgColor(ink);
|
||||
PutRGColor(ink);
|
||||
int nbld = 0;
|
||||
int sbld = 1;
|
||||
if(of.sbold) {
|
||||
nbld = abs(ff.GetHeight()) / 30;
|
||||
sbld = clamp(nbld, 1, 5);
|
||||
}
|
||||
for(int q = 0; q <= nbld; q += sbld) {
|
||||
page << "BT ";
|
||||
posx = q;
|
||||
int fi = -1;
|
||||
Pointf prev(0, 0);
|
||||
for(int i = 0; i < n; i++) {
|
||||
Pointf next(Pt(x + posx * cosa + ff.GetAscent() * sina),
|
||||
Pt(pgsz.cy - (y - posx * sina) - ff.GetAscent() * cosa));
|
||||
CharPos fp = GetCharPos(fnt, s[i]);
|
||||
if(fi != fp.fi) {
|
||||
fi = fp.fi;
|
||||
PutFontHeight(fi, fh);
|
||||
}
|
||||
if(straight)
|
||||
page << Fmt(next.x - prev.x) << ' ' << Fmt(next.y - prev.y) << " Td";
|
||||
else
|
||||
page << Fmt(m.x.x) << ' ' << Fmt(m.x.y) << ' ' << Fmt(m.y.x) << ' ' << Fmt(m.y.y)
|
||||
<< ' ' << Fmt(next.x) << ' ' << Fmt(next.y) << " Tm";
|
||||
page << " <" << FormatIntHex(fp.ci, 2);
|
||||
page << "> Tj\n";
|
||||
posx += dx ? dx[i] : ff[s[i]];
|
||||
prev = next;
|
||||
if(q == 0 && url.GetCount()) { // For now, only 'zero angle' text can have links
|
||||
UrlInfo& u = page_url.At(offset.GetCount()).Add();
|
||||
u.rect = RectC(x, y, posx, ff.GetCy()).Offseted(current_offset);
|
||||
u.url = url;
|
||||
}
|
||||
}
|
||||
page << "ET\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PdfDraw::Escape(const String& data)
|
||||
|
|
@ -384,8 +448,6 @@ void PdfDraw::Escape(const String& data)
|
|||
this->data = data.Mid(5);
|
||||
}
|
||||
|
||||
Image RenderGlyph(int cx, int x, Font font, int chr, int py, int pcy, Color fg, Color bg);
|
||||
|
||||
PdfDraw::RGlyph PdfDraw::RasterGlyph(Font fnt, int chr)
|
||||
{
|
||||
RGlyph rg;
|
||||
|
|
@ -842,8 +904,7 @@ String PdfDraw::Finish(const PdfSignatureInfo *sign)
|
|||
int fa = fnt.GetCy() - fnt.GetInternal();
|
||||
for(int i = 0; i < cs.GetCount(); i++)
|
||||
out << ' ' << 1000 * fnt[cs[i]] / fa;
|
||||
out <<
|
||||
"]\n";
|
||||
out << "]\n";
|
||||
|
||||
out << "/Resources " << resources << " 0 R\n"
|
||||
<< "/FirstChar 0 /LastChar " << cs.GetCount() - 1 <<" /ToUnicode "
|
||||
|
|
@ -853,7 +914,7 @@ String PdfDraw::Finish(const PdfSignatureInfo *sign)
|
|||
}
|
||||
else {
|
||||
TTFReader ttf;
|
||||
if(!ttf.Open(pdffont.GetKey(i)))
|
||||
if(!ttf.Open(fnt))
|
||||
return Null;
|
||||
|
||||
String name = FormatIntAlpha(i + 1, true);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <Draw/Draw.h>
|
||||
#include <plugin/z/z.h>
|
||||
|
||||
#include <Painter/Painter.h>
|
||||
|
||||
namespace Upp {
|
||||
|
||||
|
|
@ -314,7 +314,8 @@ private:
|
|||
Vector<Point> offset_stack;
|
||||
Point current_offset;
|
||||
|
||||
inline double Pt(double dot) { return 0.12 * dot; }
|
||||
double Pt(double dot) { return 0.12 * dot; }
|
||||
String Ptf(double dot) { return FormatF(Pt(dot), 5); }
|
||||
|
||||
int Pos() { return offset.GetCount() + 1; }
|
||||
int BeginObj();
|
||||
|
|
@ -337,22 +338,6 @@ private:
|
|||
|
||||
OutlineInfo GetOutlineInfo(Font fnt);
|
||||
|
||||
struct M22 {
|
||||
double a, b, c, d;
|
||||
|
||||
void Mul(double a1, double b1, double c1, double d1) {
|
||||
M22 t;
|
||||
t.a = a * a1 + b * c1;
|
||||
t.b = a * b1 + b * d1;
|
||||
t.c = c * a1 + d * c1;
|
||||
t.d = c * b1 + d * d1;
|
||||
*this = t;
|
||||
}
|
||||
|
||||
M22(double a, double b, double c, double d) : a(a), b(b), c(c), d(d) {}
|
||||
M22() : a(1), b(0), c(0), d(1) {}
|
||||
};
|
||||
|
||||
void Init(int pagecx, int pagecy, int margin, bool pdfa);
|
||||
|
||||
struct RGlyph : Moveable<RGlyph> {
|
||||
|
|
@ -361,8 +346,17 @@ private:
|
|||
int x;
|
||||
int color_image = -1;
|
||||
};
|
||||
|
||||
struct CGlyph : Moveable<CGlyph> {
|
||||
Size sz;
|
||||
int x;
|
||||
int image;
|
||||
};
|
||||
|
||||
VectorMap<Tuple<Font, int>, CGlyph> color_glyph;
|
||||
|
||||
int PdfImage(const Image& img, const Rect& src);
|
||||
CGlyph ColorGlyph(Font fnt, int chr);
|
||||
RGlyph RasterGlyph(Font fnt, int chr);
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
description "PDF output as Draw derived class\377128,0,255";
|
||||
|
||||
uses
|
||||
Draw;
|
||||
Draw,
|
||||
Painter;
|
||||
|
||||
file
|
||||
PdfDraw.h options(BUILDER_OPTION) PCH,
|
||||
|
|
|
|||
|
|
@ -3,28 +3,48 @@
|
|||
|
||||
using namespace Upp;
|
||||
|
||||
CONSOLE_APP_MAIN
|
||||
void DoPaint(Draw& w, int hg, int x1, int x2, int n = INT_MAX)
|
||||
{
|
||||
PdfDraw pdf;
|
||||
int cy = 0;
|
||||
pdf.DrawImage(5000, 20, 100, 100, CtrlImg::exclamation());
|
||||
// for(int face = Font::SERIF; face < Font::GetFaceCount(); face++)
|
||||
int face = 19;
|
||||
w.DrawImage(x2, 20, 100, 100, CtrlImg::exclamation());
|
||||
for(int face = Font::SERIF; face < min(n, Font::GetFaceCount()); face++)
|
||||
{
|
||||
Font fnt(face, 100);
|
||||
Font fnt(face, hg);
|
||||
Cout() << fnt << "\n";
|
||||
LOG(face << ' ' << fnt << ", TTF: " << fnt.IsTrueType());
|
||||
String txt = AsString(fnt) + " 訓民正音 (훈민정음) 😜 🤪 ";
|
||||
pdf.DrawText(0, cy, txt, fnt, Black);
|
||||
pdf.DrawText(3000, cy, AsString(fnt) << ' ' << face, StdFont(100), Black);
|
||||
w.DrawRect(0, cy, GetTextSize(txt, fnt).cx, fnt.GetAscent(), Blend(White(), LtBlue()));
|
||||
w.DrawRect(0, cy + fnt.GetAscent(), GetTextSize(txt, fnt).cx, fnt.GetDescent(), Blend(White(), LtRed()));
|
||||
w.DrawText(0, cy, txt, fnt, Black);
|
||||
w.DrawText(x1, cy, AsString(fnt) << ' ' << face, StdFont(hg), Black);
|
||||
cy += fnt.GetLineHeight();
|
||||
if(cy > 6000) {
|
||||
pdf.EndPage();
|
||||
pdf.StartPage();
|
||||
auto *pdf = dynamic_cast<PdfDraw *>(&w);
|
||||
if(pdf) {
|
||||
pdf->EndPage();
|
||||
pdf->StartPage();
|
||||
}
|
||||
cy = 0;
|
||||
}
|
||||
}
|
||||
String p = GetHomeDirFile("pdf.pdf");
|
||||
SaveFile(p, pdf.Finish());
|
||||
LaunchWebBrowser(p);
|
||||
}
|
||||
|
||||
struct MyApp : TopWindow {
|
||||
void Paint(Draw& w) override {
|
||||
Size sz = GetSize();
|
||||
w.DrawRect(sz, White());
|
||||
DoPaint(w, 24, sz.cx / 2, sz.cx - 100, 10);
|
||||
}
|
||||
};
|
||||
|
||||
GUI_APP_MAIN
|
||||
{
|
||||
PdfDraw pdf;
|
||||
DoPaint(pdf, 100, 3000, 5000);
|
||||
String p = GetHomeDirFile("pdf.pdf");
|
||||
String s = pdf.Finish();
|
||||
DDUMP(s.GetCount());
|
||||
SaveFile(p, s);
|
||||
LaunchWebBrowser(p);
|
||||
MyApp().Run();
|
||||
}
|
||||
|
|
|
|||
35
upptst/PdfTextAngle/PdfText.cpp
Normal file
35
upptst/PdfTextAngle/PdfText.cpp
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#include <CtrlLib/CtrlLib.h>
|
||||
#include <PdfDraw/PdfDraw.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
void DoPaint(Draw& w, int hg, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
int cy = 0;
|
||||
w.DrawImage(x2, 20, 100, 100, CtrlImg::exclamation());
|
||||
Font fnt = Serif(hg);
|
||||
for(int i = 0; i < 3600; i += 450) {
|
||||
String txt = "Text with emoji: 訓음 😜🤪 " + AsString(i);
|
||||
w.DrawText(x1, y1, i, txt, fnt, Black);
|
||||
w.DrawText(x2, y2, i, txt, fnt().Italic(), Black);
|
||||
}
|
||||
}
|
||||
|
||||
struct MyApp : TopWindow {
|
||||
void Paint(Draw& w) override {
|
||||
Size sz = GetSize();
|
||||
w.DrawRect(sz, White());
|
||||
DoPaint(w, 24, sz.cx / 4, sz.cy / 2, sz.cx - sz.cx / 4, sz.cy / 2);
|
||||
}
|
||||
};
|
||||
|
||||
GUI_APP_MAIN
|
||||
{
|
||||
PdfDraw pdf;
|
||||
DoPaint(pdf, 100, 2000, 2000, 2200, 5000);
|
||||
String p = GetHomeDirFile("pdf.pdf");
|
||||
String s = pdf.Finish();
|
||||
SaveFile(p, s);
|
||||
LaunchWebBrowser(p);
|
||||
MyApp().Run();
|
||||
}
|
||||
11
upptst/PdfTextAngle/PdfTextAngle.upp
Normal file
11
upptst/PdfTextAngle/PdfTextAngle.upp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
uses
|
||||
Core,
|
||||
PdfDraw,
|
||||
CtrlLib;
|
||||
|
||||
file
|
||||
PdfText.cpp;
|
||||
|
||||
mainconfig
|
||||
"" = "GUI";
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue