Color Management, Stage 2: Switch color pipeline to use OpenColorIO
[blender.git] / source / blender / blenfont / intern / blf_font.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation.
19  * All rights reserved.
20  *
21  * 
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/blenfont/intern/blf_font.c
28  *  \ingroup blf
29  */
30
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <math.h>
36
37 #include <ft2build.h>
38
39 #include FT_FREETYPE_H
40 #include FT_GLYPH_H
41
42 #include "MEM_guardedalloc.h"
43
44 #include "DNA_vec_types.h"
45
46 #include "BLI_listbase.h"
47 #include "BLI_math.h"
48 #include "BLI_rect.h"
49 #include "BLI_string.h"
50 #include "BLI_string_utf8.h"
51 #include "BLI_linklist.h"  /* linknode */
52
53 #include "BIF_gl.h"
54 #include "BLF_api.h"
55
56 #include "IMB_colormanagement.h"
57
58 #include "blf_internal_types.h"
59 #include "blf_internal.h"
60
61
62 /* freetype2 handle ONLY for this file!. */
63 static FT_Library ft_lib;
64
65 int blf_font_init(void)
66 {
67         return FT_Init_FreeType(&ft_lib);
68 }
69
70 void blf_font_exit(void)
71 {
72         FT_Done_FreeType(ft_lib);
73 }
74
75 void blf_font_size(FontBLF *font, int size, int dpi)
76 {
77         GlyphCacheBLF *gc;
78         FT_Error err;
79
80         err = FT_Set_Char_Size(font->face, 0, (size * 64), dpi, dpi);
81         if (err) {
82                 /* FIXME: here we can go through the fixed size and choice a close one */
83                 printf("The current font don't support the size, %d and dpi, %d\n", size, dpi);
84                 return;
85         }
86
87         font->size = size;
88         font->dpi = dpi;
89
90         gc = blf_glyph_cache_find(font, size, dpi);
91         if (gc)
92                 font->glyph_cache = gc;
93         else {
94                 gc = blf_glyph_cache_new(font);
95                 if (gc)
96                         font->glyph_cache = gc;
97                 else
98                         font->glyph_cache = NULL;
99         }
100 }
101
102 static void blf_font_ensure_ascii_table(FontBLF *font)
103 {
104         GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
105
106         /* build ascii on demand */
107         if (glyph_ascii_table['0'] == NULL) {
108                 GlyphBLF *g;
109                 unsigned int i;
110                 for (i = 0; i < 256; i++) {
111                         g = blf_glyph_search(font->glyph_cache, i);
112                         if (!g) {
113                                 FT_UInt glyph_index = FT_Get_Char_Index(font->face, i);
114                                 g = blf_glyph_add(font, glyph_index, i);
115                         }
116                         glyph_ascii_table[i] = g;
117                 }
118         }
119 }
120
121 /* Fast path for runs of ASCII characters. Given that common UTF-8
122  * input will consist of an overwhelming majority of ASCII
123  * characters.
124  */
125
126 /* Note,
127  * blf_font_ensure_ascii_table(font); must be called before this macro */
128
129 #define BLF_UTF8_NEXT_FAST(_font, _g, _str, _i, _c, _glyph_ascii_table)          \
130         if (((_c) = (_str)[_i]) < 0x80) {                                            \
131                 _g = (_glyph_ascii_table)[_c];                                           \
132                 _i++;                                                                    \
133         }                                                                            \
134         else if ((_c = BLI_str_utf8_as_unicode_step(_str, &(_i))) != BLI_UTF8_ERR) { \
135                 if ((_g = blf_glyph_search((_font)->glyph_cache, _c)) == NULL) {         \
136                         _g = blf_glyph_add(_font,                                            \
137                                           FT_Get_Char_Index((_font)->face, _c), _c);         \
138                 }                                                                        \
139         } (void)0
140
141
142 #define BLF_KERNING_VARS(_font, _has_kerning, _kern_mode)                        \
143         const short _has_kerning = FT_HAS_KERNING((_font)->face);                    \
144         const FT_UInt _kern_mode = (_has_kerning == 0) ? 0 :                         \
145                                  (((_font)->flags & BLF_KERNING_DEFAULT) ?           \
146                                   ft_kerning_default : FT_KERNING_UNFITTED)          \
147
148
149 #define BLF_KERNING_STEP(_font, _kern_mode, _g_prev, _g, _delta, _pen_x)         \
150 {                                                                                \
151         if (_g_prev) {                                                               \
152                 _delta.x = _delta.y = 0;                                                 \
153                 if (FT_Get_Kerning((_font)->face,                                        \
154                                    (_g_prev)->idx,                                       \
155                                    (_g)->idx,                                            \
156                                    _kern_mode,                                           \
157                                    &(_delta)) == 0)                                      \
158                 {                                                                        \
159                         _pen_x += _delta.x >> 6;                                             \
160                 }                                                                        \
161         }                                                                            \
162 } (void)0
163
164 void blf_font_draw(FontBLF *font, const char *str, size_t len)
165 {
166         unsigned int c;
167         GlyphBLF *g, *g_prev = NULL;
168         FT_Vector delta;
169         int pen_x = 0, pen_y = 0;
170         size_t i = 0;
171         GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
172
173         BLF_KERNING_VARS(font, has_kerning, kern_mode);
174
175         blf_font_ensure_ascii_table(font);
176
177         while (str[i] && i < len) {
178                 BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
179
180                 if (c == BLI_UTF8_ERR)
181                         break;
182                 if (g == NULL)
183                         continue;
184                 if (has_kerning)
185                         BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
186
187                 /* do not return this loop if clipped, we want every character tested */
188                 blf_glyph_render(font, g, (float)pen_x, (float)pen_y);
189
190                 pen_x += g->advance;
191                 g_prev = g;
192         }
193 }
194
195 /* faster version of blf_font_draw, ascii only for view dimensions */
196 void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len)
197 {
198         unsigned char c;
199         GlyphBLF *g, *g_prev = NULL;
200         FT_Vector delta;
201         int pen_x = 0, pen_y = 0;
202         GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
203
204         BLF_KERNING_VARS(font, has_kerning, kern_mode);
205
206         blf_font_ensure_ascii_table(font);
207
208         while ((c = *(str++)) && len--) {
209                 if ((g = glyph_ascii_table[c]) == NULL)
210                         continue;
211                 if (has_kerning)
212                         BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
213
214                 /* do not return this loop if clipped, we want every character tested */
215                 blf_glyph_render(font, g, (float)pen_x, (float)pen_y);
216
217                 pen_x += g->advance;
218                 g_prev = g;
219         }
220 }
221
222 /* Sanity checks are done by BLF_draw_buffer() */
223 void blf_font_buffer(FontBLF *font, const char *str)
224 {
225         unsigned int c;
226         GlyphBLF *g, *g_prev = NULL;
227         FT_Vector delta;
228         int pen_x = (int)font->pos[0], pen_y = 0;
229         size_t i = 0;
230         GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
231
232         /* buffer specific vars */
233         FontBufInfoBLF *buf_info = &font->buf_info;
234         float b_col_float[4];
235         const unsigned char b_col_char[4] = {buf_info->col[0] * 255,
236                                              buf_info->col[1] * 255,
237                                              buf_info->col[2] * 255,
238                                              buf_info->col[3] * 255};
239
240         unsigned char *cbuf;
241         int chx, chy;
242         int y, x;
243         float a, *fbuf;
244
245         BLF_KERNING_VARS(font, has_kerning, kern_mode);
246
247         blf_font_ensure_ascii_table(font);
248
249         /* another buffer specific call for color conversion */
250         if (buf_info->display) {
251                 copy_v4_v4(b_col_float, buf_info->col);
252                 IMB_colormanagement_display_to_scene_linear_v3(b_col_float, buf_info->display);
253         }
254         else {
255                 srgb_to_linearrgb_v4(b_col_float, buf_info->col);
256         }
257
258         while (str[i]) {
259                 BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
260
261                 if (c == BLI_UTF8_ERR)
262                         break;
263                 if (g == NULL)
264                         continue;
265                 if (has_kerning)
266                         BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
267
268                 chx = pen_x + ((int)g->pos_x);
269                 chy = (int)font->pos[1] + g->height;
270
271                 if (g->pitch < 0) {
272                         pen_y = (int)font->pos[1] + (g->height - (int)g->pos_y);
273                 }
274                 else {
275                         pen_y = (int)font->pos[1] - (g->height - (int)g->pos_y);
276                 }
277
278                 if ((chx + g->width) >= 0 && chx < buf_info->w && (pen_y + g->height) >= 0 && pen_y < buf_info->h) {
279                         /* don't draw beyond the buffer bounds */
280                         int width_clip = g->width;
281                         int height_clip = g->height;
282                         int yb_start = g->pitch < 0 ? 0 : g->height - 1;
283
284                         if (width_clip + chx > buf_info->w)
285                                 width_clip -= chx + width_clip - buf_info->w;
286                         if (height_clip + pen_y > buf_info->h)
287                                 height_clip -= pen_y + height_clip - buf_info->h;
288                         
289                         /* drawing below the image? */
290                         if (pen_y < 0) {
291                                 yb_start += (g->pitch < 0) ? -pen_y : pen_y;
292                                 height_clip += pen_y;
293                                 pen_y = 0;
294                         }
295
296                         if (buf_info->fbuf) {
297                                 int yb = yb_start;
298                                 for (y = ((chy >= 0) ? 0 : -chy); y < height_clip; y++) {
299                                         for (x = ((chx >= 0) ? 0 : -chx); x < width_clip; x++) {
300                                                 a = *(g->bitmap + x + (yb * g->pitch)) / 255.0f;
301
302                                                 if (a > 0.0f) {
303                                                         float alphatest;
304                                                         fbuf = buf_info->fbuf + buf_info->ch * ((chx + x) + ((pen_y + y) * buf_info->w));
305                                                         if (a >= 1.0f) {
306                                                                 fbuf[0] = b_col_float[0];
307                                                                 fbuf[1] = b_col_float[1];
308                                                                 fbuf[2] = b_col_float[2];
309                                                                 fbuf[3] = (alphatest = (fbuf[3] + (b_col_float[3]))) < 1.0f ? alphatest : 1.0f;
310                                                         }
311                                                         else {
312                                                                 fbuf[0] = (b_col_float[0] * a) + (fbuf[0] * (1.0f - a));
313                                                                 fbuf[1] = (b_col_float[1] * a) + (fbuf[1] * (1.0f - a));
314                                                                 fbuf[2] = (b_col_float[2] * a) + (fbuf[2] * (1.0f - a));
315                                                                 fbuf[3] = (alphatest = (fbuf[3] + (b_col_float[3] * a))) < 1.0f ? alphatest : 1.0f;
316                                                         }
317                                                 }
318                                         }
319
320                                         if (g->pitch < 0)
321                                                 yb++;
322                                         else
323                                                 yb--;
324                                 }
325                         }
326
327                         if (buf_info->cbuf) {
328                                 int yb = yb_start;
329                                 for (y = 0; y < height_clip; y++) {
330                                         for (x = 0; x < width_clip; x++) {
331                                                 a = *(g->bitmap + x + (yb * g->pitch)) / 255.0f;
332
333                                                 if (a > 0.0f) {
334                                                         int alphatest;
335                                                         cbuf = buf_info->cbuf + buf_info->ch * ((chx + x) + ((pen_y + y) * buf_info->w));
336                                                         if (a >= 1.0f) {
337                                                                 cbuf[0] = b_col_char[0];
338                                                                 cbuf[1] = b_col_char[1];
339                                                                 cbuf[2] = b_col_char[2];
340                                                                 cbuf[3] = (alphatest = ((int)cbuf[3] + (int)b_col_char[3])) < 255 ? alphatest : 255;
341                                                         }
342                                                         else {
343                                                                 cbuf[0] = (b_col_char[0] * a) + (cbuf[0] * (1.0f - a));
344                                                                 cbuf[1] = (b_col_char[1] * a) + (cbuf[1] * (1.0f - a));
345                                                                 cbuf[2] = (b_col_char[2] * a) + (cbuf[2] * (1.0f - a));
346                                                                 cbuf[3] = (alphatest = ((int)cbuf[3] + (int)((b_col_float[3] * a) * 255.0f))) <
347                                                                           255 ? alphatest : 255;
348                                                         }
349                                                 }
350                                         }
351
352                                         if (g->pitch < 0)
353                                                 yb++;
354                                         else
355                                                 yb--;
356                                 }
357                         }
358                 }
359
360                 pen_x += g->advance;
361                 g_prev = g;
362         }
363 }
364
365 void blf_font_boundbox(FontBLF *font, const char *str, rctf *box)
366 {
367         unsigned int c;
368         GlyphBLF *g, *g_prev = NULL;
369         FT_Vector delta;
370         int pen_x = 0, pen_y = 0;
371         size_t i = 0;
372         GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
373
374         rctf gbox;
375
376         BLF_KERNING_VARS(font, has_kerning, kern_mode);
377
378         box->xmin = 32000.0f;
379         box->xmax = -32000.0f;
380         box->ymin = 32000.0f;
381         box->ymax = -32000.0f;
382
383         blf_font_ensure_ascii_table(font);
384
385         while (str[i]) {
386                 BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
387
388                 if (c == BLI_UTF8_ERR)
389                         break;
390                 if (g == NULL)
391                         continue;
392                 if (has_kerning)
393                         BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
394
395                 gbox.xmin = pen_x;
396                 gbox.xmax = pen_x + g->advance;
397                 gbox.ymin = g->box.ymin + pen_y;
398                 gbox.ymax = g->box.ymax + pen_y;
399
400                 if (gbox.xmin < box->xmin) box->xmin = gbox.xmin;
401                 if (gbox.ymin < box->ymin) box->ymin = gbox.ymin;
402
403                 if (gbox.xmax > box->xmax) box->xmax = gbox.xmax;
404                 if (gbox.ymax > box->ymax) box->ymax = gbox.ymax;
405
406                 pen_x += g->advance;
407                 g_prev = g;
408         }
409
410         if (box->xmin > box->xmax) {
411                 box->xmin = 0.0f;
412                 box->ymin = 0.0f;
413                 box->xmax = 0.0f;
414                 box->ymax = 0.0f;
415         }
416 }
417
418 void blf_font_width_and_height(FontBLF *font, const char *str, float *width, float *height)
419 {
420         float xa, ya;
421         rctf box;
422
423         if (font->flags & BLF_ASPECT) {
424                 xa = font->aspect[0];
425                 ya = font->aspect[1];
426         }
427         else {
428                 xa = 1.0f;
429                 ya = 1.0f;
430         }
431
432         blf_font_boundbox(font, str, &box);
433         *width  = (BLI_RCT_SIZE_X(&box) * xa);
434         *height = (BLI_RCT_SIZE_Y(&box) * ya);
435 }
436
437 float blf_font_width(FontBLF *font, const char *str)
438 {
439         float xa;
440         rctf box;
441
442         if (font->flags & BLF_ASPECT)
443                 xa = font->aspect[0];
444         else
445                 xa = 1.0f;
446
447         blf_font_boundbox(font, str, &box);
448         return BLI_RCT_SIZE_X(&box) * xa;
449 }
450
451 float blf_font_height(FontBLF *font, const char *str)
452 {
453         float ya;
454         rctf box;
455
456         if (font->flags & BLF_ASPECT)
457                 ya = font->aspect[1];
458         else
459                 ya = 1.0f;
460
461         blf_font_boundbox(font, str, &box);
462         return BLI_RCT_SIZE_Y(&box) * ya;
463 }
464
465 float blf_font_fixed_width(FontBLF *font)
466 {
467         const unsigned int c = ' ';
468         GlyphBLF *g = blf_glyph_search(font->glyph_cache, c);
469         if (!g) {
470                 g = blf_glyph_add(font, FT_Get_Char_Index(font->face, c), c);
471
472                 /* if we don't find the glyph. */
473                 if (!g) {
474                         return 0.0f;
475                 }
476         }
477
478         return g->advance;
479 }
480
481 void blf_font_free(FontBLF *font)
482 {
483         GlyphCacheBLF *gc;
484
485         font->glyph_cache = NULL;
486         while (font->cache.first) {
487                 gc = font->cache.first;
488                 BLI_remlink(&font->cache, gc);
489                 blf_glyph_cache_free(gc);
490         }
491
492         FT_Done_Face(font->face);
493         if (font->filename)
494                 MEM_freeN(font->filename);
495         if (font->name)
496                 MEM_freeN(font->name);
497         MEM_freeN(font);
498 }
499
500 static void blf_font_fill(FontBLF *font)
501 {
502         unsigned int i;
503
504         font->aspect[0] = 1.0f;
505         font->aspect[1] = 1.0f;
506         font->aspect[2] = 1.0f;
507         font->pos[0] = 0.0f;
508         font->pos[1] = 0.0f;
509         font->angle = 0.0f;
510
511         for (i = 0; i < 16; i++)
512                 font->m[i] = 0;
513
514         font->clip_rec.xmin = 0.0f;
515         font->clip_rec.xmax = 0.0f;
516         font->clip_rec.ymin = 0.0f;
517         font->clip_rec.ymax = 0.0f;
518         font->flags = 0;
519         font->dpi = 0;
520         font->size = 0;
521         font->cache.first = NULL;
522         font->cache.last = NULL;
523         font->glyph_cache = NULL;
524         font->blur = 0;
525         font->max_tex_size = -1;
526
527         font->buf_info.fbuf = NULL;
528         font->buf_info.cbuf = NULL;
529         font->buf_info.w = 0;
530         font->buf_info.h = 0;
531         font->buf_info.ch = 0;
532         font->buf_info.col[0] = 0;
533         font->buf_info.col[1] = 0;
534         font->buf_info.col[2] = 0;
535         font->buf_info.col[3] = 0;
536
537         font->ft_lib = ft_lib;
538 }
539
540 FontBLF *blf_font_new(const char *name, const char *filename)
541 {
542         FontBLF *font;
543         FT_Error err;
544         char *mfile;
545
546         font = (FontBLF *)MEM_callocN(sizeof(FontBLF), "blf_font_new");
547         err = FT_New_Face(ft_lib, filename, 0, &font->face);
548         if (err) {
549                 MEM_freeN(font);
550                 return NULL;
551         }
552
553         err = FT_Select_Charmap(font->face, ft_encoding_unicode);
554         if (err) {
555                 printf("Can't set the unicode character map!\n");
556                 FT_Done_Face(font->face);
557                 MEM_freeN(font);
558                 return NULL;
559         }
560
561         mfile = blf_dir_metrics_search(filename);
562         if (mfile) {
563                 err = FT_Attach_File(font->face, mfile);
564                 if (err) {
565                         fprintf(stderr, "FT_Attach_File failed to load '%s' with error %d\n", filename, (int)err);
566                 }
567                 MEM_freeN(mfile);
568         }
569
570         font->name = BLI_strdup(name);
571         font->filename = BLI_strdup(filename);
572         blf_font_fill(font);
573         return font;
574 }
575
576 void blf_font_attach_from_mem(FontBLF *font, const unsigned char *mem, int mem_size)
577 {
578         FT_Open_Args open;
579
580         open.flags = FT_OPEN_MEMORY;
581         open.memory_base = (const FT_Byte *)mem;
582         open.memory_size = mem_size;
583         FT_Attach_Stream(font->face, &open);
584 }
585
586 FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, int mem_size)
587 {
588         FontBLF *font;
589         FT_Error err;
590
591         font = (FontBLF *)MEM_callocN(sizeof(FontBLF), "blf_font_new_from_mem");
592         err = FT_New_Memory_Face(ft_lib, mem, mem_size, 0, &font->face);
593         if (err) {
594                 MEM_freeN(font);
595                 return NULL;
596         }
597
598         err = FT_Select_Charmap(font->face, ft_encoding_unicode);
599         if (err) {
600                 printf("Can't set the unicode character map!\n");
601                 FT_Done_Face(font->face);
602                 MEM_freeN(font);
603                 return NULL;
604         }
605
606         font->name = BLI_strdup(name);
607         font->filename = NULL;
608         blf_font_fill(font);
609         return font;
610 }