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;