# HG changeset patch # User sheepluva # Date 1402722742 -7200 # Node ID f726e36c3e2499ee4312cbab5588fb7d0248d7ab # Parent ea0b0e2efd95f39af49dcb15d5c85cf7324ba966 tweak how chat lines are rendered diff -r ea0b0e2efd95 -r f726e36c3e24 hedgewars/uChat.pas --- 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