diff --git a/proto/glyphs.proto b/proto/glyphs.proto index 606050f7a..c44eee8d0 100644 --- a/proto/glyphs.proto +++ b/proto/glyphs.proto @@ -1,14 +1,14 @@ // Protocol Version 1 -package llmr.glyphs; +package mbgl.glyphs; option optimize_for = LITE_RUNTIME; // Stores a glyph with metrics and optional SDF bitmap information. -message glyph { +message Glyph { required uint32 id = 1; - // A signed distance field of the glyph with a border of 3 pixels. + // Signed distance field of a glyph with buffer documented in metadata. optional bytes bitmap = 2; // Glyph metrics. @@ -19,15 +19,31 @@ message glyph { required uint32 advance = 7; } -// Stores fontstack information and a list of faces. -message fontstack { - required string name = 1; - required string range = 2; - repeated glyph glyphs = 3; +// Store a face with glyphs and optional metadata. +message Face { + repeated Glyph glyphs = 1; + + // Store SDF metadata. + message Metadata { + optional uint32 size = 1; + optional uint32 buffer = 2; + optional float cutoff = 3; + optional float scale = 4; + optional uint32 granularity = 5; + optional float offset = 6; + optional uint32 radius = 7; + } + + optional Metadata metadata = 2; + + optional string family_name = 3; + optional string style_name = 4; + optional double ascender = 5; + optional double descender = 6; + optional double line_height = 7; } -message glyphs { - repeated fontstack stacks = 1; - +message Glyphs { + repeated Face faces = 1; extensions 16 to 8191; } diff --git a/src/glyphs.cpp b/src/glyphs.cpp index 4a8577af5..f183ac0a0 100644 --- a/src/glyphs.cpp +++ b/src/glyphs.cpp @@ -34,8 +34,7 @@ typedef std::pair SegmentPair; typedef std::pair SegmentValue; typedef bgi::rtree> Tree; -namespace node_fontnik -{ +namespace node_fontnik { struct FaceMetadata { std::string family_name; @@ -170,6 +169,7 @@ NAN_METHOD(Range) { start->IntegerValue(), end->IntegerValue()); uv_queue_work(uv_default_loop(), &baton->request, RangeAsync, (uv_after_work_cb)AfterRange); + NanReturnUndefined(); } @@ -177,8 +177,7 @@ struct ft_library_guard { ft_library_guard(FT_Library * lib) : library_(lib) {} - ~ft_library_guard() - { + ~ft_library_guard() { if (library_) FT_Done_FreeType(*library_); } @@ -189,8 +188,7 @@ struct ft_glyph_guard { ft_glyph_guard(FT_Glyph * glyph) : glyph_(glyph) {} - ~ft_glyph_guard() - { + ~ft_glyph_guard() { if (glyph_) FT_Done_Glyph(*glyph_); } @@ -211,8 +209,7 @@ void LoadAsync(uv_work_t* req) { } FT_Face ft_face = 0; int num_faces = 0; - for ( int i = 0; ft_face == 0 || i < num_faces; ++i ) - { + for (int i = 0; ft_face == 0 || i < num_faces; ++i) { FT_Error face_error = FT_New_Memory_Face(library, reinterpret_cast(baton->font_data), static_cast(baton->font_size), i, &ft_face); if (face_error) { baton->error_name = std::string("could not open font file"); @@ -286,25 +283,36 @@ void RangeAsync(uv_work_t* req) { FT_Face ft_face = 0; - llmr::glyphs::glyphs glyphs; + mbgl::glyphs::Glyphs glyphs; int num_faces = 0; - for ( int i = 0; ft_face == 0 || i < num_faces; ++i ) - { + for (int i = 0; ft_face == 0 || i < num_faces; ++i) { FT_Error face_error = FT_New_Memory_Face(library, reinterpret_cast(baton->font_data), static_cast(baton->font_size), i, &ft_face); if (face_error) { baton->error_name = std::string("could not open font"); return; } - llmr::glyphs::fontstack *mutable_fontstack = glyphs.add_stacks(); - mutable_fontstack->set_name(std::string(ft_face->family_name) + " " + ft_face->style_name); - mutable_fontstack->set_range(std::to_string(baton->start) + "-" + std::to_string(baton->end)); - - const double scale_factor = 1.0; + mbgl::glyphs::Face *mutable_face = glyphs.add_faces(); + // mutable_face->set_range(std::to_string(baton->start) + "-" + std::to_string(baton->end)); + mutable_face->set_family_name(ft_face->family_name); + mutable_face->set_style_name(ft_face->style_name); + mutable_face->set_ascender(ft_face->ascender); + mutable_face->set_descender(ft_face->descender); + mutable_face->set_line_height(ft_face->height); + + // Add metadata to face. + mbgl::glyphs::Face::Metadata mutable_metadata = mutable_face->metadata(); + mutable_metadata.set_size(char_size); + mutable_metadata.set_buffer(buffer_size); + mutable_metadata.set_cutoff(cutoff_size); + mutable_metadata.set_scale(scale_factor); + mutable_metadata.set_granularity(granularity); + mutable_metadata.set_offset(offset_size); + mutable_metadata.set_radius(radius_size); // Set character sizes. - double size = 24 * scale_factor; + double size = char_size * scale_factor; FT_Set_Char_Size(ft_face,0,(FT_F26Dot6)(size * (1<<6)),0,0); for (std::vector::size_type x = 0; x != baton->chars.size(); x++) { @@ -317,15 +325,15 @@ void RangeAsync(uv_work_t* req) { if (!char_index) continue; glyph.glyph_index = char_index; - RenderSDF(glyph, 24, 3, 0.25, ft_face); + RenderSDF(glyph, char_size, buffer_size, cutoff_size, ft_face); - // Add glyph to fontstack. - llmr::glyphs::glyph *mutable_glyph = mutable_fontstack->add_glyphs(); + // Add glyph to face. + mbgl::glyphs::Glyph *mutable_glyph = mutable_face->add_glyphs(); mutable_glyph->set_id(char_code); mutable_glyph->set_width(glyph.width); mutable_glyph->set_height(glyph.height); mutable_glyph->set_left(glyph.left); - mutable_glyph->set_top(glyph.top - glyph.ascender); + mutable_glyph->set_top(glyph.top); mutable_glyph->set_advance(glyph.advance); if (glyph.width > 0) { @@ -333,6 +341,7 @@ void RangeAsync(uv_work_t* req) { } } + if (ft_face) { FT_Done_Face(ft_face); } @@ -363,20 +372,17 @@ struct User { Points ring; }; -void CloseRing(Points &ring) -{ +void CloseRing(Points &ring) { const Point &first = ring.front(); const Point &last = ring.back(); if (first.get<0>() != last.get<0>() || - first.get<1>() != last.get<1>()) - { + first.get<1>() != last.get<1>()) { ring.push_back(first); } } -int MoveTo(const FT_Vector *to, void *ptr) -{ +int MoveTo(const FT_Vector *to, void *ptr) { User *user = (User*)ptr; if (!user->ring.empty()) { CloseRing(user->ring); @@ -387,8 +393,7 @@ int MoveTo(const FT_Vector *to, void *ptr) return 0; } -int LineTo(const FT_Vector *to, void *ptr) -{ +int LineTo(const FT_Vector *to, void *ptr) { User *user = (User*)ptr; user->ring.push_back(Point { float(to->x) / 64, float(to->y) / 64 }); return 0; @@ -396,8 +401,7 @@ int LineTo(const FT_Vector *to, void *ptr) int ConicTo(const FT_Vector *control, const FT_Vector *to, - void *ptr) -{ + void *ptr) { User *user = (User*)ptr; Point prev = user->ring.back(); @@ -406,8 +410,8 @@ int ConicTo(const FT_Vector *control, user->ring.pop_back(); agg_fontnik::curve3_div curve(prev.get<0>(), prev.get<1>(), - float(control->x) / 64, float(control->y) / 64, - float(to->x) / 64, float(to->y) / 64); + float(control->x) / 64, float(control->y) / 64, + float(to->x) / 64, float(to->y) / 64); curve.rewind(0); double x, y; @@ -423,8 +427,7 @@ int ConicTo(const FT_Vector *control, int CubicTo(const FT_Vector *c1, const FT_Vector *c2, const FT_Vector *to, - void *ptr) -{ + void *ptr) { User *user = (User*)ptr; Point prev = user->ring.back(); @@ -433,9 +436,9 @@ int CubicTo(const FT_Vector *c1, user->ring.pop_back(); agg_fontnik::curve4_div curve(prev.get<0>(), prev.get<1>(), - float(c1->x) / 64, float(c1->y) / 64, - float(c2->x) / 64, float(c2->y) / 64, - float(to->x) / 64, float(to->y) / 64); + float(c1->x) / 64, float(c1->y) / 64, + float(c2->x) / 64, float(c2->y) / 64, + float(to->x) / 64, float(to->y) / 64); curve.rewind(0); double x, y; @@ -449,8 +452,7 @@ int CubicTo(const FT_Vector *c1, } // point in polygon ray casting algorithm -bool PolyContainsPoint(const Rings &rings, const Point &p) -{ +bool PolyContainsPoint(const Rings &rings, const Point &p) { bool c = false; for (const Points &ring : rings) { @@ -467,8 +469,7 @@ bool PolyContainsPoint(const Rings &rings, const Point &p) return c; } -double SquaredDistance(const Point &v, const Point &w) -{ +double SquaredDistance(const Point &v, const Point &w) { const double a = v.get<0>() - w.get<0>(); const double b = v.get<1>() - w.get<1>(); return a * a + b * b; @@ -476,8 +477,7 @@ double SquaredDistance(const Point &v, const Point &w) Point ProjectPointOnLineSegment(const Point &p, const Point &v, - const Point &w) -{ + const Point &w) { const double l2 = SquaredDistance(v, w); if (l2 == 0) return v; @@ -493,16 +493,14 @@ Point ProjectPointOnLineSegment(const Point &p, double SquaredDistanceToLineSegment(const Point &p, const Point &v, - const Point &w) -{ + const Point &w) { const Point s = ProjectPointOnLineSegment(p, v, w); return SquaredDistance(p, s); } double MinDistanceToLineSegment(const Tree &tree, const Point &p, - int radius) -{ + int radius) { const int squared_radius = radius * radius; std::vector results; @@ -529,12 +527,10 @@ double MinDistanceToLineSegment(const Tree &tree, } void RenderSDF(glyph_info &glyph, - int size, - int buffer, - float cutoff, - FT_Face ft_face) -{ - + int size, + int buffer, + float cutoff, + FT_Face ft_face) { if (FT_Load_Glyph (ft_face, glyph.glyph_index, FT_LOAD_NO_HINTING)) { return; } @@ -611,8 +607,8 @@ void RenderSDF(glyph_info &glyph, glyph.height = bbox_ymax - bbox_ymin; Tree tree; - float offset = 0.5; - int radius = 8; + float offset = offset_size; + int radius = radius_size; for (const Points &ring : user.rings) { auto p1 = ring.begin(); @@ -651,7 +647,7 @@ void RenderSDF(glyph_info &glyph, double d = MinDistanceToLineSegment(tree, Point {x + offset, y + offset}, radius) * (256 / radius); // Invert if point is inside. - const bool inside = PolyContainsPoint(user.rings, Point { x + offset, y + offset }); + const bool inside = PolyContainsPoint(user.rings, Point {x + offset, y + offset}); if (inside) { d = -d; } @@ -663,8 +659,9 @@ void RenderSDF(glyph_info &glyph, // Clamp to 0-255 to prevent overflows or underflows. int n = d > 255 ? 255 : d; n = n < 0 ? 0 : n; + n = ((255 - n) / granularity) * granularity; - glyph.bitmap[i] = static_cast(255 - n); + glyph.bitmap[i] = static_cast(n); } } } diff --git a/src/glyphs.hpp b/src/glyphs.hpp index 22e02c57f..002b43cd4 100644 --- a/src/glyphs.hpp +++ b/src/glyphs.hpp @@ -1,5 +1,4 @@ -#ifndef NODE_FONTNIK_GLYPHS_HPP -#define NODE_FONTNIK_GLYPHS_HPP +#pragma once #include "glyphs.pb.h" @@ -7,32 +6,16 @@ #include // freetype2 -extern "C" -{ +extern "C" { #include #include FT_FREETYPE_H #include FT_GLYPH_H #include FT_OUTLINE_H } -namespace node_fontnik -{ +namespace node_fontnik { -NAN_METHOD(Load); -void LoadAsync(uv_work_t* req); -void AfterLoad(uv_work_t* req); -NAN_METHOD(Range); -void RangeAsync(uv_work_t* req); -void AfterRange(uv_work_t* req); -struct glyph_info; -void RenderSDF(glyph_info &glyph, - int size, - int buffer, - float cutoff, - FT_Face ft_face); - -struct glyph_info -{ +struct glyph_info { glyph_info() : glyph_index(0), bitmap(""), @@ -62,7 +45,27 @@ struct glyph_info double descender; }; +NAN_METHOD(Load); +void LoadAsync(uv_work_t* req); +void AfterLoad(uv_work_t* req); + +NAN_METHOD(Range); +void RangeAsync(uv_work_t* req); +void AfterRange(uv_work_t* req); -} // ns node_fontnik +void RenderSDF(glyph_info &glyph, + int size, + int buffer, + float cutoff, + FT_Face ft_face); -#endif // NODE_FONTNIK_GLYPHS_HPP +const static int char_size = 24; +const static int buffer_size = 3; +const static float cutoff_size = 0.25; +const static float scale_factor = 1.0; +const static int granularity = 1; + +const static float offset_size = 0.5; +const static int radius_size = 1; + +} // ns node_fontnik diff --git a/src/node_fontnik.cpp b/src/node_fontnik.cpp index 9f1627ab6..c1f6a5eda 100644 --- a/src/node_fontnik.cpp +++ b/src/node_fontnik.cpp @@ -5,13 +5,11 @@ #include #include -namespace node_fontnik -{ +namespace node_fontnik { void RegisterModule(v8::Handle target) { NODE_SET_METHOD(target, "load", node_fontnik::Load); NODE_SET_METHOD(target, "range", node_fontnik::Range); - } NODE_MODULE(fontnik, RegisterModule); diff --git a/test/expected/range.json b/test/expected/range.json index 813a004f2..4e96e3456 100644 --- a/test/expected/range.json +++ b/test/expected/range.json @@ -7,7 +7,7 @@ "width": 0, "height": 0, "left": 0, - "top": -26, + "top": 0, "advance": 6 }, "33": { @@ -15,7 +15,7 @@ "width": 3, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 6 }, "34": { @@ -23,7 +23,7 @@ "width": 6, "height": 6, "left": 2, - "top": -9, + "top": 17, "advance": 9 }, "35": { @@ -31,7 +31,7 @@ "width": 14, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 15 }, "36": { @@ -39,7 +39,7 @@ "width": 10, "height": 19, "left": 2, - "top": -8, + "top": 18, "advance": 13 }, "37": { @@ -47,7 +47,7 @@ "width": 18, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 19 }, "38": { @@ -55,7 +55,7 @@ "width": 16, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 17 }, "39": { @@ -63,7 +63,7 @@ "width": 2, "height": 6, "left": 2, - "top": -9, + "top": 17, "advance": 5 }, "40": { @@ -71,7 +71,7 @@ "width": 5, "height": 21, "left": 1, - "top": -9, + "top": 17, "advance": 7 }, "41": { @@ -79,7 +79,7 @@ "width": 5, "height": 21, "left": 1, - "top": -9, + "top": 17, "advance": 7 }, "42": { @@ -87,7 +87,7 @@ "width": 11, "height": 11, "left": 1, - "top": -8, + "top": 18, "advance": 13 }, "43": { @@ -95,7 +95,7 @@ "width": 11, "height": 11, "left": 1, - "top": -12, + "top": 14, "advance": 13 }, "44": { @@ -103,7 +103,7 @@ "width": 3, "height": 6, "left": 1, - "top": -23, + "top": 3, "advance": 5 }, "45": { @@ -111,7 +111,7 @@ "width": 6, "height": 1, "left": 1, - "top": -19, + "top": 7, "advance": 7 }, "46": { @@ -119,7 +119,7 @@ "width": 3, "height": 3, "left": 2, - "top": -23, + "top": 3, "advance": 6 }, "47": { @@ -127,7 +127,7 @@ "width": 9, "height": 17, "left": 0, - "top": -9, + "top": 17, "advance": 8 }, "48": { @@ -135,7 +135,7 @@ "width": 12, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 13 }, "49": { @@ -143,7 +143,7 @@ "width": 6, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 13 }, "50": { @@ -151,7 +151,7 @@ "width": 11, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 13 }, "51": { @@ -159,7 +159,7 @@ "width": 11, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 13 }, "52": { @@ -167,7 +167,7 @@ "width": 12, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 13 }, "53": { @@ -175,7 +175,7 @@ "width": 10, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 13 }, "54": { @@ -183,7 +183,7 @@ "width": 12, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 13 }, "55": { @@ -191,7 +191,7 @@ "width": 12, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 13 }, "56": { @@ -199,7 +199,7 @@ "width": 11, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 13 }, "57": { @@ -207,7 +207,7 @@ "width": 11, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 13 }, "58": { @@ -215,7 +215,7 @@ "width": 3, "height": 13, "left": 2, - "top": -13, + "top": 13, "advance": 6 }, "59": { @@ -223,7 +223,7 @@ "width": 4, "height": 16, "left": 1, - "top": -13, + "top": 13, "advance": 6 }, "60": { @@ -231,7 +231,7 @@ "width": 11, "height": 12, "left": 1, - "top": -11, + "top": 15, "advance": 13 }, "61": { @@ -239,7 +239,7 @@ "width": 11, "height": 7, "left": 1, - "top": -14, + "top": 12, "advance": 13 }, "62": { @@ -247,7 +247,7 @@ "width": 11, "height": 12, "left": 1, - "top": -11, + "top": 15, "advance": 13 }, "63": { @@ -255,7 +255,7 @@ "width": 10, "height": 17, "left": 0, - "top": -9, + "top": 17, "advance": 10 }, "64": { @@ -263,7 +263,7 @@ "width": 19, "height": 19, "left": 1, - "top": -9, + "top": 17, "advance": 21 }, "65": { @@ -271,7 +271,7 @@ "width": 15, "height": 17, "left": 0, - "top": -9, + "top": 17, "advance": 15 }, "66": { @@ -279,7 +279,7 @@ "width": 12, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 15 }, "67": { @@ -287,7 +287,7 @@ "width": 13, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 15 }, "68": { @@ -295,7 +295,7 @@ "width": 14, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 17 }, "69": { @@ -303,7 +303,7 @@ "width": 10, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 13 }, "70": { @@ -311,7 +311,7 @@ "width": 10, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 12 }, "71": { @@ -319,7 +319,7 @@ "width": 15, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 17 }, "72": { @@ -327,7 +327,7 @@ "width": 13, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 17 }, "73": { @@ -335,7 +335,7 @@ "width": 2, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 6 }, "74": { @@ -343,7 +343,7 @@ "width": 6, "height": 22, "left": -2, - "top": -9, + "top": 17, "advance": 6 }, "75": { @@ -351,7 +351,7 @@ "width": 13, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 14 }, "76": { @@ -359,7 +359,7 @@ "width": 10, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 12 }, "77": { @@ -367,7 +367,7 @@ "width": 17, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 21 }, "78": { @@ -375,7 +375,7 @@ "width": 14, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 18 }, "79": { @@ -383,7 +383,7 @@ "width": 16, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 18 }, "80": { @@ -391,7 +391,7 @@ "width": 11, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 14 }, "81": { @@ -399,7 +399,7 @@ "width": 16, "height": 21, "left": 1, - "top": -9, + "top": 17, "advance": 18 }, "82": { @@ -407,7 +407,7 @@ "width": 12, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 14 }, "83": { @@ -415,7 +415,7 @@ "width": 11, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 13 }, "84": { @@ -423,7 +423,7 @@ "width": 13, "height": 17, "left": 0, - "top": -9, + "top": 17, "advance": 13 }, "85": { @@ -431,7 +431,7 @@ "width": 13, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 17 }, "86": { @@ -439,7 +439,7 @@ "width": 14, "height": 17, "left": 0, - "top": -9, + "top": 17, "advance": 14 }, "87": { @@ -447,7 +447,7 @@ "width": 22, "height": 17, "left": 0, - "top": -9, + "top": 17, "advance": 22 }, "88": { @@ -455,7 +455,7 @@ "width": 14, "height": 17, "left": 0, - "top": -9, + "top": 17, "advance": 13 }, "89": { @@ -463,7 +463,7 @@ "width": 13, "height": 17, "left": 0, - "top": -9, + "top": 17, "advance": 13 }, "90": { @@ -471,7 +471,7 @@ "width": 12, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 13 }, "91": { @@ -479,7 +479,7 @@ "width": 5, "height": 21, "left": 2, - "top": -9, + "top": 17, "advance": 7 }, "92": { @@ -487,7 +487,7 @@ "width": 9, "height": 17, "left": 0, - "top": -9, + "top": 17, "advance": 8 }, "93": { @@ -495,7 +495,7 @@ "width": 5, "height": 21, "left": 1, - "top": -9, + "top": 17, "advance": 7 }, "94": { @@ -503,7 +503,7 @@ "width": 11, "height": 11, "left": 1, - "top": -9, + "top": 17, "advance": 13 }, "95": { @@ -511,7 +511,7 @@ "width": 11, "height": 2, "left": 0, - "top": -28, + "top": -2, "advance": 10 }, "96": { @@ -519,7 +519,7 @@ "width": 4, "height": 3, "left": 5, - "top": -8, + "top": 18, "advance": 13 }, "97": { @@ -527,7 +527,7 @@ "width": 10, "height": 13, "left": 1, - "top": -13, + "top": 13, "advance": 13 }, "98": { @@ -535,7 +535,7 @@ "width": 11, "height": 18, "left": 2, - "top": -8, + "top": 18, "advance": 14 }, "99": { @@ -543,7 +543,7 @@ "width": 10, "height": 13, "left": 1, - "top": -13, + "top": 13, "advance": 11 }, "100": { @@ -551,7 +551,7 @@ "width": 12, "height": 18, "left": 1, - "top": -8, + "top": 18, "advance": 14 }, "101": { @@ -559,7 +559,7 @@ "width": 11, "height": 13, "left": 1, - "top": -13, + "top": 13, "advance": 13 }, "102": { @@ -567,7 +567,7 @@ "width": 9, "height": 18, "left": 0, - "top": -8, + "top": 18, "advance": 8 }, "103": { @@ -575,7 +575,7 @@ "width": 13, "height": 19, "left": 0, - "top": -13, + "top": 13, "advance": 13 }, "104": { @@ -583,7 +583,7 @@ "width": 11, "height": 18, "left": 2, - "top": -8, + "top": 18, "advance": 14 }, "105": { @@ -591,7 +591,7 @@ "width": 2, "height": 18, "left": 2, - "top": -8, + "top": 18, "advance": 6 }, "106": { @@ -599,7 +599,7 @@ "width": 5, "height": 24, "left": -1, - "top": -8, + "top": 18, "advance": 6 }, "107": { @@ -607,7 +607,7 @@ "width": 10, "height": 18, "left": 2, - "top": -8, + "top": 18, "advance": 12 }, "108": { @@ -615,7 +615,7 @@ "width": 2, "height": 18, "left": 2, - "top": -8, + "top": 18, "advance": 6 }, "109": { @@ -623,7 +623,7 @@ "width": 18, "height": 13, "left": 2, - "top": -13, + "top": 13, "advance": 22 }, "110": { @@ -631,7 +631,7 @@ "width": 11, "height": 13, "left": 2, - "top": -13, + "top": 13, "advance": 14 }, "111": { @@ -639,7 +639,7 @@ "width": 12, "height": 13, "left": 1, - "top": -13, + "top": 13, "advance": 14 }, "112": { @@ -647,7 +647,7 @@ "width": 11, "height": 19, "left": 2, - "top": -13, + "top": 13, "advance": 14 }, "113": { @@ -655,7 +655,7 @@ "width": 12, "height": 19, "left": 1, - "top": -13, + "top": 13, "advance": 14 }, "114": { @@ -663,7 +663,7 @@ "width": 7, "height": 13, "left": 2, - "top": -13, + "top": 13, "advance": 9 }, "115": { @@ -671,7 +671,7 @@ "width": 9, "height": 13, "left": 1, - "top": -13, + "top": 13, "advance": 11 }, "116": { @@ -679,7 +679,7 @@ "width": 8, "height": 16, "left": 0, - "top": -10, + "top": 16, "advance": 8 }, "117": { @@ -687,7 +687,7 @@ "width": 11, "height": 13, "left": 2, - "top": -13, + "top": 13, "advance": 14 }, "118": { @@ -695,7 +695,7 @@ "width": 12, "height": 13, "left": 0, - "top": -13, + "top": 13, "advance": 12 }, "119": { @@ -703,7 +703,7 @@ "width": 18, "height": 13, "left": 0, - "top": -13, + "top": 13, "advance": 18 }, "120": { @@ -711,7 +711,7 @@ "width": 12, "height": 13, "left": 0, - "top": -13, + "top": 13, "advance": 12 }, "121": { @@ -719,7 +719,7 @@ "width": 12, "height": 19, "left": 0, - "top": -13, + "top": 13, "advance": 12 }, "122": { @@ -727,7 +727,7 @@ "width": 9, "height": 13, "left": 1, - "top": -13, + "top": 13, "advance": 11 }, "123": { @@ -735,7 +735,7 @@ "width": 7, "height": 21, "left": 1, - "top": -9, + "top": 17, "advance": 9 }, "124": { @@ -743,7 +743,7 @@ "width": 1, "height": 24, "left": 6, - "top": -8, + "top": 18, "advance": 13 }, "125": { @@ -751,7 +751,7 @@ "width": 7, "height": 21, "left": 1, - "top": -9, + "top": 17, "advance": 9 }, "126": { @@ -759,7 +759,7 @@ "width": 11, "height": 3, "left": 1, - "top": -16, + "top": 10, "advance": 13 }, "160": { @@ -767,7 +767,7 @@ "width": 0, "height": 0, "left": 0, - "top": -26, + "top": 0, "advance": 6 }, "161": { @@ -775,7 +775,7 @@ "width": 3, "height": 17, "left": 2, - "top": -13, + "top": 13, "advance": 6 }, "162": { @@ -783,7 +783,7 @@ "width": 10, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 13 }, "163": { @@ -791,7 +791,7 @@ "width": 12, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 13 }, "164": { @@ -799,7 +799,7 @@ "width": 11, "height": 11, "left": 1, - "top": -12, + "top": 14, "advance": 13 }, "165": { @@ -807,7 +807,7 @@ "width": 13, "height": 17, "left": 0, - "top": -9, + "top": 17, "advance": 13 }, "166": { @@ -815,7 +815,7 @@ "width": 1, "height": 24, "left": 6, - "top": -8, + "top": 18, "advance": 13 }, "167": { @@ -823,7 +823,7 @@ "width": 10, "height": 18, "left": 1, - "top": -8, + "top": 18, "advance": 12 }, "168": { @@ -831,7 +831,7 @@ "width": 6, "height": 2, "left": 4, - "top": -9, + "top": 17, "advance": 13 }, "169": { @@ -839,7 +839,7 @@ "width": 18, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 19 }, "170": { @@ -847,7 +847,7 @@ "width": 6, "height": 8, "left": 1, - "top": -9, + "top": 17, "advance": 8 }, "171": { @@ -855,7 +855,7 @@ "width": 10, "height": 10, "left": 1, - "top": -15, + "top": 11, "advance": 11 }, "172": { @@ -863,7 +863,7 @@ "width": 11, "height": 6, "left": 1, - "top": -17, + "top": 9, "advance": 13 }, "173": { @@ -871,7 +871,7 @@ "width": 6, "height": 1, "left": 1, - "top": -19, + "top": 7, "advance": 7 }, "174": { @@ -879,7 +879,7 @@ "width": 18, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 19 }, "175": { @@ -887,7 +887,7 @@ "width": 12, "height": 2, "left": 0, - "top": -6, + "top": 20, "advance": 12 }, "176": { @@ -895,7 +895,7 @@ "width": 8, "height": 7, "left": 1, - "top": -9, + "top": 17, "advance": 10 }, "177": { @@ -903,7 +903,7 @@ "width": 11, "height": 14, "left": 1, - "top": -12, + "top": 14, "advance": 13 }, "178": { @@ -911,7 +911,7 @@ "width": 7, "height": 10, "left": 1, - "top": -9, + "top": 17, "advance": 8 }, "179": { @@ -919,7 +919,7 @@ "width": 8, "height": 10, "left": 0, - "top": -9, + "top": 17, "advance": 8 }, "180": { @@ -927,7 +927,7 @@ "width": 4, "height": 3, "left": 5, - "top": -8, + "top": 18, "advance": 13 }, "181": { @@ -935,7 +935,7 @@ "width": 11, "height": 19, "left": 2, - "top": -13, + "top": 13, "advance": 14 }, "182": { @@ -943,7 +943,7 @@ "width": 12, "height": 21, "left": 1, - "top": -8, + "top": 18, "advance": 15 }, "183": { @@ -951,7 +951,7 @@ "width": 3, "height": 3, "left": 2, - "top": -16, + "top": 10, "advance": 6 }, "184": { @@ -959,7 +959,7 @@ "width": 5, "height": 6, "left": 0, - "top": -26, + "top": 0, "advance": 5 }, "185": { @@ -967,7 +967,7 @@ "width": 5, "height": 10, "left": 1, - "top": -9, + "top": 17, "advance": 8 }, "186": { @@ -975,7 +975,7 @@ "width": 7, "height": 8, "left": 1, - "top": -9, + "top": 17, "advance": 9 }, "187": { @@ -983,7 +983,7 @@ "width": 10, "height": 10, "left": 1, - "top": -15, + "top": 11, "advance": 11 }, "188": { @@ -991,7 +991,7 @@ "width": 16, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 18 }, "189": { @@ -999,7 +999,7 @@ "width": 17, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 18 }, "190": { @@ -1007,7 +1007,7 @@ "width": 18, "height": 17, "left": 0, - "top": -9, + "top": 17, "advance": 18 }, "191": { @@ -1015,7 +1015,7 @@ "width": 9, "height": 18, "left": 1, - "top": -13, + "top": 13, "advance": 10 }, "192": { @@ -1023,7 +1023,7 @@ "width": 15, "height": 22, "left": 0, - "top": -4, + "top": 22, "advance": 15 }, "193": { @@ -1031,7 +1031,7 @@ "width": 15, "height": 22, "left": 0, - "top": -4, + "top": 22, "advance": 15 }, "194": { @@ -1039,7 +1039,7 @@ "width": 15, "height": 22, "left": 0, - "top": -4, + "top": 22, "advance": 15 }, "195": { @@ -1047,7 +1047,7 @@ "width": 15, "height": 22, "left": 0, - "top": -4, + "top": 22, "advance": 15 }, "196": { @@ -1055,7 +1055,7 @@ "width": 15, "height": 21, "left": 0, - "top": -5, + "top": 21, "advance": 15 }, "197": { @@ -1063,7 +1063,7 @@ "width": 15, "height": 22, "left": 0, - "top": -4, + "top": 22, "advance": 15 }, "198": { @@ -1071,7 +1071,7 @@ "width": 20, "height": 17, "left": 0, - "top": -9, + "top": 17, "advance": 20 }, "199": { @@ -1079,7 +1079,7 @@ "width": 13, "height": 23, "left": 1, - "top": -9, + "top": 17, "advance": 15 }, "200": { @@ -1087,7 +1087,7 @@ "width": 10, "height": 22, "left": 2, - "top": -4, + "top": 22, "advance": 13 }, "201": { @@ -1095,7 +1095,7 @@ "width": 10, "height": 22, "left": 2, - "top": -4, + "top": 22, "advance": 13 }, "202": { @@ -1103,7 +1103,7 @@ "width": 10, "height": 22, "left": 2, - "top": -4, + "top": 22, "advance": 13 }, "203": { @@ -1111,7 +1111,7 @@ "width": 10, "height": 21, "left": 2, - "top": -5, + "top": 21, "advance": 13 }, "204": { @@ -1119,7 +1119,7 @@ "width": 4, "height": 22, "left": 0, - "top": -4, + "top": 22, "advance": 6 }, "205": { @@ -1127,7 +1127,7 @@ "width": 4, "height": 22, "left": 2, - "top": -4, + "top": 22, "advance": 6 }, "206": { @@ -1135,7 +1135,7 @@ "width": 8, "height": 22, "left": -1, - "top": -4, + "top": 22, "advance": 6 }, "207": { @@ -1143,7 +1143,7 @@ "width": 6, "height": 21, "left": 0, - "top": -5, + "top": 21, "advance": 6 }, "208": { @@ -1151,7 +1151,7 @@ "width": 15, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 17 }, "209": { @@ -1159,7 +1159,7 @@ "width": 14, "height": 22, "left": 2, - "top": -4, + "top": 22, "advance": 18 }, "210": { @@ -1167,7 +1167,7 @@ "width": 16, "height": 22, "left": 1, - "top": -4, + "top": 22, "advance": 18 }, "211": { @@ -1175,7 +1175,7 @@ "width": 16, "height": 22, "left": 1, - "top": -4, + "top": 22, "advance": 18 }, "212": { @@ -1183,7 +1183,7 @@ "width": 16, "height": 22, "left": 1, - "top": -4, + "top": 22, "advance": 18 }, "213": { @@ -1191,7 +1191,7 @@ "width": 16, "height": 22, "left": 1, - "top": -4, + "top": 22, "advance": 18 }, "214": { @@ -1199,7 +1199,7 @@ "width": 16, "height": 21, "left": 1, - "top": -5, + "top": 21, "advance": 18 }, "215": { @@ -1207,7 +1207,7 @@ "width": 10, "height": 11, "left": 2, - "top": -12, + "top": 14, "advance": 13 }, "216": { @@ -1215,7 +1215,7 @@ "width": 16, "height": 19, "left": 1, - "top": -8, + "top": 18, "advance": 18 }, "217": { @@ -1223,7 +1223,7 @@ "width": 13, "height": 22, "left": 2, - "top": -4, + "top": 22, "advance": 17 }, "218": { @@ -1231,7 +1231,7 @@ "width": 13, "height": 22, "left": 2, - "top": -4, + "top": 22, "advance": 17 }, "219": { @@ -1239,7 +1239,7 @@ "width": 13, "height": 22, "left": 2, - "top": -4, + "top": 22, "advance": 17 }, "220": { @@ -1247,7 +1247,7 @@ "width": 13, "height": 21, "left": 2, - "top": -5, + "top": 21, "advance": 17 }, "221": { @@ -1255,7 +1255,7 @@ "width": 13, "height": 22, "left": 0, - "top": -4, + "top": 22, "advance": 13 }, "222": { @@ -1263,7 +1263,7 @@ "width": 11, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 14 }, "223": { @@ -1271,7 +1271,7 @@ "width": 12, "height": 18, "left": 2, - "top": -8, + "top": 18, "advance": 14 }, "224": { @@ -1279,7 +1279,7 @@ "width": 10, "height": 18, "left": 1, - "top": -8, + "top": 18, "advance": 13 }, "225": { @@ -1287,7 +1287,7 @@ "width": 10, "height": 18, "left": 1, - "top": -8, + "top": 18, "advance": 13 }, "226": { @@ -1295,7 +1295,7 @@ "width": 10, "height": 18, "left": 1, - "top": -8, + "top": 18, "advance": 13 }, "227": { @@ -1303,7 +1303,7 @@ "width": 10, "height": 18, "left": 1, - "top": -8, + "top": 18, "advance": 13 }, "228": { @@ -1311,7 +1311,7 @@ "width": 10, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 13 }, "229": { @@ -1319,7 +1319,7 @@ "width": 10, "height": 20, "left": 1, - "top": -6, + "top": 20, "advance": 13 }, "230": { @@ -1327,7 +1327,7 @@ "width": 18, "height": 13, "left": 1, - "top": -13, + "top": 13, "advance": 20 }, "231": { @@ -1335,7 +1335,7 @@ "width": 10, "height": 19, "left": 1, - "top": -13, + "top": 13, "advance": 11 }, "232": { @@ -1343,7 +1343,7 @@ "width": 11, "height": 18, "left": 1, - "top": -8, + "top": 18, "advance": 13 }, "233": { @@ -1351,7 +1351,7 @@ "width": 11, "height": 18, "left": 1, - "top": -8, + "top": 18, "advance": 13 }, "234": { @@ -1359,7 +1359,7 @@ "width": 11, "height": 18, "left": 1, - "top": -8, + "top": 18, "advance": 13 }, "235": { @@ -1367,7 +1367,7 @@ "width": 11, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 13 }, "236": { @@ -1375,7 +1375,7 @@ "width": 4, "height": 18, "left": 0, - "top": -8, + "top": 18, "advance": 6 }, "237": { @@ -1383,7 +1383,7 @@ "width": 4, "height": 18, "left": 2, - "top": -8, + "top": 18, "advance": 6 }, "238": { @@ -1391,7 +1391,7 @@ "width": 8, "height": 18, "left": -1, - "top": -8, + "top": 18, "advance": 6 }, "239": { @@ -1399,7 +1399,7 @@ "width": 6, "height": 17, "left": 0, - "top": -9, + "top": 17, "advance": 6 }, "240": { @@ -1407,7 +1407,7 @@ "width": 12, "height": 18, "left": 1, - "top": -8, + "top": 18, "advance": 14 }, "241": { @@ -1415,7 +1415,7 @@ "width": 11, "height": 18, "left": 2, - "top": -8, + "top": 18, "advance": 14 }, "242": { @@ -1423,7 +1423,7 @@ "width": 12, "height": 18, "left": 1, - "top": -8, + "top": 18, "advance": 14 }, "243": { @@ -1431,7 +1431,7 @@ "width": 12, "height": 18, "left": 1, - "top": -8, + "top": 18, "advance": 14 }, "244": { @@ -1439,7 +1439,7 @@ "width": 12, "height": 18, "left": 1, - "top": -8, + "top": 18, "advance": 14 }, "245": { @@ -1447,7 +1447,7 @@ "width": 12, "height": 18, "left": 1, - "top": -8, + "top": 18, "advance": 14 }, "246": { @@ -1455,7 +1455,7 @@ "width": 12, "height": 17, "left": 1, - "top": -9, + "top": 17, "advance": 14 }, "247": { @@ -1463,7 +1463,7 @@ "width": 11, "height": 11, "left": 1, - "top": -12, + "top": 14, "advance": 13 }, "248": { @@ -1471,7 +1471,7 @@ "width": 12, "height": 15, "left": 1, - "top": -12, + "top": 14, "advance": 14 }, "249": { @@ -1479,7 +1479,7 @@ "width": 11, "height": 18, "left": 2, - "top": -8, + "top": 18, "advance": 14 }, "250": { @@ -1487,7 +1487,7 @@ "width": 11, "height": 18, "left": 2, - "top": -8, + "top": 18, "advance": 14 }, "251": { @@ -1495,7 +1495,7 @@ "width": 11, "height": 18, "left": 2, - "top": -8, + "top": 18, "advance": 14 }, "252": { @@ -1503,7 +1503,7 @@ "width": 11, "height": 17, "left": 2, - "top": -9, + "top": 17, "advance": 14 }, "253": { @@ -1511,7 +1511,7 @@ "width": 12, "height": 24, "left": 0, - "top": -8, + "top": 18, "advance": 12 }, "254": { @@ -1519,7 +1519,7 @@ "width": 11, "height": 24, "left": 2, - "top": -8, + "top": 18, "advance": 14 }, "255": { @@ -1527,7 +1527,7 @@ "width": 12, "height": 23, "left": 0, - "top": -9, + "top": 17, "advance": 12 }, "256": { @@ -1535,7 +1535,7 @@ "width": 15, "height": 20, "left": 0, - "top": -6, + "top": 20, "advance": 15 } },