From 1ba642be477818ba73be34b5e96484b5e91d8c66 Mon Sep 17 00:00:00 2001 From: Sam Moore Date: Tue, 12 Aug 2014 14:36:47 +0800 Subject: [PATCH 1/1] Make adding text to the document easier tl;dr Use Document::AddText() to put text in places Pass the font file in the Document constructor or call Document::SetFont() to change fonts ts;iwtrm I am not freeing the font data buffer because I strongly suspect we will want to keep it. You might be able to have arbitrary precision text only documents really easily if you just re-add the glyphs at a new scale. That might be better than reparenting each individual bezier. We could add a Document::Finalize() to free memory like the font data which is used in creating the document but not needed afterwards. But I want to be able to interactively add text anyway, so there doesn't seem to be much point at the moment. --- src/document.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++ src/document.h | 24 +++++++++++++++++++----- src/main.cpp | 23 ++++------------------- 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/src/document.cpp b/src/document.cpp index 8f35644..fe3482f 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -521,6 +521,53 @@ void Document::ParseSVGPathData(const string & d, const Rect & bounds) } } +void Document::SetFont(const string & font_filename) +{ + if (m_font_data != NULL) + { + free(m_font_data); + } + + FILE *font_file = fopen("DejaVuSansMono.ttf", "rb"); + fseek(font_file, 0, SEEK_END); + size_t font_file_size = ftell(font_file); + fseek(font_file, 0, SEEK_SET); + m_font_data = (unsigned char*)malloc(font_file_size); + size_t read = fread(m_font_data, 1, font_file_size, font_file); + if (read != font_file_size) + { + Fatal("Failed to read font data from \"%s\" - Read %u bytes expected %u - %s", font_filename.c_str(), read, font_file_size, strerror(errno)); + } + fclose(font_file); + stbtt_InitFont(&m_font, m_font_data, 0); +} + +void Document::AddText(const string & text, Real scale, Real x, Real y) +{ + if (m_font_data == NULL) + { + Warn("No font loaded"); + return; + } + + float font_scale = stbtt_ScaleForPixelHeight(&m_font, scale); + Real x0(x); + //Real y0(y); + for (unsigned i = 0; i < text.size(); ++i) + { + if (text[i] == '\n') + { + y += 0.5*scale; + x = x0; + } + if (!isprint(text[i])) + continue; + + AddFontGlyphAtPoint(&m_font, text[i], font_scale, x, y); + x += 0.5*scale; + } +} + void Document::AddFontGlyphAtPoint(stbtt_fontinfo *font, int character, Real scale, Real x, Real y) { int glyph_index = stbtt_FindGlyphIndex(font, character); diff --git a/src/document.h b/src/document.h index 8e63f5b..8f2c087 100644 --- a/src/document.h +++ b/src/document.h @@ -5,7 +5,7 @@ #include "quadtree.h" #include "../contrib/pugixml-1.4/src/pugixml.hpp" - +#include "stb_truetype.h" typedef struct stbtt_fontinfo stbtt_fontinfo; @@ -14,8 +14,16 @@ namespace IPDF class Document { public: - Document(const std::string & filename = "") : m_objects(), m_count(0) {Load(filename);} - virtual ~Document() {} + Document(const std::string & filename = "", const std::string & font_filename = "DejaVuSansMono.ttf") : m_objects(), m_count(0), m_font_data(NULL), m_font() + { + Load(filename); + if (font_filename != "") + SetFont(font_filename); + } + virtual ~Document() + { + free(m_font_data); + } @@ -32,8 +40,7 @@ namespace IPDF void Add(ObjectType type, const Rect & bounds, unsigned data_index = 0); unsigned AddBezierData(const Bezier & bezier); - - + /** SVG Related functions **/ @@ -45,6 +52,10 @@ namespace IPDF /** Parse an SVG path with string **/ void ParseSVGPathData(const std::string & d, const Rect & bounds); + /** Font related functions **/ + void SetFont(const std::string & font_filename); + void AddText(const std::string & text, Real scale, Real x, Real y); + void AddFontGlyphAtPoint(stbtt_fontinfo *font, int character, Real scale, Real x, Real y); #ifndef QUADTREE_DISABLED @@ -61,6 +72,9 @@ namespace IPDF void GenBaseQuadtree(); #endif unsigned m_count; + unsigned char * m_font_data; + stbtt_fontinfo m_font; + }; diff --git a/src/main.cpp b/src/main.cpp index d5d4da8..49c818e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,6 @@ #include "main.h" #include // Because we can. -#include "stb_truetype.h" + int main(int argc, char ** argv) { #ifndef __STDC_IEC_559__ @@ -87,25 +87,10 @@ int main(int argc, char ** argv) doc.AddBezierData(Bezier(0,0,1,1,1,0)); doc.AddBezierData(Bezier(0,1,1,0,0,1));*/ - stbtt_fontinfo font; - FILE *font_file = fopen("DejaVuSansMono.ttf", "rb"); - fseek(font_file, 0, SEEK_END); - size_t font_file_size = ftell(font_file); - fseek(font_file, 0, SEEK_SET); - unsigned char *font_file_data = (unsigned char*)malloc(font_file_size); - SDL_assert(fread(font_file_data, 1, font_file_size, font_file) == font_file_size); - fclose(font_file); - stbtt_InitFont(&font, font_file_data, 0); - - float font_scale = stbtt_ScaleForPixelHeight(&font, 1); - doc.AddFontGlyphAtPoint(&font,'a', Real(font_scale), Real(0), Real(1)); - doc.AddFontGlyphAtPoint(&font,'b', Real(font_scale), Real(0.5), Real(1)); - doc.AddFontGlyphAtPoint(&font,'c', Real(font_scale), Real(1), Real(1)); - doc.AddFontGlyphAtPoint(&font,'d', Real(font_scale), Real(1.5), Real(1)); - - free(font_file_data); - + + doc.AddText("abcde", 0.5, Real(0), Real(1)); + for(int x = 0; x < 8; ++x) { -- 2.20.1