f12b8aeeca505ba69d1d9578d16588a0ea06167d
[blender-staging.git] / source / blender / editors / interface / interface_style.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  * Contributor(s): Blender Foundation
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 #include <limits.h>
27 #include <math.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "DNA_screen_types.h"
34 #include "DNA_userdef_types.h"
35
36 #include "BLI_math.h"
37 #include "BLI_listbase.h"
38 #include "BLI_rect.h"
39 #include "BLI_string.h"
40
41 #include "BKE_context.h"
42 #include "BKE_global.h"
43 #include "BKE_utildefines.h"
44
45 #include "BIF_gl.h"
46 #include "BIF_glutil.h"
47
48 #include "BLF_api.h"
49
50 #include "UI_interface.h"
51
52 #include "ED_datafiles.h"
53
54 #include "interface_intern.h"
55
56
57 /* style + theme + layout-engine = UI */
58
59 /* 
60  This is a complete set of layout rules, the 'state' of the Layout 
61  Engine. Multiple styles are possible, defined via C or Python. Styles 
62  get a name, and will typically get activated per region type, like 
63  "Header", or "Listview" or "Toolbar". Properties of Style definitions 
64  are:
65  
66  - default collumn properties, internal spacing, aligning, min/max width
67  - button alignment rules (for groups)
68  - label placement rules
69  - internal labeling or external labeling default
70  - default minimum widths for buttons/labels (in amount of characters)
71  - font types, styles and relative sizes for Panel titles, labels, etc.
72
73 */
74
75
76 /* ********************************************** */
77
78 static uiStyle *ui_style_new(ListBase *styles, const char *name)
79 {
80         uiStyle *style= MEM_callocN(sizeof(uiStyle), "new style");
81         
82         BLI_addtail(styles, style);
83         BLI_strncpy(style->name, name, MAX_STYLE_NAME);
84         
85         style->panelzoom= 1.0;
86
87         style->paneltitle.uifont_id= UIFONT_DEFAULT;
88         style->paneltitle.points= 12;
89         style->paneltitle.kerning= 1;
90         style->paneltitle.shadow= 1;
91         style->paneltitle.shadx= 0;
92         style->paneltitle.shady= -1;
93         style->paneltitle.shadowalpha= 0.15f;
94         style->paneltitle.shadowcolor= 1.0f;
95         
96         style->grouplabel.uifont_id= UIFONT_DEFAULT;
97         style->grouplabel.points= 12;
98         style->grouplabel.kerning= 1;
99         style->grouplabel.shadow= 3;
100         style->grouplabel.shadx= 0;
101         style->grouplabel.shady= -1;
102         style->grouplabel.shadowalpha= 0.25f;
103         
104         style->widgetlabel.uifont_id= UIFONT_DEFAULT;
105         style->widgetlabel.points= 11;
106         style->widgetlabel.kerning= 1;
107         style->widgetlabel.shadow= 3;
108         style->widgetlabel.shadx= 0;
109         style->widgetlabel.shady= -1;
110         style->widgetlabel.shadowalpha= 0.15f;
111         style->widgetlabel.shadowcolor= 1.0f;
112         
113         style->widget.uifont_id= UIFONT_DEFAULT;
114         style->widget.points= 11;
115         style->widget.kerning= 1;
116         style->widget.shadowalpha= 0.25f;
117
118         style->columnspace= 8;
119         style->templatespace= 5;
120         style->boxspace= 5;
121         style->buttonspacex= 8;
122         style->buttonspacey= 2;
123         style->panelspace= 8;
124         style->panelouter= 4;
125         
126         return style;
127 }
128
129 static uiFont *uifont_to_blfont(int id)
130 {
131         uiFont *font= U.uifonts.first;
132         
133         for(; font; font= font->next) {
134                 if(font->uifont_id==id) {
135                         return font;
136                 }
137         }
138         return U.uifonts.first;
139 }
140
141 /* *************** draw ************************ */
142
143 void uiStyleFontDraw(uiFontStyle *fs, rcti *rect, char *str)
144 {
145         float height;
146         int xofs=0, yofs;
147         
148         uiStyleFontSet(fs);
149         
150         height= BLF_height(fs->uifont_id, "2"); /* correct offset is on baseline, the j is below that */
151         yofs= floor( 0.5f*(rect->ymax - rect->ymin - height));
152
153         if(fs->align==UI_STYLE_TEXT_CENTER)
154                 xofs= floor( 0.5f*(rect->xmax - rect->xmin - BLF_width(fs->uifont_id, str)));
155         else if(fs->align==UI_STYLE_TEXT_RIGHT)
156                 xofs= rect->xmax - rect->xmin - BLF_width(fs->uifont_id, str) - 1;
157         
158         /* clip is very strict, so we give it some space */
159         BLF_clipping(fs->uifont_id, rect->xmin-1, rect->ymin-4, rect->xmax+1, rect->ymax+4);
160         BLF_enable(fs->uifont_id, BLF_CLIPPING);
161         BLF_position(fs->uifont_id, rect->xmin+xofs, rect->ymin+yofs, 0.0f);
162
163         if (fs->shadow) {
164                 BLF_enable(fs->uifont_id, BLF_SHADOW);
165                 BLF_shadow(fs->uifont_id, fs->shadow, fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha);
166                 BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady);
167         }
168
169         if (fs->kerning == 1)
170                 BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
171
172         BLF_draw(fs->uifont_id, str);
173         BLF_disable(fs->uifont_id, BLF_CLIPPING);
174         if (fs->shadow)
175                 BLF_disable(fs->uifont_id, BLF_SHADOW);
176         if (fs->kerning == 1)
177                 BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
178 }
179
180 /* drawn same as above, but at 90 degree angle */
181 void uiStyleFontDrawRotated(uiFontStyle *fs, rcti *rect, char *str)
182 {
183         float height;
184         int xofs, yofs;
185         float angle;
186         rcti txtrect;
187
188         uiStyleFontSet(fs);
189
190         height= BLF_height(fs->uifont_id, "2"); /* correct offset is on baseline, the j is below that */
191         /* becomes x-offset when rotated */
192         xofs= floor( 0.5f*(rect->ymax - rect->ymin - height)) + 1;
193
194         /* ignore UI_STYLE, always aligned to top */
195
196         /* rotate counter-clockwise for now (assumes left-to-right language)*/
197         xofs+= height;
198         yofs= BLF_width(fs->uifont_id, str) + 5;
199         angle= 90.0f;
200
201         /* translate rect to vertical */
202         txtrect.xmin= rect->xmin - (rect->ymax - rect->ymin);
203         txtrect.ymin= rect->ymin - (rect->xmax - rect->xmin);
204         txtrect.xmax= rect->xmin;
205         txtrect.ymax= rect->ymin;
206
207         /* clip is very strict, so we give it some space */
208         /* clipping is done without rotation, so make rect big enough to contain both positions */
209         BLF_clipping(fs->uifont_id, txtrect.xmin-1, txtrect.ymin-yofs-xofs-4, rect->xmax+1, rect->ymax+4);
210         BLF_enable(fs->uifont_id, BLF_CLIPPING);
211         BLF_position(fs->uifont_id, txtrect.xmin+xofs, txtrect.ymax-yofs, 0.0f);
212
213         BLF_enable(fs->uifont_id, BLF_ROTATION);
214         BLF_rotation(fs->uifont_id, angle);
215
216         if (fs->shadow) {
217                 BLF_enable(fs->uifont_id, BLF_SHADOW);
218                 BLF_shadow(fs->uifont_id, fs->shadow, fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha);
219                 BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady);
220         }
221
222         if (fs->kerning == 1)
223                 BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
224
225         BLF_draw(fs->uifont_id, str);
226         BLF_disable(fs->uifont_id, BLF_ROTATION);
227         BLF_disable(fs->uifont_id, BLF_CLIPPING);
228         if (fs->shadow)
229                 BLF_disable(fs->uifont_id, BLF_SHADOW);
230         if (fs->kerning == 1)
231                 BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
232 }
233
234 /* ************** helpers ************************ */
235
236 /* temporarily, does widget font */
237 int UI_GetStringWidth(char *str)
238 {
239         uiStyle *style= U.uistyles.first;
240         uiFontStyle *fstyle= &style->widget;
241         int width;
242         
243         if (fstyle->kerning==1) /* for BLF_width */
244                 BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
245         
246         uiStyleFontSet(fstyle);
247         width= BLF_width(fstyle->uifont_id, str);       
248         
249         if (fstyle->kerning==1)
250                 BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
251         
252         return width;
253 }
254
255 /* temporarily, does widget font */
256 void UI_DrawString(float x, float y, char *str)
257 {
258         uiStyle *style= U.uistyles.first;
259         
260         uiStyleFontSet(&style->widget);
261         BLF_position(style->widget.uifont_id, x, y, 0.0f);
262         BLF_draw(style->widget.uifont_id, str);
263 }
264
265 /* ************** init exit ************************ */
266
267 /* called on each startup.blend read */
268 /* reading without uifont will create one */
269 void uiStyleInit(void)
270 {
271         uiFont *font= U.uifonts.first;
272         uiStyle *style= U.uistyles.first;
273         
274         /* recover from uninitialized dpi */
275         CLAMP(U.dpi, 72, 240);
276         
277         /* default builtin */
278         if(font==NULL) {
279                 font= MEM_callocN(sizeof(uiFont), "ui font");
280                 BLI_addtail(&U.uifonts, font);
281                 
282                 strcpy(font->filename, "default");
283                 font->uifont_id= UIFONT_DEFAULT;
284         }
285         
286         for(font= U.uifonts.first; font; font= font->next) {
287                 
288                 if(font->uifont_id==UIFONT_DEFAULT) {
289                         font->blf_id= BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
290                 }               
291                 else {
292                         font->blf_id= BLF_load(font->filename);
293                         if(font->blf_id == -1)
294                                 font->blf_id= BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
295                 }
296
297                 if (font->blf_id == -1) {
298                         if (G.f & G_DEBUG)
299                                 printf("uiStyleInit error, no fonts available\n");
300                 }
301                 else {
302                         /* ? just for speed to initialize?
303                          * Yes, this build the glyph cache and create
304                          * the texture.
305                          */
306                         BLF_size(font->blf_id, 11, U.dpi);
307                         BLF_size(font->blf_id, 12, U.dpi);
308                         BLF_size(font->blf_id, 14, U.dpi);
309                 }
310         }
311         
312         if(style==NULL) {
313                 ui_style_new(&U.uistyles, "Default Style");
314         }
315 }
316
317 void uiStyleFontSet(uiFontStyle *fs)
318 {
319         uiFont *font= uifont_to_blfont(fs->uifont_id);
320         
321         BLF_size(font->blf_id, fs->points, U.dpi);
322 }
323