mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
230 lines
4.7 KiB
C++
230 lines
4.7 KiB
C++
#include "PdfDraw.h"
|
|
|
|
namespace Upp {
|
|
|
|
#define LLOG(x) // LOG(x)
|
|
#define LDUMP(x) // LLOG(#x << " = " << x);
|
|
|
|
int TTFReader::Peek8(const char *s)
|
|
{
|
|
if(s + 1 > current_table.End())
|
|
Error();
|
|
return (byte)*s;
|
|
}
|
|
|
|
int TTFReader::Peek16(const char *s)
|
|
{
|
|
if(s + 2 > current_table.End())
|
|
Error();
|
|
return ((byte)s[0] << 8) | (byte)s[1];
|
|
}
|
|
|
|
int TTFReader::Peek32(const char *s)
|
|
{
|
|
if(s + 4 > current_table.End())
|
|
Error();
|
|
return ((byte)s[0] << 24) | ((byte)s[1] << 16) | ((byte)s[2] << 8) | (byte)s[3];
|
|
}
|
|
|
|
int TTFReader::Peek8(const char *s, int i)
|
|
{
|
|
return Peek16(s + i);
|
|
}
|
|
|
|
int TTFReader::Peek16(const char *s, int i)
|
|
{
|
|
return Peek16(s + 2 * i);
|
|
}
|
|
|
|
int TTFReader::Peek32(const char *s, int i)
|
|
{
|
|
return Peek32(s + 4 * i);
|
|
}
|
|
|
|
int TTFReader::Read8(const char *&s)
|
|
{
|
|
int q = byte(*s); s++; return q;
|
|
}
|
|
|
|
int TTFReader::Read16(const char *&s)
|
|
{
|
|
int q = Peek16(s); s += 2; return q;
|
|
}
|
|
|
|
int TTFReader::Read32(const char *&s)
|
|
{
|
|
int q = Peek32(s); s += 4; return q;
|
|
}
|
|
|
|
String TTFReader::Read(const char *&s, int n)
|
|
{
|
|
if(s + n > current_table.End())
|
|
Error();
|
|
String q(s, n);
|
|
s += n;
|
|
return q;
|
|
}
|
|
|
|
void TTFReader::Reset()
|
|
{
|
|
glyph_map.Clear();
|
|
}
|
|
|
|
void TTFReader::SetGlyph(wchar chr, word glyph)
|
|
{
|
|
glyph_map.GetAdd(chr) = glyph;
|
|
}
|
|
|
|
const char *TTFReader::Seek(const char *tab, int& len)
|
|
{
|
|
ASSERT(strlen(tab) == 4);
|
|
current_table = font.GetData(tab);
|
|
len = current_table.GetCount();
|
|
return current_table;
|
|
}
|
|
|
|
const char *TTFReader::Seek(const char *tab)
|
|
{
|
|
int dummy;
|
|
return Seek(tab, dummy);
|
|
}
|
|
|
|
void TTFReader::Seek(const char *tab, TTFStreamIn& s)
|
|
{
|
|
int len;
|
|
s.beg = s.s = Seek(tab, len);
|
|
s.lim = s.s + len;
|
|
}
|
|
|
|
String TTFReader::GetTable(const char *tab)
|
|
{
|
|
ASSERT(strlen(tab) == 4);
|
|
return font.GetData(tab);
|
|
}
|
|
|
|
bool TTFReader::Open(const Font& fnt, bool symbol, bool justcheck)
|
|
{
|
|
try {
|
|
int i;
|
|
Reset();
|
|
table.Clear();
|
|
glyphinfo.Clear();
|
|
font = fnt;
|
|
|
|
TTFStreamIn is;
|
|
Seek("head", is);
|
|
head.Serialize(is);
|
|
if(head.magicNumber != 0x5F0F3CF5)
|
|
Error();
|
|
|
|
LDUMP(head.unitsPerEm);
|
|
LDUMP(head.xMin);
|
|
LDUMP(head.yMin);
|
|
LDUMP(head.xMax);
|
|
LDUMP(head.yMax);
|
|
LDUMP(head.indexToLocFormat);
|
|
|
|
Seek("maxp", is);
|
|
maxp.Serialize(is);
|
|
LDUMP(maxp.numGlyphs);
|
|
|
|
Seek("post", is);
|
|
post.Serialize(is);
|
|
// LLOGHEXLDUMP(is.s, is.lim - is.s);
|
|
LDUMP((post.format >> 16));
|
|
LDUMP(post.italicAngle);
|
|
LDUMP(post.italicAngle);
|
|
LDUMP(post.underlinePosition);
|
|
LDUMP(post.underlineThickness);
|
|
LDUMP(post.italicAngle);
|
|
|
|
Seek("hhea", is);
|
|
hhea.Serialize(is);
|
|
LDUMP(hhea.ascent);
|
|
LDUMP(hhea.descent);
|
|
LDUMP(hhea.lineGap);
|
|
LDUMP(hhea.advanceWidthMax);
|
|
LDUMP(hhea.numOfLongHorMetrics);
|
|
|
|
if(hhea.numOfLongHorMetrics > maxp.numGlyphs)
|
|
Error();
|
|
|
|
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);
|
|
glyphinfo[i].leftSideBearing = (int16)Read16(s);
|
|
}
|
|
for(; i < maxp.numGlyphs; i++) {
|
|
glyphinfo[i].advanceWidth = aw;
|
|
glyphinfo[i].leftSideBearing = (int16)Read16(s);
|
|
}
|
|
|
|
s = Seek("loca");
|
|
if(!s) Error();
|
|
for(i = 0; i < maxp.numGlyphs; i++)
|
|
if(head.indexToLocFormat) {
|
|
glyphinfo[i].offset = Peek32(s, i);
|
|
glyphinfo[i].size = Peek32(s, i + 1) - glyphinfo[i].offset;
|
|
}
|
|
else {
|
|
glyphinfo[i].offset = 2 * (word)Peek16(s, i);
|
|
glyphinfo[i].size = 2 * (word)Peek16(s, i + 1) - glyphinfo[i].offset;
|
|
}
|
|
|
|
for(i = 0; i < maxp.numGlyphs; i++)
|
|
LLOG(i << " advance: " << glyphinfo[i].advanceWidth << ", left: " << glyphinfo[i].leftSideBearing
|
|
<< ", offset: " << glyphinfo[i].offset << ", size: " << glyphinfo[i].size);
|
|
|
|
ReadCmap(fnt, [&](int start, int end, int glyph) {
|
|
for(int ch = start; ch <= end; ch++)
|
|
SetGlyph(ch, glyph++);
|
|
}, CMAP_GLYPHS|CMAP_ALLOW_SYMBOL);
|
|
|
|
const char *strings = Seek("name");
|
|
if(!strings) Error();
|
|
s = strings + 2;
|
|
int count = Read16(s);
|
|
strings += (word)Read16(s);
|
|
for(int i = 0; i < count; i++) {
|
|
int platform = Read16(s);
|
|
s += 4;
|
|
if(Read16(s) == 6) {
|
|
int len = Read16(s);
|
|
int offset = Read16(s);
|
|
if(platform == 1)
|
|
ps_name = String(strings + offset, len);
|
|
else {
|
|
s = strings + offset;
|
|
len >>= 1;
|
|
while(len--)
|
|
ps_name.Cat(Read16(s));
|
|
}
|
|
break;
|
|
}
|
|
s += 4;
|
|
}
|
|
LDUMP(ps_name);
|
|
}
|
|
catch(Fail) {
|
|
return false;
|
|
}
|
|
catch(TTFStream::Fail) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
TTFReader::TTFReader()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
}
|