Update to newer font code
diff --git a/skia/font_converter/src/font.cpp b/skia/font_converter/src/font.cpp index 0fe5480..f080832 100644 --- a/skia/font_converter/src/font.cpp +++ b/skia/font_converter/src/font.cpp
@@ -90,15 +90,13 @@ // uint16_t x,y x,y x,y }; -void RiveFont::load(sk_sp<SkTypeface> tf, const std::string& str) { +void RiveFont::load(sk_sp<SkTypeface> tf, const char str[], size_t len) { this->clear(); SkFont font(std::move(tf), 1.0f); - size_t len = str.size(); uint16_t glyphIDs[len]; - int glyphCount = font.textToGlyphs(str.data(), len, SkTextEncoding::kUTF8, - glyphIDs, len); + int glyphCount = font.textToGlyphs(str, len, SkTextEncoding::kUTF8, glyphIDs, len); assert(glyphCount == (int)len); struct Rec { @@ -107,14 +105,27 @@ uint16_t dstGlyph; }; std::vector<Rec> rec; - uint16_t newGlyphID = 1; + uint16_t newDstGlyphID = 1; // leave room for glyphID==0 for missing glyph + // build vector of unique chars for (size_t i = 0; i < len; ++i) { uint16_t code = str[i]; auto iter = std::find_if(rec.begin(), rec.end(), [code](const auto& r) { return r.charCode == code; }); if (iter == rec.end()) { - rec.push_back({code, glyphIDs[i], glyphIDs[i] == 0 ? glyphIDs[i] : newGlyphID++}); + // gonna add code -- now see if its glyph is unique + uint16_t srcGlyph = glyphIDs[i]; + auto it2 = std::find_if(rec.begin(), rec.end(), [srcGlyph](const auto& r) { + return r.srcGlyph == srcGlyph; + }); + uint16_t dstGlyph; + if (it2 == rec.end()) { + // srcGlyph is unique (or zero) + dstGlyph = srcGlyph ? newDstGlyphID++ : 0; + } else { + dstGlyph = it2->dstGlyph; // reuse prev dstGlyph + } + rec.push_back({code, srcGlyph, dstGlyph}); } } @@ -122,7 +133,7 @@ return a.charCode < b.charCode; }); for (const auto& r : rec) { - printf("'%c' %d -> %d\n", r.charCode, r.srcGlyph, r.dstGlyph); + printf("'%c' [%d] %d -> %d\n", r.charCode, r.charCode, r.srcGlyph, r.dstGlyph); fCMap.push_back({r.charCode, r.dstGlyph}); } @@ -141,12 +152,12 @@ }; append_glyph(0); // missing glyph - assert(newGlyphID == rec.size() + 1); - for (size_t i = 0; i < rec.size(); ++i) { - const auto& r = rec[i]; - assert(r.dstGlyph == i + 1); - assert(r.srcGlyph != 0); - append_glyph(r.srcGlyph); + for (int i = 1; i < newDstGlyphID; ++i) { // walk through our glyphs + auto iter = std::find_if(rec.begin(), rec.end(), [i](const auto& r) { + return r.dstGlyph == i; + }); + assert(iter != rec.end()); + append_glyph(iter->srcGlyph); } }
diff --git a/skia/font_converter/src/font.h b/skia/font_converter/src/font.h index d5f109c..b87418e 100644 --- a/skia/font_converter/src/font.h +++ b/skia/font_converter/src/font.h
@@ -29,7 +29,7 @@ fGlyphs.clear(); } - void load(sk_sp<SkTypeface>, const std::string& chars); + void load(sk_sp<SkTypeface>, const char text[], size_t length); sk_sp<SkData> encode() const; bool decode(const void*, size_t);
diff --git a/skia/font_converter/src/font_arguments.hpp b/skia/font_converter/src/font_arguments.hpp index 35ba1a9..58522ac 100644 --- a/skia/font_converter/src/font_arguments.hpp +++ b/skia/font_converter/src/font_arguments.hpp
@@ -12,29 +12,28 @@ public: FontArguments(int argc, const char** argv) - { - // PARSE INPUT - m_Parser = new args::ArgumentParser( - "Record playback of a Rive file as a movie, gif, etc (eventually " - "should support image sequences saved in a zip/archive too).", - "Experimental...."); + : m_Parser( + "Convert a font file into the rive format.", + "Experimental....") + { args::HelpFlag help( - *m_Parser, "help", "Display this help menu", {'h', "help"}); - args::Group required( - *m_Parser, "required arguments:", args::Group::Validators::All); - args::Group optional(*m_Parser, + m_Parser, "help", "Display this help menu", {'h', "help"}); + args::Group required(m_Parser, "required arguments:", args::Group::Validators::All); + args::Group optional(m_Parser, "optional arguments:", args::Group::Validators::DontCare); args::ValueFlag<std::string> source( required, "path", "source filename", {'s', "source"}); - args::ValueFlag<std::string> destination( - required, "path", "destination filename", {'d', "destination"}); + args::ValueFlag<std::string> destination( + required, "path", "destination filename", {'d', "destination"}); + args::ValueFlag<std::string> charset( + optional, "path", "charset filename", {'c', "charset"}); - args::CompletionFlag completion(*m_Parser, {"complete"}); + args::CompletionFlag completion(m_Parser, {"complete"}); try { - m_Parser->ParseCLI(argc, argv); + m_Parser.ParseCLI(argc, argv); } catch (const std::invalid_argument e) { @@ -65,23 +64,18 @@ } m_Destination = args::get(destination); - m_Source = args::get(source); - } - - ~FontArguments() - { - if (m_Parser != nullptr) - { - delete m_Parser; - } - } + m_Source = args::get(source); + m_Charset = args::get(charset); + } const std::string& destination() const { return m_Destination; } - const std::string& source() const { return m_Source; } + const std::string& source() const { return m_Source; } + const std::string& charset() const { return m_Charset; } private: - args::ArgumentParser* m_Parser; + args::ArgumentParser m_Parser; std::string m_Destination; std::string m_Source; + std::string m_Charset; }; -#endif \ No newline at end of file +#endif
diff --git a/skia/font_converter/src/main.cpp b/skia/font_converter/src/main.cpp index a50b0da..7c10a08 100644 --- a/skia/font_converter/src/main.cpp +++ b/skia/font_converter/src/main.cpp
@@ -3,56 +3,81 @@ #include "font.h" #include "font_arguments.hpp" +#include "include/core/SkData.h" +#include "include/core/SkFontMgr.h" +#include "include/core/SkStream.h" +#include "include/core/SkTypeface.h" +#include <vector> -void readFile(const char* path, uint8_t*& bytes, long& length) -{ +static std::vector<char> readFile(const char path[]) { FILE* fp = fopen(path, "r"); - if (fp == nullptr) - { + if (fp == nullptr) { fclose(fp); std::ostringstream errorStream; errorStream << "Failed to open file " << path; throw std::invalid_argument(errorStream.str()); } fseek(fp, 0, SEEK_END); - length = ftell(fp); + size_t length = ftell(fp); fseek(fp, 0, SEEK_SET); - bytes = new uint8_t[length]; + std::vector<char> data; + data.resize(length); - if (fread(bytes, 1, length, fp) != length) - { + if (fread(data.data(), 1, length, fp) != length) { fclose(fp); - delete[] bytes; std::ostringstream errorStream; errorStream << "Failed to read file into bytes array " << path; throw std::invalid_argument(errorStream.str()); } fclose(fp); + return data; } -int main(int argc, const char* argv[]) -{ - try - { +static void writeFile(const char path[], const void* bytes, size_t length) { + FILE* pFile = fopen(path, "wb"); + fwrite(bytes, sizeof(char), length, pFile); + fclose(pFile); +} + +static std::vector<char> build_default_charset() { + std::vector<char> charset; + for (int i = 32; i < 127; ++i) { + charset.push_back(i); + } + return charset; +} + +int main(int argc, const char* argv[]) { + try { FontArguments args(argc, argv); - RiveFont* font = new RiveFont(); + sk_sp<SkTypeface> typeface; - uint8_t* bytes; - long length = 0; - readFile(args.source().c_str(), bytes, length); - // font->decode(bytes, length); - // font->encode(); + auto src = readFile(args.source().c_str()); + auto srcData = SkData::MakeWithCopy(src.data(), src.size()); + typeface = SkTypeface::MakeFromData(srcData); + if (!typeface) { + fprintf(stderr, "Failed to convert file to SkTypeface\n"); + return 1; + } - FILE* pFile; - pFile = fopen(args.destination().c_str(), "wb"); - fwrite(bytes, sizeof(char), length, pFile); - fclose(pFile); + std::vector<char> charset; + auto charsetFile = args.charset(); + if (charsetFile.size() > 0) { + charset = readFile(args.charset().c_str()); + } else { + charset = build_default_charset(); + } - delete[] bytes; - } + RiveFont font; + font.load(typeface, charset.data(), charset.size()); + + auto dst = font.encode(); + + writeFile(args.destination().c_str(), dst->data(), dst->size()); + } catch (const args::Completion& e) { return 0;