#include "font.h" #include Font::Font(const std::string& p_path): path(p_path), tables(), cmap(0), hhea(0), hmtx(0), head(0), name(0) { std::ifstream file(path, std::ios::in | std::ios::binary); char * buffer; buffer = new char[4]; file.read(buffer, 4); uint32_t sfntVersion = ntohl(*((uint32_t*) buffer)); if (sfntVersion == 0x00010000) { version = TrueTypeOutlines; } else if (sfntVersion == 0x4f54544f) { version = WithCFFData; } else { std::cout << "unsupported sfntVersion" << std::endl; throw 1; } delete[] buffer; buffer = new char[2]; file.read(buffer, 2); numberTables = ntohs(*((uint16_t*) buffer)); file.read(buffer, 2); searchRange = ntohs(*((uint16_t*) buffer)); file.read(buffer, 2); entrySelector = ntohs(*((uint16_t*) buffer)); file.read(buffer, 2); rangeShift = ntohs(*((uint16_t*) buffer)); for (int i = 0; i < numberTables; ++i) { Table* t = Table::fromIfStream(file); tables.insert(std::make_pair(t->tag, t)); } file.close(); } Font::~Font() { std::map::const_iterator beg = tables.begin(); std::map::const_iterator end = tables.end(); for (; beg != end; ++beg) { delete beg->second; } } bool Font::hasTable(const std::string& tag) const { std::map::const_iterator itr = tables.find(tag); return itr != tables.end(); } std::list Font::availableTables() const { std::list res; std::map::const_iterator beg = tables.begin(); std::map::const_iterator end = tables.end(); for (; beg != end; ++beg) { res.push_back(beg->first); } return res; } std::map Font::getCharCodeToCIDTable(uint32_t start, uint32_t end) { if (cmap == NULL) { cmap = static_cast(tables.at("cmap")); cmap->read(path); } std::map res; for (uint32_t i = start; i <= end; ++i) { res.insert(std::make_pair(i, cmap->getCID(i))); } return res; } std::map Font::getCharCodeMetrics(uint32_t start, uint32_t end) { std::map CCtoCID = getCharCodeToCIDTable(start, end); std::map res; if (hmtx == NULL) { hmtx = static_cast(tables.at("hmtx")); if (hhea == NULL) { hhea = static_cast(tables.at("hhea")); hhea->read(path); } hmtx->numOfLongHorMetrics = hhea->numOfLongHorMetrics; hmtx->read(path); } std::map::const_iterator itr = CCtoCID.begin(); std::map::const_iterator mend = CCtoCID.end(); for (; itr != mend; ++itr) { res.insert(std::make_pair(itr->first, hmtx->getMetric(itr->second))); } return res; } Table * Font::getTable(const std::string& tag) { std::map::iterator itr = tables.find(tag); return itr->second; } uint16_t Font::getUnitsPerEm() { if (head == NULL) { head = static_cast(tables.at("head")); head->read(path); } return head->unitsPerEm; } int16_t Font::getAscent() { if (hhea == NULL) { hhea = static_cast(tables.at("hhea")); hhea->read(path); } return hhea->ascent; } int16_t Font::getDescent() { if (hhea == NULL) { hhea = static_cast(tables.at("hhea")); hhea->read(path); } return hhea->descent; } int16_t Font::getLineGap() { if (hhea == NULL) { hhea = static_cast(tables.at("hhea")); hhea->read(path); } return hhea->lineGap; } std::string Font::getNameField(std::string key) { if (name == NULL) { name = static_cast(tables.at("name")); name->read(path); } return name->getRecord(key); } int16_t Font::getCaretSlopeRise() { if (hhea == NULL) { hhea = static_cast(tables.at("hhea")); hhea->read(path); } return hhea->caretSlopeRise; } int16_t Font::getCaretSlopeRun() { if (hhea == NULL) { hhea = static_cast(tables.at("hhea")); hhea->read(path); } return hhea->caretSlopeRun; } int16_t Font::getXMax() { if (head == NULL) { head = static_cast(tables.at("head")); head->read(path); } return head->xMax; } int16_t Font::getXMin() { if (head == NULL) { head = static_cast(tables.at("head")); head->read(path); } return head->xMin; } int16_t Font::getYMax() { if (head == NULL) { head = static_cast(tables.at("head")); head->read(path); } return head->yMax; } int16_t Font::getYMin() { if (head == NULL) { head = static_cast(tables.at("head")); head->read(path); } return head->yMin; }