-rw-r--r-- | agg-plot/strpp.h | 2 | ||||
-rw-r--r-- | agg-plot/text.cpp | 5 | ||||
-rw-r--r-- | agg-plot/text.h | 123 |
diff --git a/agg-plot/strpp.h b/agg-plot/strpp.h index c241fea7..bcc54a73 100644 --- a/agg-plot/strpp.h +++ b/agg-plot/strpp.h @@ -19,6 +19,8 @@ public: const char* cstr() const { return CSTR(this); } unsigned len() const { return this->length; } + char operator [] (unsigned j) const { return (j < len() ? heap[j] : 0); } + void append(const str& s, int sep = 0) { str_append(this, &s, sep); } void append(const char* s, int sep = 0) { str_append_c(this, s, sep); } diff --git a/agg-plot/text.cpp b/agg-plot/text.cpp index 5cdc64f7..d23ecf25 100644 --- a/agg-plot/text.cpp +++ b/agg-plot/text.cpp @@ -8,6 +8,7 @@ namespace draw { +#if 0 void text::rewind(unsigned path_id) { @@ -20,6 +21,7 @@ namespace draw { { return m_stroke.vertex(x, y); } +#endif void text::apply_transform(const agg::trans_affine& m, double as) @@ -97,6 +99,7 @@ namespace draw { return s; } +#if 0 bool text::render(pixel_type::lcd_fmt& pixbuf, agg::rasterizer_scanline_aa<>& ras, agg::scanline_u8& sl, agg::rgba8 c) @@ -117,5 +120,5 @@ namespace draw { return true; } - +#endif } diff --git a/agg-plot/text.h b/agg-plot/text.h index a725d4ce..ca5bf81f 100644 --- a/agg-plot/text.h +++ b/agg-plot/text.h @@ -6,13 +6,20 @@ #include "agg_conv_transform.h" #include "agg_conv_stroke.h" #include "agg_conv_curve.h" +#include "agg_renderer_scanline.h" +#include "agg_font_freetype.h" #include "sg_object.h" -#include "font_renderer.h" namespace draw { class text : public sg_object { + + enum { scale_x = 100, subpixel_scale = 3 }; + + typedef agg::font_engine_freetype_int32 font_engine_type; + typedef agg::font_cache_manager<font_engine_type> font_manager_type; + typedef agg::gsv_text vs_text; typedef agg::conv_transform<vs_text> vs_trans_text; typedef agg::conv_stroke<vs_trans_text> vs_stroked_text; @@ -34,7 +41,20 @@ namespace draw { double m_hjustif; double m_vjustif; - font_renderer m_font_ren; + unsigned m_text_pos; + // double m_text_start_x; + double m_text_x, m_text_y; + double m_advance_x, m_advance_y; + // const agg::glyph_cache* m_glyph; + // font_renderer::font_engine_type::path_adaptor_type m_text_path; + + font_engine_type m_font_eng; + font_manager_type m_font_man; + + agg::trans_affine m_text_mtx; + agg::conv_curve<font_manager_type::path_adaptor_type> m_text_curve; + agg::conv_transform<agg::conv_curve<font_manager_type::path_adaptor_type> > m_text_trans; +// font_renderer m_font_ren; public: text(const char* text, double size = 10.0, double width = 1.0, @@ -43,8 +63,10 @@ namespace draw { m_text(), m_trans(m_text, m_user_matrix), m_stroke(m_trans), m_x(0.0), m_y(0.0), m_angle(0.0), m_text_width(0.0), m_text_height(size), - m_hjustif(hjustif), m_vjustif(vjustif), - m_font_ren("LiberationSans-Regular.ttf", 1.4*size) + m_hjustif(hjustif), m_vjustif(vjustif), m_text_pos(0), + m_font_eng(), m_font_man(m_font_eng), + m_text_mtx(), m_text_curve(m_font_man.path_adaptor()), m_text_trans(m_text_curve, m_text_mtx) + // m_font_ren("LiberationSans-Regular.ttf", 1.4*size) { m_text.text(m_text_buf.cstr()); m_text.size(size); @@ -53,6 +75,72 @@ namespace draw { m_stroke.width(width); m_stroke.line_cap(agg::round_cap); m_stroke.line_join(agg::round_join); + + agg::glyph_rendering gren = agg::glyph_ren_outline; + m_font_eng.load_font("LiberationSans-Regular.ttf", 0, gren); + m_font_eng.hinting(true); + + double text_height = 1.4 * size; + m_font_eng.height(text_height); + m_font_eng.width(text_height * scale_x); + } + + bool load_glyph() + { + m_text_x += m_advance_x; + m_text_y += m_advance_y; + + if (m_text_pos >= m_text_buf.len()) + return false; + + char c = m_text_buf[m_text_pos]; + const agg::glyph_cache *glyph = m_font_man.glyph(c); + m_font_man.add_kerning(&m_text_x, &m_text_y); + m_font_man.init_embedded_adaptors(glyph, 0, 0); + + if(glyph->data_type == agg::glyph_data_outline) + { + m_text_mtx.tx = m_text_x / scale_x; + m_text_mtx.ty = floor(m_text_y + 0.5); + m_matrix.transform(&m_text_mtx.tx, &m_text_mtx.ty); + + m_advance_x = glyph->advance_x; + m_advance_y = glyph->advance_y; + + return true; + } + + return false; + } + + virtual void rewind(unsigned path_id) + { + m_text_x = scale_x * (-m_hjustif * get_text_width()); + m_text_y = -m_vjustif * (1.4 * m_text_height); + m_advance_x = 0; + m_advance_y = 0; + m_text_pos = 0; + + m_text_mtx = m_matrix; + agg::trans_affine_scaling scale_mtx(1.0 / double(scale_x), 1.0); + trans_affine_compose (m_text_mtx, scale_mtx); + + load_glyph(); + } + + virtual unsigned vertex(double* x, double* y) + { + unsigned cmd = m_text_trans.vertex(x, y); + if (agg::is_stop(cmd)) + { + m_text_pos++; + if (load_glyph()) + { + return vertex(x, y); + } + return agg::path_cmd_stop; + } + return cmd; } void angle(double th) { @@ -81,19 +169,42 @@ namespace draw { void hjustif(double hj) { m_hjustif = hj; } void vjustif(double vj) { m_vjustif = vj; } - virtual void rewind(unsigned path_id); - virtual unsigned vertex(double* x, double* y); +// virtual void rewind(unsigned path_id); +// virtual unsigned vertex(double* x, double* y); virtual void apply_transform(const agg::trans_affine& m, double as); virtual void bounding_box(double *x1, double *y1, double *x2, double *y2); virtual str write_svg(int id, agg::rgba8 c, double h); +#if 0 virtual bool render(pixel_type::lcd_fmt& ren_buf, agg::rasterizer_scanline_aa<>& ras, agg::scanline_u8& sl, agg::rgba8 c); +#endif const vs_text& self() const { return m_text; }; vs_text& self() { return m_text; }; + + protected: + double get_text_width() + { + unsigned text_length = m_text_buf.len(); + double x = 0, y = 0; + + const char* text = m_text_buf.cstr(); + for (const char* p = text; p < text + text_length; p++) + { + const agg::glyph_cache* glyph = m_font_man.glyph(*p); + + if (glyph) + { + m_font_man.add_kerning(&x, &y); + x += glyph->advance_x; + } + } + + return x / double(scale_x); + } }; } |