|
Blender
V2.59
|
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 00046 #include "BKE_global.h" 00047 00048 00049 #include "BLF_api.h" 00050 00051 #include "UI_interface.h" 00052 00053 #include "ED_datafiles.h" 00054 00055 #include "interface_intern.h" 00056 00057 00058 /* style + theme + layout-engine = UI */ 00059 00060 /* 00061 This is a complete set of layout rules, the 'state' of the Layout 00062 Engine. Multiple styles are possible, defined via C or Python. Styles 00063 get a name, and will typically get activated per region type, like 00064 "Header", or "Listview" or "Toolbar". Properties of Style definitions 00065 are: 00066 00067 - default collumn properties, internal spacing, aligning, min/max width 00068 - button alignment rules (for groups) 00069 - label placement rules 00070 - internal labeling or external labeling default 00071 - default minimum widths for buttons/labels (in amount of characters) 00072 - font types, styles and relative sizes for Panel titles, labels, etc. 00073 00074 */ 00075 00076 00077 /* ********************************************** */ 00078 00079 static uiStyle *ui_style_new(ListBase *styles, const char *name) 00080 { 00081 uiStyle *style= MEM_callocN(sizeof(uiStyle), "new style"); 00082 00083 BLI_addtail(styles, style); 00084 BLI_strncpy(style->name, name, MAX_STYLE_NAME); 00085 00086 style->panelzoom= 1.0; /* unused */ 00087 00088 style->paneltitle.uifont_id= UIFONT_DEFAULT; 00089 style->paneltitle.points= 12; 00090 style->paneltitle.kerning= 1; 00091 style->paneltitle.shadow= 1; 00092 style->paneltitle.shadx= 0; 00093 style->paneltitle.shady= -1; 00094 style->paneltitle.shadowalpha= 0.15f; 00095 style->paneltitle.shadowcolor= 1.0f; 00096 00097 style->grouplabel.uifont_id= UIFONT_DEFAULT; 00098 style->grouplabel.points= 12; 00099 style->grouplabel.kerning= 1; 00100 style->grouplabel.shadow= 3; 00101 style->grouplabel.shadx= 0; 00102 style->grouplabel.shady= -1; 00103 style->grouplabel.shadowalpha= 0.25f; 00104 00105 style->widgetlabel.uifont_id= UIFONT_DEFAULT; 00106 style->widgetlabel.points= 11; 00107 style->widgetlabel.kerning= 1; 00108 style->widgetlabel.shadow= 3; 00109 style->widgetlabel.shadx= 0; 00110 style->widgetlabel.shady= -1; 00111 style->widgetlabel.shadowalpha= 0.15f; 00112 style->widgetlabel.shadowcolor= 1.0f; 00113 00114 style->widget.uifont_id= UIFONT_DEFAULT; 00115 style->widget.points= 11; 00116 style->widget.kerning= 1; 00117 style->widget.shadowalpha= 0.25f; 00118 00119 style->columnspace= 8; 00120 style->templatespace= 5; 00121 style->boxspace= 5; 00122 style->buttonspacex= 8; 00123 style->buttonspacey= 2; 00124 style->panelspace= 8; 00125 style->panelouter= 4; 00126 00127 return style; 00128 } 00129 00130 static uiFont *uifont_to_blfont(int id) 00131 { 00132 uiFont *font= U.uifonts.first; 00133 00134 for(; font; font= font->next) { 00135 if(font->uifont_id==id) { 00136 return font; 00137 } 00138 } 00139 return U.uifonts.first; 00140 } 00141 00142 /* *************** draw ************************ */ 00143 00144 00145 void uiStyleFontDrawExt(uiFontStyle *fs, rcti *rect, const char *str, 00146 float *r_xofs, float *r_yofs) 00147 { 00148 float height; 00149 int xofs=0, yofs; 00150 00151 uiStyleFontSet(fs); 00152 00153 height= BLF_ascender(fs->uifont_id); 00154 yofs= ceil( 0.5f*(rect->ymax - rect->ymin - height)); 00155 00156 if(fs->align==UI_STYLE_TEXT_CENTER) { 00157 xofs= floor( 0.5f*(rect->xmax - rect->xmin - BLF_width(fs->uifont_id, str))); 00158 /* don't center text if it chops off the start of the text, 2 gives some margin */ 00159 if(xofs < 2) { 00160 xofs= 2; 00161 } 00162 } 00163 else if(fs->align==UI_STYLE_TEXT_RIGHT) { 00164 xofs= rect->xmax - rect->xmin - BLF_width(fs->uifont_id, str) - 1; 00165 } 00166 00167 /* clip is very strict, so we give it some space */ 00168 BLF_clipping(fs->uifont_id, rect->xmin-1, rect->ymin-4, rect->xmax+1, rect->ymax+4); 00169 BLF_enable(fs->uifont_id, BLF_CLIPPING); 00170 BLF_position(fs->uifont_id, rect->xmin+xofs, rect->ymin+yofs, 0.0f); 00171 00172 if (fs->shadow) { 00173 BLF_enable(fs->uifont_id, BLF_SHADOW); 00174 BLF_shadow(fs->uifont_id, fs->shadow, fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha); 00175 BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady); 00176 } 00177 00178 if (fs->kerning == 1) 00179 BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT); 00180 00181 BLF_draw(fs->uifont_id, str, 65535); /* XXX, use real length */ 00182 BLF_disable(fs->uifont_id, BLF_CLIPPING); 00183 if (fs->shadow) 00184 BLF_disable(fs->uifont_id, BLF_SHADOW); 00185 if (fs->kerning == 1) 00186 BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT); 00187 00188 *r_xofs= xofs; 00189 *r_yofs= yofs; 00190 } 00191 00192 void uiStyleFontDraw(uiFontStyle *fs, rcti *rect, const char *str) 00193 { 00194 float xofs, yofs; 00195 uiStyleFontDrawExt(fs, rect, str, 00196 &xofs, &yofs); 00197 } 00198 00199 /* drawn same as above, but at 90 degree angle */ 00200 void uiStyleFontDrawRotated(uiFontStyle *fs, rcti *rect, const char *str) 00201 { 00202 float height; 00203 int xofs, yofs; 00204 float angle; 00205 rcti txtrect; 00206 00207 uiStyleFontSet(fs); 00208 00209 height= BLF_ascender(fs->uifont_id); 00210 /* becomes x-offset when rotated */ 00211 xofs= ceil( 0.5f*(rect->ymax - rect->ymin - height)); 00212 00213 /* ignore UI_STYLE, always aligned to top */ 00214 00215 /* rotate counter-clockwise for now (assumes left-to-right language)*/ 00216 xofs+= height; 00217 yofs= BLF_width(fs->uifont_id, str) + 5; 00218 angle= 90.0f; 00219 00220 /* translate rect to vertical */ 00221 txtrect.xmin= rect->xmin - (rect->ymax - rect->ymin); 00222 txtrect.ymin= rect->ymin - (rect->xmax - rect->xmin); 00223 txtrect.xmax= rect->xmin; 00224 txtrect.ymax= rect->ymin; 00225 00226 /* clip is very strict, so we give it some space */ 00227 /* clipping is done without rotation, so make rect big enough to contain both positions */ 00228 BLF_clipping(fs->uifont_id, txtrect.xmin-1, txtrect.ymin-yofs-xofs-4, rect->xmax+1, rect->ymax+4); 00229 BLF_enable(fs->uifont_id, BLF_CLIPPING); 00230 BLF_position(fs->uifont_id, txtrect.xmin+xofs, txtrect.ymax-yofs, 0.0f); 00231 00232 BLF_enable(fs->uifont_id, BLF_ROTATION); 00233 BLF_rotation(fs->uifont_id, angle); 00234 00235 if (fs->shadow) { 00236 BLF_enable(fs->uifont_id, BLF_SHADOW); 00237 BLF_shadow(fs->uifont_id, fs->shadow, fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha); 00238 BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady); 00239 } 00240 00241 if (fs->kerning == 1) 00242 BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT); 00243 00244 BLF_draw(fs->uifont_id, str, 65535); /* XXX, use real length */ 00245 BLF_disable(fs->uifont_id, BLF_ROTATION); 00246 BLF_disable(fs->uifont_id, BLF_CLIPPING); 00247 if (fs->shadow) 00248 BLF_disable(fs->uifont_id, BLF_SHADOW); 00249 if (fs->kerning == 1) 00250 BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT); 00251 } 00252 00253 /* ************** helpers ************************ */ 00254 00255 /* temporarily, does widget font */ 00256 int UI_GetStringWidth(const char *str) 00257 { 00258 uiStyle *style= U.uistyles.first; 00259 uiFontStyle *fstyle= &style->widget; 00260 int width; 00261 00262 if (fstyle->kerning==1) /* for BLF_width */ 00263 BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT); 00264 00265 uiStyleFontSet(fstyle); 00266 width= BLF_width(fstyle->uifont_id, str); 00267 00268 if (fstyle->kerning==1) 00269 BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT); 00270 00271 return width; 00272 } 00273 00274 /* temporarily, does widget font */ 00275 void UI_DrawString(float x, float y, const char *str) 00276 { 00277 uiStyle *style= U.uistyles.first; 00278 00279 if (style->widget.kerning == 1) 00280 BLF_enable(style->widget.uifont_id, BLF_KERNING_DEFAULT); 00281 00282 uiStyleFontSet(&style->widget); 00283 BLF_position(style->widget.uifont_id, x, y, 0.0f); 00284 BLF_draw(style->widget.uifont_id, str, 65535); /* XXX, use real length */ 00285 00286 if (style->widget.kerning == 1) 00287 BLF_disable(style->widget.uifont_id, BLF_KERNING_DEFAULT); 00288 } 00289 00290 /* ************** init exit ************************ */ 00291 00292 /* called on each startup.blend read */ 00293 /* reading without uifont will create one */ 00294 void uiStyleInit(void) 00295 { 00296 uiFont *font= U.uifonts.first; 00297 uiStyle *style= U.uistyles.first; 00298 00299 /* recover from uninitialized dpi */ 00300 if(U.dpi == 0) 00301 U.dpi= 72; 00302 CLAMP(U.dpi, 48, 128); 00303 00304 /* default builtin */ 00305 if(font==NULL) { 00306 font= MEM_callocN(sizeof(uiFont), "ui font"); 00307 BLI_addtail(&U.uifonts, font); 00308 00309 strcpy(font->filename, "default"); 00310 font->uifont_id= UIFONT_DEFAULT; 00311 } 00312 00313 for(font= U.uifonts.first; font; font= font->next) { 00314 00315 if(font->uifont_id==UIFONT_DEFAULT) { 00316 font->blf_id= BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size); 00317 } 00318 else { 00319 font->blf_id= BLF_load(font->filename); 00320 if(font->blf_id == -1) 00321 font->blf_id= BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size); 00322 } 00323 00324 if (font->blf_id == -1) { 00325 if (G.f & G_DEBUG) 00326 printf("uiStyleInit error, no fonts available\n"); 00327 } 00328 else { 00329 /* ? just for speed to initialize? 00330 * Yes, this build the glyph cache and create 00331 * the texture. 00332 */ 00333 BLF_size(font->blf_id, 11, U.dpi); 00334 BLF_size(font->blf_id, 12, U.dpi); 00335 BLF_size(font->blf_id, 14, U.dpi); 00336 } 00337 } 00338 00339 if(style==NULL) { 00340 ui_style_new(&U.uistyles, "Default Style"); 00341 } 00342 00343 // XXX, this should be moved into a style, but for now best only load the monospaced font once. 00344 if (blf_mono_font == -1) 00345 blf_mono_font= BLF_load_mem_unique("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size); 00346 00347 BLF_size(blf_mono_font, 12, 72); 00348 00349 /* second for rendering else we get threading problems */ 00350 if (blf_mono_font_render == -1) 00351 blf_mono_font_render= BLF_load_mem_unique("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size); 00352 00353 BLF_size(blf_mono_font_render, 12, 72); 00354 } 00355 00356 void uiStyleFontSet(uiFontStyle *fs) 00357 { 00358 uiFont *font= uifont_to_blfont(fs->uifont_id); 00359 00360 BLF_size(font->blf_id, fs->points, U.dpi); 00361 } 00362