Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2009 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * Contributor(s): Blender Foundation 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 */ 00025 00031 #include <limits.h> 00032 #include <math.h> 00033 #include <stdlib.h> 00034 #include <string.h> 00035 00036 #include "MEM_guardedalloc.h" 00037 00038 #include "DNA_screen_types.h" 00039 #include "DNA_userdef_types.h" 00040 00041 #include "BLI_math.h" 00042 #include "BLI_listbase.h" 00043 #include "BLI_rect.h" 00044 #include "BLI_string.h" 00045 #include "BLI_utildefines.h" 00046 00047 #include "BKE_global.h" 00048 00049 00050 #include "BLF_api.h" 00051 #include "BLF_translation.h" 00052 00053 #include "UI_interface.h" 00054 00055 #include "ED_datafiles.h" 00056 00057 #include "interface_intern.h" 00058 00059 00060 /* style + theme + layout-engine = UI */ 00061 00062 /* 00063 This is a complete set of layout rules, the 'state' of the Layout 00064 Engine. Multiple styles are possible, defined via C or Python. Styles 00065 get a name, and will typically get activated per region type, like 00066 "Header", or "Listview" or "Toolbar". Properties of Style definitions 00067 are: 00068 00069 - default collumn properties, internal spacing, aligning, min/max width 00070 - button alignment rules (for groups) 00071 - label placement rules 00072 - internal labeling or external labeling default 00073 - default minimum widths for buttons/labels (in amount of characters) 00074 - font types, styles and relative sizes for Panel titles, labels, etc. 00075 00076 */ 00077 00078 00079 /* ********************************************** */ 00080 00081 static uiStyle *ui_style_new(ListBase *styles, const char *name, short uifont_id) 00082 { 00083 uiStyle *style= MEM_callocN(sizeof(uiStyle), "new style"); 00084 00085 BLI_addtail(styles, style); 00086 BLI_strncpy(style->name, name, MAX_STYLE_NAME); 00087 00088 style->panelzoom= 1.0; /* unused */ 00089 00090 style->paneltitle.uifont_id= uifont_id; 00091 style->paneltitle.points= 12; 00092 style->paneltitle.kerning= 1; 00093 style->paneltitle.shadow= 1; 00094 style->paneltitle.shadx= 0; 00095 style->paneltitle.shady= -1; 00096 style->paneltitle.shadowalpha= 0.15f; 00097 style->paneltitle.shadowcolor= 1.0f; 00098 00099 style->grouplabel.uifont_id= uifont_id; 00100 style->grouplabel.points= 12; 00101 style->grouplabel.kerning= 1; 00102 style->grouplabel.shadow= 3; 00103 style->grouplabel.shadx= 0; 00104 style->grouplabel.shady= -1; 00105 style->grouplabel.shadowalpha= 0.25f; 00106 00107 style->widgetlabel.uifont_id= uifont_id; 00108 style->widgetlabel.points= 11; 00109 style->widgetlabel.kerning= 1; 00110 style->widgetlabel.shadow= 3; 00111 style->widgetlabel.shadx= 0; 00112 style->widgetlabel.shady= -1; 00113 style->widgetlabel.shadowalpha= 0.15f; 00114 style->widgetlabel.shadowcolor= 1.0f; 00115 00116 style->widget.uifont_id= uifont_id; 00117 style->widget.points= 11; 00118 style->widget.kerning= 1; 00119 style->widget.shadowalpha= 0.25f; 00120 00121 style->columnspace= 8; 00122 style->templatespace= 5; 00123 style->boxspace= 5; 00124 style->buttonspacex= 8; 00125 style->buttonspacey= 2; 00126 style->panelspace= 8; 00127 style->panelouter= 4; 00128 00129 return style; 00130 } 00131 00132 static uiFont *uifont_to_blfont(int id) 00133 { 00134 uiFont *font= U.uifonts.first; 00135 00136 for(; font; font= font->next) { 00137 if(font->uifont_id==id) { 00138 return font; 00139 } 00140 } 00141 return U.uifonts.first; 00142 } 00143 00144 /* *************** draw ************************ */ 00145 00146 00147 void uiStyleFontDrawExt(uiFontStyle *fs, rcti *rect, const char *str, 00148 float *r_xofs, float *r_yofs) 00149 { 00150 float height; 00151 int xofs=0, yofs; 00152 00153 uiStyleFontSet(fs); 00154 00155 height= BLF_ascender(fs->uifont_id); 00156 yofs= ceil( 0.5f*(rect->ymax - rect->ymin - height)); 00157 00158 if(fs->align==UI_STYLE_TEXT_CENTER) { 00159 xofs= floor( 0.5f*(rect->xmax - rect->xmin - BLF_width(fs->uifont_id, str))); 00160 /* don't center text if it chops off the start of the text, 2 gives some margin */ 00161 if(xofs < 2) { 00162 xofs= 2; 00163 } 00164 } 00165 else if(fs->align==UI_STYLE_TEXT_RIGHT) { 00166 xofs= rect->xmax - rect->xmin - BLF_width(fs->uifont_id, str) - 1; 00167 } 00168 00169 /* clip is very strict, so we give it some space */ 00170 BLF_clipping(fs->uifont_id, rect->xmin-1, rect->ymin-4, rect->xmax+1, rect->ymax+4); 00171 BLF_enable(fs->uifont_id, BLF_CLIPPING); 00172 BLF_position(fs->uifont_id, rect->xmin+xofs, rect->ymin+yofs, 0.0f); 00173 00174 if (fs->shadow) { 00175 BLF_enable(fs->uifont_id, BLF_SHADOW); 00176 BLF_shadow(fs->uifont_id, fs->shadow, fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha); 00177 BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady); 00178 } 00179 00180 if (fs->kerning == 1) 00181 BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT); 00182 00183 BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX); 00184 BLF_disable(fs->uifont_id, BLF_CLIPPING); 00185 if (fs->shadow) 00186 BLF_disable(fs->uifont_id, BLF_SHADOW); 00187 if (fs->kerning == 1) 00188 BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT); 00189 00190 *r_xofs= xofs; 00191 *r_yofs= yofs; 00192 } 00193 00194 void uiStyleFontDraw(uiFontStyle *fs, rcti *rect, const char *str) 00195 { 00196 float xofs, yofs; 00197 uiStyleFontDrawExt(fs, rect, str, 00198 &xofs, &yofs); 00199 } 00200 00201 /* drawn same as above, but at 90 degree angle */ 00202 void uiStyleFontDrawRotated(uiFontStyle *fs, rcti *rect, const char *str) 00203 { 00204 float height; 00205 int xofs, yofs; 00206 float angle; 00207 rcti txtrect; 00208 00209 uiStyleFontSet(fs); 00210 00211 height= BLF_ascender(fs->uifont_id); 00212 /* becomes x-offset when rotated */ 00213 xofs= ceil( 0.5f*(rect->ymax - rect->ymin - height)); 00214 00215 /* ignore UI_STYLE, always aligned to top */ 00216 00217 /* rotate counter-clockwise for now (assumes left-to-right language)*/ 00218 xofs+= height; 00219 yofs= BLF_width(fs->uifont_id, str) + 5; 00220 angle= 90.0f; 00221 00222 /* translate rect to vertical */ 00223 txtrect.xmin= rect->xmin - (rect->ymax - rect->ymin); 00224 txtrect.ymin= rect->ymin - (rect->xmax - rect->xmin); 00225 txtrect.xmax= rect->xmin; 00226 txtrect.ymax= rect->ymin; 00227 00228 /* clip is very strict, so we give it some space */ 00229 /* clipping is done without rotation, so make rect big enough to contain both positions */ 00230 BLF_clipping(fs->uifont_id, txtrect.xmin-1, txtrect.ymin-yofs-xofs-4, rect->xmax+1, rect->ymax+4); 00231 BLF_enable(fs->uifont_id, BLF_CLIPPING); 00232 BLF_position(fs->uifont_id, txtrect.xmin+xofs, txtrect.ymax-yofs, 0.0f); 00233 00234 BLF_enable(fs->uifont_id, BLF_ROTATION); 00235 BLF_rotation(fs->uifont_id, angle); 00236 00237 if (fs->shadow) { 00238 BLF_enable(fs->uifont_id, BLF_SHADOW); 00239 BLF_shadow(fs->uifont_id, fs->shadow, fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha); 00240 BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady); 00241 } 00242 00243 if (fs->kerning == 1) 00244 BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT); 00245 00246 BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX); 00247 BLF_disable(fs->uifont_id, BLF_ROTATION); 00248 BLF_disable(fs->uifont_id, BLF_CLIPPING); 00249 if (fs->shadow) 00250 BLF_disable(fs->uifont_id, BLF_SHADOW); 00251 if (fs->kerning == 1) 00252 BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT); 00253 } 00254 00255 /* ************** helpers ************************ */ 00256 /* XXX: read a style configure */ 00257 uiStyle* UI_GetStyle(void) 00258 { 00259 uiStyle *style = NULL; 00260 /* offset is two struct uiStyle pointers */ 00261 /* style = BLI_findstring( &U.uistyles, "Unifont Style", sizeof(style)*2 ) */; 00262 return (style != NULL) ? style : U.uistyles.first; 00263 } 00264 00265 /* temporarily, does widget font */ 00266 int UI_GetStringWidth(const char *str) 00267 { 00268 uiStyle *style= UI_GetStyle(); 00269 uiFontStyle *fstyle= &style->widget; 00270 int width; 00271 00272 if (fstyle->kerning==1) /* for BLF_width */ 00273 BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT); 00274 00275 uiStyleFontSet(fstyle); 00276 width= BLF_width(fstyle->uifont_id, str); 00277 00278 if (fstyle->kerning==1) 00279 BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT); 00280 00281 return width; 00282 } 00283 00284 /* temporarily, does widget font */ 00285 void UI_DrawString(float x, float y, const char *str) 00286 { 00287 uiStyle *style= UI_GetStyle(); 00288 00289 if (style->widget.kerning == 1) 00290 BLF_enable(style->widget.uifont_id, BLF_KERNING_DEFAULT); 00291 00292 uiStyleFontSet(&style->widget); 00293 BLF_position(style->widget.uifont_id, x, y, 0.0f); 00294 BLF_draw(style->widget.uifont_id, str, BLF_DRAW_STR_DUMMY_MAX); 00295 00296 if (style->widget.kerning == 1) 00297 BLF_disable(style->widget.uifont_id, BLF_KERNING_DEFAULT); 00298 } 00299 00300 /* ************** init exit ************************ */ 00301 00302 /* called on each startup.blend read */ 00303 /* reading without uifont will create one */ 00304 void uiStyleInit(void) 00305 { 00306 uiFont *font= U.uifonts.first; 00307 uiStyle *style= U.uistyles.first; 00308 00309 /* recover from uninitialized dpi */ 00310 if(U.dpi == 0) 00311 U.dpi= 72; 00312 CLAMP(U.dpi, 48, 128); 00313 00314 /* default builtin */ 00315 if(font==NULL) { 00316 font= MEM_callocN(sizeof(uiFont), "ui font"); 00317 BLI_addtail(&U.uifonts, font); 00318 00319 BLI_strncpy(font->filename, "default", sizeof(font->filename)); 00320 font->uifont_id= UIFONT_DEFAULT; 00321 } 00322 00323 for(font= U.uifonts.first; font; font= font->next) { 00324 00325 if(font->uifont_id==UIFONT_DEFAULT) { 00326 #ifdef WITH_INTERNATIONAL 00327 int font_size= datatoc_bfont_ttf_size; 00328 unsigned char *font_ttf= (unsigned char*)datatoc_bfont_ttf; 00329 static int last_font_size = 0; 00330 00331 /* use unicode font for translation */ 00332 if(U.transopts & USER_DOTRANSLATE) { 00333 font_ttf= BLF_get_unifont(&font_size); 00334 00335 if(!font_ttf) { 00336 /* fall back if not found */ 00337 font_size= datatoc_bfont_ttf_size; 00338 font_ttf= (unsigned char*)datatoc_bfont_ttf; 00339 } 00340 } 00341 00342 /* relload only if needed */ 00343 if(last_font_size != font_size) { 00344 BLF_unload("default"); 00345 last_font_size = font_size; 00346 } 00347 00348 font->blf_id= BLF_load_mem("default", font_ttf, font_size); 00349 #else 00350 font->blf_id= BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size); 00351 #endif 00352 } 00353 else { 00354 font->blf_id= BLF_load(font->filename); 00355 if(font->blf_id == -1) 00356 font->blf_id= BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size); 00357 } 00358 00359 if (font->blf_id == -1) { 00360 if (G.f & G_DEBUG) 00361 printf("%s: error, no fonts available\n", __func__); 00362 } 00363 else { 00364 /* ? just for speed to initialize? 00365 * Yes, this build the glyph cache and create 00366 * the texture. 00367 */ 00368 BLF_size(font->blf_id, 11, U.dpi); 00369 BLF_size(font->blf_id, 12, U.dpi); 00370 BLF_size(font->blf_id, 14, U.dpi); 00371 } 00372 } 00373 00374 if(style==NULL) { 00375 ui_style_new(&U.uistyles, "Default Style", UIFONT_DEFAULT ); 00376 } 00377 00378 // XXX, this should be moved into a style, but for now best only load the monospaced font once. 00379 if (blf_mono_font == -1) 00380 blf_mono_font= BLF_load_mem_unique("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size); 00381 00382 BLF_size(blf_mono_font, 12, 72); 00383 00384 /* second for rendering else we get threading problems */ 00385 if (blf_mono_font_render == -1) 00386 blf_mono_font_render= BLF_load_mem_unique("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size); 00387 00388 BLF_size(blf_mono_font_render, 12, 72); 00389 } 00390 00391 void uiStyleFontSet(uiFontStyle *fs) 00392 { 00393 uiFont *font= uifont_to_blfont(fs->uifont_id); 00394 00395 BLF_size(font->blf_id, fs->points, U.dpi); 00396 } 00397