summaryrefslogtreecommitdiff
path: root/fscalc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'fscalc.cpp')
-rw-r--r--fscalc.cpp102
1 files changed, 102 insertions, 0 deletions
diff --git a/fscalc.cpp b/fscalc.cpp
new file mode 100644
index 0000000..6842a65
--- /dev/null
+++ b/fscalc.cpp
@@ -0,0 +1,102 @@
+#include <stdexcept>
+#include "fscalc.h"
+
+Font::Font(std::string s, int slant, int weight) {
+ FcPattern *tmp1, *tmp2, *final;
+ FcResult res;
+ FcChar8 *filename;
+ int fontindex;
+
+ if(!(fc = FcInitLoadConfigAndFonts()))
+ throw(std::runtime_error("failed to initialize fontconfig"));
+
+ if(FT_Init_FreeType(&library))
+ throw(std::runtime_error("failed to initialize freetype"));
+
+ aux = FcPatternCreate();
+
+ tmp1 = FcPatternBuild(NULL,
+ FC_FAMILY, FcTypeString, s.c_str(),
+ FC_SLANT, FcTypeInteger, slant,
+ FC_WEIGHT, FcTypeInteger, weight ? 300 : 100,
+ NULL);
+ if(!tmp1)
+ throw(std::runtime_error("failed to load font"));
+
+ tmp2 = FcFontRenderPrepare(fc, tmp1, aux);
+ FcPatternDestroy(tmp1);
+ final = FcFontMatch(fc, tmp2, &res);
+ FcPatternDestroy(tmp2);
+ if(!final)
+ throw(std::runtime_error("failed to load font"));
+
+ if(FcPatternGetString(final, FC_FILE, 0, &filename) != FcResultMatch || FcPatternGetInteger(final, FC_INDEX, 0, &fontindex) != FcResultMatch) {
+ FcPatternDestroy(final);
+ throw(std::runtime_error("failed to locate font"));
+ }
+
+ if(FT_New_Face(library, (char*)filename, fontindex, &face)) {
+ FcPatternDestroy(final);
+ throw(std::runtime_error("failed to create new face"));
+ }
+
+ FcPatternDestroy(final);
+ FcPatternDestroy(aux);
+// FcFini();
+}
+
+Font::~Font() {
+ FT_Done_Face(face);
+ FT_Done_FreeType(library);
+}
+
+void Font::set_font_size(int size) {
+ FT_Size_RequestRec req;
+ TT_OS2 *os2;
+ TT_HoriHeader *hori;
+ float scale = 1.0;
+
+ FT_Size_Metrics *m = &face->size->metrics;
+
+ os2 = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
+ hori = (TT_HoriHeader*)FT_Get_Sfnt_Table(face, ft_sfnt_hhea);
+ if(os2 && hori) {
+ int horisum = hori->Ascender - hori->Descender;
+ unsigned int winsum = os2->usWinAscent + os2->usWinDescent;
+ scale = (float)horisum / (float)winsum;
+ }
+
+ req.type = FT_SIZE_REQUEST_TYPE_REAL_DIM;
+ req.width = 0;
+ req.height = (FT_F26Dot6)(size * 64 * scale);
+ req.horiResolution = 0;
+ req.vertResolution = 0;
+ FT_Request_Size(face, &req);
+}
+
+double Font::get_kerning(FT_UInt left, FT_UInt right) {
+ if(FT_HAS_KERNING(face)) {
+ FT_Vector d;
+ FT_Get_Kerning(face, left, right, 0, &d);
+ return (double)d.x / 64.0;
+ } else return 0;
+}
+
+unsigned int Font::get_text_width(std::string s) {
+ FT_UInt prev = 0;
+ bool kerning = FT_HAS_KERNING(face);
+ double width = 0;
+ for(std::string::iterator c = s.begin(); c < s.end(); c++) {
+ int i = FT_Get_Char_Index(face, *c);
+ if(kerning && prev && i)
+ width += get_kerning(prev, i);
+ if(FT_Load_Char(face, *c, 0))
+ throw(std::runtime_error("failed to load char"));
+ width += (double)face->glyph->advance.x / 64.0;
+ }
+ return int(width);
+}
+
+unsigned int Font::get_line_height() {
+ return face->bbox.yMax - face->bbox.yMin;
+}