aboutsummaryrefslogtreecommitdiff
path: root/drw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drw.c')
-rw-r--r--drw.c204
1 files changed, 157 insertions, 47 deletions
diff --git a/drw.c b/drw.c
index f65f330..dc220dc 100644
--- a/drw.c
+++ b/drw.c
@@ -1,6 +1,9 @@
+#include <stdint.h>
#include <sys/mman.h>
#include <unistd.h>
#include <math.h>
+#include <memory.h>
+#include <stdlib.h>
#include <grapheme.h>
#include "drw.h"
@@ -10,6 +13,10 @@
static Color to_color(uint32_t color);
static uint32_t to_uint32_t(Color color);
static void draw_bitmap(Canvas *canvas, FT_Bitmap *bitmap, unsigned x, unsigned y, uint32_t color);
+static void init_font(Font *font);
+static FontFamily *create_font_family(FontPath fontpath);
+static void free_font_family(FontFamily *fontfamily);
+static Font *get_font_with_charcode(FontCache *fontcache, uint_least32_t charcode);
Color
@@ -112,40 +119,114 @@ draw_rect(Canvas *canvas, unsigned x, unsigned y, unsigned width, unsigned heigh
}
}
-Font *
-create_font(const char *fontpath, unsigned size)
+
+FontCache *
+create_font_cache(FontPath *fontpath, int size, unsigned fontsize)
{
- FT_Error error;
- Font * font;
+ FontCache *fontcache = malloc(sizeof(FontCache));
+ FontCacheElement *current;
+ Font *font;
+ int i;
+
+ fontcache->fontsize = fontsize;
+ fontcache->fonttype = FONT_NORMAL;
+
+ if (size == 0) {
+ die("fontcache has to contain at least one font");
+ }
+
+ fontcache->first = malloc(sizeof(FontCacheElement));
+ current = fontcache->first;
+ current->family = create_font_family(fontpath[0]);
+ current->next = 0;
+
+ for (i = 1; i < size; ++i) {
+ current->next = malloc(sizeof(FontCacheElement));
+ current = current->next;
+ current->family = create_font_family(fontpath[i]);
+ current->next = 0;
+ }
+
+ font_cache_generate_box(fontcache);
+
+ return fontcache;
+}
+
+
+void
+font_cache_generate_box(FontCache *fontcache)
+{
+ Font *font = get_font_with_charcode(fontcache, 0);
+ FT_Set_Pixel_Sizes(font->face, 0, fontcache->fontsize);
+ fprintf(stderr, "fontsize: %i\n", fontcache->fontsize);
+ fontcache->box.width = (font->face->bbox.xMax - font->face->bbox.xMin) >> 6;
+ fontcache->box.height = (font->face->size->metrics.height) >> 6;
+ fprintf(stderr, "width: %i, height: %i\n", fontcache->box.width, fontcache->box.height);
+}
+
+
+void
+free_font_cache(FontCache *fontcache)
+{
+ FontCacheElement *current = fontcache->first;
+ FontCacheElement *next;
- font = malloc(sizeof(Font));
+ for (; current; current = next) {
+ next = current->next;
+ free_font_family(current->family);
+ free(current);
+ }
+
+ free(fontcache);
+}
+
+
+FontFamily *
+create_font_family(FontPath fontpath)
+{
+ int i;
+ FontFamily *fontfamily = malloc(sizeof(FontFamily));
+
+ for (i = 0; i < FONT_TYPE_SIZE; ++i) {
+ if (fontpath[i]) {
+ (*fontfamily)[i].path = fontpath[i];
+ (*fontfamily)[i].loaded = 0;
+ }
+ }
+
+ return fontfamily;
+}
+
+void
+free_font_family(FontFamily *fontfamily)
+{
+ int i;
+ for (i = 0; i < FONT_TYPE_SIZE; ++i) {
+ if ((*fontfamily)[i].loaded) {
+ FT_Done_Face((*fontfamily)[i].face);
+ FT_Done_FreeType((*fontfamily)[i].library);
+ }
+ }
+}
+
+
+void
+init_font(Font *font)
+{
+ FT_Error error;
error = FT_Init_FreeType(&font->library);
if (error)
die("cannot init library");
- error = FT_New_Face(font->library, fontpath, 0, &font->face);
+ error = FT_New_Face(font->library, font->path, 0, &font->face);
if (error)
die("cannot open face");
- error = FT_Set_Pixel_Sizes(font->face, 0, size);
- if (error)
- die("cannot set char size");
-
error = FT_Select_Charmap(font->face, ft_encoding_unicode);
if (error)
die("cannot set unicode");
-
- return font;
-}
-
-void
-free_font(Font *font)
-{
- FT_Done_Face(font->face);
- FT_Done_FreeType(font->library);
- free(font);
}
@@ -196,69 +277,98 @@ draw_bitmap(Canvas *canvas, FT_Bitmap *bitmap, unsigned x, unsigned y, uint32_t
}
}
+Font *
+get_font_with_charcode(FontCache *fontcache, uint_least32_t charcode)
+{
+ FT_UInt glyph_index;
+ FontCacheElement *element = fontcache->first;
+ Font *font;
+
+ for (; element; element = element->next) {
+ font = &(*element->family)[fontcache->fonttype];
+ if (!font->loaded) {
+ init_font(font);
+ font->loaded = 1;
+ }
+
+ glyph_index = FT_Get_Char_Index(font->face, charcode);
+
+ if (glyph_index)
+ return font;
+ }
+
+ font = fontcache->first->family[fontcache->fonttype];
+ init_font(font);
+ font->loaded = 1;
+ return font;
+}
+
unsigned
-draw_font(Canvas *canvas, Font *font, const char *text, unsigned x, unsigned y, uint32_t color)
+draw_char(Canvas *canvas, FontCache *fontcache, uint_least32_t charcode, unsigned x, unsigned y, uint32_t color)
{
FT_GlyphSlot slot;
FT_Error error;
FT_UInt glyph_index;
FT_UInt previous = 0;
- uint_least32_t charcode;
- FT_Bool has_kerning = FT_HAS_KERNING(font->face);
+ FT_Bool has_kerning;
FT_Vector delta;
+ Font *current_font;
- slot = font->face->glyph;
-
- for (; *text;) {
- text += grapheme_decode_utf8(text, sizeof(uint_least32_t), &charcode);
+ current_font = get_font_with_charcode(fontcache, charcode);
+ FT_Set_Pixel_Sizes(current_font->face, 0, fontcache->fontsize);
- glyph_index = FT_Get_Char_Index(font->face, charcode);
+ slot = current_font->face->glyph;
+ glyph_index = FT_Get_Char_Index(current_font->face, charcode);
- if (has_kerning && previous && glyph_index) {
- FT_Get_Kerning(font->face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
- x += delta.x >> 6;
- }
+ has_kerning = FT_HAS_KERNING(current_font->face);
+ if (has_kerning && previous && glyph_index) {
+ FT_Get_Kerning(current_font->face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
+ x += delta.x >> 6;
+ }
- error = FT_Load_Glyph(font->face, glyph_index, FT_LOAD_RENDER);
- if (error) {
- fprintf(stderr, "warning: char not loaded, skipping...\n");
- continue;
- }
+ error = FT_Load_Glyph(current_font->face, glyph_index, FT_LOAD_RENDER);
+ if (error) {
+ fprintf(stderr, "warning: char not loaded, skipping...\n");
+ return x;
+ }
- draw_bitmap(canvas, &slot->bitmap, x + slot->bitmap_left, y - slot->bitmap_top, color);
+ draw_bitmap(canvas, &slot->bitmap, x + slot->bitmap_left, y - slot->bitmap_top, color);
- x += slot->advance.x >> 6;
- }
+ x += slot->advance.x >> 6;
return x;
}
unsigned
-font_width(Font *font, const char *text)
+font_width(FontCache *fontcache, const char *text)
{
FT_GlyphSlot slot;
FT_Error error;
FT_UInt glyph_index;
FT_UInt previous = 0;
uint_least32_t charcode;
- FT_Bool has_kerning = FT_HAS_KERNING(font->face);
+ FT_Bool has_kerning;
FT_Vector delta;
unsigned x = 0;
-
- slot = font->face->glyph;
+ Font *current_font;
for (; *text;) {
text += grapheme_decode_utf8(text, sizeof(uint_least32_t), &charcode);
- glyph_index = FT_Get_Char_Index(font->face, charcode);
+ current_font = get_font_with_charcode(fontcache, charcode);
+ FT_Set_Pixel_Sizes(current_font->face, 0, fontcache->fontsize);
+
+ slot = current_font->face->glyph;
+ glyph_index = FT_Get_Char_Index(current_font->face, charcode);
+ has_kerning = FT_HAS_KERNING(current_font->face);
if (has_kerning && previous && glyph_index) {
- FT_Get_Kerning(font->face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
+ FT_Get_Kerning(current_font->face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
x += delta.x >> 6;
}
- error = FT_Load_Glyph(font->face, glyph_index, FT_LOAD_RENDER);
+ error = FT_Load_Glyph(current_font->face, glyph_index, FT_LOAD_RENDER);
if (error) {
fprintf(stderr, "warning: char not loaded, skipping...\n");
continue;