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;