hedgewars/uChat.pas
changeset 10303 f726e36c3e24
parent 10127 7f29a65aa1e4
child 10304 7e40820b7ed6
--- a/hedgewars/uChat.pas	Sat Jun 14 02:25:49 2014 +0200
+++ b/hedgewars/uChat.pas	Sat Jun 14 07:12:22 2014 +0200
@@ -41,6 +41,7 @@
     Time: Longword;
     Width: LongInt;
     s: shortstring;
+    Color: TSDL_Color;
     end;
     TChatCmd = (ccQuit, ccPause, ccFinish, ccShowHistory, ccFullScreen);
 
@@ -78,43 +79,95 @@
             (ChatCmd: '/fullscreen'; ProcedureCallChatCmd: 'fullscr')
             );
 
+
+const Padding  = 2;
+      ClHeight = 2 * Padding + 16; // font height
+
+procedure RenderChatLineTex(var cl: TChatLine; var str: shortstring);
+var strSurface,
+    resSurface: PSDL_Surface;
+    dstrect   : TSDL_Rect; // destination rectangle for blitting
+    font      : THWFont;
+const
+    shadowcolor: TSDL_Color = (r:$00; g:$00; b:$00; a:$80);
+    shadowint  = $80 shl AShift;
+begin
+
+font:= CheckCJKFont(ansistring(str), fnt16);
+
+// get render size of text
+TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @cl.Width, nil);
+
+// calculate and save size
+cl.Width := cl.Width  + 2 * Padding;
+
+// create surface to draw on
+resSurface:= SDL_CreateRGBSurface(
+                0, toPowerOf2(cl.Width), toPowerOf2(ClHeight),
+                32, RMask, GMask, BMask, AMask);
+
+// define area we want to draw in
+dstrect.x:= 0;
+dstrect.y:= 0;
+dstrect.w:= cl.Width;
+dstrect.h:= ClHeight;
+
+// draw background
+SDL_FillRect(resSurface, @dstrect, shadowint);
+
+// prepare destination rectangle for text shadow
+// start position in texture should have padding; add 1 px as shadow offset
+dstrect.x:= Padding + 1;
+dstrect.y:= Padding + 1;
+// doesn't matter if .w and .h still include padding, SDL_UpperBlit will clip
+
+
+// create and blit text shadow
+strSurface:= TTF_RenderUTF8_Solid(Fontz[font].Handle, Str2PChar(str), shadowcolor);
+SDL_UpperBlit(strSurface, nil, resSurface, @dstrect);
+SDL_FreeSurface(strSurface);
+
+// non-shadow text starts at padding
+dstrect.x:= Padding;
+dstrect.y:= Padding;
+
+// create and blit text
+strSurface:= TTF_RenderUTF8_Solid(Fontz[font].Handle, Str2PChar(str), cl.color);
+SDL_UpperBlit(strSurface, nil, resSurface, @dstrect);
+SDL_FreeSurface(strSurface);
+
+cl.Tex:= Surface2Tex(resSurface, false);
+
+SDL_FreeSurface(resSurface)
+end;
+
+const ClDisplayDuration = 12500;
+
 procedure SetLine(var cl: TChatLine; str: shortstring; isInput: boolean);
-var strSurface, resSurface: PSDL_Surface;
-    w, h: LongInt;
-    color: TSDL_Color;
-    font: THWFont;
+var color  : TSDL_Color;
 begin
 if cl.Tex <> nil then
     FreeTexture(cl.Tex);
 
-cl.s:= str;
-
 if isInput then
     begin
+    cl.s:= str;
     color:= colors[#6];
     str:= UserNick + '> ' + str + '_'
     end
 else
     begin
     color:= colors[str[1]];
-    delete(str, 1, 1)
+    delete(str, 1, 1);
+    cl.s:= str;
     end;
 
-font:= CheckCJKFont(ansistring(str), fnt16);
-w:= 0; h:= 0; // avoid compiler hints
-TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @w, @h);
-
-resSurface:= SDL_CreateRGBSurface(0, toPowerOf2(w), toPowerOf2(h), 32, RMask, GMask, BMask, AMask);
+cl.color:= color;
 
-strSurface:= TTF_RenderUTF8_Solid(Fontz[font].Handle, Str2PChar(str), color);
-cl.Width:= w + 4;
-SDL_UpperBlit(strSurface, nil, resSurface, nil);
-SDL_FreeSurface(strSurface);
+// set texture, note: variables cl.s and str will be different here if isInput
+RenderChatLineTex(cl, str);
 
-cl.Time:= RealTicks + 12500;
-cl.Tex:= Surface2Tex(resSurface, false);
-
-SDL_FreeSurface(resSurface)
+cl.Time:= RealTicks + ClDisplayDuration;
 end;
 
 // For uStore texture recreation
@@ -152,8 +205,7 @@
 end;
 
 procedure DrawChat;
-var i, t, cnt: Longword;
-    r: TSDL_Rect;
+var i, t, left, top, cnt: Longword;
 begin
 ChatReady:= true; // maybe move to somewhere else?
 if MissedCount <> 0 then // there are chat strings we missed, so print them now
@@ -162,36 +214,27 @@
         AddChatString(MStrs[i]);
     MissedCount:= 0;
     end;
-cnt:= 0;
-t:= 0;
 i:= lastStr;
 
-r.x:= 6 - cScreenWidth div 2;
-r.y:= (visibleCount - t) * 16 + 10;
-r.h:= 16;
+left:= 4 - cScreenWidth div 2;
+top := 10;
 
 if (GameState = gsChat) and (InputStr.Tex <> nil) then
     begin
-    r.w:= InputStr.Width;
-    DrawFillRect(r);
-    Tint($00, $00, $00, $80);
-    DrawTexture(9 - cScreenWidth div 2, visibleCount * 16 + 11, InputStr.Tex);
-    untint;
-    DrawTexture(8 - cScreenWidth div 2, visibleCount * 16 + 10, InputStr.Tex);
+    // draw under all other lines
+    DrawTexture(left, top + visibleCount * ClHeight, InputStr.Tex);
     end;
 
-dec(r.y, 16);
 
+cnt:= 0; // count of lines displayed
+t  := 1; // # of current line processed
+
+// draw lines in reverse order
 while (((t < 7) and (Strs[i].Time > RealTicks)) or ((t < MaxStrIndex) and showAll))
 and (Strs[i].Tex <> nil) do
     begin
-    r.w:= Strs[i].Width;
-    DrawFillRect(r);
-    Tint($00, $00, $00, $80);
-    DrawTexture(9 - cScreenWidth div 2, (visibleCount - t) * 16 - 5, Strs[i].Tex);
-    untint;
-    DrawTexture(8 - cScreenWidth div 2, (visibleCount - t) * 16 - 6, Strs[i].Tex);
-    dec(r.y, 16);
+    // draw lines 4px away from left screen border and 2px away from top
+    DrawTexture(left, top + (visibleCount - t) * ClHeight, Strs[i].Tex);
 
     if i = 0 then
         i:= MaxStrIndex