Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
render2dsentence.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19 /***********************************************************************************************
20 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
21 ***********************************************************************************************
22 * *
23 * Project Name : WW3D *
24 * *
25 * $Archive:: /Commando/Code/ww3d2/render2dsentence.cpp $*
26 * *
27 * $Author:: Patrick $*
28 * *
29 * $Modtime:: 8/29/01 11:16a $*
30 * *
31 * $Revision:: 13 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
36
37#include "render2dsentence.h"
38#include "surfaceclass.h"
39#include "texture.h"
40#include "wwprofile.h"
41#include "wwmemlog.h"
42#include "dx8wrapper.h"
43
44#ifdef _INTERNAL
45// for occasional debugging...
46//#pragma optimize("", off)
47//#pragma message("************************************** WARNING, optimization disabled for debugging purposes")
48#endif
49
51// Local constants
53#define no_TEST_PLACEMENT 1 // Shows alignment markers for text.
54
55#define TEXTURE_OFFSET 2
57//
58// Render2DSentenceClass
59//
62 Font (NULL),
63 Location (0.0F,0.0F),
64 Cursor (0.0F,0.0F),
65 TextureOffset (0, 0),
66 TextureStartX (0),
67 CurSurface (NULL),
68 CurrTextureSize (0),
69 MonoSpaced (false),
70 IsClippedEnabled (false),
71 ClipRect (0, 0, 0, 0),
72 BaseLocation (0, 0),
73 LockedPtr (NULL),
74 LockedStride (0),
75 TextureSizeHint (0),
76 WrapWidth (0),
77 Centered (false),
78 DrawExtents (0, 0, 0, 0),
79 ParseHotKey( false ),
80 useHardWordWrap( false)
81{
83 return ;
84}
85
86
88//
89// ~Render2DSentenceClass
90//
98
99
101//
102// Set_Font
103//
105void
107{
108 Reset ();
109 REF_PTR_SET (Font, font);
110 return ;
111}
112
113
115//
116// Reset_Polys
117//
119void
121{
122 for (int index = 0; index < Renderers.Count (); index ++) {
123 Renderers[index].Renderer->Reset ();
124 }
125
126 return ;
127}
128
129
131//
132// Reset
133//
135void
137{
138 //
139 // Make sure we unlock the current surface (if necessary)
140 //
141 if (LockedPtr != NULL) {
142 CurSurface->Unlock ();
143 LockedPtr = NULL;
144 }
145
146 //
147 // Release our hold on the current surface
148 //
149 REF_PTR_RELEASE (CurSurface);
150
151 //
152 // Free each renderer
153 //
154 while (Renderers.Count () > 0) {
155 delete Renderers[0].Renderer;
156 Renderers.Delete(0);
157 }
158
159 Cursor.Set (0, 0);
160 MonoSpaced = false;
161 ParseHotKey = false;
162
163 Release_Pending_Surfaces ();
164 Reset_Sentence_Data ();
165 return ;
166}
167
168
170//
171// Make_Additive
172//
174void
176{
177 Shader.Set_Dst_Blend_Func (ShaderClass::DSTBLEND_ONE);
178 Shader.Set_Src_Blend_Func (ShaderClass::SRCBLEND_ONE);
179 Shader.Set_Primary_Gradient (ShaderClass::GRADIENT_MODULATE);
180 Shader.Set_Secondary_Gradient (ShaderClass::SECONDARY_GRADIENT_DISABLE);
181
182 Set_Shader (Shader);
183 return ;
184}
185
186
188//
189// Make_Additive
190//
192void
194{
195 Shader = shader;
196
197 //
198 // Change each renderer's shader
199 //
200 for (int i = 0; i < Renderers.Count (); i ++) {
201 ShaderClass *curr_shader = Renderers[i].Renderer->Get_Shader ();
202 (*curr_shader) = Shader;
203 }
204
205 return ;
206}
207
208
210//
211// Render
212//
214void
216{
217 //
218 // Build any textures that are pending
219 //
220 Build_Textures ();
221
222 //
223 // Ask each renderer to draw its contents
224 //
225 for (int i = 0; i < Renderers.Count (); i ++) {
226 Renderers[i].Renderer->Render ();
227 }
228
229 return ;
230}
231
232
234//
235// Set_Base_Location
236//
238void
240{
241 Vector2 dif = loc - BaseLocation;
242 BaseLocation = loc;
243 for (int i = 0; i < Renderers.Count (); i ++) {
244 Renderers[i].Renderer->Move (dif);
245 }
246
247 return ;
248}
249
250
252//
253// Set_Location
254//
256void
258{
259 Location = loc;
260 return ;
261}
262
263
265//
266// Get_Text_Extents
267//
271{
272 Vector2 extent (0, Font->Get_Char_Height());
273
274 while (*text) {
275 WCHAR ch = *text++;
276
277 if ( ch != (WCHAR)'\n' ) {
278 extent.X += Font->Get_Char_Spacing( ch );
279 }
280 }
281
282 return extent;
283}
284
285
287//
288// Get_Formatted_Text_Extents
289//
293{
294 return Build_Sentence_Not_Centered(text, NULL, NULL, true);
295}
296
297
299//
300// Reset_Sentence_Data
301//
303void
304Render2DSentenceClass::Reset_Sentence_Data (void)
305{
306 //
307 // Release our hold on each texture used in the sentence
308 //
309 for (int index = 0; index < SentenceData.Count (); index ++) {
310 REF_PTR_RELEASE (SentenceData[index].Surface);
311 }
312
313 if (SentenceData.Count()>0) {
314 SentenceData.Delete_All ();
315 }
316 return ;
317}
318
319
321//
322// Release_Pending_Surfaces
323//
325void
326Render2DSentenceClass::Release_Pending_Surfaces (void)
327{
328 //
329 // Release our hold on each pending surface
330 //
331 for (int index = 0; index < PendingSurfaces.Count (); index ++) {
332 SurfaceClass *curr_surface = PendingSurfaces[index].Surface;
333 REF_PTR_RELEASE (curr_surface);
334 }
335
336 if (PendingSurfaces.Count()>0) PendingSurfaces.Delete_All ();
337 return;
338}
339
340
342//
343// Build_Textures
344//
346void
347Render2DSentenceClass::Build_Textures (void)
348{
350
351 //
352 // Make sure we unlock the current surface
353 //
354 if (LockedPtr != NULL) {
355 CurSurface->Unlock ();
356 LockedPtr = NULL;
357 }
358
359 //
360 // Release our hold on the current surface
361 //
362 REF_PTR_RELEASE (CurSurface);
363 TextureOffset.Set (0, 0);
364 TextureStartX = 0;
365
366 //
367 // Convert all pending surfaces to textures
368 //
369 for (int index = 0; index < PendingSurfaces.Count (); index ++) {
370 PendingSurfaceStruct &surface_info = PendingSurfaces[index];
371 SurfaceClass *curr_surface = surface_info.Surface;
372
373 //
374 // Get the dimensions of the surface
375 //
376 SurfaceClass::SurfaceDescription desc;
377 curr_surface->Get_Description (desc);
378
379 //
380 // Create the new texture
381 //
382 TextureClass *new_texture = W3DNEW TextureClass (desc.Width, desc.Width, WW3D_FORMAT_A4R4G4B4, MIP_LEVELS_1);
383 SurfaceClass *texture_surface = new_texture->Get_Surface_Level ();
384
390
391 //
392 // Copy the contents of the texture from the surface
393 //
394 DX8Wrapper::_Copy_DX8_Rects (curr_surface->Peek_D3D_Surface (), NULL, 0, texture_surface->Peek_D3D_Surface (), NULL);
395 REF_PTR_RELEASE (texture_surface);
396
397 //
398 // Assign this texture to any renderers that need it
399 //
400 for (int renderer_index = 0; renderer_index < surface_info.Renderers.Count (); renderer_index ++) {
401 Render2DClass *renderer = surface_info.Renderers[renderer_index];
402 renderer->Set_Texture (new_texture);
403 }
404
405 //
406 // Release our hold on the objects
407 //
408 REF_PTR_RELEASE (new_texture);
409 REF_PTR_RELEASE (curr_surface);
410 }
411
412 //
413 // Reset the list
414 //
415 if (PendingSurfaces.Count()>0) {
416 PendingSurfaces.Delete_All ();
417 }
418 return ;
419}
420
421
423//
424// Draw_Sentence
425//
427void
429{
430 Render2DClass *curr_renderer = NULL;
431 SurfaceClass *curr_surface = NULL;
432
433 DrawExtents.Set (0, 0, 0, 0);
434
435 int offset = 0;
436 //
437 // Loop over all the parts of the sentence
438 //
439 for (int index = 0; index < SentenceData.Count (); index ++) {
440 SentenceDataStruct &data = SentenceData[index];
441
442 //
443 // Has the surface changed?
444 //
445 if (data.Surface != curr_surface) {
446 curr_surface = data.Surface;
447
448 //
449 // Try to find a renderer that uses the same "texture"
450 //
451 bool found = false;
452 for (int renderer_index = 0; renderer_index < Renderers.Count (); renderer_index ++) {
453 if (Renderers[renderer_index].Surface == curr_surface) {
454 found = true;
455 curr_renderer = Renderers[renderer_index].Renderer;
456 break;
457 }
458 }
459
460 //
461 // Create a new renderer if we couldn't find an appropriate one
462 //
463 if (found == false) {
464
465 //
466 // Allocate a new renderer
467 //
468 curr_renderer = W3DNEW Render2DClass;
470 ShaderClass *curr_shader = curr_renderer->Get_Shader ();
471 (*curr_shader) = Shader;
472
473 //
474 // Add it to our list
475 //
476 RendererDataStruct render_info;
477 render_info.Renderer = curr_renderer;
478 render_info.Surface = curr_surface;
479 Renderers.Add (render_info);
480
481 //
482 // Now, add this renderer to the surface pending list
483 //
484 for (int surface_index = 0; surface_index < PendingSurfaces.Count (); surface_index ++) {
485 PendingSurfaceStruct &surface_info = PendingSurfaces[surface_index];
486 if (surface_info.Surface == curr_surface) {
487 surface_info.Renderers.Add (curr_renderer);
488 }
489 }
490 }
491 }
492
493 //
494 // Get the dimensions of the surface
495 //
497 curr_surface->Get_Description (desc);
498
499 //
500 // Add a quad that contains this sentence chunk
501 //
502 RectClass screen_rect = data.ScreenRect;
503 screen_rect += Location;
504 RectClass uv_rect = data.UVRect;
505
506 //
507 // Clip the quad (as necessary)
508 //
509 bool add_quad = true;
510 if (IsClippedEnabled) {
511
512 //
513 // Check for completely clipped
514 //
515 if ( screen_rect.Right <= ClipRect.Left ||
516 screen_rect.Bottom <= ClipRect.Top)
517 {
518 add_quad = false;
519 } else {
520
521 //
522 // Clip the polygons to the specified area
523 //
524 RectClass clipped_rect;
525 clipped_rect.Left = max (screen_rect.Left, ClipRect.Left);
526 clipped_rect.Right = min (screen_rect.Right, ClipRect.Right);
527 clipped_rect.Top = max (screen_rect.Top, ClipRect.Top);
528 clipped_rect.Bottom = min (screen_rect.Bottom, ClipRect.Bottom);
529
530 //
531 // Clip the texture to the specified area
532 //
533 RectClass clipped_uv_rect;
534 float percent = ((clipped_rect.Left - screen_rect.Left) / screen_rect.Width ());
535 clipped_uv_rect.Left = uv_rect.Left + (uv_rect.Width () * percent);
536
537 percent = ((clipped_rect.Right - screen_rect.Left) / screen_rect.Width ());
538 clipped_uv_rect.Right = uv_rect.Left + (uv_rect.Width () * percent);
539
540 percent = ((clipped_rect.Top - screen_rect.Top) / screen_rect.Height ());
541 clipped_uv_rect.Top = uv_rect.Top + (uv_rect.Height () * percent);
542
543 percent = ((clipped_rect.Bottom - screen_rect.Top) / screen_rect.Height ());
544 clipped_uv_rect.Bottom = uv_rect.Top + (uv_rect.Height () * percent);
545
546 //
547 // Use the clipped rectangles to render
548 //
549 screen_rect = clipped_rect;
550 uv_rect = clipped_uv_rect;
551
552 if (screen_rect.Right <= screen_rect.Left ||
553 screen_rect.Bottom <= screen_rect.Top)
554 {
555 add_quad = false;
556 }
557 }
558 }
559
560 if (add_quad) {
561 //uv_rect.Bottom += 0.5f;
562 uv_rect *= 1.0F / ((float)desc.Width);
563#ifdef TEST_PLACEMENT
564 screen_rect.Left += offset*3;
565 screen_rect.Right += offset*3;
566#endif
567 offset++;
568 curr_renderer->Add_Quad (screen_rect, uv_rect, color);
569
570 //
571 // Add this rectangle to the total draw extents
572 //
573 if (DrawExtents.Width () == 0) {
574 DrawExtents = screen_rect;
575 } else {
576 DrawExtents += screen_rect;
577 }
578 }
579 }
580
581 return ;
582}
583
584
586//
587// Record_Sentence_Chunk
588//
590void
591Render2DSentenceClass::Record_Sentence_Chunk (void)
592{
593 //
594 // Do we have anything to store?
595 //
596 int width = TextureOffset.I - TextureStartX;
597 if (width > 0) {
598 float char_height = Font->Get_Char_Height ();
599
600 //
601 // Build a structure that contains enough information
602 // to hold this portion of the sentence
603 //
604 SentenceDataStruct sentence_data;
605 sentence_data.Surface = CurSurface;
606 sentence_data.Surface->Add_Ref ();
607 sentence_data.ScreenRect.Left = Cursor.X;
608 sentence_data.ScreenRect.Right = Cursor.X + width;
609 sentence_data.ScreenRect.Top = Cursor.Y;
610 sentence_data.ScreenRect.Bottom = Cursor.Y + char_height;
611 sentence_data.UVRect.Left = TextureStartX;
612 sentence_data.UVRect.Top = TextureOffset.J;
613 sentence_data.UVRect.Right = TextureOffset.I;
614 sentence_data.UVRect.Bottom = TextureOffset.J + char_height;
615
616 //
617 // Add this information to our list
618 //
619 SentenceData.Add (sentence_data);
620 }
621
622 return ;
623}
624
625
627//
628// Allocate_New_Surface
629//
631void
632Render2DSentenceClass::Allocate_New_Surface (const WCHAR *text, bool justCalcExtents)
633{
634 if (!justCalcExtents)
635 {
636 //
637 // Unlock the last surface (if necessary)
638 //
639 if (LockedPtr != NULL) {
640 CurSurface->Unlock ();
641 LockedPtr = NULL;
642 }
643 }
644
645 //
646 // Calculate the width of the text
647 //
648 int text_width = 0;
649 for (int index = 0; text[index] != 0; index ++) {
650 text_width += Font->Get_Char_Spacing (text[index]);
651 }
652
653 int char_height = Font->Get_Char_Height ();
654
655 //
656 // Find the best texture size for the remaining text
657 //
658 CurrTextureSize = 256;
659 int best_tex_mem_usage = 999999999;
660 for (int pow2 = 6; pow2 <= 8; pow2 ++) {
661
662 int size = 1 << pow2;
663 int row_count = (text_width / size) + 1;
664 int rows_per_texture = size / (char_height + 1);
665
666 //
667 // Can we even fit one character on this texture?
668 //
669 if (rows_per_texture > 0) {
670
671 //
672 // How many textures (at this size) would it take to render
673 // the remaining text?
674 //
675 int texture_count = row_count / rows_per_texture;
676 texture_count = max (texture_count, 1);
677
678 //
679 // Is this the best usage of texture memory we've found yet?
680 //
681 int texture_mem_usage = (texture_count * size * size);
682 if (texture_mem_usage < best_tex_mem_usage) {
683 CurrTextureSize = size;
684 best_tex_mem_usage = texture_mem_usage;
685 }
686 }
687 }
688
689 //
690 // Use whichever is larger, the hint or the calculated size
691 //
692 CurrTextureSize = max (TextureSizeHint, CurrTextureSize);
693
694 if (!justCalcExtents)
695 {
696 //
697 // Release our extra hold on the old surface
698 //
699 REF_PTR_RELEASE (CurSurface);
700
701 //
702 // Create the new surface
703 //
704 CurSurface = NEW_REF (SurfaceClass, (CurrTextureSize, CurrTextureSize, WW3D_FORMAT_A4R4G4B4));
705 WWASSERT (CurSurface != NULL);
706 CurSurface->Add_Ref ();
707
708 //
709 // Add this surface to our list
710 //
711 PendingSurfaceStruct surface_info;
712 surface_info.Surface = CurSurface;
713 PendingSurfaces.Add (surface_info);
714 }
715
716 //
717 // Reset to the upper left corner
718 //
719 TextureOffset.Set (0, 0);
720 TextureStartX = 0;
721 return ;
722}
723
724float FindStartingXPos( const WCHAR *text )
725{
726
727 return 1;
728}
729
730//
731// Build_Sentence_Centered
732//
734void Render2DSentenceClass::Build_Sentence_Centered (const WCHAR *text, int *hkX, int *hkY)
735{
736 float char_height = Font->Get_Char_Height ();
737 int wordWidth = 0;
738 int notCenteredHotkeyX = 0;
739 int notCenteredHotkeyY = 0;
740 Vector2 extent = Build_Sentence_Not_Centered(text,&notCenteredHotkeyX, &notCenteredHotkeyY, TRUE); //Get_Formatted_Text_Extents(text);
741
742 //
743 // Start fresh
744 //
745 Reset_Sentence_Data ();
746 Cursor.Set (0, 0);
747
748 //
749 // Ensure we have a surface to start with
750 //
751 if (CurSurface == NULL) {
752 Allocate_New_Surface (text);
753 }
754
755
756
757 //
758 // Loop over all the characters in the string
759 //
760 bool end = false;
761 const WCHAR *word;
762 int word_width = 0;
763 int line_width = 0;
764 int charCount = 0;
765 int wordCount = 0;
766 int hotKeyPosX = 0;
767 int hotKeyPosY = 0;
768 bool calcHotKeyX = false;
769 bool dontBlit = false;
770 while (!end)
771 {
772 //
773 // Re-init everything for the next line
774 //
775 word = text;
776 word_width = 0;
777 line_width = 0;
778 charCount = 0;
779 wordCount = 0;
780 //
781 //first find the length of the line till we wrap
782 //
783 while ( 1 )
784 {
785 //
786 // read a word
787 //
788 int charWidth = 0;
789 while ((*word != 0) && (*word > L' ') && (*word != L'\n')) {
790 if( ParseHotKey && (*word == L'&') && (*word+1 != 0) && (*word+1 > L' ') && (*word+1 != L'\n'))
791 {
792 int offset = 0;
793 //Added By Saad
794 if (word_width != 0 )
795 {
796 const WCHAR *word_back = word;
797 *word_back--;
798 if (*word_back == L' ')
799 {
800 line_width -= word_width;
801 offset =-1;
802 }
803 }
804 //
805 *word++;
806 calcHotKeyX = true;
807 }
808
809 charWidth = Font->Get_Char_Spacing (*word++);
810 word_width += charWidth;
811 wordCount++;
812
813 if (WrapWidth > 0 && word_width >= WrapWidth && useHardWordWrap)
814 break;
815 }
816 //
817 // If this word is unworthy to be on the current line, decrement the space and break
818 //
819 if(WrapWidth > 0 && (line_width + word_width >= WrapWidth))
820 {
821 //
822 //Take care of the case that the word is too big for the allocated space...
823 //If that's the case, drop out and process the word anyway
824 //
825 if(charCount == 0)
826 {
827 charCount +=wordCount - 1;
828 line_width += word_width - charWidth;
829 if(*word == 0)
830 end = true;
831 break;
832 }
833 charCount--;
834 break;
835 }
836 //
837 // if we reached the end of the text, set the values and break, also set the end flag
838 //
839 if( *word == 0 )
840 {
841 charCount +=wordCount;
842 line_width += word_width;
843 end = true;
844 break;
845 }
846 //
847 // otherwise, increment the counts
848 //
849 charCount +=wordCount + 1;
850 line_width += word_width;
851 //
852 // We were some a new line character break and process
853 //
854 if(*word != L' ')
855 break;
856 //
857 // add the space to our width
858 //
859 word_width = Font->Get_Char_Spacing (*word++);
860 wordCount = 0;
861 //Added By Saad
862 line_width += word_width;
863 }
864 //
865 // we now hold the length of the line and it's width lets set our cursor position to center it
866 //
867 Cursor.X = (int)((extent.X - line_width) / 2);
868 if(Cursor.X < 0)
869 Cursor.X = 0;
870 if(calcHotKeyX)
871 {
872 calcHotKeyX = false;
873 hotKeyPosX = Cursor.X + notCenteredHotkeyX;
874 }
875
876 for(int i = 0; i <= charCount; i++) {
877 WCHAR ch = *text++;
878 dontBlit = false;
879 //
880 // Determine how much horizontal space this character requires
881 //
882 if(ParseHotKey && (ch == L'&') && (*text != 0) && (*text > L' ') && (*text != L'\n'))
883 {
884 ch = *text++;
885 dontBlit = true;
886 }
887 float char_spacing = Font->Get_Char_Spacing (ch);
888
889 bool exceeded_texture_width = ((TextureOffset.I + char_spacing) >= CurrTextureSize);
890 bool encountered_break_char = (ch == L' ' || ch == L'\n' || ch == 0);
891
892 //
893 // Do we need to record this portion of the sentence to its own chunk?
894 //
895 if (exceeded_texture_width || encountered_break_char) {
896 Record_Sentence_Chunk ();
897
898 //
899 // Adjust the positions
900 //
901 Cursor.X += (TextureOffset.I - TextureStartX);
902 TextureStartX = TextureOffset.I;
903
904 //
905 // Adjust the output coordinates
906 //
907 if (ch == L' ') {
908 Cursor.X += char_spacing;
909 } else if ((ch == 0 )|| (ch == L'\n')) {
910 break;
911 }
912
913 //
914 // Did the text extend past the edge of the texture?
915 //
916 if (exceeded_texture_width) {
917 TextureStartX = 0;
918 TextureOffset.I = TextureStartX;
919 TextureOffset.J += char_height;
920
921 //
922 // Did the text extent completely off the texture?
923 //
924 if ((TextureOffset.J + char_height) >= CurrTextureSize) {
925 Allocate_New_Surface (text);
926 }
927 }
928 }
929 //
930 // Adjust the output coordinates
931 //
932 if (ch != L'\n' && ch != L' ') {
933
934 //
935 // Ensure the surface is locked
936 //
937 if (LockedPtr == NULL) {
938 LockedPtr = (uint16 *)CurSurface->Lock (&LockedStride);
939 WWASSERT (LockedPtr != NULL);
940 }
941
942 //
943 // Check to ensure the text will fit on this texture
944 //
945 WWASSERT (((TextureOffset.I + char_spacing) < CurrTextureSize) && ((TextureOffset.J + char_height) < CurrTextureSize));
946
947 //
948 // Blit the character to the surface
949 //
950 if(!dontBlit)
951 Font->Blit_Char (ch, LockedPtr, LockedStride, TextureOffset.I, TextureOffset.J);
952
953 if (dontBlit) {
954 // we don't blit for a hot key character. So add extra spacing.
955 char_spacing += Font->Get_Extra_Overlap();
956 // Brutal hack #27 Gamma - Bolded M's are just a problem. jba.
957 if (ch=='M') {
958 char_spacing++;
959 }
960 }
961
962 TextureOffset.I += char_spacing;
963 }
964 }
965 //
966 // reset our cursor and add a line of text to the cursor position
967 //
968 Cursor.X = 0;
969 Cursor.Y += char_height;
970 line_width = 0;
971 }
972
973 if(hkX)
974 *hkX = hotKeyPosX;
975 if(hkX)
976 *hkY = hotKeyPosY;
977 return ;
978}
980//
981// Build_Sentence_NotCentered
982//
984Vector2 Render2DSentenceClass::Build_Sentence_Not_Centered (const WCHAR *text, int *hkX, int *hkY, bool justCalcExtents)
985{
986 Vector2 cursor = Cursor;
987 int textureStartX = TextureStartX;
988 float maxX = 0;
989
990 int hotKeyPosX = 0;
991 int hotKeyPosY = 0;
992 bool calcHotKeyX = false;
993 bool dontBlit = false;
994 Vector2i textureOffset = TextureOffset;
995
996
997 //
998 // Start fresh
999 //
1000 if (!justCalcExtents)
1001 {
1002 Reset_Sentence_Data ();
1003 }
1004 Cursor.Set (0, 0);
1005
1006 //
1007 // Ensure we have a surface to start with
1008 //
1009 if (CurSurface == NULL) {
1010 Allocate_New_Surface (text, justCalcExtents);
1011 }
1012
1013 TextureOffset.Set (TEXTURE_OFFSET, 0);
1014 TextureStartX = TEXTURE_OFFSET;
1015
1016 float char_height = Font->Get_Char_Height ();
1017
1018 //
1019 // Loop over all the characters in the string
1020 //
1021 while (text != NULL) {
1022 WCHAR ch = *text++;
1023 dontBlit = false;
1024 //
1025 // Determine how much horizontal space this character requires
1026 //
1027 if(ParseHotKey && (ch == L'&') && (*text != 0) && (*text > L' ') && (*text != L'\n'))
1028 {
1029 hotKeyPosY = Cursor.Y;
1030 if (calcHotKeyX)
1031 hotKeyPosX = 0;
1032 else
1033 hotKeyPosX = Cursor.X + TextureOffset.I -TextureStartX;//TextureOffset.I;
1034
1035 ch = *text++;
1036 dontBlit = true;
1037 }
1038 float char_spacing = Font->Get_Char_Spacing (ch);
1039
1040 bool exceeded_texture_width = ((TextureOffset.I + char_spacing) >= CurrTextureSize);
1041 bool encountered_break_char = (ch == L' ' || ch == L'\n' || ch == 0);
1042 bool wordBiggerThenLine = ((useHardWordWrap) && ( WrapWidth != 0 ) &&((Cursor.X + TextureOffset.I -TextureStartX + char_spacing) >= WrapWidth));
1043 //
1044 // Do we need to record this portion of the sentence to its own chunk?
1045 //
1046 if (exceeded_texture_width || encountered_break_char|| wordBiggerThenLine) {
1047 if (!justCalcExtents)
1048 {
1049 Record_Sentence_Chunk ();
1050 }
1051
1052 //
1053 // Adjust the positions
1054 //
1055 Cursor.X += (TextureOffset.I - TextureStartX);
1056 maxX = max(maxX, Cursor.X);
1057 TextureStartX = TextureOffset.I;
1058
1059 //
1060 // Adjust the output coordinates
1061 //
1062 if (ch == L' ') {
1063 //Cursor.X += char_spacing;
1064 //maxX = max(maxX, Cursor.X);
1065
1066 //
1067 // Check to see if we need to wrap on this word-break
1068 //
1069 if (WrapWidth > 0) {
1070
1071 //
1072 // Find the length of the next word
1073 //
1074 const WCHAR *word = text;
1075 float word_width = char_spacing;
1076 while ((*word != 0) && (*word > L' ')) {
1077 if(ParseHotKey && (*word == L'&') && (*word+1 != 0) && (*word+1 > L' ') && (*word+1 != L'\n'))
1078 *word++;
1079 word_width += Font->Get_Char_Spacing (*word++);
1080 }
1081
1082 //
1083 // Should we wrap the next word?
1084 //
1085 if ((Cursor.X + word_width) >= WrapWidth) {
1086 Cursor.X = 0;
1087 Cursor.Y += char_height;
1088 calcHotKeyX = true;
1089 }
1090 }
1091
1092 } else if (ch == L'\n') {
1093 Cursor.X = 0;
1094 Cursor.Y += char_height;
1095 } else if (ch == 0) {
1096 break;
1097 } else if (wordBiggerThenLine){ // we've entered this loop because we're greater then the wordwrap so we need to force a wordwrap
1098 Cursor.X = 0;
1099 Cursor.Y += char_height;
1100 }
1101
1102
1103 //
1104 // Did the text extend past the edge of the texture?
1105 //
1106 if (exceeded_texture_width) {
1107 TextureStartX = TEXTURE_OFFSET;
1108 TextureOffset.I = TextureStartX;
1109 TextureOffset.J += char_height;
1110
1111 //
1112 // Did the text extent completely off the texture?
1113 //
1114 if ((TextureOffset.J + char_height) >= CurrTextureSize) {
1115 Allocate_New_Surface (text, justCalcExtents);
1116 }
1117 }
1118 }
1119
1120 if (ch != L'\n' ) {
1121
1122 //
1123 // Ensure the surface is locked
1124 //
1125 if (!justCalcExtents)
1126 {
1127 if (LockedPtr == NULL) {
1128 LockedPtr = (uint16 *)CurSurface->Lock (&LockedStride);
1129 WWASSERT (LockedPtr != NULL);
1130 }
1131 }
1132
1133 //
1134 // Check to ensure the text will fit on this texture
1135 //
1136 WWASSERT (((TextureOffset.I + char_spacing) < CurrTextureSize) && ((TextureOffset.J + char_height) < CurrTextureSize));
1137
1138 //
1139 // Blit the character to the surface
1140 //
1141 if (!justCalcExtents && !dontBlit )
1142 {
1143 Font->Blit_Char (ch, LockedPtr, LockedStride, TextureOffset.I, TextureOffset.J);
1144 }
1145 TextureOffset.I += char_spacing;
1146 }
1147 }
1148
1149 Vector2 extent;
1150 extent.X = maxX + Font->Get_Extra_Overlap();
1151 extent.Y = Cursor.Y + char_height;
1152
1153 Cursor = cursor;
1154 TextureOffset = textureOffset;
1155 TextureStartX = textureStartX;
1156
1157 if(hkX)
1158 *hkX = hotKeyPosX;
1159 if(hkX)
1160 *hkY = hotKeyPosY;
1161
1162 return extent;
1163}
1164
1165
1167//
1168// Build_Sentence
1169//
1171void
1172Render2DSentenceClass::Build_Sentence (const WCHAR *text, int *hkX, int *hkY)
1173{
1174 if (text == NULL) {
1175 return ;
1176 }
1177
1178
1179 if(Centered && (WrapWidth > 0 || wcschr(text,L'\n')))
1180 Build_Sentence_Centered(text, hkX, hkY);
1181 else
1182 Build_Sentence_Not_Centered(text, hkX, hkY);
1183
1184 return;
1185
1186}
1187
1188
1190//
1191// FontCharsClass
1192//
1195 OldGDIFont( NULL ),
1196 OldGDIBitmap( NULL ),
1197 GDIFont( NULL ),
1198 GDIBitmap( NULL ),
1199 GDIBitmapBits ( NULL ),
1200 MemDC( NULL ),
1201 CurrPixelOffset( 0 ),
1202 PointSize( 0 ),
1203 CharHeight( 0 ),
1204 UnicodeCharArray( NULL ),
1205 FirstUnicodeChar( 0xFFFF ),
1206 LastUnicodeChar( 0 ),
1207 IsBold (false)
1208{
1210 ::memset( ASCIICharArray, 0, sizeof (ASCIICharArray) );
1211 return ;
1212}
1213
1214
1216//
1217// ~FontCharsClass
1218//
1221{
1222 while ( BufferList.Count() ) {
1223 delete [] BufferList[0];
1224 BufferList.Delete(0);
1225 }
1226
1227 Free_GDI_Font();
1228 Free_Character_Arrays();
1229 return ;
1230}
1231
1232
1234//
1235// Get_Char_Data
1236//
1239FontCharsClass::Get_Char_Data (WCHAR ch)
1240{
1241 const FontCharsClassCharDataStruct *retval = NULL;
1242
1243 if ( ch < 256 )
1244 {
1245 retval = ASCIICharArray[ch];
1246 }
1247 else if ( AlternateUnicodeFont && this != AlternateUnicodeFont )
1248 {
1249 return AlternateUnicodeFont->Get_Char_Data( ch );
1250 }
1251 else
1252 {
1253 Grow_Unicode_Array( ch );
1254 retval = UnicodeCharArray[ch - FirstUnicodeChar];
1255 }
1256
1257 //
1258 // If the character wasn't found, then add it to our list
1259 //
1260 if ( retval == NULL ) {
1261 retval = Store_GDI_Char( ch );
1262 }
1263
1264 WWASSERT( retval->Value == ch );
1265 return retval;
1266}
1267
1268
1270//
1271// Get_Char_Width
1272//
1274int
1276{
1277 const FontCharsClassCharDataStruct * data = Get_Char_Data( ch );
1278 if ( data != NULL ) {
1279 return data->Width;
1280 }
1281
1282 return 0;
1283}
1284
1285
1287//
1288// Get_Char_Spacing
1289//
1291int
1293{
1294 const FontCharsClassCharDataStruct * data = Get_Char_Data( ch );
1295 if ( data != NULL ) {
1296 if ( data->Width != 0 ) {
1297 return data->Width - PixelOverlap - CharOverhang;
1298 }
1299 }
1300
1301 return 0;
1302}
1303
1304
1306//
1307// Blit_Char
1308//
1310void
1311FontCharsClass::Blit_Char (WCHAR ch, uint16 *dest_ptr, int dest_stride, int x, int y)
1312{
1313 const FontCharsClassCharDataStruct * data = Get_Char_Data( ch );
1314 if ( data != NULL && data->Width != 0 ) {
1315
1316 //
1317 // Setup the src and destination pointers
1318 //
1319 int dest_inc = (dest_stride >> 1);
1320 uint16 *src_ptr = data->Buffer;
1321 dest_ptr += (dest_inc * y) + x;
1322
1323 //
1324 // Simply copy the data from the src buffer to the destination
1325 //
1326 for ( int row = 0; row < CharHeight; row ++ ) {
1327 for ( int col = 0; col < data->Width; col ++ ) {
1328 uint16 curData = *src_ptr;
1329 if (col<PixelOverlap) {
1330 curData |= dest_ptr[col];
1331 }
1332 dest_ptr[col] = curData;
1333 src_ptr++;
1334 }
1335 dest_ptr += dest_inc;
1336 }
1337 }
1338
1339 return ;
1340}
1341
1342
1344//
1345// Store_GDI_Char
1346//
1349FontCharsClass::Store_GDI_Char (WCHAR ch)
1350{
1351 int width = PointSize * 2;
1352 int height = PointSize * 2;
1353
1354 //
1355 // Draw the character into the memory DC
1356 //
1357 RECT rect = { 0, 0, width, height };
1358 int xOrigin = 0;
1359 if (ch == 'W') {
1360 xOrigin = 1;
1361 }
1362 ::ExtTextOutW( MemDC, xOrigin, 0, ETO_OPAQUE, &rect, &ch, 1, NULL);
1363
1364 //
1365 // Get the size of the character we just drew
1366 //
1367 SIZE char_size = { 0 };
1368 ::GetTextExtentPoint32W( MemDC, &ch, 1, &char_size );
1369 char_size.cx += PixelOverlap + xOrigin;
1370 //
1371 // Get a pointer to the surface that this character should use
1372 //
1373 Update_Current_Buffer( char_size.cx );
1374 uint16* curr_buffer_p = BufferList[BufferList.Count () - 1]->Buffer;
1375 curr_buffer_p += CurrPixelOffset;
1376
1377 //
1378 // Copy the BMP contents to the buffer
1379 //
1380 int stride = (((width * 3) + 3) & ~3);
1381 for (int row = 0; row < char_size.cy; row ++) {
1382
1383 //
1384 // Compute the indices into the BMP and surface
1385 //
1386 int index = (row * stride);
1387
1388 //
1389 // Loop over each column
1390 //
1391 for (int col = 0; col < char_size.cx; col ++) {
1392
1393 //
1394 // Get the pixel color at this location
1395 //
1396 uint8 pixel_value = GDIBitmapBits[index];
1397 index += 3;
1398#ifdef TEST_PLACEMENT
1399 if (row==CharHeight-1&&col==0) {
1400 pixel_value = 0xff;
1401 }
1402 if (row==CharHeight-2&&col==1) {
1403 pixel_value = 0xff;
1404 }
1405 if (row==0&&col==0) {
1406 pixel_value = 0xff;
1407 }
1408 if (row==1&&col==1) {
1409 pixel_value = 0xff;
1410 }
1411 if (row==CharHeight-1&&col==char_size.cx-1-PixelOverlap) {
1412 pixel_value = 0xff;
1413 }
1414 if (row==CharHeight-2&&col==char_size.cx-2-PixelOverlap) {
1415 pixel_value = 0xff;
1416 }
1417 if (row==0&&col==char_size.cx-1-PixelOverlap) {
1418 pixel_value = 0xff;
1419 }
1420 if (row==1&&col==char_size.cx-2-PixelOverlap) {
1421 pixel_value = 0xff;
1422 }
1423 if (pixel_value == 0x00) {
1424 pixel_value = 0x40;
1425 }
1426#endif
1427
1428 uint16 pixel_color = 0;
1429 if (pixel_value != 0) {
1430 pixel_color = 0x0FFF;
1431 }
1432
1433 //
1434 // Convert the pixel intensity from 8bit to 4bit and
1435 // store it in our buffer
1436 //
1437 uint8 alpha_value = ((pixel_value >> 4) & 0xF);
1438 *curr_buffer_p++ = pixel_color | (alpha_value << 12);
1439 }
1440 }
1441
1442 //
1443 // Save information about this character in our list
1444 //
1445 FontCharsClassCharDataStruct *char_data = W3DNEW FontCharsClassCharDataStruct;
1446 char_data->Value = ch;
1447 char_data->Width = char_size.cx;
1448 char_data->Buffer = BufferList[BufferList.Count () - 1]->Buffer + CurrPixelOffset;
1449
1450 //
1451 // Insert this character into our array
1452 //
1453 if ( ch < 256 ) {
1454 ASCIICharArray[ch] = char_data;
1455 } else {
1456 UnicodeCharArray[ch - FirstUnicodeChar] = char_data;
1457 }
1458
1459 //
1460 // Advance the character position
1461 //
1462 CurrPixelOffset += ((char_size.cx+PixelOverlap) * CharHeight);
1463
1464 //
1465 // Return the index of the entry we just added
1466 //
1467 return char_data;
1468}
1469
1470
1472//
1473// Update_Current_Buffer
1474//
1476void
1477FontCharsClass::Update_Current_Buffer (int char_width)
1478{
1479 //
1480 // Check to see if we need to allocate a new buffer
1481 //
1482 bool needs_new_buffer = (BufferList.Count () == 0);
1483 if (needs_new_buffer == false) {
1484
1485 //
1486 // Would we extend past this buffer?
1487 //
1488 if ( (CurrPixelOffset + (char_width * CharHeight)) > CHAR_BUFFER_LEN ) {
1489 needs_new_buffer = true;
1490 }
1491 }
1492
1493 //
1494 // Do we need to create a new surface?
1495 //
1496 if (needs_new_buffer)
1497 {
1498 FontCharsBuffer* new_buffer = W3DNEW FontCharsBuffer;
1499 BufferList.Add( new_buffer );
1500 CurrPixelOffset = 0;
1501 }
1502
1503 return ;
1504}
1505
1506
1508//
1509// Create_GDI_Font
1510//
1512void
1513FontCharsClass::Create_GDI_Font (const char *font_name)
1514{
1515 HDC screen_dc = ::GetDC ((HWND)WW3D::Get_Window());
1516
1517 const char *fontToUseForGenerals = "Arial";
1518 bool doingGenerals = false;
1519 if (strcmp(font_name, "Generals")==0) {
1520 font_name = fontToUseForGenerals;
1521 doingGenerals = true;
1522 }
1523
1524 //
1525 // Calculate the height of the font in logical units
1526 //
1527 const int dotsPerInch = 96; // always use 96. jba.
1528 int font_height = -MulDiv (PointSize, dotsPerInch, 72);
1529
1530 int fontWidth = 0; // use font default.
1531 if (doingGenerals) {
1532 //fontWidth = -font_height*0.35f; //2 pixels tighter.
1533 fontWidth = -font_height*0.40f; // one pixel tighter
1534 }
1535 PixelOverlap = (-font_height)/8;
1536
1537 // Sanity check in case of perversion. :)
1538 if (PixelOverlap<0) PixelOverlap = 0;
1539 if (PixelOverlap>4) PixelOverlap = 4;
1540 //
1541 // Create the Windows font
1542 //
1543 DWORD bold = IsBold ? FW_BOLD : FW_NORMAL;
1544 DWORD italic = 0;
1545 GDIFont = ::CreateFont (font_height, fontWidth, 0, 0, bold, italic,
1546 FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
1547 CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
1548 VARIABLE_PITCH, font_name);
1549
1550 //
1551 // Set-up the fields of the BITMAPINFOHEADER
1552 // Note: Top-down DIBs use negative height in Win32.
1553 //
1554 BITMAPINFOHEADER bitmap_info = { 0 };
1555 bitmap_info.biSize = sizeof (BITMAPINFOHEADER);
1556 bitmap_info.biWidth = PointSize * 2;
1557 bitmap_info.biHeight = -(PointSize * 2);
1558 bitmap_info.biPlanes = 1;
1559 bitmap_info.biBitCount = 24;
1560 bitmap_info.biCompression = BI_RGB;
1561 bitmap_info.biSizeImage = ((PointSize * PointSize * 4) * 3);
1562 bitmap_info.biXPelsPerMeter = 0;
1563 bitmap_info.biYPelsPerMeter = 0;
1564 bitmap_info.biClrUsed = 0;
1565 bitmap_info.biClrImportant = 0;
1566
1567 //
1568 // Create a bitmap that we can access the bits directly of
1569 //
1570 GDIBitmap = ::CreateDIBSection ( screen_dc,
1571 (const BITMAPINFO *)&bitmap_info,
1572 DIB_RGB_COLORS,
1573 (void **)&GDIBitmapBits,
1574 NULL,
1575 0L);
1576
1577 //
1578 // Create a device context we can select the font and bitmap into
1579 //
1580 MemDC = ::CreateCompatibleDC (screen_dc);
1581
1582 //
1583 // Release our temporary screen DC
1584 //
1585 ::ReleaseDC ((HWND)WW3D::Get_Window(), screen_dc);
1586
1587 //
1588 // Now select the BMP and font into the DC
1589 //
1590 OldGDIBitmap = (HBITMAP)::SelectObject (MemDC, GDIBitmap);
1591 OldGDIFont = (HFONT)::SelectObject (MemDC, GDIFont);
1592 ::SetBkColor (MemDC, RGB (0, 0, 0));
1593 ::SetTextColor (MemDC, RGB (255, 255, 255));
1594
1595 //
1596 // Lookup the pixel height of the font
1597 //
1598 TEXTMETRIC text_metric = { 0 };
1599 ::GetTextMetrics (MemDC, &text_metric);
1600 CharHeight = text_metric.tmHeight;
1601 CharAscent = text_metric.tmAscent;
1602 CharOverhang = text_metric.tmOverhang;
1603 if (doingGenerals) {
1604 CharOverhang = 0;
1605 }
1606}
1607
1608
1610//
1611// Free_GDI_Font
1612//
1614void
1615FontCharsClass::Free_GDI_Font (void)
1616{
1617 //
1618 // Select the old font back into the DC and delete
1619 // our font object
1620 //
1621 if ( GDIFont != NULL ) {
1622 ::SelectObject( MemDC, OldGDIFont );
1623 ::DeleteObject( GDIFont );
1624 GDIFont = NULL;
1625 }
1626
1627 //
1628 // Select the old bitmap back into the DC and delete
1629 // our bitmap object
1630 //
1631 if ( GDIBitmap != NULL ) {
1632 ::SelectObject( MemDC, OldGDIBitmap );
1633 ::DeleteObject( GDIBitmap );
1634 GDIBitmap = NULL;
1635 }
1636
1637 //
1638 // Delete our memory DC
1639 //
1640 if ( MemDC != NULL ) {
1641 ::DeleteDC( MemDC );
1642 MemDC = NULL;
1643 }
1644
1645 return ;
1646}
1647
1648
1650//
1651// Initialize_GDI_Font
1652//
1654void
1655FontCharsClass::Initialize_GDI_Font (const char *font_name, int point_size, bool is_bold)
1656{
1657 //
1658 // Build a unique name from the font name and its size
1659 //
1660 Name.Format ("%s%d", font_name, point_size);
1661
1662 //
1663 // Remember these settings
1664 //
1665 GDIFontName = font_name;
1666 PointSize = point_size;
1667 IsBold = is_bold;
1668
1669 //
1670 // Create the actual font object
1671 //
1672 Create_GDI_Font (font_name);
1673 return ;
1674}
1675
1676
1678//
1679// Is_Font
1680//
1682bool
1683FontCharsClass::Is_Font (const char *font_name, int point_size, bool is_bold)
1684{
1685 bool retval = false;
1686
1687 //
1688 // Check to see if both the name and height matches...
1689 //
1690 if ( (GDIFontName.Compare_No_Case (font_name) == 0) &&
1691 (point_size == PointSize) &&
1692 (is_bold == IsBold))
1693 {
1694 retval = true;
1695 }
1696
1697 return retval;
1698}
1699
1700
1702//
1703// Grow_Unicode_Array
1704//
1706void
1707FontCharsClass::Grow_Unicode_Array (WCHAR ch)
1708{
1709 //
1710 // Don't do anything if character is in the ASCII range
1711 //
1712 if ( ch < 256 ) {
1713 return ;
1714 }
1715
1716 //
1717 // Don't do anything if character is in the currently allocated range
1718 //
1719 if ( ch >= FirstUnicodeChar && ch <= LastUnicodeChar ) {
1720 return ;
1721 }
1722
1723 uint16 first_index = min( FirstUnicodeChar, ch );
1724 uint16 last_index = max( LastUnicodeChar, ch );
1725 uint16 count = (last_index - first_index) + 1;
1726
1727 //
1728 // Allocate enough memory to hold the new cells
1729 //
1730 FontCharsClassCharDataStruct **new_array = W3DNEWARRAY FontCharsClassCharDataStruct *[count];
1731 ::memset (new_array, 0, sizeof (FontCharsClassCharDataStruct *) * count);
1732
1733 //
1734 // Copy the contents of the old array into the new array
1735 //
1736 if ( UnicodeCharArray != NULL ) {
1737 int start_offset = (FirstUnicodeChar - first_index);
1738 int old_count = (LastUnicodeChar - FirstUnicodeChar) + 1;
1739 ::memcpy (&new_array[start_offset], UnicodeCharArray, sizeof (FontCharsClassCharDataStruct *) * old_count);
1740
1741 //
1742 // Delete the old array
1743 //
1744 delete [] UnicodeCharArray;
1745 UnicodeCharArray = NULL;
1746 }
1747
1748 FirstUnicodeChar = first_index;
1749 LastUnicodeChar = last_index;
1750 UnicodeCharArray = new_array;
1751 return ;
1752}
1753
1754
1756//
1757// Free_Character_Arrays
1758//
1760void
1761FontCharsClass::Free_Character_Arrays (void)
1762{
1763 if ( UnicodeCharArray != NULL ) {
1764
1765 int count = (LastUnicodeChar - FirstUnicodeChar) + 1;
1766
1767 //
1768 // Delete each member of the unicode array
1769 //
1770 for (int index = 0; index < count; index ++) {
1771 if ( UnicodeCharArray[index] != NULL ) {
1772 delete UnicodeCharArray[index];
1773 UnicodeCharArray[index] = NULL;
1774 }
1775 }
1776
1777 //
1778 // Delete the array itself
1779 //
1780 delete [] UnicodeCharArray;
1781 UnicodeCharArray = NULL;
1782 }
1783
1784 //
1785 // Delete each member of the ascii character array
1786 //
1787 for (int index = 0; index < 256; index ++) {
1788 if ( ASCIICharArray[index] != NULL ) {
1789 delete ASCIICharArray[index];
1790 ASCIICharArray[index] = NULL;
1791 }
1792 }
1793
1794 return ;
1795}
#define NULL
Definition BaseType.h:92
#define TRUE
Definition BaseType.h:109
#define FALSE
Definition BaseType.h:113
#define min(x, y)
Definition BaseType.h:101
#define max(x, y)
Definition BaseType.h:105
#define WWASSERT
#define W3DNEWARRAY
Definition always.h:110
#define W3DNEW
Definition always.h:109
unsigned short uint16
Definition bittype.h:45
unsigned long uint32
Definition bittype.h:46
unsigned char uint8
Definition bittype.h:44
unsigned long DWORD
Definition bittype.h:57
@ false
Definition bool.h:59
static void _Copy_DX8_Rects(IDirect3DSurface8 *pSourceSurface, CONST RECT *pSourceRectsArray, UINT cRects, IDirect3DSurface8 *pDestinationSurface, CONST POINT *pDestPointsArray)
Definition dx8wrapper.h:942
int Count(void) const
Definition Vector.H:507
bool Add(T const &object)
Definition Vector.H:671
int Get_Char_Height(void)
void Initialize_GDI_Font(const char *font_name, int point_size, bool is_bold)
void Blit_Char(WCHAR ch, uint16 *dest_ptr, int dest_stride, int x, int y)
FontCharsClass * AlternateUnicodeFont
bool Is_Font(const char *font_name, int point_size, bool is_bold)
int Get_Char_Spacing(WCHAR ch)
int Get_Char_Width(WCHAR ch)
float Left
Definition rect.h:50
float Height(void) const
Definition rect.h:69
float Top
Definition rect.h:51
float Bottom
Definition rect.h:53
float Width(void) const
Definition rect.h:68
float Right
Definition rect.h:52
void Add_Ref(void) const
Definition refcount.cpp:171
void Add_Quad(const Vector2 &v0, const Vector2 &v1, const Vector2 &v2, const Vector2 &v3, const RectClass &uv, unsigned long color=0xFFFFFFFF)
Definition render2d.cpp:413
void Set_Coordinate_Range(const RectClass &range)
Definition render2d.cpp:188
static const RectClass & Get_Screen_Resolution(void)
Definition render2d.h:164
void Set_Texture(TextureClass *tex)
Definition render2d.cpp:130
ShaderClass * Get_Shader(void)
Definition render2d.h:120
static ShaderClass Get_Default_Shader(void)
Definition render2d.cpp:105
void Set_Base_Location(const Vector2 &loc)
Vector2 Get_Formatted_Text_Extents(const WCHAR *text)
void Build_Sentence(const WCHAR *text, int *hkX, int *hkY)
Vector2 Get_Text_Extents(const WCHAR *text)
void Set_Font(FontCharsClass *font)
void Draw_Sentence(uint32 color=0xFFFFFFFF)
void Set_Shader(ShaderClass shader)
void Set_Location(const Vector2 &loc)
virtual void Reset(void)
@ GRADIENT_MODULATE
Definition shader.h:193
@ SECONDARY_GRADIENT_DISABLE
Definition shader.h:203
@ SRCBLEND_ONE
Definition shader.h:211
@ DSTBLEND_ONE
Definition shader.h:173
void Get_Description(SurfaceDescription &surface_desc)
IDirect3DSurface8 * Peek_D3D_Surface(void)
SurfaceClass * Get_Surface_Level(unsigned int level=0)
Get surface from mip level.
Definition texture.cpp:986
TextureFilterClass & Get_Filter()
Definition texture.h:336
void Set_Mip_Mapping(FilterType mipmap)
Set mip mapping filter (legacy)
void Set_Mag_Filter(FilterType filter)
void Set_Min_Filter(FilterType filter)
void Set_V_Addr_Mode(TxtAddrMode mode)
void Set_U_Addr_Mode(TxtAddrMode mode)
float Y
Definition vector2.h:79
WWINLINE void Set(float x, float y)
Definition vector2.h:92
float X
Definition vector2.h:74
int I
Definition vector2i.h:51
int J
Definition vector2i.h:52
static void * Get_Window(void)
Definition ww3d.cpp:489
int percent
Definition patch.cpp:426
else return(RetVal)
#define REF_PTR_RELEASE(x)
Definition refcount.h:80
#define REF_PTR_SET(dst, src)
Definition refcount.h:79
#define NEW_REF(C, P)
Definition refcount.h:62
#define TEXTURE_OFFSET
float FindStartingXPos(const WCHAR *text)
@ CHAR_BUFFER_LEN
@ MIP_LEVELS_1
@ WW3D_FORMAT_A4R4G4B4
Definition ww3dformat.h:83
@ MEM_TEXTURE
Definition wwmemlog.h:61
#define WWMEMLOG(category)
Definition wwmemlog.h:183