diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 95b3a7ca..6c004e4c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -102,7 +102,15 @@ add_custom_command( ${chars} DEPENDS unifont2c ${chars}) +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/generated/vectorfont.table.h" + COMMAND $ + "${CMAKE_CURRENT_BINARY_DIR}/generated/vectorfont.table.h" + "${CMAKE_CURRENT_SOURCE_DIR}/fonts/unicode.lff.gz" + DEPENDS lff2c ${chars}) + set(generated_HEADERS + ${CMAKE_CURRENT_BINARY_DIR}/generated/vectorfont.table.h ${CMAKE_CURRENT_BINARY_DIR}/generated/bitmapfont.table.h ${CMAKE_CURRENT_BINARY_DIR}/generated/icons.h) @@ -236,7 +244,6 @@ set(solvespace_HEADERS config.h dsc.h expr.h - font.table.h polygon.h sketch.h solvespace.h diff --git a/src/drawconstraint.cpp b/src/drawconstraint.cpp index f9b8f9b0..ef97bfda 100644 --- a/src/drawconstraint.cpp +++ b/src/drawconstraint.cpp @@ -93,7 +93,7 @@ void Constraint::DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu) { } std::string s = Label(); - double swidth = ssglStrWidth(s.c_str(), th), + double swidth = ssglStrWidth(s, th), sheight = ssglStrHeight(th); // By default, the reference is from the center; but the style could @@ -164,7 +164,7 @@ int Constraint::DoLineTrimmedAgainstBox(Vector ref, Vector a, Vector b) { double pixels = 1.0 / SS.GW.scale; std::string s = Label(); - double swidth = ssglStrWidth(s.c_str(), DEFAULT_TEXT_HEIGHT) + 4*pixels, + double swidth = ssglStrWidth(s, DEFAULT_TEXT_HEIGHT) + 4*pixels, sheight = ssglStrHeight(DEFAULT_TEXT_HEIGHT) + 8*pixels; struct { @@ -370,7 +370,7 @@ void Constraint::DoArcForAngle(Vector a0, Vector da, Vector b0, Vector db, // complex and this looks pretty good. double tl = atan2(rm.Dot(gu), rm.Dot(gr)); double adj = EllipticalInterpolation( - ssglStrWidth(Label().c_str(), DEFAULT_TEXT_HEIGHT)/2, + ssglStrWidth(Label(), DEFAULT_TEXT_HEIGHT)/2, ssglStrHeight(DEFAULT_TEXT_HEIGHT)/2, tl); *ref = (*ref).Plus(rm.WithMagnitude(adj + 3/SS.GW.scale)); diff --git a/src/drawentity.cpp b/src/drawentity.cpp index 759c0359..6d1233ac 100644 --- a/src/drawentity.cpp +++ b/src/drawentity.cpp @@ -614,7 +614,7 @@ void Entity::DrawOrGetDistance(void) { if(dogd.drawing) { ssglWriteText(str.c_str(), th, mm2, u, v, NULL, NULL); } else { - Vector pos = mm2.Plus(u.ScaledBy(ssglStrWidth(str.c_str(), th)/2)).Plus( + Vector pos = mm2.Plus(u.ScaledBy(ssglStrWidth(str, th)/2)).Plus( v.ScaledBy(ssglStrHeight(th)/2)); Point2d pp = SS.GW.ProjectPoint(pos); dogd.dmin = min(dogd.dmin, pp.DistanceTo(dogd.mp) - 10); diff --git a/src/font.table.h b/src/font.table.h deleted file mode 100644 index 2bfc93d8..00000000 --- a/src/font.table.h +++ /dev/null @@ -1,1774 +0,0 @@ - - -#define PEN_UP 127 - -static const struct { - int points; - int width; - signed char coord[120]; -} Font[] = { - // character 32 (' ') - { 0, 16, - { 1 - } - }, - - // character 33 ('!') - { 8, 10, - { - 5, 21, - 5, 7, - PEN_UP, PEN_UP, - 5, 2, - 4, 1, - 5, 0, - 6, 1, - 5, 2, - } - }, - - // character 34 ('"') - { 5, 16, - { - 4, 21, - 4, 14, - PEN_UP, PEN_UP, - 12, 21, - 12, 14, - } - }, - - // character 35 ('#') - { 11, 21, - { - 11, 25, - 4, -7, - PEN_UP, PEN_UP, - 17, 25, - 10, -7, - PEN_UP, PEN_UP, - 4, 12, - 18, 12, - PEN_UP, PEN_UP, - 3, 6, - 17, 6, - } - }, - - // character 36 ('$') - { 26, 20, - { - 8, 25, - 8, -4, - PEN_UP, PEN_UP, - 12, 25, - 12, -4, - PEN_UP, PEN_UP, - 17, 18, - 15, 20, - 12, 21, - 8, 21, - 5, 20, - 3, 18, - 3, 16, - 4, 14, - 5, 13, - 7, 12, - 13, 10, - 15, 9, - 16, 8, - 17, 6, - 17, 3, - 15, 1, - 12, 0, - 8, 0, - 5, 1, - 3, 3, - } - }, - - // character 37 ('%') - { 31, 24, - { - 21, 21, - 3, 0, - PEN_UP, PEN_UP, - 8, 21, - 10, 19, - 10, 17, - 9, 15, - 7, 14, - 5, 14, - 3, 16, - 3, 18, - 4, 20, - 6, 21, - 8, 21, - 10, 20, - 13, 19, - 16, 19, - 19, 20, - 21, 21, - PEN_UP, PEN_UP, - 17, 7, - 15, 6, - 14, 4, - 14, 2, - 16, 0, - 18, 0, - 20, 1, - 21, 3, - 21, 5, - 19, 7, - 17, 7, - } - }, - - // character 38 ('&') - { 34, 26, - { - 23, 12, - 23, 13, - 22, 14, - 21, 14, - 20, 13, - 19, 11, - 17, 6, - 15, 3, - 13, 1, - 11, 0, - 7, 0, - 5, 1, - 4, 2, - 3, 4, - 3, 6, - 4, 8, - 5, 9, - 12, 13, - 13, 14, - 14, 16, - 14, 18, - 13, 20, - 11, 21, - 9, 20, - 8, 18, - 8, 16, - 9, 13, - 11, 10, - 16, 3, - 18, 1, - 20, 0, - 22, 0, - 23, 1, - 23, 2, - } - }, - - // character 39 (''') - { 7, 10, - { - 5, 19, - 4, 20, - 5, 21, - 6, 20, - 6, 18, - 5, 16, - 4, 15, - } - }, - - // character 40 ('(') - { 10, 14, - { - 11, 25, - 9, 23, - 7, 20, - 5, 16, - 4, 11, - 4, 7, - 5, 2, - 7, -2, - 9, -5, - 11, -7, - } - }, - - // character 41 (')') - { 10, 14, - { - 3, 25, - 5, 23, - 7, 20, - 9, 16, - 10, 11, - 10, 7, - 9, 2, - 7, -2, - 5, -5, - 3, -7, - } - }, - - // character 42 ('*') - { 8, 16, - { - 8, 21, - 8, 9, - PEN_UP, PEN_UP, - 3, 18, - 13, 12, - PEN_UP, PEN_UP, - 13, 18, - 3, 12, - } - }, - - // character 43 ('+') - { 5, 26, - { - 13, 18, - 13, 0, - PEN_UP, PEN_UP, - 4, 9, - 22, 9, - } - }, - - // character 44 (',') - { 8, 10, - { - 6, 1, - 5, 0, - 4, 1, - 5, 2, - 6, 1, - 6, -1, - 5, -3, - 4, -4, - } - }, - - // character 45 ('-') - { 2, 26, - { - 4, 9, - 22, 9, - } - }, - - // character 46 ('.') - { 5, 10, - { - 5, 2, - 4, 1, - 5, 0, - 6, 1, - 5, 2, - } - }, - - // character 47 ('/') - { 2, 22, - { - 20, 25, - 2, -7, - } - }, - - // character 48 ('0') - { 17, 20, - { - 9, 21, - 6, 20, - 4, 17, - 3, 12, - 3, 9, - 4, 4, - 6, 1, - 9, 0, - 11, 0, - 14, 1, - 16, 4, - 17, 9, - 17, 12, - 16, 17, - 14, 20, - 11, 21, - 9, 21, - } - }, - - // character 49 ('1') - { 4, 20, - { - 6, 17, - 8, 18, - 11, 21, - 11, 0, - } - }, - - // character 50 ('2') - { 14, 20, - { - 4, 16, - 4, 17, - 5, 19, - 6, 20, - 8, 21, - 12, 21, - 14, 20, - 15, 19, - 16, 17, - 16, 15, - 15, 13, - 13, 10, - 3, 0, - 17, 0, - } - }, - - // character 51 ('3') - { 15, 20, - { - 5, 21, - 16, 21, - 10, 13, - 13, 13, - 15, 12, - 16, 11, - 17, 8, - 17, 6, - 16, 3, - 14, 1, - 11, 0, - 8, 0, - 5, 1, - 4, 2, - 3, 4, - } - }, - - // character 52 ('4') - { 6, 20, - { - 13, 21, - 3, 7, - 18, 7, - PEN_UP, PEN_UP, - 13, 21, - 13, 0, - } - }, - - // character 53 ('5') - { 17, 20, - { - 15, 21, - 5, 21, - 4, 12, - 5, 13, - 8, 14, - 11, 14, - 14, 13, - 16, 11, - 17, 8, - 17, 6, - 16, 3, - 14, 1, - 11, 0, - 8, 0, - 5, 1, - 4, 2, - 3, 4, - } - }, - - // character 54 ('6') - { 23, 20, - { - 16, 18, - 15, 20, - 12, 21, - 10, 21, - 7, 20, - 5, 17, - 4, 12, - 4, 7, - 5, 3, - 7, 1, - 10, 0, - 11, 0, - 14, 1, - 16, 3, - 17, 6, - 17, 7, - 16, 10, - 14, 12, - 11, 13, - 10, 13, - 7, 12, - 5, 10, - 4, 7, - } - }, - - // character 55 ('7') - { 5, 20, - { - 17, 21, - 7, 0, - PEN_UP, PEN_UP, - 3, 21, - 17, 21, - } - }, - - // character 56 ('8') - { 29, 20, - { - 8, 21, - 5, 20, - 4, 18, - 4, 16, - 5, 14, - 7, 13, - 11, 12, - 14, 11, - 16, 9, - 17, 7, - 17, 4, - 16, 2, - 15, 1, - 12, 0, - 8, 0, - 5, 1, - 4, 2, - 3, 4, - 3, 7, - 4, 9, - 6, 11, - 9, 12, - 13, 13, - 15, 14, - 16, 16, - 16, 18, - 15, 20, - 12, 21, - 8, 21, - } - }, - - // character 57 ('9') - { 23, 20, - { - 16, 14, - 15, 11, - 13, 9, - 10, 8, - 9, 8, - 6, 9, - 4, 11, - 3, 14, - 3, 15, - 4, 18, - 6, 20, - 9, 21, - 10, 21, - 13, 20, - 15, 18, - 16, 14, - 16, 9, - 15, 4, - 13, 1, - 10, 0, - 8, 0, - 5, 1, - 4, 3, - } - }, - - // character 58 (':') - { 11, 10, - { - 5, 14, - 4, 13, - 5, 12, - 6, 13, - 5, 14, - PEN_UP, PEN_UP, - 5, 2, - 4, 1, - 5, 0, - 6, 1, - 5, 2, - } - }, - - // character 59 (';') - { 14, 10, - { - 5, 14, - 4, 13, - 5, 12, - 6, 13, - 5, 14, - PEN_UP, PEN_UP, - 6, 1, - 5, 0, - 4, 1, - 5, 2, - 6, 1, - 6, -1, - 5, -3, - 4, -4, - } - }, - - // character 60 ('<') - { 3, 24, - { - 20, 18, - 4, 9, - 20, 0, - } - }, - - // character 61 ('=') - { 5, 26, - { - 4, 12, - 22, 12, - PEN_UP, PEN_UP, - 4, 6, - 22, 6, - } - }, - - // character 62 ('>') - { 3, 24, - { - 4, 18, - 20, 9, - 4, 0, - } - }, - - // character 63 ('?') - { 20, 18, - { - 3, 16, - 3, 17, - 4, 19, - 5, 20, - 7, 21, - 11, 21, - 13, 20, - 14, 19, - 15, 17, - 15, 15, - 14, 13, - 13, 12, - 9, 10, - 9, 7, - PEN_UP, PEN_UP, - 9, 2, - 8, 1, - 9, 0, - 10, 1, - 9, 2, - } - }, - - // character 64 ('@') - { 55, 27, - { - 18, 13, - 17, 15, - 15, 16, - 12, 16, - 10, 15, - 9, 14, - 8, 11, - 8, 8, - 9, 6, - 11, 5, - 14, 5, - 16, 6, - 17, 8, - PEN_UP, PEN_UP, - 12, 16, - 10, 14, - 9, 11, - 9, 8, - 10, 6, - 11, 5, - PEN_UP, PEN_UP, - 18, 16, - 17, 8, - 17, 6, - 19, 5, - 21, 5, - 23, 7, - 24, 10, - 24, 12, - 23, 15, - 22, 17, - 20, 19, - 18, 20, - 15, 21, - 12, 21, - 9, 20, - 7, 19, - 5, 17, - 4, 15, - 3, 12, - 3, 9, - 4, 6, - 5, 4, - 7, 2, - 9, 1, - 12, 0, - 15, 0, - 18, 1, - 20, 2, - 21, 3, - PEN_UP, PEN_UP, - 19, 16, - 18, 8, - 18, 6, - 19, 5, - } - }, - - // character 65 ('A') - { 8, 18, - { - 9, 21, - 1, 0, - PEN_UP, PEN_UP, - 9, 21, - 17, 0, - PEN_UP, PEN_UP, - 4, 7, - 14, 7, - } - }, - - // character 66 ('B') - { 23, 21, - { - 4, 21, - 4, 0, - PEN_UP, PEN_UP, - 4, 21, - 13, 21, - 16, 20, - 17, 19, - 18, 17, - 18, 15, - 17, 13, - 16, 12, - 13, 11, - PEN_UP, PEN_UP, - 4, 11, - 13, 11, - 16, 10, - 17, 9, - 18, 7, - 18, 4, - 17, 2, - 16, 1, - 13, 0, - 4, 0, - } - }, - - // character 67 ('C') - { 18, 21, - { - 18, 16, - 17, 18, - 15, 20, - 13, 21, - 9, 21, - 7, 20, - 5, 18, - 4, 16, - 3, 13, - 3, 8, - 4, 5, - 5, 3, - 7, 1, - 9, 0, - 13, 0, - 15, 1, - 17, 3, - 18, 5, - } - }, - - // character 68 ('D') - { 15, 21, - { - 4, 21, - 4, 0, - PEN_UP, PEN_UP, - 4, 21, - 11, 21, - 14, 20, - 16, 18, - 17, 16, - 18, 13, - 18, 8, - 17, 5, - 16, 3, - 14, 1, - 11, 0, - 4, 0, - } - }, - - // character 69 ('E') - { 11, 19, - { - 4, 21, - 4, 0, - PEN_UP, PEN_UP, - 4, 21, - 17, 21, - PEN_UP, PEN_UP, - 4, 11, - 12, 11, - PEN_UP, PEN_UP, - 4, 0, - 17, 0, - } - }, - - // character 70 ('F') - { 8, 18, - { - 4, 21, - 4, 0, - PEN_UP, PEN_UP, - 4, 21, - 17, 21, - PEN_UP, PEN_UP, - 4, 11, - 12, 11, - } - }, - - // character 71 ('G') - { 22, 21, - { - 18, 16, - 17, 18, - 15, 20, - 13, 21, - 9, 21, - 7, 20, - 5, 18, - 4, 16, - 3, 13, - 3, 8, - 4, 5, - 5, 3, - 7, 1, - 9, 0, - 13, 0, - 15, 1, - 17, 3, - 18, 5, - 18, 8, - PEN_UP, PEN_UP, - 13, 8, - 18, 8, - } - }, - - // character 72 ('H') - { 8, 22, - { - 4, 21, - 4, 0, - PEN_UP, PEN_UP, - 18, 21, - 18, 0, - PEN_UP, PEN_UP, - 4, 11, - 18, 11, - } - }, - - // character 73 ('I') - { 2, 8, - { - 4, 21, - 4, 0, - } - }, - - // character 74 ('J') - { 10, 16, - { - 12, 21, - 12, 5, - 11, 2, - 10, 1, - 8, 0, - 6, 0, - 4, 1, - 3, 2, - 2, 5, - 2, 7, - } - }, - - // character 75 ('K') - { 8, 21, - { - 4, 21, - 4, 0, - PEN_UP, PEN_UP, - 18, 21, - 4, 7, - PEN_UP, PEN_UP, - 9, 12, - 18, 0, - } - }, - - // character 76 ('L') - { 5, 17, - { - 4, 21, - 4, 0, - PEN_UP, PEN_UP, - 4, 0, - 16, 0, - } - }, - - // character 77 ('M') - { 11, 24, - { - 4, 21, - 4, 0, - PEN_UP, PEN_UP, - 4, 21, - 12, 0, - PEN_UP, PEN_UP, - 20, 21, - 12, 0, - PEN_UP, PEN_UP, - 20, 21, - 20, 0, - } - }, - - // character 78 ('N') - { 8, 22, - { - 4, 21, - 4, 0, - PEN_UP, PEN_UP, - 4, 21, - 18, 0, - PEN_UP, PEN_UP, - 18, 21, - 18, 0, - } - }, - - // character 79 ('O') - { 21, 22, - { - 9, 21, - 7, 20, - 5, 18, - 4, 16, - 3, 13, - 3, 8, - 4, 5, - 5, 3, - 7, 1, - 9, 0, - 13, 0, - 15, 1, - 17, 3, - 18, 5, - 19, 8, - 19, 13, - 18, 16, - 17, 18, - 15, 20, - 13, 21, - 9, 21, - } - }, - - // character 80 ('P') - { 13, 21, - { - 4, 21, - 4, 0, - PEN_UP, PEN_UP, - 4, 21, - 13, 21, - 16, 20, - 17, 19, - 18, 17, - 18, 14, - 17, 12, - 16, 11, - 13, 10, - 4, 10, - } - }, - - // character 81 ('Q') - { 24, 22, - { - 9, 21, - 7, 20, - 5, 18, - 4, 16, - 3, 13, - 3, 8, - 4, 5, - 5, 3, - 7, 1, - 9, 0, - 13, 0, - 15, 1, - 17, 3, - 18, 5, - 19, 8, - 19, 13, - 18, 16, - 17, 18, - 15, 20, - 13, 21, - 9, 21, - PEN_UP, PEN_UP, - 12, 4, - 18, -2, - } - }, - - // character 82 ('R') - { 16, 21, - { - 4, 21, - 4, 0, - PEN_UP, PEN_UP, - 4, 21, - 13, 21, - 16, 20, - 17, 19, - 18, 17, - 18, 15, - 17, 13, - 16, 12, - 13, 11, - 4, 11, - PEN_UP, PEN_UP, - 11, 11, - 18, 0, - } - }, - - // character 83 ('S') - { 20, 20, - { - 17, 18, - 15, 20, - 12, 21, - 8, 21, - 5, 20, - 3, 18, - 3, 16, - 4, 14, - 5, 13, - 7, 12, - 13, 10, - 15, 9, - 16, 8, - 17, 6, - 17, 3, - 15, 1, - 12, 0, - 8, 0, - 5, 1, - 3, 3, - } - }, - - // character 84 ('T') - { 5, 16, - { - 8, 21, - 8, 0, - PEN_UP, PEN_UP, - 1, 21, - 15, 21, - } - }, - - // character 85 ('U') - { 10, 22, - { - 4, 21, - 4, 6, - 5, 3, - 7, 1, - 10, 0, - 12, 0, - 15, 1, - 17, 3, - 18, 6, - 18, 21, - } - }, - - // character 86 ('V') - { 5, 18, - { - 1, 21, - 9, 0, - PEN_UP, PEN_UP, - 17, 21, - 9, 0, - } - }, - - // character 87 ('W') - { 11, 24, - { - 2, 21, - 7, 0, - PEN_UP, PEN_UP, - 12, 21, - 7, 0, - PEN_UP, PEN_UP, - 12, 21, - 17, 0, - PEN_UP, PEN_UP, - 22, 21, - 17, 0, - } - }, - - // character 88 ('X') - { 5, 20, - { - 3, 21, - 17, 0, - PEN_UP, PEN_UP, - 17, 21, - 3, 0, - } - }, - - // character 89 ('Y') - { 6, 18, - { - 1, 21, - 9, 11, - 9, 0, - PEN_UP, PEN_UP, - 17, 21, - 9, 11, - } - }, - - // character 90 ('Z') - { 8, 20, - { - 17, 21, - 3, 0, - PEN_UP, PEN_UP, - 3, 21, - 17, 21, - PEN_UP, PEN_UP, - 3, 0, - 17, 0, - } - }, - - // character 91 ('[') - { 11, 14, - { - 4, 25, - 4, -7, - PEN_UP, PEN_UP, - 5, 25, - 5, -7, - PEN_UP, PEN_UP, - 4, 25, - 11, 25, - PEN_UP, PEN_UP, - 4, -7, - 11, -7, - } - }, - - // character 92 ('\') - { 2, 14, - { - 0, 21, - 14, -3, - } - }, - - // character 93 (']') - { 11, 14, - { - 9, 25, - 9, -7, - PEN_UP, PEN_UP, - 10, 25, - 10, -7, - PEN_UP, PEN_UP, - 3, 25, - 10, 25, - PEN_UP, PEN_UP, - 3, -7, - 10, -7, - } - }, - - // character 94 ('^') - { 10, 16, - { - 6, 15, - 8, 18, - 10, 15, - PEN_UP, PEN_UP, - 3, 12, - 8, 17, - 13, 12, - PEN_UP, PEN_UP, - 8, 17, - 8, 0, - } - }, - - // character 95 ('_') - { 2, 16, - { - 0, -2, - 16, -2, - } - }, - - // character 96 ('`') - { 7, 10, - { - 6, 21, - 5, 20, - 4, 18, - 4, 16, - 5, 15, - 6, 16, - 5, 17, - } - }, - - // character 97 ('a') - { 17, 19, - { - 15, 14, - 15, 0, - PEN_UP, PEN_UP, - 15, 11, - 13, 13, - 11, 14, - 8, 14, - 6, 13, - 4, 11, - 3, 8, - 3, 6, - 4, 3, - 6, 1, - 8, 0, - 11, 0, - 13, 1, - 15, 3, - } - }, - - // character 98 ('b') - { 17, 19, - { - 4, 21, - 4, 0, - PEN_UP, PEN_UP, - 4, 11, - 6, 13, - 8, 14, - 11, 14, - 13, 13, - 15, 11, - 16, 8, - 16, 6, - 15, 3, - 13, 1, - 11, 0, - 8, 0, - 6, 1, - 4, 3, - } - }, - - // character 99 ('c') - { 14, 18, - { - 15, 11, - 13, 13, - 11, 14, - 8, 14, - 6, 13, - 4, 11, - 3, 8, - 3, 6, - 4, 3, - 6, 1, - 8, 0, - 11, 0, - 13, 1, - 15, 3, - } - }, - - // character 100 ('d') - { 17, 19, - { - 15, 21, - 15, 0, - PEN_UP, PEN_UP, - 15, 11, - 13, 13, - 11, 14, - 8, 14, - 6, 13, - 4, 11, - 3, 8, - 3, 6, - 4, 3, - 6, 1, - 8, 0, - 11, 0, - 13, 1, - 15, 3, - } - }, - - // character 101 ('e') - { 17, 18, - { - 3, 8, - 15, 8, - 15, 10, - 14, 12, - 13, 13, - 11, 14, - 8, 14, - 6, 13, - 4, 11, - 3, 8, - 3, 6, - 4, 3, - 6, 1, - 8, 0, - 11, 0, - 13, 1, - 15, 3, - } - }, - - // character 102 ('f') - { 8, 12, - { - 10, 21, - 8, 21, - 6, 20, - 5, 17, - 5, 0, - PEN_UP, PEN_UP, - 2, 14, - 9, 14, - } - }, - - // character 103 ('g') - { 22, 19, - { - 15, 14, - 15, -2, - 14, -5, - 13, -6, - 11, -7, - 8, -7, - 6, -6, - PEN_UP, PEN_UP, - 15, 11, - 13, 13, - 11, 14, - 8, 14, - 6, 13, - 4, 11, - 3, 8, - 3, 6, - 4, 3, - 6, 1, - 8, 0, - 11, 0, - 13, 1, - 15, 3, - } - }, - - // character 104 ('h') - { 10, 19, - { - 4, 21, - 4, 0, - PEN_UP, PEN_UP, - 4, 10, - 7, 13, - 9, 14, - 12, 14, - 14, 13, - 15, 10, - 15, 0, - } - }, - - // character 105 ('i') - { 8, 8, - { - 3, 21, - 4, 20, - 5, 21, - 4, 22, - 3, 21, - PEN_UP, PEN_UP, - 4, 14, - 4, 0, - } - }, - - // character 106 ('j') - { 11, 10, - { - 5, 21, - 6, 20, - 7, 21, - 6, 22, - 5, 21, - PEN_UP, PEN_UP, - 6, 14, - 6, -3, - 5, -6, - 3, -7, - 1, -7, - } - }, - - // character 107 ('k') - { 8, 17, - { - 4, 21, - 4, 0, - PEN_UP, PEN_UP, - 14, 14, - 4, 4, - PEN_UP, PEN_UP, - 8, 8, - 15, 0, - } - }, - - // character 108 ('l') - { 2, 8, - { - 4, 21, - 4, 0, - } - }, - - // character 109 ('m') - { 18, 30, - { - 4, 14, - 4, 0, - PEN_UP, PEN_UP, - 4, 10, - 7, 13, - 9, 14, - 12, 14, - 14, 13, - 15, 10, - 15, 0, - PEN_UP, PEN_UP, - 15, 10, - 18, 13, - 20, 14, - 23, 14, - 25, 13, - 26, 10, - 26, 0, - } - }, - - // character 110 ('n') - { 10, 19, - { - 4, 14, - 4, 0, - PEN_UP, PEN_UP, - 4, 10, - 7, 13, - 9, 14, - 12, 14, - 14, 13, - 15, 10, - 15, 0, - } - }, - - // character 111 ('o') - { 17, 19, - { - 8, 14, - 6, 13, - 4, 11, - 3, 8, - 3, 6, - 4, 3, - 6, 1, - 8, 0, - 11, 0, - 13, 1, - 15, 3, - 16, 6, - 16, 8, - 15, 11, - 13, 13, - 11, 14, - 8, 14, - } - }, - - // character 112 ('p') - { 17, 19, - { - 4, 14, - 4, -7, - PEN_UP, PEN_UP, - 4, 11, - 6, 13, - 8, 14, - 11, 14, - 13, 13, - 15, 11, - 16, 8, - 16, 6, - 15, 3, - 13, 1, - 11, 0, - 8, 0, - 6, 1, - 4, 3, - } - }, - - // character 113 ('q') - { 17, 19, - { - 15, 14, - 15, -7, - PEN_UP, PEN_UP, - 15, 11, - 13, 13, - 11, 14, - 8, 14, - 6, 13, - 4, 11, - 3, 8, - 3, 6, - 4, 3, - 6, 1, - 8, 0, - 11, 0, - 13, 1, - 15, 3, - } - }, - - // character 114 ('r') - { 8, 13, - { - 4, 14, - 4, 0, - PEN_UP, PEN_UP, - 4, 8, - 5, 11, - 7, 13, - 9, 14, - 12, 14, - } - }, - - // character 115 ('s') - { 17, 17, - { - 14, 11, - 13, 13, - 10, 14, - 7, 14, - 4, 13, - 3, 11, - 4, 9, - 6, 8, - 11, 7, - 13, 6, - 14, 4, - 14, 3, - 13, 1, - 10, 0, - 7, 0, - 4, 1, - 3, 3, - } - }, - - // character 116 ('t') - { 8, 12, - { - 5, 21, - 5, 4, - 6, 1, - 8, 0, - 10, 0, - PEN_UP, PEN_UP, - 2, 14, - 9, 14, - } - }, - - // character 117 ('u') - { 10, 19, - { - 4, 14, - 4, 4, - 5, 1, - 7, 0, - 10, 0, - 12, 1, - 15, 4, - PEN_UP, PEN_UP, - 15, 14, - 15, 0, - } - }, - - // character 118 ('v') - { 5, 16, - { - 2, 14, - 8, 0, - PEN_UP, PEN_UP, - 14, 14, - 8, 0, - } - }, - - // character 119 ('w') - { 11, 22, - { - 3, 14, - 7, 0, - PEN_UP, PEN_UP, - 11, 14, - 7, 0, - PEN_UP, PEN_UP, - 11, 14, - 15, 0, - PEN_UP, PEN_UP, - 19, 14, - 15, 0, - } - }, - - // character 120 ('x') - { 5, 17, - { - 3, 14, - 14, 0, - PEN_UP, PEN_UP, - 14, 14, - 3, 0, - } - }, - - // character 121 ('y') - { 9, 16, - { - 2, 14, - 8, 0, - PEN_UP, PEN_UP, - 14, 14, - 8, 0, - 6, -4, - 4, -6, - 2, -7, - 1, -7, - } - }, - - // character 122 ('z') - { 8, 17, - { - 14, 14, - 3, 0, - PEN_UP, PEN_UP, - 3, 14, - 14, 14, - PEN_UP, PEN_UP, - 3, 0, - 14, 0, - } - }, - - // character 123 ('{') - { 39, 14, - { - 9, 25, - 7, 24, - 6, 23, - 5, 21, - 5, 19, - 6, 17, - 7, 16, - 8, 14, - 8, 12, - 6, 10, - PEN_UP, PEN_UP, - 7, 24, - 6, 22, - 6, 20, - 7, 18, - 8, 17, - 9, 15, - 9, 13, - 8, 11, - 4, 9, - 8, 7, - 9, 5, - 9, 3, - 8, 1, - 7, 0, - 6, -2, - 6, -4, - 7, -6, - PEN_UP, PEN_UP, - 6, 8, - 8, 6, - 8, 4, - 7, 2, - 6, 1, - 5, -1, - 5, -3, - 6, -5, - 7, -6, - 9, -7, - } - }, - - // character 124 ('|') - { 2, 8, - { - 4, 25, - 4, -7, - } - }, - - // character 125 ('}') - { 39, 14, - { - 5, 25, - 7, 24, - 8, 23, - 9, 21, - 9, 19, - 8, 17, - 7, 16, - 6, 14, - 6, 12, - 8, 10, - PEN_UP, PEN_UP, - 7, 24, - 8, 22, - 8, 20, - 7, 18, - 6, 17, - 5, 15, - 5, 13, - 6, 11, - 10, 9, - 6, 7, - 5, 5, - 5, 3, - 6, 1, - 7, 0, - 8, -2, - 8, -4, - 7, -6, - PEN_UP, PEN_UP, - 8, 8, - 6, 6, - 6, 4, - 7, 2, - 8, 1, - 9, -1, - 9, -3, - 8, -5, - 7, -6, - 5, -7, - } - }, - - // character 126 ('~') - { 23, 24, - { - 3, 6, - 3, 8, - 4, 11, - 6, 12, - 8, 12, - 10, 11, - 14, 8, - 16, 7, - 18, 7, - 20, 8, - 21, 10, - PEN_UP, PEN_UP, - 3, 8, - 4, 10, - 6, 11, - 8, 11, - 10, 10, - 14, 7, - 16, 6, - 18, 6, - 20, 7, - 21, 10, - 21, 12, - } - }, -}; - diff --git a/src/fonts/unicode.lff.gz b/src/fonts/unicode.lff.gz new file mode 100644 index 00000000..98153b13 Binary files /dev/null and b/src/fonts/unicode.lff.gz differ diff --git a/src/glhelper.cpp b/src/glhelper.cpp index 54335365..81e7de63 100644 --- a/src/glhelper.cpp +++ b/src/glhelper.cpp @@ -8,8 +8,8 @@ namespace SolveSpace { -// A public-domain Hershey vector font ("Simplex"). -#include "font.table.h" +// A vector font. +#include "generated/vectorfont.table.h" // A bitmap font. #include "generated/bitmapfont.table.h" @@ -17,25 +17,51 @@ namespace SolveSpace { static bool ColorLocked; static bool DepthOffsetLocked; -#define FONT_SCALE(h) ((h)/22.0) -double ssglStrWidth(const char *str, double h) -{ - int w = 0; - for(; *str; str++) { - int c = *str; - if(c < 32 || c > 126) c = 32; - c -= 32; - - w += Font[c].width; +static const VectorGlyph &GetVectorGlyph(char32_t chr) { + int first = 0; + int last = sizeof(VectorFont) / sizeof(VectorGlyph); + while(first <= last) { + int mid = (first + last) / 2; + char32_t midChr = VectorFont[mid].character; + if(midChr > chr) { + last = mid - 1; // and first stays the same + continue; + } + if(midChr < chr) { + first = mid + 1; // and last stays the same + continue; + } + return VectorFont[mid]; } - return w*FONT_SCALE(h)/SS.GW.scale; + return GetVectorGlyph(0xfffd); // replacement character +} + +#define FONT_SCALE(h) ((h)/75.0) +double ssglStrWidth(const std::string &str, double h) +{ + int width = 0; + const char *iter = str.c_str(); + while(*iter) { + char32_t chr; + iter = ReadUTF8(iter, &chr); + + const VectorGlyph &glyph = GetVectorGlyph(chr); + int glyphWidth = glyph.width; + if(glyph.baseCharacter != 0) { + const VectorGlyph &baseGlyph = GetVectorGlyph(glyph.baseCharacter); + width += max(glyph.width, baseGlyph.width); + } else { + width += glyph.width; + } + } + return width * FONT_SCALE(h) / SS.GW.scale; } double ssglStrHeight(double h) { - // The characters have height ~22, as they appear in the table. - return 22.0*FONT_SCALE(h)/SS.GW.scale; + // The characters have height ~90, as they appear in the table. + return 90.0 * FONT_SCALE(h) / SS.GW.scale; } -void ssglWriteTextRefCenter(const char *str, double h, Vector t, Vector u, Vector v, +void ssglWriteTextRefCenter(const std::string &str, double h, Vector t, Vector u, Vector v, ssglLineFn *fn, void *fndata) { u = u.WithMagnitude(1); @@ -82,43 +108,55 @@ static void LineDrawCallback(void *fndata, Vector a, Vector b) glEnd(); } -void ssglWriteText(const char *str, double h, Vector t, Vector u, Vector v, +int ssglDrawCharacter(const VectorGlyph &glyph, Vector t, Vector o, Vector u, Vector v, + double scale, ssglLineFn *fn, void *fndata) { + int width = glyph.width; + + if(glyph.baseCharacter != 0) { + const VectorGlyph &baseGlyph = GetVectorGlyph(glyph.baseCharacter); + int baseWidth = ssglDrawCharacter(baseGlyph, t, o, u, v, scale, fn, fndata); + width = max(glyph.width, baseWidth); + } + + const int8_t *data = glyph.data; + bool pen_up = true; + Vector prevp; + while(true) { + int8_t x = *data++; + int8_t y = *data++; + + if(x == PEN_UP && y == PEN_UP) { + if(pen_up) break; + pen_up = true; + } else { + Vector p = t; + p = p.Plus(u.ScaledBy((o.x + x) * scale)); + p = p.Plus(v.ScaledBy((o.y + y) * scale)); + if(!pen_up) fn(fndata, prevp, p); + prevp = p; + pen_up = false; + } + } + + return width; +} + +void ssglWriteText(const std::string &str, double h, Vector t, Vector u, Vector v, ssglLineFn *fn, void *fndata) { if(!fn) fn = LineDrawCallback; u = u.WithMagnitude(1); v = v.WithMagnitude(1); - double scale = FONT_SCALE(h)/SS.GW.scale; - int xo = 5; - int yo = 5; + double scale = FONT_SCALE(h) / SS.GW.scale; + Vector o = { 5.0, 5.0 }; + const char *iter = str.c_str(); + while(*iter) { + char32_t chr; + iter = ReadUTF8(iter, &chr); - for(; *str; str++) { - int c = *str; - if(c < 32 || c > 126) c = 32; - - c -= 32; - - int j; - Vector prevp = Vector::From(VERY_POSITIVE, 0, 0); - for(j = 0; j < Font[c].points; j++) { - int x = Font[c].coord[j*2]; - int y = Font[c].coord[j*2+1]; - - if(x == PEN_UP && y == PEN_UP) { - prevp.x = VERY_POSITIVE; - } else { - Vector p = t; - p = p.Plus(u.ScaledBy((xo + x)*scale)); - p = p.Plus(v.ScaledBy((yo + y)*scale)); - if(EXACT(prevp.x != VERY_POSITIVE)) { - fn(fndata, prevp, p); - } - prevp = p; - } - } - - xo += Font[c].width; + const VectorGlyph &glyph = GetVectorGlyph(chr); + o.x += ssglDrawCharacter(glyph, t, o, u, v, scale, fn, fndata); } } diff --git a/src/solvespace.h b/src/solvespace.h index c942b01a..8aceaa62 100644 --- a/src/solvespace.h +++ b/src/solvespace.h @@ -330,11 +330,11 @@ void ssglDrawEdges(SEdgeList *l, bool endpointsToo); void ssglDebugMesh(SMesh *m); void ssglMarkPolygonNormal(SPolygon *p); typedef void ssglLineFn(void *data, Vector a, Vector b); -void ssglWriteText(const char *str, double h, Vector t, Vector u, Vector v, +void ssglWriteText(const std::string &str, double h, Vector t, Vector u, Vector v, ssglLineFn *fn, void *fndata); -void ssglWriteTextRefCenter(const char *str, double h, Vector t, Vector u, Vector v, +void ssglWriteTextRefCenter(const std::string &str, double h, Vector t, Vector u, Vector v, ssglLineFn *fn, void *fndata); -double ssglStrWidth(const char *str, double h); +double ssglStrWidth(const std::string &str, double h); double ssglStrHeight(double h); void ssglLockColorTo(RgbaColor rgb); void ssglFatLine(Vector a, Vector b, double width); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 9ad55a97..93fb7505 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -15,3 +15,9 @@ add_executable(unifont2c target_link_libraries(unifont2c ${PNG_LIBRARIES} ${ZLIB_LIBRARIES}) + +add_executable(lff2c + lff2c.cpp) + +target_link_libraries(lff2c + ${ZLIB_LIBRARIES}) diff --git a/tools/lff2c.cpp b/tools/lff2c.cpp new file mode 100644 index 00000000..ab9ef693 --- /dev/null +++ b/tools/lff2c.cpp @@ -0,0 +1,396 @@ +#define _USE_MATH_DEFINES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TOLERANCE 1e-6 + +double correctAngle(double a) { + return M_PI + remainder(a - M_PI, 2 * M_PI); +} + +struct Point { + double x; + double y; + + Point operator+(const Point &o) const { return { x + o.x, y + o.y }; } + Point operator-(const Point &o) const { return { x - o.x, y - o.y }; } + Point operator*(const Point &o) const { return { x * o.x, y * o.y }; } + Point operator/(const Point &o) const { return { x / o.x, y / o.y }; } + + Point operator*(double k) const { return { x * k, y * k }; } + Point operator/(double k) const { return { x / k, y / k }; } + + double length() const{ + return sqrt(x * x + y * y); + } + + double angle() const { + return correctAngle(atan2(y, x)); + } + + double distanceTo(const Point &v) const { + return (*this - v).length(); + } + + double angleTo(const Point &v) const { + return (v - *this).angle(); + } + + static Point polar(double radius, double angle) { + return { radius * cos(angle), radius * sin(angle) }; + } + + bool operator==(const Point &o) const { return x == o.x && y == o.y; } + bool operator!=(const Point &o) const { return x != o.x || y != o.y; } + +}; + +struct Curve { + std::vector points; +}; + +struct Glyph { + char32_t character; + char32_t baseCharacter; + std::vector curves; + + void getBoundWidth(double *rminw, double *rmaxw) const { + if(curves.empty()) { + *rminw = 0.0; + *rmaxw = 0.0; + return; + } + double minw = curves[0].points[0].x; + double maxw = minw; + for(const Curve &c : curves) { + for(const Point &p : c.points) { + maxw = std::max(maxw, p.x); + minw = std::min(minw, p.x); + } + } + *rminw = minw; + *rmaxw = maxw; + } + + void getBoundHeight(double *rminh, double *rmaxh) const { + if(curves.empty()) { + *rminh = 0.0; + *rmaxh = 0.0; + return; + } + double minh = curves[0].points[0].y; + double maxh = minh; + for(const Curve &c : curves) { + for(const Point &p : c.points) { + maxh = std::max(maxh, p.y); + minh = std::min(minh, p.y); + } + } + *rminh = minh; + *rmaxh = maxh; + } + + double getWidth() const { + double maxw; + double minw; + getBoundWidth(&minw, &maxw); + return maxw - minw; + } + + double getHeight() const { + double maxh; + double minh; + getBoundHeight(&minh, &maxh); + return maxh - minh; + } + + bool operator<(const Glyph &o) const { return character < o.character; } +}; + +struct Font { + double letterSpacing; + double wordSpacing; + std::vector glyphs; + + void getGlyphBound(double *rminw, double *rminh, double *rmaxw, double *rmaxh) { + if(glyphs.empty()) { + *rminw = 0.0; + *rmaxw = 0.0; + *rminh = 0.0; + *rmaxh = 0.0; + return; + } + + glyphs[0].getBoundWidth(rminw, rmaxw); + glyphs[0].getBoundHeight(rminh, rmaxh); + for(const Glyph &g : glyphs) { + double minw, minh, maxw, maxh; + g.getBoundWidth(&minw, &maxw); + g.getBoundHeight(&minh, &maxh); + *rminw = std::min(*rminw, minw); + *rminh = std::min(*rminh, minh); + *rmaxw = std::max(*rmaxw, maxw); + *rmaxh = std::max(*rmaxh, maxh); + } + } + + void createArc(Curve &curve, const Point &cp, double radius, + double a1, double a2, bool reversed) { + if (radius < 1e-6) return; + + double aSign = 1.0; + if(reversed) { + if(a1 <= a2 + TOLERANCE) a1 += 2.0 * M_PI; + aSign = -1.0; + } else { + if(a2 <= a1 + TOLERANCE) a2 += 2.0 * M_PI; + } + + // Angle Step (rad) + double da = fabs(a2 - a1); + int numPoints = 8; + double aStep = aSign * da / double(numPoints); + + for(int i = 0; i <= numPoints; i++) { + curve.points.push_back(cp + Point::polar(radius, a1 + aStep * i)); + } + } + + void createBulge(const Point &v, double bulge, Curve &curve) { + bool reversed = bulge < 0.0; + double alpha = atan(bulge) * 4.0; + Point &point = curve.points.back(); + + Point middle = (point + v) / 2.0; + double dist = point.distanceTo(v) / 2.0; + double angle = point.angleTo(v); + + // alpha can't be 0.0 at this point + double radius = fabs(dist / sin(alpha / 2.0)); + double wu = fabs(radius*radius - dist*dist); + double h = sqrt(wu); + + if(bulge > 0.0) { + angle += M_PI_2; + } else { + angle -= M_PI_2; + } + + if (fabs(alpha) > M_PI) { + h *= -1.0; + } + + Point center = Point::polar(h, angle); + center = center + middle; + + double a1 = center.angleTo(point); + double a2 = center.angleTo(v); + createArc(curve, center, radius, a1, a2, reversed); + } + + void readLff(const std::string &path) { + gzFile lfffont = gzopen(path.c_str(), "rb"); + if(!lfffont) { + std::cerr << path << ": gzopen failed" << std::endl; + std::exit(1); + } + + // Read line by line until we find a new letter: + Glyph *currentGlyph = NULL; + while(!gzeof(lfffont)) { + std::string line; + do { + char buf[128] = {0}; + if(!gzgets(lfffont, buf, sizeof(buf))) + break; + line += buf; + } while(line.back() != '\n'); + + if(line.empty() || line[0] == '\n') { + continue; + } else if(line[0] == '#') { + // This is comment or metadata. + std::istringstream ss(line.substr(1)); + + std::vector tokens; + while(!ss.eof()) { + std::string token; + std::getline(ss, token, ':'); + std::istringstream(token) >> token; // trim + if(!token.empty()) + tokens.push_back(token); + } + + // If not in form of "a:b" then it's not metadata, just a comment. + if (tokens.size() != 2) + continue; + + std::string &identifier = tokens[0]; + std::string &value = tokens[1]; + + std::transform(identifier.begin(), identifier.end(), identifier.begin(), + ::tolower); + if (identifier == "letterspacing") { + std::istringstream(value) >> letterSpacing; + } else if (identifier == "wordspacing") { + std::istringstream(value) >> wordSpacing; + } else if (identifier == "linespacingfactor") { + /* don't care */ + } else if (identifier == "author") { + /* don't care */ + } else if (identifier == "name") { + /* don't care */ + } else if (identifier == "license") { + /* don't care */ + } else if (identifier == "encoding") { + /* don't care */ + } else if (identifier == "created") { + /* don't care */ + } + } else if(line[0] == '[') { + // This is a glyph. + size_t closingPos; + char32_t chr = std::stoi(line.substr(1), &closingPos, 16);; + if(line[closingPos + 1] != ']') { + std::cerr << "unrecognized character number: " << line << std::endl; + currentGlyph = NULL; + continue; + } + + glyphs.emplace_back(); + currentGlyph = &glyphs.back(); + currentGlyph->character = chr; + currentGlyph->baseCharacter = 0; + } else if(currentGlyph != NULL) { + if (line[0] == 'C') { + // This is a reference to another glyph. + currentGlyph->baseCharacter = std::stoi(line.substr(1), NULL, 16); + } else { + // This is a series of curves. + currentGlyph->curves.emplace_back(); + Curve &curve = currentGlyph->curves.back(); + + std::stringstream ss(line); + while (!ss.eof()) { + std::string vertex; + std::getline(ss, vertex, ';'); + + std::stringstream ssv(vertex); + std::string coord; + Point p; + + if(!std::getline(ssv, coord, ',')) continue; + p.x = std::stod(coord); + + if(!std::getline(ssv, coord, ',')) continue; + p.y = std::stod(coord); + + if(!std::getline(ssv, coord, ',') || coord[0] != 'A') { + // This is just a point. + curve.points.push_back(p); + } else { + // This is a point with a bulge. + double bulge = std::stod(coord.substr(1)); + createBulge(p, bulge, curve); + } + } + } + } else { + std::cerr << "unrecognized line: " << line << std::endl; + } + } + gzclose(lfffont); + } + + void writeCppHeader(const std::string &hName) { + std::sort(glyphs.begin(), glyphs.end()); + + std::ofstream ts(hName, std::ios::out); + + double minX, minY, maxX, maxY; + getGlyphBound(&minX, &minY, &maxX, &maxY); + + double size = 126.0; + double scale = size / std::max({ fabs(maxX), fabs(minX), fabs(maxY), fabs(minY) }); + + // We use tabs for indentation here to make compilation slightly faster + ts << + "/**** This is a generated file - do not edit ****/\n\n" + "#ifndef __VECTORFONT_TABLE_H\n" + "#define __VECTORFONT_TABLE_H\n" + "\n" + "#define PEN_UP 127\n" + "#define UP PEN_UP\n" + "\n" + "struct VectorGlyph {\n" + "\tchar32_t character;\n" + "\tchar32_t baseCharacter;\n" + "\tint width;\n" + "\tconst int8_t *data;\n" + "};\n" + "\n" + "const int8_t VectorFontData[] = {\n" + "\tUP, UP,\n"; + + std::map glyphIndexes; + size_t index = 2; + for(const Glyph &g : glyphs) { + ts << "\t// U+" << std::hex << g.character << std::dec << "\n"; + glyphIndexes[g.character] = index; + for(const Curve &c : g.curves) { + for(const Point &p : c.points) { + ts << "\t" << int(floor(p.x * scale)) << ", " << + int(floor(p.y * scale)) << ",\n"; + index += 2; + } + ts << "\tUP, UP,\n"; + index += 2; + } + ts << "\tUP, UP,\n"; // end-of-glyph marker + index += 2; + } + + ts << + "};\n" + "\n" + "const VectorGlyph VectorFont[] = {\n" + "\t// U+20\n" + "\t{ 32, 0, " << int(floor(wordSpacing * scale)) << ", &VectorFontData[0] },\n"; + + for(const Glyph &g : glyphs) { + ts << "\t// U+" << std::hex << g.character << std::dec << "\n"; + ts << "\t{ " << g.character << ", " + << g.baseCharacter << ", " + << int(floor((g.getWidth() + letterSpacing) * scale)) << ", "; + ts << "&VectorFontData[" << glyphIndexes[g.character] << "] },\n"; + } + + ts << + "};\n" + "\n" + "#undef UP\n" + "\n" + "#endif\n"; + } +}; + +int main(int argc, char** argv) { + if(argc != 3) { + std::cerr << "Usage: " << argv[0] << "
\n" << std::endl; + return 1; + } + + Font font; + font.readLff(argv[2]); + font.writeCppHeader(argv[1]); + + return 0; +}