radio/lib/fontParser/tables/name.cpp
2018-08-05 00:48:17 +03:00

137 lines
4.2 KiB
C++

#include "name.h"
#include <arpa/inet.h>
#include <list>
#include <set>
#include <codecvt>
#include <locale>
const std::map<std::string, uint16_t> Name::nameIds({
{ "copyright", 0 },
{ "fontFamily", 1 },
{ "fontSubfamily", 2 },
{ "uniqueSubfamilyId", 3 },
{ "fullFontName", 4 },
{ "nameTableVersion", 5 },
{ "postScriptName", 6 },
{ "trademarkNotice", 7 },
{ "manufacturerName", 8 },
{ "designerName", 9 },
{ "description", 10 },
{ "vendorURL", 11 },
{ "designerURL", 12 },
{ "licenseDescription", 13 },
{ "licenseURL", 14 },
{ "preferredFamily", 16 },
{ "preferredSubfamily", 17 },
{ "compatibleFull", 18 },
{ "sampleText", 19 },
{ "postScriptCID", 20 }
});
Name::Name(const std::string& p_tag, uint32_t p_checkSum, uint32_t p_offset, uint32_t p_length):
Table(p_tag, p_checkSum, p_offset, p_length),
names()
{
}
Name::~Name()
{
}
void Name::read(const std::string& path)
{
std::ifstream file(path, std::ios::in | std::ios::binary);
file.seekg(offset);
char * buffer;
buffer = new char[2];
file.read(buffer, 2); //format. it is always 0 or 1 for stupid microsoft langTags, but I don't cate, gonna use offset;
file.read(buffer, 2);
uint16_t count = ntohs(*((uint16_t*) buffer));
file.read(buffer, 2);
uint32_t storageOffset = offset + ntohs(*((uint16_t*) buffer));
std::list<NameRecord> list;
std::set<uint16_t> ids;
for (int i = 0; i < count; ++i) {
file.read(buffer, 2);
uint16_t pid = ntohs(*((uint16_t*) buffer));
file.read(buffer, 2);
uint16_t eid = ntohs(*((uint16_t*) buffer));
file.read(buffer, 2);
uint16_t lid = ntohs(*((uint16_t*) buffer));
file.read(buffer, 2);
uint16_t nid = ntohs(*((uint16_t*) buffer));
file.read(buffer, 2);
uint16_t length = ntohs(*((uint16_t*) buffer));
file.read(buffer, 2);
uint16_t nameOffset = ntohs(*((uint16_t*) buffer));
//std::cout << "Found pid " << pid << ", eid " << eid << ", nid " << nid << std::endl;
if (ids.find(nid) == ids.end()) {
if ((pid == 0 && (eid == 3 || eid == 4)) || (pid == 3 && eid == 1)) { //screw microsoft, screw apple;
list.emplace_back(pid, eid, lid, nid, length, nameOffset);
ids.insert(nid);
}
}
}
std::list<NameRecord>::const_iterator itr;
for (itr = list.begin(); itr != list.end(); ++itr) {
const NameRecord& nr = *itr;
file.seekg(storageOffset + nr.offset);
if ((nr.platformId == 0 && (nr.encodingId == 3 || nr.encodingId == 4)) || (nr.platformId == 3 && nr.encodingId == 1)) {
char16_t buf[nr.length / 2];
for (int i = 0; i < nr.length / 2; ++i) {
file.read(buffer, 2);
buf[i] = ntohs(*((char16_t*) buffer));
}
std::u16string string(buf, nr.length / 2);
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
names.insert(std::make_pair(nr.nameId, convert.to_bytes(string)));
}
}
delete[] buffer;
file.close();
}
std::string Name::getRecord(uint16_t id) const
{
std::string res("");
std::map<uint16_t, std::string>::const_iterator itr = names.find(id);
if (itr != names.end()) {
res = itr->second;
}
return res;
}
std::string Name::getRecord(const std::string& name) const
{
std::map<std::string, uint16_t>::const_iterator itr = nameIds.find(name);
if (itr == nameIds.end()) {
return "";
} else {
return getRecord(itr->second);
}
}
NameRecord::NameRecord(uint16_t pid, uint16_t eid, uint16_t lid, uint16_t nid, uint16_t p_l, uint16_t p_o):
platformId(pid),
encodingId(eid),
languageId(lid),
nameId(nid),
length(p_l),
offset(p_o)
{
}