doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DeviceContext.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "../idlib/precompiled.h"
30 #pragma hdrstop
31 
32 #include "DeviceContext.h"
33 
43 
44 
45 idCVar gui_smallFontLimit( "gui_smallFontLimit", "0.30", CVAR_GUI | CVAR_ARCHIVE, "" );
46 idCVar gui_mediumFontLimit( "gui_mediumFontLimit", "0.60", CVAR_GUI | CVAR_ARCHIVE, "" );
47 
48 
50 
51 int idDeviceContext::FindFont( const char *name ) {
52  int c = fonts.Num();
53  for (int i = 0; i < c; i++) {
54  if (idStr::Icmp(name, fonts[i].name) == 0) {
55  return i;
56  }
57  }
58 
59  // If the font was not found, try to register it
60  idStr fileName = name;
61  fileName.Replace("fonts", va("fonts/%s", fontLang.c_str()) );
62 
63  fontInfoEx_t fontInfo;
64  int index = fonts.Append( fontInfo );
65  if ( renderSystem->RegisterFont( fileName, fonts[index] ) ){
66  idStr::Copynz( fonts[index].name, name, sizeof( fonts[index].name ) );
67  return index;
68  } else {
69  common->Printf( "Could not register font %s [%s]\n", name, fileName.c_str() );
70  return -1;
71 }
72 }
73 
75  fonts.SetGranularity( 1 );
76 
77  fontLang = cvarSystem->GetCVarString( "sys_lang" );
78 
79  // western european languages can use the english font
80  if ( fontLang == "french" || fontLang == "german" || fontLang == "spanish" || fontLang == "italian" ) {
81  fontLang = "english";
82  }
83 
84  // Default font has to be added first
85  FindFont( "fonts" );
86 }
87 
89  if ( num >= 0 && num < fonts.Num() ) {
90  activeFont = &fonts[num];
91  } else {
92  activeFont = &fonts[0];
93  }
94 }
95 
96 
98  xScale = 0.0;
100  whiteImage = declManager->FindMaterial("guis/assets/white.tga");
102  mbcs = false;
103  SetupFonts();
104  activeFont = &fonts[0];
105  colorPurple = idVec4(1, 0, 1, 1);
106  colorOrange = idVec4(1, 1, 0, 1);
107  colorYellow = idVec4(0, 1, 1, 1);
108  colorGreen = idVec4(0, 1, 0, 1);
109  colorBlue = idVec4(0, 0, 1, 1);
110  colorRed = idVec4(1, 0, 0, 1);
111  colorWhite = idVec4(1, 1, 1, 1);
112  colorBlack = idVec4(0, 0, 0, 1);
113  colorNone = idVec4(0, 0, 0, 0);
114  cursorImages[CURSOR_ARROW] = declManager->FindMaterial("ui/assets/guicursor_arrow.tga");
115  cursorImages[CURSOR_HAND] = declManager->FindMaterial("ui/assets/guicursor_hand.tga");
116  scrollBarImages[SCROLLBAR_HBACK] = declManager->FindMaterial("ui/assets/scrollbarh.tga");
117  scrollBarImages[SCROLLBAR_VBACK] = declManager->FindMaterial("ui/assets/scrollbarv.tga");
118  scrollBarImages[SCROLLBAR_THUMB] = declManager->FindMaterial("ui/assets/scrollbar_thumb.tga");
119  scrollBarImages[SCROLLBAR_RIGHT] = declManager->FindMaterial("ui/assets/scrollbar_right.tga");
120  scrollBarImages[SCROLLBAR_LEFT] = declManager->FindMaterial("ui/assets/scrollbar_left.tga");
121  scrollBarImages[SCROLLBAR_UP] = declManager->FindMaterial("ui/assets/scrollbar_up.tga");
122  scrollBarImages[SCROLLBAR_DOWN] = declManager->FindMaterial("ui/assets/scrollbar_down.tga");
133  enableClipping = true;
134  overStrikeMode = true;
135  mat.Identity();
136  origin.Zero();
137  initialized = true;
138 }
139 
141  fontName.Clear();
142  clipRects.Clear();
143  fonts.Clear();
144  Clear();
145 }
146 
148  initialized = false;
149  useFont = NULL;
150  activeFont = NULL;
151  mbcs = false;
152 }
153 
155  Clear();
156 }
157 
158 void idDeviceContext::SetTransformInfo(const idVec3 &org, const idMat3 &m) {
159  origin = org;
160  mat = m;
161 }
162 
163 //
164 // added method
166 {
167  m = mat;
168  org = origin;
169 }
170 //
171 
173  if (clipRects.Num()) {
175  }
176 }
177 
179  clipRects.Append(r);
180 }
181 
182 void idDeviceContext::PushClipRect(float x, float y, float w, float h) {
183  clipRects.Append(idRectangle(x, y, w, h));
184 }
185 
186 bool idDeviceContext::ClippedCoords(float *x, float *y, float *w, float *h, float *s1, float *t1, float *s2, float *t2) {
187 
188  if ( enableClipping == false || clipRects.Num() == 0 ) {
189  return false;
190  }
191 
192  int c = clipRects.Num();
193  while( --c > 0 ) {
194  idRectangle *clipRect = &clipRects[c];
195 
196  float ox = *x;
197  float oy = *y;
198  float ow = *w;
199  float oh = *h;
200 
201  if ( ow <= 0.0f || oh <= 0.0f ) {
202  break;
203  }
204 
205  if (*x < clipRect->x) {
206  *w -= clipRect->x - *x;
207  *x = clipRect->x;
208  } else if (*x > clipRect->x + clipRect->w) {
209  *x = *w = *y = *h = 0;
210  }
211  if (*y < clipRect->y) {
212  *h -= clipRect->y - *y;
213  *y = clipRect->y;
214  } else if (*y > clipRect->y + clipRect->h) {
215  *x = *w = *y = *h = 0;
216  }
217  if (*w > clipRect->w) {
218  *w = clipRect->w - *x + clipRect->x;
219  } else if (*x + *w > clipRect->x + clipRect->w) {
220  *w = clipRect->Right() - *x;
221  }
222  if (*h > clipRect->h) {
223  *h = clipRect->h - *y + clipRect->y;
224  } else if (*y + *h > clipRect->y + clipRect->h) {
225  *h = clipRect->Bottom() - *y;
226  }
227 
228  if ( s1 && s2 && t1 && t2 && ow > 0.0f ) {
229  float ns1, ns2, nt1, nt2;
230  // upper left
231  float u = ( *x - ox ) / ow;
232  ns1 = *s1 * ( 1.0f - u ) + *s2 * ( u );
233 
234  // upper right
235  u = ( *x + *w - ox ) / ow;
236  ns2 = *s1 * ( 1.0f - u ) + *s2 * ( u );
237 
238  // lower left
239  u = ( *y - oy ) / oh;
240  nt1 = *t1 * ( 1.0f - u ) + *t2 * ( u );
241 
242  // lower right
243  u = ( *y + *h - oy ) / oh;
244  nt2 = *t1 * ( 1.0f - u ) + *t2 * ( u );
245 
246  // set values
247  *s1 = ns1;
248  *s2 = ns2;
249  *t1 = nt1;
250  *t2 = nt2;
251  }
252  }
253 
254  return (*w == 0 || *h == 0) ? true : false;
255 }
256 
257 
258 void idDeviceContext::AdjustCoords(float *x, float *y, float *w, float *h) {
259  if (x) {
260  *x *= xScale;
261  }
262  if (y) {
263  *y *= yScale;
264  }
265  if (w) {
266  *w *= xScale;
267  }
268  if (h) {
269  *h *= yScale;
270  }
271 }
272 
273 void idDeviceContext::DrawStretchPic(float x, float y, float w, float h, float s1, float t1, float s2, float t2, const idMaterial *shader) {
274  idDrawVert verts[4];
275  glIndex_t indexes[6];
276  indexes[0] = 3;
277  indexes[1] = 0;
278  indexes[2] = 2;
279  indexes[3] = 2;
280  indexes[4] = 0;
281  indexes[5] = 1;
282  verts[0].xyz[0] = x;
283  verts[0].xyz[1] = y;
284  verts[0].xyz[2] = 0;
285  verts[0].st[0] = s1;
286  verts[0].st[1] = t1;
287  verts[0].normal[0] = 0;
288  verts[0].normal[1] = 0;
289  verts[0].normal[2] = 1;
290  verts[0].tangents[0][0] = 1;
291  verts[0].tangents[0][1] = 0;
292  verts[0].tangents[0][2] = 0;
293  verts[0].tangents[1][0] = 0;
294  verts[0].tangents[1][1] = 1;
295  verts[0].tangents[1][2] = 0;
296  verts[1].xyz[0] = x + w;
297  verts[1].xyz[1] = y;
298  verts[1].xyz[2] = 0;
299  verts[1].st[0] = s2;
300  verts[1].st[1] = t1;
301  verts[1].normal[0] = 0;
302  verts[1].normal[1] = 0;
303  verts[1].normal[2] = 1;
304  verts[1].tangents[0][0] = 1;
305  verts[1].tangents[0][1] = 0;
306  verts[1].tangents[0][2] = 0;
307  verts[1].tangents[1][0] = 0;
308  verts[1].tangents[1][1] = 1;
309  verts[1].tangents[1][2] = 0;
310  verts[2].xyz[0] = x + w;
311  verts[2].xyz[1] = y + h;
312  verts[2].xyz[2] = 0;
313  verts[2].st[0] = s2;
314  verts[2].st[1] = t2;
315  verts[2].normal[0] = 0;
316  verts[2].normal[1] = 0;
317  verts[2].normal[2] = 1;
318  verts[2].tangents[0][0] = 1;
319  verts[2].tangents[0][1] = 0;
320  verts[2].tangents[0][2] = 0;
321  verts[2].tangents[1][0] = 0;
322  verts[2].tangents[1][1] = 1;
323  verts[2].tangents[1][2] = 0;
324  verts[3].xyz[0] = x;
325  verts[3].xyz[1] = y + h;
326  verts[3].xyz[2] = 0;
327  verts[3].st[0] = s1;
328  verts[3].st[1] = t2;
329  verts[3].normal[0] = 0;
330  verts[3].normal[1] = 0;
331  verts[3].normal[2] = 1;
332  verts[3].tangents[0][0] = 1;
333  verts[3].tangents[0][1] = 0;
334  verts[3].tangents[0][2] = 0;
335  verts[3].tangents[1][0] = 0;
336  verts[3].tangents[1][1] = 1;
337  verts[3].tangents[1][2] = 0;
338 
339  bool ident = !mat.IsIdentity();
340  if ( ident ) {
341  verts[0].xyz -= origin;
342  verts[0].xyz *= mat;
343  verts[0].xyz += origin;
344  verts[1].xyz -= origin;
345  verts[1].xyz *= mat;
346  verts[1].xyz += origin;
347  verts[2].xyz -= origin;
348  verts[2].xyz *= mat;
349  verts[2].xyz += origin;
350  verts[3].xyz -= origin;
351  verts[3].xyz *= mat;
352  verts[3].xyz += origin;
353  }
354 
355  renderSystem->DrawStretchPic( &verts[0], &indexes[0], 4, 6, shader, ident );
356 
357 }
358 
359 
360 void idDeviceContext::DrawMaterial(float x, float y, float w, float h, const idMaterial *mat, const idVec4 &color, float scalex, float scaley) {
361 
362  renderSystem->SetColor(color);
363 
364  float s0, s1, t0, t1;
365 //
366 // handle negative scales as well
367  if ( scalex < 0 )
368  {
369  w *= -1;
370  scalex *= -1;
371  }
372  if ( scaley < 0 )
373  {
374  h *= -1;
375  scaley *= -1;
376  }
377 //
378  if( w < 0 ) { // flip about vertical
379  w = -w;
380  s0 = 1 * scalex;
381  s1 = 0;
382  }
383  else {
384  s0 = 0;
385  s1 = 1 * scalex;
386  }
387 
388  if( h < 0 ) { // flip about horizontal
389  h = -h;
390  t0 = 1 * scaley;
391  t1 = 0;
392  }
393  else {
394  t0 = 0;
395  t1 = 1 * scaley;
396  }
397 
398  if ( ClippedCoords( &x, &y, &w, &h, &s0, &t0, &s1, &t1 ) ) {
399  return;
400  }
401 
402  AdjustCoords(&x, &y, &w, &h);
403 
404  DrawStretchPic( x, y, w, h, s0, t0, s1, t1, mat);
405 }
406 
407 void idDeviceContext::DrawMaterialRotated(float x, float y, float w, float h, const idMaterial *mat, const idVec4 &color, float scalex, float scaley, float angle) {
408 
409  renderSystem->SetColor(color);
410 
411  float s0, s1, t0, t1;
412  //
413  // handle negative scales as well
414  if ( scalex < 0 )
415  {
416  w *= -1;
417  scalex *= -1;
418  }
419  if ( scaley < 0 )
420  {
421  h *= -1;
422  scaley *= -1;
423  }
424  //
425  if( w < 0 ) { // flip about vertical
426  w = -w;
427  s0 = 1 * scalex;
428  s1 = 0;
429  }
430  else {
431  s0 = 0;
432  s1 = 1 * scalex;
433  }
434 
435  if( h < 0 ) { // flip about horizontal
436  h = -h;
437  t0 = 1 * scaley;
438  t1 = 0;
439  }
440  else {
441  t0 = 0;
442  t1 = 1 * scaley;
443  }
444 
445  if ( angle == 0.0f && ClippedCoords( &x, &y, &w, &h, &s0, &t0, &s1, &t1 ) ) {
446  return;
447  }
448 
449  AdjustCoords(&x, &y, &w, &h);
450 
451  DrawStretchPicRotated( x, y, w, h, s0, t0, s1, t1, mat, angle);
452 }
453 
454 void idDeviceContext::DrawStretchPicRotated(float x, float y, float w, float h, float s1, float t1, float s2, float t2, const idMaterial *shader, float angle) {
455 
456  idDrawVert verts[4];
457  glIndex_t indexes[6];
458  indexes[0] = 3;
459  indexes[1] = 0;
460  indexes[2] = 2;
461  indexes[3] = 2;
462  indexes[4] = 0;
463  indexes[5] = 1;
464  verts[0].xyz[0] = x;
465  verts[0].xyz[1] = y;
466  verts[0].xyz[2] = 0;
467  verts[0].st[0] = s1;
468  verts[0].st[1] = t1;
469  verts[0].normal[0] = 0;
470  verts[0].normal[1] = 0;
471  verts[0].normal[2] = 1;
472  verts[0].tangents[0][0] = 1;
473  verts[0].tangents[0][1] = 0;
474  verts[0].tangents[0][2] = 0;
475  verts[0].tangents[1][0] = 0;
476  verts[0].tangents[1][1] = 1;
477  verts[0].tangents[1][2] = 0;
478  verts[1].xyz[0] = x + w;
479  verts[1].xyz[1] = y;
480  verts[1].xyz[2] = 0;
481  verts[1].st[0] = s2;
482  verts[1].st[1] = t1;
483  verts[1].normal[0] = 0;
484  verts[1].normal[1] = 0;
485  verts[1].normal[2] = 1;
486  verts[1].tangents[0][0] = 1;
487  verts[1].tangents[0][1] = 0;
488  verts[1].tangents[0][2] = 0;
489  verts[1].tangents[1][0] = 0;
490  verts[1].tangents[1][1] = 1;
491  verts[1].tangents[1][2] = 0;
492  verts[2].xyz[0] = x + w;
493  verts[2].xyz[1] = y + h;
494  verts[2].xyz[2] = 0;
495  verts[2].st[0] = s2;
496  verts[2].st[1] = t2;
497  verts[2].normal[0] = 0;
498  verts[2].normal[1] = 0;
499  verts[2].normal[2] = 1;
500  verts[2].tangents[0][0] = 1;
501  verts[2].tangents[0][1] = 0;
502  verts[2].tangents[0][2] = 0;
503  verts[2].tangents[1][0] = 0;
504  verts[2].tangents[1][1] = 1;
505  verts[2].tangents[1][2] = 0;
506  verts[3].xyz[0] = x;
507  verts[3].xyz[1] = y + h;
508  verts[3].xyz[2] = 0;
509  verts[3].st[0] = s1;
510  verts[3].st[1] = t2;
511  verts[3].normal[0] = 0;
512  verts[3].normal[1] = 0;
513  verts[3].normal[2] = 1;
514  verts[3].tangents[0][0] = 1;
515  verts[3].tangents[0][1] = 0;
516  verts[3].tangents[0][2] = 0;
517  verts[3].tangents[1][0] = 0;
518  verts[3].tangents[1][1] = 1;
519  verts[3].tangents[1][2] = 0;
520 
521  bool ident = !mat.IsIdentity();
522  if ( ident ) {
523  verts[0].xyz -= origin;
524  verts[0].xyz *= mat;
525  verts[0].xyz += origin;
526  verts[1].xyz -= origin;
527  verts[1].xyz *= mat;
528  verts[1].xyz += origin;
529  verts[2].xyz -= origin;
530  verts[2].xyz *= mat;
531  verts[2].xyz += origin;
532  verts[3].xyz -= origin;
533  verts[3].xyz *= mat;
534  verts[3].xyz += origin;
535  }
536 
537  //Generate a translation so we can translate to the center of the image rotate and draw
538  idVec3 origTrans;
539  origTrans.x = x+(w/2);
540  origTrans.y = y+(h/2);
541  origTrans.z = 0;
542 
543 
544  //Rotate the verts about the z axis before drawing them
545  idMat4 rotz;
546  rotz.Identity();
547  float sinAng = idMath::Sin(angle);
548  float cosAng = idMath::Cos(angle);
549  rotz[0][0] = cosAng;
550  rotz[0][1] = sinAng;
551  rotz[1][0] = -sinAng;
552  rotz[1][1] = cosAng;
553  for(int i = 0; i < 4; i++) {
554  //Translate to origin
555  verts[i].xyz -= origTrans;
556 
557  //Rotate
558  verts[i].xyz = rotz * verts[i].xyz;
559 
560  //Translate back
561  verts[i].xyz += origTrans;
562  }
563 
564 
565  renderSystem->DrawStretchPic( &verts[0], &indexes[0], 4, 6, shader, (angle == 0.0) ? false : true );
566 }
567 
568 void idDeviceContext::DrawFilledRect( float x, float y, float w, float h, const idVec4 &color) {
569 
570  if ( color.w == 0.0f ) {
571  return;
572  }
573 
574  renderSystem->SetColor(color);
575 
576  if (ClippedCoords(&x, &y, &w, &h, NULL, NULL, NULL, NULL)) {
577  return;
578  }
579 
580  AdjustCoords(&x, &y, &w, &h);
581  DrawStretchPic( x, y, w, h, 0, 0, 0, 0, whiteImage);
582 }
583 
584 
585 void idDeviceContext::DrawRect( float x, float y, float w, float h, float size, const idVec4 &color) {
586 
587  if ( color.w == 0.0f ) {
588  return;
589  }
590 
591  renderSystem->SetColor(color);
592 
593  if (ClippedCoords(&x, &y, &w, &h, NULL, NULL, NULL, NULL)) {
594  return;
595  }
596 
597  AdjustCoords(&x, &y, &w, &h);
598  DrawStretchPic( x, y, size, h, 0, 0, 0, 0, whiteImage );
599  DrawStretchPic( x + w - size, y, size, h, 0, 0, 0, 0, whiteImage );
600  DrawStretchPic( x, y, w, size, 0, 0, 0, 0, whiteImage );
601  DrawStretchPic( x, y + h - size, w, size, 0, 0, 0, 0, whiteImage );
602 }
603 
604 void idDeviceContext::DrawMaterialRect( float x, float y, float w, float h, float size, const idMaterial *mat, const idVec4 &color) {
605 
606  if ( color.w == 0.0f ) {
607  return;
608  }
609 
610  renderSystem->SetColor(color);
611  DrawMaterial( x, y, size, h, mat, color );
612  DrawMaterial( x + w - size, y, size, h, mat, color );
613  DrawMaterial( x, y, w, size, mat, color );
614  DrawMaterial( x, y + h - size, w, size, mat, color );
615 }
616 
617 
620 }
621 
622 void idDeviceContext::DrawCursor(float *x, float *y, float size) {
623  if (*x < 0) {
624  *x = 0;
625  }
626 
627  if (*x >= vidWidth) {
628  *x = vidWidth;
629  }
630 
631  if (*y < 0) {
632  *y = 0;
633  }
634 
635  if (*y >= vidHeight) {
636  *y = vidHeight;
637  }
638 
640  AdjustCoords(x, y, &size, &size);
641  DrawStretchPic( *x, *y, size, size, 0, 0, 1, 1, cursorImages[cursor]);
642 }
643 /*
644  =======================================================================================================================
645  =======================================================================================================================
646  */
647 
648 void idDeviceContext::PaintChar(float x,float y,float width,float height,float scale,float s,float t,float s2,float t2,const idMaterial *hShader) {
649  float w, h;
650  w = width * scale;
651  h = height * scale;
652 
653  if (ClippedCoords(&x, &y, &w, &h, &s, &t, &s2, &t2)) {
654  return;
655  }
656 
657  AdjustCoords(&x, &y, &w, &h);
658  DrawStretchPic(x, y, w, h, s, t, s2, t2, hShader);
659 }
660 
661 
663  if (scale <= gui_smallFontLimit.GetFloat()) {
667  } else if (scale <= gui_mediumFontLimit.GetFloat()) {
671  } else {
675  }
676 }
677 
678 int idDeviceContext::DrawText(float x, float y, float scale, idVec4 color, const char *text, float adjust, int limit, int style, int cursor) {
679  int len, count;
680  idVec4 newColor;
681  const glyphInfo_t *glyph;
682  float useScale;
683  SetFontByScale(scale);
684  useScale = scale * useFont->glyphScale;
685  count = 0;
686  if ( text && color.w != 0.0f ) {
687  const unsigned char *s = (const unsigned char*)text;
688  renderSystem->SetColor(color);
689  memcpy(&newColor[0], &color[0], sizeof(idVec4));
690  len = strlen(text);
691  if (limit > 0 && len > limit) {
692  len = limit;
693  }
694 
695  while (s && *s && count < len) {
697  s++;
698  continue;
699  }
700  glyph = &useFont->glyphs[*s];
701 
702  //
703  // int yadj = Assets.textFont.glyphs[text[i]].bottom +
704  // Assets.textFont.glyphs[text[i]].top; float yadj = scale *
705  // (Assets.textFont.glyphs[text[i]].imageHeight -
706  // Assets.textFont.glyphs[text[i]].height);
707  //
708  if ( idStr::IsColor((const char*)s) ) {
709  if ( *(s+1) == C_COLOR_DEFAULT ) {
710  newColor = color;
711  } else {
712  newColor = idStr::ColorForIndex( *(s+1) );
713  newColor[3] = color[3];
714  }
715  if (cursor == count || cursor == count+1) {
716  float partialSkip = ((glyph->xSkip * useScale) + adjust) / 5.0f;
717  if ( cursor == count ) {
718  partialSkip *= 2.0f;
719  } else {
720  renderSystem->SetColor(newColor);
721  }
722  DrawEditCursor(x - partialSkip, y, scale);
723  }
724  renderSystem->SetColor(newColor);
725  s += 2;
726  count += 2;
727  continue;
728  } else {
729  float yadj = useScale * glyph->top;
730  PaintChar(x,y - yadj,glyph->imageWidth,glyph->imageHeight,useScale,glyph->s,glyph->t,glyph->s2,glyph->t2,glyph->glyph);
731 
732  if (cursor == count) {
733  DrawEditCursor(x, y, scale);
734  }
735  x += (glyph->xSkip * useScale) + adjust;
736  s++;
737  count++;
738  }
739  }
740  if (cursor == len) {
741  DrawEditCursor(x, y, scale);
742  }
743  }
744  return count;
745 }
746 
750  xScale = yScale = 0.0f;
751  if ( width != 0.0f && height != 0.0f ) {
752  xScale = vidWidth * ( 1.0f / width );
753  yScale = vidHeight * ( 1.0f / height );
754  }
755 }
756 
757 int idDeviceContext::CharWidth( const char c, float scale ) {
758  glyphInfo_t *glyph;
759  float useScale;
760  SetFontByScale(scale);
761  fontInfo_t *font = useFont;
762  useScale = scale * font->glyphScale;
763  glyph = &font->glyphs[(const unsigned char)c];
764  return idMath::FtoiFast( glyph->xSkip * useScale );
765 }
766 
767 int idDeviceContext::TextWidth( const char *text, float scale, int limit ) {
768  int i, width;
769 
770  SetFontByScale( scale );
771  const glyphInfo_t *glyphs = useFont->glyphs;
772 
773  if ( text == NULL ) {
774  return 0;
775  }
776 
777  width = 0;
778  if ( limit > 0 ) {
779  for ( i = 0; text[i] != '\0' && i < limit; i++ ) {
780  if ( idStr::IsColor( text + i ) ) {
781  i++;
782  } else {
783  width += glyphs[((const unsigned char *)text)[i]].xSkip;
784  }
785  }
786  } else {
787  for ( i = 0; text[i] != '\0'; i++ ) {
788  if ( idStr::IsColor( text + i ) ) {
789  i++;
790  } else {
791  width += glyphs[((const unsigned char *)text)[i]].xSkip;
792  }
793  }
794  }
795  return idMath::FtoiFast( scale * useFont->glyphScale * width );
796 }
797 
798 int idDeviceContext::TextHeight(const char *text, float scale, int limit) {
799  int len, count;
800  float max;
801  glyphInfo_t *glyph;
802  float useScale;
803  const char *s = text;
804  SetFontByScale(scale);
805  fontInfo_t *font = useFont;
806 
807  useScale = scale * font->glyphScale;
808  max = 0;
809  if (text) {
810  len = strlen(text);
811  if (limit > 0 && len > limit) {
812  len = limit;
813  }
814 
815  count = 0;
816  while (s && *s && count < len) {
817  if ( idStr::IsColor(s) ) {
818  s += 2;
819  continue;
820  }
821  else {
822  glyph = &font->glyphs[*(const unsigned char*)s];
823  if (max < glyph->height) {
824  max = glyph->height;
825  }
826 
827  s++;
828  count++;
829  }
830  }
831  }
832 
833  return idMath::FtoiFast( max * useScale );
834 }
835 
837  SetFontByScale(scale);
838  float useScale = scale * useFont->glyphScale;
839  return idMath::FtoiFast( activeFont->maxWidth * useScale );
840 }
841 
843  SetFontByScale(scale);
844  float useScale = scale * useFont->glyphScale;
845  return idMath::FtoiFast( activeFont->maxHeight * useScale );
846 }
847 
849  if (index >= SCROLLBAR_HBACK && index < SCROLLBAR_COUNT) {
850  return scrollBarImages[index];
851  }
853 }
854 
855 // this only supports left aligned text
856 idRegion *idDeviceContext::GetTextRegion(const char *text, float textScale, idRectangle rectDraw, float xStart, float yStart) {
857 #if 0
858  const char *p, *textPtr, *newLinePtr;
859  char buff[1024];
860  int len, textWidth, newLine, newLineWidth;
861  float y;
862 
863  float charSkip = MaxCharWidth(textScale) + 1;
864  float lineSkip = MaxCharHeight(textScale);
865 
866  textWidth = 0;
867  newLinePtr = NULL;
868 #endif
869  return NULL;
870 /*
871  if (text == NULL) {
872  return;
873  }
874 
875  textPtr = text;
876  if (*textPtr == '\0') {
877  return;
878  }
879 
880  y = lineSkip + rectDraw.y + yStart;
881  len = 0;
882  buff[0] = '\0';
883  newLine = 0;
884  newLineWidth = 0;
885  p = textPtr;
886 
887  textWidth = 0;
888  while (p) {
889  if (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\0') {
890  newLine = len;
891  newLinePtr = p + 1;
892  newLineWidth = textWidth;
893  }
894 
895  if ((newLine && textWidth > rectDraw.w) || *p == '\n' || *p == '\0') {
896  if (len) {
897 
898  float x = rectDraw.x ;
899 
900  buff[newLine] = '\0';
901  DrawText(x, y, textScale, color, buff, 0, 0, 0);
902  if (!wrap) {
903  return;
904  }
905  }
906 
907  if (*p == '\0') {
908  break;
909  }
910 
911  y += lineSkip + 5;
912  p = newLinePtr;
913  len = 0;
914  newLine = 0;
915  newLineWidth = 0;
916  continue;
917  }
918 
919  buff[len++] = *p++;
920  buff[len] = '\0';
921  textWidth = TextWidth( buff, textScale, -1 );
922  }
923 */
924 }
925 
926 void idDeviceContext::DrawEditCursor( float x, float y, float scale ) {
927  if ( (int)( com_ticNumber >> 4 ) & 1 ) {
928  return;
929  }
930  SetFontByScale(scale);
931  float useScale = scale * useFont->glyphScale;
932  const glyphInfo_t *glyph2 = &useFont->glyphs[(overStrikeMode) ? '_' : '|'];
933  float yadj = useScale * glyph2->top;
934  PaintChar(x, y - yadj,glyph2->imageWidth,glyph2->imageHeight,useScale,glyph2->s,glyph2->t,glyph2->s2,glyph2->t2,glyph2->glyph);
935 }
936 
937 int idDeviceContext::DrawText( const char *text, float textScale, int textAlign, idVec4 color, idRectangle rectDraw, bool wrap, int cursor, bool calcOnly, idList<int> *breaks, int limit ) {
938  const char *p, *textPtr, *newLinePtr;
939  char buff[1024];
940  int len, newLine, newLineWidth, count;
941  float y;
942  float textWidth;
943 
944  float charSkip = MaxCharWidth( textScale ) + 1;
945  float lineSkip = MaxCharHeight( textScale );
946 
947  float cursorSkip = ( cursor >= 0 ? charSkip : 0 );
948 
949  bool lineBreak, wordBreak;
950 
951  SetFontByScale( textScale );
952 
953  textWidth = 0;
954  newLinePtr = NULL;
955 
956  if (!calcOnly && !(text && *text)) {
957  if (cursor == 0) {
958  renderSystem->SetColor(color);
959  DrawEditCursor(rectDraw.x, lineSkip + rectDraw.y, textScale);
960  }
961  return idMath::FtoiFast( rectDraw.w / charSkip );
962  }
963 
964  textPtr = text;
965 
966  y = lineSkip + rectDraw.y;
967  len = 0;
968  buff[0] = '\0';
969  newLine = 0;
970  newLineWidth = 0;
971  p = textPtr;
972 
973  if ( breaks ) {
974  breaks->Append(0);
975  }
976  count = 0;
977  textWidth = 0;
978  lineBreak = false;
979  wordBreak = false;
980  while (p) {
981 
982  if ( *p == '\n' || *p == '\r' || *p == '\0' ) {
983  lineBreak = true;
984  if ((*p == '\n' && *(p + 1) == '\r') || (*p == '\r' && *(p + 1) == '\n')) {
985  p++;
986  }
987  }
988 
989  int nextCharWidth = ( idStr::CharIsPrintable(*p) ? CharWidth( *p, textScale ) : cursorSkip );
990  // FIXME: this is a temp hack until the guis can be fixed not not overflow the bounding rectangles
991  // the side-effect is that list boxes and edit boxes will draw over their scroll bars
992  // The following line and the !linebreak in the if statement below should be removed
993  nextCharWidth = 0;
994 
995  if ( !lineBreak && ( textWidth + nextCharWidth ) > rectDraw.w ) {
996  // The next character will cause us to overflow, if we haven't yet found a suitable
997  // break spot, set it to be this character
998  if ( len > 0 && newLine == 0 ) {
999  newLine = len;
1000  newLinePtr = p;
1001  newLineWidth = textWidth;
1002  }
1003  wordBreak = true;
1004  } else if ( lineBreak || ( wrap && (*p == ' ' || *p == '\t') ) ) {
1005  // The next character is in view, so if we are a break character, store our position
1006  newLine = len;
1007  newLinePtr = p + 1;
1008  newLineWidth = textWidth;
1009  }
1010 
1011  if ( lineBreak || wordBreak ) {
1012  float x = rectDraw.x;
1013 
1014  if (textAlign == ALIGN_RIGHT) {
1015  x = rectDraw.x + rectDraw.w - newLineWidth;
1016  } else if (textAlign == ALIGN_CENTER) {
1017  x = rectDraw.x + (rectDraw.w - newLineWidth) / 2;
1018  }
1019 
1020  if ( wrap || newLine > 0 ) {
1021  buff[newLine] = '\0';
1022 
1023  // This is a special case to handle breaking in the middle of a word.
1024  // if we didn't do this, the cursor would appear on the end of this line
1025  // and the beginning of the next.
1026  if ( wordBreak && cursor >= newLine && newLine == len ) {
1027  cursor++;
1028  }
1029  }
1030 
1031  if (!calcOnly) {
1032  count += DrawText(x, y, textScale, color, buff, 0, 0, 0, cursor);
1033  }
1034 
1035  if ( cursor < newLine ) {
1036  cursor = -1;
1037  } else if ( cursor >= 0 ) {
1038  cursor -= ( newLine + 1 );
1039  }
1040 
1041  if ( !wrap ) {
1042  return newLine;
1043  }
1044 
1045  if ( ( limit && count > limit ) || *p == '\0' ) {
1046  break;
1047  }
1048 
1049  y += lineSkip + 5;
1050 
1051  if ( !calcOnly && y > rectDraw.Bottom() ) {
1052  break;
1053  }
1054 
1055  p = newLinePtr;
1056 
1057  if (breaks) {
1058  breaks->Append(p - text);
1059  }
1060 
1061  len = 0;
1062  newLine = 0;
1063  newLineWidth = 0;
1064  textWidth = 0;
1065  lineBreak = false;
1066  wordBreak = false;
1067  continue;
1068  }
1069 
1070  buff[len++] = *p++;
1071  buff[len] = '\0';
1072  // update the width
1073  if ( *( buff + len - 1 ) != C_COLOR_ESCAPE && (len <= 1 || *( buff + len - 2 ) != C_COLOR_ESCAPE)) {
1074  textWidth += textScale * useFont->glyphScale * useFont->glyphs[ (const unsigned char)*( buff + len - 1 ) ].xSkip;
1075  }
1076  }
1077 
1078  return idMath::FtoiFast( rectDraw.w / charSkip );
1079 }
1080 
1081 /*
1082 =============
1083 idRectangle::String
1084 =============
1085 */
1086 char *idRectangle::String( void ) const {
1087  static int index = 0;
1088  static char str[ 8 ][ 48 ];
1089  char *s;
1090 
1091  // use an array so that multiple toString's won't collide
1092  s = str[ index ];
1093  index = (index + 1)&7;
1094 
1095  sprintf( s, "%.2f %.2f %.2f %.2f", x, y, w, h );
1096 
1097  return s;
1098 }
void SetTransformInfo(const idVec3 &origin, const idMat3 &mat)
byte color[4]
Definition: MegaTexture.cpp:54
fontInfo_t * useFont
virtual void SetColor(const idVec4 &rgba)=0
const idMaterial * glyph
Definition: RenderSystem.h:121
const int C_COLOR_DEFAULT
Definition: Str.h:83
idCVarSystem * cvarSystem
Definition: CVarSystem.cpp:487
const int VIRTUAL_WIDTH
Definition: DeviceContext.h:37
glyphInfo_t glyphs[GLYPHS_PER_FONT]
Definition: RenderSystem.h:126
static idVec4 colorYellow
float GetFloat(void) const
Definition: CVarSystem.h:144
void DrawEditCursor(float x, float y, float scale)
fontInfo_t fontInfoLarge
Definition: RenderSystem.h:134
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:4804
float glyphScale
Definition: RenderSystem.h:127
idCVar gui_mediumFontLimit("gui_mediumFontLimit","0.60", CVAR_GUI|CVAR_ARCHIVE,"")
void DrawMaterialRect(float x, float y, float w, float h, float size, const idMaterial *mat, const idVec4 &color)
idVec3 xyz
Definition: DrawVert.h:42
GLenum GLint GLint y
Definition: glext.h:2849
GLenum GLsizei n
Definition: glext.h:3705
idRenderSystem * renderSystem
float z
Definition: Vector.h:320
static idVec4 colorGreen
const idMaterial * whiteImage
idVec3 tangents[2]
Definition: DrawVert.h:45
virtual bool RegisterFont(const char *fontName, fontInfoEx_t &font)=0
void SetGranularity(int newgranularity)
Definition: List.h:305
Definition: Vector.h:316
static idVec4 colorOrange
fontInfoEx_t * activeFont
volatile int com_ticNumber
Definition: Common.cpp:96
static idVec4 colorWhite
void PushClipRect(float x, float y, float w, float h)
virtual const idMaterial * FindMaterial(const char *name, bool makeDefault=true)=0
GLdouble s
Definition: glext.h:2935
GLenum GLsizei len
Definition: glext.h:3472
void Identity(void)
Definition: Matrix.h:591
float x
Definition: Vector.h:318
GLenum GLint x
Definition: glext.h:2849
int i
Definition: process.py:33
fontInfo_t fontInfoMedium
Definition: RenderSystem.h:133
void SetFont(int num)
GLuint GLuint num
Definition: glext.h:5390
static idVec4 & ColorForIndex(int i)
Definition: Str.cpp:71
bool ClippedCoords(float *x, float *y, float *w, float *h)
void SetFontByScale(float scale)
static idVec4 colorPurple
int Icmp(const char *text) const
Definition: Str.h:667
int FindFont(const char *name)
fontInfo_t fontInfoSmall
Definition: RenderSystem.h:132
void DrawMaterialRotated(float x, float y, float w, float h, const idMaterial *mat, const idVec4 &color, float scalex=1.0, float scaley=1.0, float angle=0.0f)
const int GLYPH_END
Definition: RenderSystem.h:104
idVec2 st
Definition: DrawVert.h:43
static idVec4 colorBlue
GLuint GLuint GLsizei count
Definition: glext.h:2845
int MaxCharWidth(float scale)
const idMaterial * scrollBarImages[SCROLLBAR_COUNT]
int DrawText(const char *text, float textScale, int textAlign, idVec4 color, idRectangle rectDraw, bool wrap, int cursor=-1, bool calcOnly=false, idList< int > *breaks=NULL, int limit=0)
GLuint index
Definition: glext.h:3476
const GLubyte * c
Definition: glext.h:4677
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:3454
Definition: Vector.h:808
idRegion * GetTextRegion(const char *text, float textScale, idRectangle rectDraw, float xStart, float yStart)
int TextWidth(const char *text, float scale, int limit)
static int FtoiFast(float f)
Definition: Math.h:801
static float Sin(float a)
Definition: Math.h:310
float y
Definition: Rectangle.h:37
idCommon * common
Definition: Common.cpp:206
void DrawFilledRect(float x, float y, float width, float height, const idVec4 &color)
#define NULL
Definition: Lib.h:88
virtual const char * GetCVarString(const char *name) const =0
int glIndex_t
Definition: Model.h:52
bool IsIdentity(const float epsilon=MATRIX_EPSILON) const
Definition: Matrix.h:595
float y
Definition: Vector.h:319
void DrawStretchPic(float x, float y, float w, float h, float s0, float t0, float s1, float t1, const idMaterial *mat)
void GetTransformInfo(idVec3 &origin, idMat3 &mat)
static void Copynz(char *dest, const char *src, int destsize)
Definition: Str.cpp:1376
float w
Definition: Vector.h:813
idVec3 normal
Definition: DrawVert.h:44
void Clear(void)
Definition: Str.h:724
idCVar gui_smallFontLimit("gui_smallFontLimit","0.30", CVAR_GUI|CVAR_ARCHIVE,"")
GLenum GLsizei width
Definition: glext.h:2846
int MaxCharHeight(float scale)
char * String(void) const
virtual void Printf(const char *fmt,...) id_attribute((format(printf
static idVec4 colorNone
virtual void DrawStretchPic(const idDrawVert *verts, const glIndex_t *indexes, int vertCount, int indexCount, const idMaterial *material, bool clip=true, float min_x=0.0f, float min_y=0.0f, float max_x=640.0f, float max_y=480.0f)=0
GLenum GLsizei GLsizei height
Definition: glext.h:2856
void DrawCursor(float *x, float *y, float size)
static idVec4 colorBlack
float x
Definition: Rectangle.h:36
idDeclManager * declManager
int CharWidth(const char c, float scale)
idList< idRectangle > clipRects
float Right() const
Definition: Rectangle.h:43
int Append(const type &obj)
Definition: List.h:646
GLdouble GLdouble GLdouble r
Definition: glext.h:2951
Definition: Matrix.h:333
void AdjustCoords(float *x, float *y, float *w, float *h)
tuple f
Definition: idal.py:89
int Num(void) const
Definition: List.h:265
bool RemoveIndex(int index)
Definition: List.h:849
const GLcharARB * name
Definition: glext.h:3629
GLsizeiptr size
Definition: glext.h:3112
void PaintChar(float x, float y, float width, float height, float scale, float s, float t, float s2, float t2, const idMaterial *hShader)
float Bottom() const
Definition: Rectangle.h:42
Definition: Str.h:116
float w
Definition: Rectangle.h:38
const char * c_str(void) const
Definition: Str.h:487
void SetCursor(int n)
const idMaterial * cursorImages[CURSOR_COUNT]
int TextHeight(const char *text, float scale, int limit)
static idList< fontInfoEx_t > fonts
void SetSort(float s) const
Definition: Material.h:513
float h
Definition: Rectangle.h:39
char * va(const char *fmt,...)
Definition: Str.cpp:1568
const int C_COLOR_ESCAPE
Definition: Str.h:82
#define max(x, y)
Definition: os.h:70
void SetSize(float width, float height)
void Replace(const char *old, const char *nw)
Definition: Str.cpp:563
GLfloat GLfloat p
Definition: glext.h:4674
void DrawStretchPicRotated(float x, float y, float w, float h, float s0, float t0, float s1, float t1, const idMaterial *mat, float angle=0.0f)
void DrawMaterial(float x, float y, float w, float h, const idMaterial *mat, const idVec4 &color, float scalex=1.0, float scaley=1.0)
Definition: Matrix.h:764
void Zero(void)
Definition: Vector.h:415
const idMaterial * GetScrollBarImage(int index)
int sprintf(idStr &string, const char *fmt,...)
Definition: Str.cpp:1528
bool IsColor(void) const
Definition: Str.h:837
void DrawRect(float x, float y, float width, float height, float size, const idVec4 &color)
static idVec4 colorRed
GLdouble GLdouble t
Definition: glext.h:2943
static float Cos(float a)
Definition: Math.h:346
void Clear(void)
Definition: List.h:184
static bool CharIsPrintable(int c)
Definition: Str.h:1003
const int VIRTUAL_HEIGHT
Definition: DeviceContext.h:38
void Identity(void)
Definition: Matrix.h:1053