PdfDraw: Fixed nonBMP glyphs export

This commit is contained in:
Mirek Fidler 2022-01-02 23:14:17 +01:00
parent 815ce70fa2
commit 405c6ff0da
11 changed files with 107 additions and 72 deletions

View file

@ -978,6 +978,10 @@ 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);
bool GetPanoseNumber(Font font, byte *panose);
}
#endif

View file

@ -234,20 +234,20 @@ struct sRFace {
#include "Fonts.i"
};
bool ReadCmap(Font font, Event<int, int, int> range, bool glyphs = false) {
String data = font.GetData("cmap");
auto Get16 = [&](int i) { return i >= 0 && i + 2 <= data.GetCount() ? Peek16be(~data + i) : 0; };
auto Get32 = [&](int i) { return i >= 0 && i + 4 <= data.GetCount() ? Peek32be(~data + i) : 0; };
bool ReadCmap(const char *ptr, int count, Event<int, int, int> range, bool glyphs)
{
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++) {
int p = 0;
p += 2;
int n = Get16(p);
p += 2;
while(n-- && p < data.GetCount()) {
while(n-- && p < count) {
int pid = Get16(p); p += 2;
int psid = Get16(p); p += 2;
int offset = Get32(p); p += 4;
if(offset < 0 || offset > data.GetCount())
if(offset < 0 || offset > count)
return false;
int format = Get16(offset);
LLOG("cmap pid: " << pid << " psid: " << psid << " format: " << format);
@ -264,7 +264,7 @@ bool ReadCmap(Font font, Event<int, int, int> range, bool glyphs = false) {
return true;
}
else
if((pid == 3 && psid == 1) || (pid == 0 && psid == 3) && format == 4 && pass == 1) {
if(((pid == 3 && psid == 1) || (pid == 0 && psid == 3) && format == 4) && pass == 1) {
int p = offset;
int n = Get16(p + 6) >> 1;
int seg_end = p + 14;
@ -300,6 +300,12 @@ bool ReadCmap(Font font, Event<int, int, int> range, bool glyphs = false) {
return false;
}
bool ReadCmap(Font font, Event<int, int, int> range, bool glyphs)
{
String h = font.GetData("cmap");
return ReadCmap(h, h.GetCount(), range, glyphs);
}
bool GetPanoseNumber(Font font, byte *panose)
{
memset(panose, 0, 10);

View file

@ -297,7 +297,7 @@ PdfDraw::OutlineInfo PdfDraw::GetOutlineInfo(Font fnt)
of.sitalic = of.ttf = false;
TTFReader ttf;
if(ttf.Open(fnt.GetData(), false, true)) {
if(ttf.Open(fnt, false, true)) {
of.ttf = true;
of.sitalic = fnt.IsItalic() && (ttf.head.macStyle & 2) == 0;
of.sbold = fnt.IsBold() && (ttf.head.macStyle & 1) == 0;
@ -906,11 +906,8 @@ String PdfDraw::Finish(const PdfSignatureInfo *sign)
EndObj();
}
else {
String fontbuffer;
fontbuffer = pdffont.GetKey(i).GetData();
TTFReader ttf;
if(!ttf.Open(fontbuffer))
if(!ttf.Open(pdffont.GetKey(i)))
return Null;
String name = FormatIntAlpha(i + 1, true);

View file

@ -55,16 +55,16 @@ class TTFReader {
virtual ~TTFStreamOut() {}
};
String font;
Font font;
String current_table;
struct Table : Moveable<Table> {
int offset;
int length;
};
VectorMap<String, Table> table;
word zero[256];
word *cmap[256];
VectorMap<wchar, int> glyph_map;
struct GlyphInfo : Moveable<GlyphInfo> {
int offset;
@ -92,7 +92,6 @@ class TTFReader {
int Read32(const char *&s);
String Read(const char *&s, int n);
void Free();
void Reset();
const char *Seek(const char *tab, int& len);
@ -217,14 +216,13 @@ public:
Post post;
String ps_name;
int GetGlyph(wchar chr) { return cmap[HIBYTE(chr)][LOBYTE(chr)]; }
int GetGlyph(wchar chr) { return glyph_map.Get(chr, 0); }
word GetAdvanceWidth(wchar chr) { return glyphinfo[GetGlyph(chr)].advanceWidth; }
String Subset(const Vector<wchar>& chars, int first = 0, bool os2 = false);
bool Open(const String& fnt, bool symbol = false, bool justcheck = false);
bool Open(const Font& fnt, bool symbol = false, bool justcheck = false);
TTFReader();
~TTFReader();
};
struct PdfSignatureInfo {

View file

@ -7,8 +7,8 @@ file
PdfDraw.h options(BUILDER_OPTION) PCH,
TTFStream.cpp,
TTFStruct.cpp,
TTFReader.cpp,
TTFSubset.cpp,
TTFReader.cpp,
ICCColorSpace.i,
PdfDraw.cpp,
PdfReport.cpp,

View file

@ -7,21 +7,21 @@ namespace Upp {
int TTFReader::Peek8(const char *s)
{
if(s + 1 > font.End())
if(s + 1 > current_table.End())
Error();
return (byte)*s;
}
int TTFReader::Peek16(const char *s)
{
if(s + 2 > font.End())
if(s + 2 > current_table.End())
Error();
return ((byte)s[0] << 8) | (byte)s[1];
}
int TTFReader::Peek32(const char *s)
{
if(s + 4 > font.End())
if(s + 4 > current_table.End())
Error();
return ((byte)s[0] << 24) | ((byte)s[1] << 16) | ((byte)s[2] << 8) | (byte)s[3];
}
@ -58,7 +58,7 @@ int TTFReader::Read32(const char *&s)
String TTFReader::Read(const char *&s, int n)
{
if(s + n > font.End())
if(s + n > current_table.End())
Error();
String q(s, n);
s += n;
@ -67,34 +67,20 @@ String TTFReader::Read(const char *&s, int n)
void TTFReader::Reset()
{
memset(zero, 0, sizeof(zero));
for(int i = 0; i < 256; i++)
cmap[i] = zero;
}
void TTFReader::Free()
{
for(int i = 0; i < 256; i++)
if(cmap[i] != zero)
delete[] cmap[i];
glyph_map.Clear();
}
void TTFReader::SetGlyph(wchar chr, word glyph)
{
int h = HIBYTE(chr);
if(cmap[h] == zero)
memset(cmap[h] = new word[256], 0, 256 * sizeof(word));
cmap[h][LOBYTE(chr)] = glyph;
glyph_map.GetAdd(chr) = glyph;
}
const char *TTFReader::Seek(const char *tab, int& len)
{
ASSERT(strlen(tab) == 4);
int q = table.Find(tab);
if(q < 0)
Error();
len = table[q].length;
return ~font + table[q].offset;
current_table = font.GetData(tab);
len = current_table.GetCount();
return current_table;
}
const char *TTFReader::Seek(const char *tab)
@ -113,35 +99,17 @@ void TTFReader::Seek(const char *tab, TTFStreamIn& s)
String TTFReader::GetTable(const char *tab)
{
ASSERT(strlen(tab) == 4);
int q = table.Find(tab);
if(q < 0)
return Null;
return String(~font + table[q].offset, table[q].length);
return font.GetData(tab);
}
bool TTFReader::Open(const String& fnt, bool symbol, bool justcheck)
bool TTFReader::Open(const Font& fnt, bool symbol, bool justcheck)
{
try {
int i;
Free();
Reset();
table.Clear();
glyphinfo.Clear();
font = fnt;
const char *s = fnt;
int q = Read32(s);
if(q != 0x74727565 && q != 0x00010000)
Error();
int n = Read16(s);
s += 6;
while(n--) {
Table& t = table.Add(Read(s, 4));
s += 4;
t.offset = Read32(s);
t.length = Read32(s);
}
for(i = 0; i < table.GetCount(); i++)
LLOG("table: " << table.GetKey(i) << " offset: " << table[i].offset << " length: " << table[i].length);
TTFStreamIn is;
Seek("head", is);
@ -186,7 +154,7 @@ bool TTFReader::Open(const String& fnt, bool symbol, bool justcheck)
glyphinfo.SetCount(maxp.numGlyphs);
s = Seek("hmtx");
const char *s = Seek("hmtx");
int aw = 0;
for(i = 0; i < hhea.numOfLongHorMetrics; i++) {
aw = glyphinfo[i].advanceWidth = (uint16)Read16(s);
@ -212,6 +180,14 @@ bool TTFReader::Open(const String& 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) {
for(int ch = start; ch <= end; ch++)
SetGlyph(ch, glyph++);
}, true);
#if 0
s = Seek("cmap");
const char *p = s;
p += 2;
@ -262,7 +238,7 @@ bool TTFReader::Open(const String& fnt, bool symbol, bool justcheck)
break;
}
}
#endif
const char *strings = Seek("name");
s = strings + 2;
@ -303,9 +279,4 @@ TTFReader::TTFReader()
Reset();
}
TTFReader::~TTFReader()
{
Free();
}
}

View file

@ -0,0 +1,10 @@
uses
CtrlLib,
PdfDraw;
file
main.cpp;
mainconfig
"" = "GUI";

12
upptst/PdfEmoji/main.cpp Normal file
View file

@ -0,0 +1,12 @@
#include <CtrlLib/CtrlLib.h>
#include <PdfDraw/PdfDraw.h>
#include <RichText/RichText.h>
using namespace Upp;
GUI_APP_MAIN
{
String p = GetHomeDirFile("pdf.pdf");
SaveFile(p, Pdf(ParseQTF("Some emojis: 🤣 😇 🙂 🙃 😉 😌 😍 🥰 😘 😗 😙 😚 😋 😛 😝 😜 🤪")));
LaunchWebBrowser(p);
}

View file

@ -6,7 +6,7 @@ CONSOLE_APP_MAIN
{
PdfDraw pdf;
int cy = 0;
for(int face = Font::SERIF; face < min(9, Font::GetFaceCount()); face++)
for(int face = Font::SERIF; face < min(20, Font::GetFaceCount()); face++)
// int face = 6;
for(int strikeout = 0; strikeout < 2; strikeout++)
for(int underline = 0; underline < 2; underline++)

View file

@ -0,0 +1,27 @@
#include <PdfDraw/PdfDraw.h>
using namespace Upp;
CONSOLE_APP_MAIN
{
PdfDraw pdf;
int cy = 0;
for(int face = Font::SERIF; face < Font::GetFaceCount(); face++) {
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 p = GetHomeDirFile("pdf.pdf");
SaveFile(p, pdf.Finish());
LaunchWebBrowser(p);
}

View file

@ -0,0 +1,10 @@
uses
Core,
PdfDraw;
file
PdfText.cpp;
mainconfig
"" = "";