mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
PdfDraw: Improvements
This commit is contained in:
parent
4f32c54c69
commit
f2ce3bfc75
9 changed files with 63 additions and 102 deletions
|
|
@ -5,15 +5,15 @@ namespace Upp {
|
|||
#define TFILE <CtrlCore/CtrlCore.t>
|
||||
#include <Core/t.h>
|
||||
|
||||
static Image sRenderGlyph(int cx, int x, Font font, int chr, int py, int pcy)
|
||||
static Image sRenderGlyph(int cx, int x, Font font, int chr, int py, int pcy, Color fg, Color bg)
|
||||
{
|
||||
ImageDraw iw(cx, pcy);
|
||||
iw.DrawRect(0, 0, cx, pcy, White);
|
||||
iw.DrawText(x, -py, WString(chr, 1), font, Black);
|
||||
iw.DrawRect(0, 0, cx, pcy, bg);
|
||||
iw.DrawText(x, -py, WString(chr, 1), font, fg);
|
||||
return iw;
|
||||
}
|
||||
|
||||
void SetRenderGlyph(Image (*f)(int cx, int x, Font font, int chr, int py, int pcy));
|
||||
void SetRenderGlyph(Image (*f)(int cx, int x, Font font, int chr, int py, int pcy, Color fg, Color bg));
|
||||
|
||||
INITIALIZER(CtrlCore) {
|
||||
SetRenderGlyph(sRenderGlyph);
|
||||
|
|
|
|||
|
|
@ -103,11 +103,11 @@ public:
|
|||
SANSSERIF,
|
||||
MONOSPACE,
|
||||
#ifdef PLATFORM_WIN32
|
||||
SYMBOL,
|
||||
WINGDINGS,
|
||||
TAHOMA,
|
||||
SYMBOL, // deprecated
|
||||
WINGDINGS, // deprecated
|
||||
TAHOMA, // deprecated
|
||||
#endif
|
||||
OTHER,
|
||||
OTHER, // deprecated
|
||||
|
||||
// Backward compatibility:
|
||||
ROMAN = SERIF,
|
||||
|
|
@ -978,8 +978,13 @@ IsJPGFnType GetIsJPGFn();
|
|||
#include "DDARasterizer.h"
|
||||
#include "SDraw.h"
|
||||
|
||||
bool ReadCmap(const char *ptr, int count, Event<int, int, int> range, bool glyphs);
|
||||
bool ReadCmap(Font font, Event<int, int, int> range, bool glyphs = false);
|
||||
enum {
|
||||
CMAP_GLYPHS = 1,
|
||||
CMAP_ALLOW_SYMBOL = 2,
|
||||
};
|
||||
|
||||
bool ReadCmap(const char *ptr, int count, Event<int, int, int> range, dword flags = 0);
|
||||
bool ReadCmap(Font font, Event<int, int, int> range, dword flags = 0);
|
||||
bool GetPanoseNumber(Font font, byte *panose);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -611,22 +611,22 @@ IsJPGFnType GetIsJPGFn()
|
|||
return sIsJPG;
|
||||
}
|
||||
|
||||
Image (*render_glyph)(int cx, int x, Font font, int chr, int py, int pcy);
|
||||
Image (*render_glyph)(int cx, int x, Font font, int chr, int py, int pcy, Color fg, Color bg);
|
||||
|
||||
Image RenderGlyph(int cx, int x, Font font, int chr, int py, int pcy)
|
||||
Image RenderGlyph(int cx, int x, Font font, int chr, int py, int pcy, Color fg, Color bg)
|
||||
{
|
||||
if(render_glyph)
|
||||
return (*render_glyph)(cx, x, font, chr, py, pcy);
|
||||
return (*render_glyph)(cx, x, font, chr, py, pcy, fg, bg);
|
||||
if(ImageAnyDraw::IsAvailable()) {
|
||||
ImageAnyDraw iw(cx, pcy);
|
||||
iw.DrawRect(0, 0, cx, pcy, White);
|
||||
iw.DrawText(x, -py, WString(chr, 1), font, Black);
|
||||
iw.DrawRect(0, 0, cx, pcy, bg);
|
||||
iw.DrawText(x, -py, WString(chr, 1), font, fg);
|
||||
return iw;
|
||||
}
|
||||
return Null;
|
||||
}
|
||||
|
||||
void SetRenderGlyph(Image (*f)(int cx, int x, Font font, int chr, int py, int pcy))
|
||||
void SetRenderGlyph(Image (*f)(int cx, int x, Font font, int chr, int py, int pcy, Color fg, Color bg))
|
||||
{
|
||||
render_glyph = f;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -234,11 +234,12 @@ struct sRFace {
|
|||
#include "Fonts.i"
|
||||
};
|
||||
|
||||
bool ReadCmap(const char *ptr, int count, Event<int, int, int> range, bool glyphs)
|
||||
bool ReadCmap(const char *ptr, int count, Event<int, int, int> range, dword flags)
|
||||
{
|
||||
auto Get8 = [&](int i) { return i >= 0 && i + 1 <= count ? (byte)ptr[i] : 0; };
|
||||
auto Get16 = [&](int i) { return i >= 0 && i + 2 <= count ? Peek16be(ptr + i) : 0; };
|
||||
auto Get32 = [&](int i) { return i >= 0 && i + 4 <= count ? Peek32be(ptr + i) : 0; };
|
||||
for(int pass = 0; pass < 2; pass++) {
|
||||
for(int pass = 0; pass < (flags & CMAP_ALLOW_SYMBOL ? 3 : 2); pass++) {
|
||||
int p = 0;
|
||||
p += 2;
|
||||
int n = Get16(p);
|
||||
|
|
@ -263,7 +264,6 @@ bool ReadCmap(const char *ptr, int count, Event<int, int, int> range, bool glyph
|
|||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if(((pid == 3 && psid == 1) || (pid == 0 && psid == 3) && format == 4) && pass == 1) {
|
||||
int p = offset;
|
||||
int n = Get16(p + 6) >> 1;
|
||||
|
|
@ -276,7 +276,7 @@ bool ReadCmap(const char *ptr, int count, Event<int, int, int> range, bool glyph
|
|||
int end = Get16(seg_end + 2 * i);
|
||||
int delta = Get16(idDelta + 2 * i);
|
||||
int ro = Get16(idRangeOffset + 2 * i);
|
||||
if(glyphs) {
|
||||
if(flags & CMAP_GLYPHS) {
|
||||
if (ro && delta == 0) {
|
||||
LLOG("RangeOffset start: " << start << ", end: " << end << ", delta: " << (int16)delta);
|
||||
int q = idRangeOffset + 2 * i + ro;
|
||||
|
|
@ -295,15 +295,21 @@ bool ReadCmap(const char *ptr, int count, Event<int, int, int> range, bool glyph
|
|||
}
|
||||
return true;
|
||||
}
|
||||
if(pid == 1 && psid == 0 && Get16(offset) == 0 && pass == 2) {
|
||||
LLOG("Reading symbol cmap");
|
||||
for(int i = 0; i < 256; i++)
|
||||
range(i, i, Get8(offset + 6 + i));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReadCmap(Font font, Event<int, int, int> range, bool glyphs)
|
||||
bool ReadCmap(Font font, Event<int, int, int> range, dword flags)
|
||||
{
|
||||
String h = font.GetData("cmap");
|
||||
return ReadCmap(h, h.GetCount(), range, glyphs);
|
||||
return ReadCmap(h, h.GetCount(), range, flags);
|
||||
}
|
||||
|
||||
bool GetPanoseNumber(Font font, byte *panose)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "PdfDraw.h"
|
||||
#include "CtrlLib/CtrlLib.h"
|
||||
|
||||
namespace Upp {
|
||||
|
||||
|
|
@ -294,11 +295,11 @@ PdfDraw::OutlineInfo PdfDraw::GetOutlineInfo(Font fnt)
|
|||
if(q >= 0)
|
||||
return outline_info[q];
|
||||
OutlineInfo of;
|
||||
of.sitalic = of.ttf = false;
|
||||
of.sitalic = of.standard_ttf = false;
|
||||
|
||||
TTFReader ttf;
|
||||
if(ttf.Open(fnt, false, true)) {
|
||||
of.ttf = true;
|
||||
of.standard_ttf = true;
|
||||
of.sitalic = fnt.IsItalic() && (ttf.head.macStyle & 2) == 0;
|
||||
of.sbold = fnt.IsBold() && (ttf.head.macStyle & 1) == 0;
|
||||
LLOG(fnt << ", sbold: " << of.sbold << ", sitalic: " << of.sitalic);
|
||||
|
|
@ -324,7 +325,7 @@ void PdfDraw::DrawTextOp(int x, int y, int angle, const wchar *s, Font fnt,
|
|||
Font ff = fnt;
|
||||
int fh = fnt.GetHeight();
|
||||
OutlineInfo of = GetOutlineInfo(fnt);
|
||||
if(of.ttf)
|
||||
if(of.standard_ttf)
|
||||
fnt.Height(FONTHEIGHT_TTF);
|
||||
String txt;
|
||||
PutrgColor(ink);
|
||||
|
|
@ -385,7 +386,7 @@ 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);
|
||||
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)
|
||||
{
|
||||
|
|
@ -409,7 +410,7 @@ PdfDraw::RGlyph PdfDraw::RasterGlyph(Font fnt, int chr)
|
|||
int y = 0;
|
||||
while(y < rg.sz.cy) {
|
||||
int ccy = min(16, rg.sz.cy - y);
|
||||
Image m = RenderGlyph(rg.sz.cx, rg.x, fnt, chr, y, ccy);
|
||||
Image m = RenderGlyph(rg.sz.cx, rg.x, fnt, chr, y, ccy, Black(), White());
|
||||
for(int i = 0; i < m.GetHeight(); i++) {
|
||||
fmt.Write(ob, m[i], rg.sz.cx, NULL);
|
||||
rg.data.Cat((const char *)~ob, linebytes);
|
||||
|
|
@ -865,8 +866,8 @@ String PdfDraw::Finish(const PdfSignatureInfo *sign)
|
|||
<< " "
|
||||
<< -1000 * fi.GetDescent() / fa
|
||||
<< " cm BI /W " << rg.sz.cx << " /H " << rg.sz.cy
|
||||
<< " /BPC 1 /IM true /D [0 1] ID\n"
|
||||
<< rg.data
|
||||
<< " /BPC 1 /IM true /D [0 1]"
|
||||
<< " ID\n" << rg.data
|
||||
<< "\nEI Q"
|
||||
;
|
||||
PutStream(proc);
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ public:
|
|||
String ps_name;
|
||||
|
||||
int GetGlyph(wchar chr) { return glyph_map.Get(chr, 0); }
|
||||
word GetAdvanceWidth(wchar chr) { return glyphinfo[GetGlyph(chr)].advanceWidth; }
|
||||
word GetAdvanceWidth(wchar chr) { int i = glyph_map.Get(chr, 0); return i < glyphinfo.GetCount() ? glyphinfo[GetGlyph(chr)].advanceWidth : 0; }
|
||||
|
||||
String Subset(const Vector<wchar>& chars, int first = 0, bool os2 = false);
|
||||
bool Open(const Font& fnt, bool symbol = false, bool justcheck = false);
|
||||
|
|
@ -278,7 +278,7 @@ private:
|
|||
struct CharPos : Moveable<CharPos> { word fi, ci; };
|
||||
|
||||
struct OutlineInfo : Moveable<OutlineInfo> {
|
||||
bool ttf;
|
||||
bool standard_ttf;
|
||||
bool sitalic;
|
||||
bool sbold;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -138,9 +138,6 @@ bool TTFReader::Open(const Font& fnt, bool symbol, bool justcheck)
|
|||
LDUMP(post.underlineThickness);
|
||||
LDUMP(post.italicAngle);
|
||||
|
||||
if(justcheck)
|
||||
return true;
|
||||
|
||||
Seek("hhea", is);
|
||||
hhea.Serialize(is);
|
||||
LDUMP(hhea.ascent);
|
||||
|
|
@ -154,7 +151,11 @@ bool TTFReader::Open(const Font& fnt, bool symbol, bool justcheck)
|
|||
|
||||
glyphinfo.SetCount(maxp.numGlyphs);
|
||||
|
||||
if(justcheck)
|
||||
return ReadCmap(fnt, [&](int, int, int) {}, CMAP_ALLOW_SYMBOL);
|
||||
|
||||
const char *s = Seek("hmtx");
|
||||
if(!s) Error();
|
||||
int aw = 0;
|
||||
for(i = 0; i < hhea.numOfLongHorMetrics; i++) {
|
||||
aw = glyphinfo[i].advanceWidth = (uint16)Read16(s);
|
||||
|
|
@ -166,6 +167,7 @@ bool TTFReader::Open(const Font& fnt, bool symbol, bool justcheck)
|
|||
}
|
||||
|
||||
s = Seek("loca");
|
||||
if(!s) Error();
|
||||
for(i = 0; i < maxp.numGlyphs; i++)
|
||||
if(head.indexToLocFormat) {
|
||||
glyphinfo[i].offset = Peek32(s, i);
|
||||
|
|
@ -180,67 +182,13 @@ bool TTFReader::Open(const Font& fnt, bool symbol, bool justcheck)
|
|||
LLOG(i << " advance: " << glyphinfo[i].advanceWidth << ", left: " << glyphinfo[i].leftSideBearing
|
||||
<< ", offset: " << glyphinfo[i].offset << ", size: " << glyphinfo[i].size);
|
||||
|
||||
int len;
|
||||
const char *cmap = Seek("cmap", len);
|
||||
ReadCmap(cmap, len, [&](int start, int end, int glyph) {
|
||||
ReadCmap(fnt, [&](int start, int end, int glyph) {
|
||||
for(int ch = start; ch <= end; ch++)
|
||||
SetGlyph(ch, glyph++);
|
||||
}, true);
|
||||
|
||||
#if 0
|
||||
s = Seek("cmap");
|
||||
const char *p = s;
|
||||
p += 2;
|
||||
n = Read16(p);
|
||||
while(n--) {
|
||||
int pid = Read16(p);
|
||||
int psid = Read16(p);
|
||||
int offset = Read32(p);
|
||||
LLOG("cmap pid: " << pid << " psid: " << psid << " format: " << Peek16(s + offset));
|
||||
//Test with Symbol font !!!; improve - Unicode first, 256 bytes later..., symbol...
|
||||
if(symbol) {
|
||||
if(pid == 1 && psid == 0 && Peek16(s + offset) == 0) {
|
||||
LLOG("Reading symbol table");
|
||||
p = s + offset + 6;
|
||||
for(int i = 0; i < 256; i++)
|
||||
SetGlyph(i, (byte)p[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(pid == 3 && psid == 1) {
|
||||
p = s + offset;
|
||||
n = Peek16(p + 6) >> 1;
|
||||
LLOG("Found UNICODE encoding, offset " << offset << ", segments " << n);
|
||||
const char *seg_end = p + 14;
|
||||
const char *seg_start = seg_end + 2 * n + 2;
|
||||
const char *idDelta = seg_start + 2 * n;
|
||||
const char *idRangeOffset = idDelta + 2 * n;
|
||||
for(int i = 0; i < n; i++) {
|
||||
int start = Peek16(seg_start, i);
|
||||
int end = Peek16(seg_end, i);
|
||||
int delta = Peek16(idDelta, i);
|
||||
int ro = Peek16(idRangeOffset, i);
|
||||
if (ro && delta == 0) {
|
||||
LLOG("RangeOffset start: " << start << ", end: " << end << ", delta: " << (int16)delta);
|
||||
LLOG("ro " << ro);
|
||||
const char *q = idRangeOffset + 2 * i + ro;
|
||||
for(int c = start; c <= end; c++) {
|
||||
SetGlyph(c, (word)Read16(q));
|
||||
}
|
||||
}
|
||||
else {
|
||||
LLOG("start: " << start << ", end: " << end << ", delta: " << (int16)delta);
|
||||
for(int c = start; c <= end; c++)
|
||||
SetGlyph(c, c + delta);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}, CMAP_GLYPHS|CMAP_ALLOW_SYMBOL);
|
||||
|
||||
const char *strings = Seek("name");
|
||||
if(!strings) Error();
|
||||
s = strings + 2;
|
||||
int count = Read16(s);
|
||||
strings += (word)Read16(s);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include <CtrlLib/CtrlLib.h>
|
||||
#include <PdfDraw/PdfDraw.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
|
@ -10,15 +11,14 @@ CONSOLE_APP_MAIN
|
|||
Font fnt(face, 100);
|
||||
Cout() << fnt << "\n";
|
||||
LOG(face << ' ' << fnt << ", TTF: " << fnt.IsTrueType());
|
||||
if(1 || fnt.IsTrueType()) {
|
||||
pdf.DrawText(0, cy, AsString(fnt), fnt, Black);
|
||||
pdf.DrawText(200, cy, AsString(fnt), StdFont(100), Black);
|
||||
cy += fnt.GetLineHeight();
|
||||
if(cy > 6000) {
|
||||
pdf.EndPage();
|
||||
pdf.StartPage();
|
||||
cy = 0;
|
||||
}
|
||||
String txt = AsString(fnt) + " 訓民正音 (훈민정음) 😜 🤪 ";
|
||||
pdf.DrawText(0, cy, txt, fnt, Black);
|
||||
pdf.DrawText(3000, cy, AsString(fnt), StdFont(100), Black);
|
||||
cy += fnt.GetLineHeight();
|
||||
if(cy > 6000) {
|
||||
pdf.EndPage();
|
||||
pdf.StartPage();
|
||||
cy = 0;
|
||||
}
|
||||
}
|
||||
String p = GetHomeDirFile("pdf.pdf");
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
uses
|
||||
Core,
|
||||
PdfDraw;
|
||||
PdfDraw,
|
||||
CtrlLib;
|
||||
|
||||
file
|
||||
PdfText.cpp;
|
||||
|
||||
mainconfig
|
||||
"" = "";
|
||||
"" = "GUI";
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue