mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
214 lines
5.3 KiB
C++
214 lines
5.3 KiB
C++
#include "TypeReader.h"
|
|
|
|
#define LLOG(x) // LOG(x)
|
|
#define LDUMP(x) // LOG(#x << " = " << x);
|
|
|
|
int FontTypeReader::Error()
|
|
{
|
|
throw Fail(); return 0;
|
|
}
|
|
|
|
int FontTypeReader::Peek8(const char *s)
|
|
{
|
|
return s + 1 < data.end() ? (byte)*s : Error();
|
|
}
|
|
|
|
int FontTypeReader::Peek16(const char *s)
|
|
{
|
|
return s + 2 < data.end() ? Peek16be(s) : Error();
|
|
}
|
|
|
|
int FontTypeReader::Peek32(const char *s)
|
|
{
|
|
return s + 4 < data.end() ? Peek32be(s) : Error();
|
|
}
|
|
|
|
int FontTypeReader::Peek8(const char *s, int i)
|
|
{
|
|
return Peek8(s + i);
|
|
}
|
|
|
|
int FontTypeReader::Peek16(const char *s, int i)
|
|
{
|
|
return Peek16(s + 2 * i);
|
|
}
|
|
|
|
int FontTypeReader::Peek32(const char *s, int i)
|
|
{
|
|
return Peek32(s + 4 * i);
|
|
}
|
|
|
|
int FontTypeReader::Read8(const char *&s)
|
|
{
|
|
int q = byte(*s);
|
|
s++;
|
|
return q;
|
|
}
|
|
|
|
int FontTypeReader::Read16(const char *&s)
|
|
{
|
|
int q = Peek16(s);
|
|
s += 2;
|
|
return q;
|
|
}
|
|
|
|
int FontTypeReader::Read32(const char *&s)
|
|
{
|
|
int q = Peek32(s);
|
|
s += 4;
|
|
return q;
|
|
}
|
|
|
|
bool FontTypeReader::Open(Font font, bool symbol, bool justcheck)
|
|
{
|
|
// DDUMP(fnt.GetCount());
|
|
try {
|
|
int i;
|
|
#if 0
|
|
for(i = 0; i < table.GetCount(); i++)
|
|
LLOG("table: " << table.GetKey(i) << " offset: " << table[i].offset << " length: " << table[i].length);
|
|
|
|
s = Seek("hmtx");
|
|
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");
|
|
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);
|
|
#endif
|
|
|
|
data = font.GetData("OS/2");
|
|
panose.Clear();
|
|
if(data.GetCount() > 32 + 10)
|
|
panose = data.Mid(32, 10);
|
|
|
|
bool found = false;
|
|
data = font.GetData("cmap");
|
|
for(int pass = 0; pass < 2; pass++) {
|
|
const char *p = data;
|
|
// LOGHEXDUMP(p, 256);
|
|
p += 2;
|
|
int n = Read16(p);
|
|
// DDUMP(n);
|
|
while(n--) {
|
|
int pid = Read16(p);
|
|
int psid = Read16(p);
|
|
int offset = Read32(p);
|
|
if(offset < 0 || offset > data.GetCount())
|
|
Error();
|
|
int format = Peek16(~data + offset);
|
|
LLOG("cmap pid: " << pid << " psid: " << psid << " format: " << format);
|
|
//Test with Symbol font !!!; improve - Unicode first, 256 bytes later..., symbol...
|
|
if(symbol) {
|
|
if(pid == 1 && psid == 0 && Peek16(~data + offset) == 0) {
|
|
LLOG("Reading symbol table");
|
|
p = ~data + offset + 6;
|
|
for(int i = 0; i < 256; i++);
|
|
//SetGlyph(i, (byte)p[i]);
|
|
goto done;
|
|
}
|
|
}
|
|
else
|
|
if((pid == 3 && psid == 10) || (pid == 0 && psid == 4) && format == 12 && pass == 0) {
|
|
const char *p = ~data + offset;
|
|
int ngroups = Peek32(p + 12);
|
|
p += 16; // pointer to groups table
|
|
for(int i = 0; i < ngroups; i++) {
|
|
LLOG(Peek32(p) << " - " << Peek32(p + 4) << ", glyphi: " << Peek32(p + 8));
|
|
ranges.Add(MakeTuple(Peek32(p), Peek32(p + 4)));
|
|
p += 12;
|
|
}
|
|
goto done;
|
|
}
|
|
else
|
|
if((pid == 3 && psid == 1) || (pid == 0 && psid == 3) && format == 4 && pass == 1) {
|
|
const char *p = ~data + offset;
|
|
int 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);
|
|
ranges.Add(MakeTuple(start, end));
|
|
#if 0
|
|
int delta = Peek16(idDelta, i);
|
|
int ro = Peek16(idRangeOffset, i);
|
|
if (ro && delta == 0) {
|
|
LOG(start << " - " << end);
|
|
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 {
|
|
LOG(start << " - " << end);
|
|
LLOG("Delta start: " << start << ", end: " << end << ", delta: " << (int16)delta);
|
|
// for(int c = start; c <= end; c++);
|
|
// SetGlyph(c, c + delta);
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
done:;
|
|
#if 0
|
|
String names = font.GetData("name");
|
|
if(names.GetCount()) {
|
|
const char *strings = names;
|
|
const char *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;
|
|
}
|
|
}
|
|
DDUMP(ps_name);
|
|
#endif
|
|
}
|
|
catch(Fail) {
|
|
LLOG("ERROR");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|