mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
PdfDraw: Fixed nonBMP glyphs export
This commit is contained in:
parent
815ce70fa2
commit
405c6ff0da
11 changed files with 107 additions and 72 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
10
upptst/PdfEmoji/PdfEmoji.upp
Normal file
10
upptst/PdfEmoji/PdfEmoji.upp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
uses
|
||||
CtrlLib,
|
||||
PdfDraw;
|
||||
|
||||
file
|
||||
main.cpp;
|
||||
|
||||
mainconfig
|
||||
"" = "GUI";
|
||||
|
||||
12
upptst/PdfEmoji/main.cpp
Normal file
12
upptst/PdfEmoji/main.cpp
Normal 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);
|
||||
}
|
||||
|
|
@ -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++)
|
||||
|
|
|
|||
27
upptst/PdfText2/PdfText.cpp
Normal file
27
upptst/PdfText2/PdfText.cpp
Normal 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);
|
||||
}
|
||||
10
upptst/PdfText2/PdfText2.upp
Normal file
10
upptst/PdfText2/PdfText2.upp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
uses
|
||||
Core,
|
||||
PdfDraw;
|
||||
|
||||
file
|
||||
PdfText.cpp;
|
||||
|
||||
mainconfig
|
||||
"" = "";
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue