From: David Gow Date: Thu, 7 Aug 2014 13:34:33 +0000 (+0800) Subject: The power of truetype font rendering! X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=7e00a47f18e0ccdb0c7255f30bc7820cabb3206a;p=ipdf%2Fcode.git The power of truetype font rendering! --- diff --git a/src/document.cpp b/src/document.cpp index 71f3ed4..d4d8eac 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -3,6 +3,8 @@ #include #include +#include "stb_truetype.h" + using namespace IPDF; using namespace std; @@ -508,3 +510,57 @@ void Document::AddPathFromString(const string & d, const Rect & bounds) prev_i = i; } } + +void Document::AddFontGlyphAtPoint(stbtt_fontinfo *font, int character, Real scale, Real x, Real y) +{ + int glyph_index = stbtt_FindGlyphIndex(font, character); + + // Check if there is actully a glyph to render. + if (stbtt_IsGlyphEmpty(font, glyph_index)) + { + return; + } + + stbtt_vertex *instructions; + int num_instructions = stbtt_GetGlyphShape(font, glyph_index, &instructions); + + Real current_x(0), current_y(0); + + for (int i = 0; i < num_instructions; ++i) + { + // TTF uses 16-bit signed ints for coordinates: + // with the y-axis inverted compared to us. + // Convert and scale any data. + Real inst_x = Real(instructions[i].x)*scale; + Real inst_y = Real(instructions[i].y)*-scale; + Real inst_cx = Real(instructions[i].cx)*scale; + Real inst_cy = Real(instructions[i].cy)*-scale; + Real old_x(current_x), old_y(current_y); + current_x = inst_x; + current_y = inst_y; + unsigned bezier_index; + switch(instructions[i].type) + { + // Move To + case STBTT_vmove: + break; + // Line To + case STBTT_vline: + bezier_index = AddBezierData(Bezier(old_x + x, old_y + y, old_x + x, old_y + y, current_x + x, current_y + y, current_x + x, current_y + y)); + Add(BEZIER,Rect(0,0,1,1),bezier_index); + break; + // Quadratic Bezier To: + case STBTT_vcurve: + // Quadratic -> Cubic: + // - Endpoints are the same. + // - cubic1 = quad0+(2/3)*(quad1-quad0) + // - cubic2 = quad2+(2/3)*(quad1-quad2) + bezier_index = AddBezierData(Bezier(old_x + x, old_y + y, old_x + Real(2)*(inst_cx-old_x)/Real(3) + x, old_y + Real(2)*(inst_cy-old_y)/Real(3) + y, + current_x + Real(2)*(inst_cx-current_x)/Real(3) + x, current_y + Real(2)*(inst_cy-current_y)/Real(3) + y, current_x + x, current_y + y)); + Add(BEZIER,Rect(0,0,1,1),bezier_index); + break; + } + } + + stbtt_FreeShape(font, instructions); +} diff --git a/src/document.h b/src/document.h index 14a87d8..c1f026b 100644 --- a/src/document.h +++ b/src/document.h @@ -4,6 +4,8 @@ #include "ipdf.h" #include "quadtree.h" +typedef struct stbtt_fontinfo stbtt_fontinfo; + namespace IPDF { class Document @@ -29,6 +31,8 @@ namespace IPDF void AddPathFromString(const std::string & d, const Rect & bounds); + void AddFontGlyphAtPoint(stbtt_fontinfo *font, int character, Real scale, Real x, Real y); + #ifndef QUADTREE_DISABLED inline const QuadTree& GetQuadTree() { if (m_quadtree.root_id == QUADTREE_EMPTY) { GenBaseQuadtree(); } return m_quadtree; } QuadTreeIndex GenQuadChild(QuadTreeIndex parent, QuadTreeNodeChildren type); diff --git a/src/main.cpp b/src/main.cpp index d7df87a..d5d4da8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include "main.h" #include // Because we can. +#include "stb_truetype.h" int main(int argc, char ** argv) { #ifndef __STDC_IEC_559__ @@ -81,11 +82,28 @@ int main(int argc, char ** argv) } else { - doc.AddBezierData(Bezier(0,0,0,1,1,0)); +/* doc.AddBezierData(Bezier(0,0,0,1,1,0)); doc.AddBezierData(Bezier(0,0,1,0,0,1)); doc.AddBezierData(Bezier(0,0,1,1,1,0)); - doc.AddBezierData(Bezier(0,1,1,0,0,1)); + 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); for(int x = 0; x < 8; ++x) @@ -97,10 +115,10 @@ int main(int argc, char ** argv) //doc.Add(BEZIER, Rect(0.2+x-4.0, 0.2+y-4.0, 0.6,0.6), (x^y)%3); } } - doc.Add(BEZIER, Rect(0.1,0.1,0.8,0.8), 0); + /* doc.Add(BEZIER, Rect(0.1,0.1,0.8,0.8), 0); doc.Add(BEZIER, Rect(0.1,0.1,0.8,0.8), 1); doc.Add(BEZIER, Rect(0.1,0.1,0.8,0.8), 2); - doc.Add(BEZIER, Rect(0.1,0.1,0.8,0.8), 3); + doc.Add(BEZIER, Rect(0.1,0.1,0.8,0.8), 3);*/ //doc.Add(CIRCLE_FILLED, Rect(0.1,0.1,0.8,0.8), 0); } Debug("Start!");