hedgewars/uStore.pas
changeset 4380 b78638b36b89
parent 4378 91655618a510
child 4385 f679ffa2dc8c
equal deleted inserted replaced
4379:6cd6b77df8b8 4380:b78638b36b89
    25 procedure initModule;
    25 procedure initModule;
    26 procedure freeModule;
    26 procedure freeModule;
    27 
    27 
    28 procedure StoreLoad;
    28 procedure StoreLoad;
    29 procedure StoreRelease;
    29 procedure StoreRelease;
    30 procedure DrawRoundRect(rect: PSDL_Rect; BorderColor, FillColor: Longword; Surface: PSDL_Surface; Clear: boolean);
       
    31 procedure DrawHedgehog(X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
    30 procedure DrawHedgehog(X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
    32 function  CheckCJKFont(s: ansistring; font: THWFont): THWFont;
       
    33 function  RenderStringTex(s: ansistring; Color: Longword; font: THWFont): PTexture;
       
    34 function  RenderSpeechBubbleTex(s: ansistring; SpeechType: Longword; font: THWFont): PTexture;
       
    35 procedure flipSurface(Surface: PSDL_Surface; Vertical: Boolean);
       
    36 //procedure rotateSurface(Surface: PSDL_Surface);
       
    37 procedure copyRotatedSurface(src, dest: PSDL_Surface); // this is necessary since width/height are read only in SDL
       
    38 procedure copyToXY(src, dest: PSDL_Surface; destX, destY: LongInt);
       
    39 procedure RenderHealth(var Hedgehog: THedgehog);
    31 procedure RenderHealth(var Hedgehog: THedgehog);
    40 procedure AddProgress;
    32 procedure AddProgress;
    41 procedure FinishProgress;
    33 procedure FinishProgress;
    42 function  LoadImage(const filename: shortstring; imageFlags: LongInt): PSDL_Surface;
    34 function  LoadImage(const filename: shortstring; imageFlags: LongInt): PSDL_Surface;
    43 procedure SetupOpenGL;
    35 procedure SetupOpenGL;
    46 procedure RenderWeaponTooltip(atype: TAmmoType);
    38 procedure RenderWeaponTooltip(atype: TAmmoType);
    47 procedure ShowWeaponTooltip(x, y: LongInt);
    39 procedure ShowWeaponTooltip(x, y: LongInt);
    48 procedure FreeWeaponTooltip;
    40 procedure FreeWeaponTooltip;
    49 
    41 
    50 implementation
    42 implementation
    51 uses uMisc, uConsole, uLocale, uMobile, uVariables, uUtils, uTextures, uIO, uRender;
    43 uses uMisc, uConsole, uLocale, uMobile, uVariables, uUtils, uTextures, uIO, uRender, uRenderUtils;
    52 
    44 
    53 type TGPUVendor = (gvUnknown, gvNVIDIA, gvATI, gvIntel, gvApple);
    45 type TGPUVendor = (gvUnknown, gvNVIDIA, gvATI, gvIntel, gvApple);
    54 
    46 
    55 var HHTexture: PTexture;
    47 var HHTexture: PTexture;
    56     MaxTextureSize: LongInt;
    48     MaxTextureSize: LongInt;
    57     cGPUVendor: TGPUVendor;
    49     cGPUVendor: TGPUVendor;
    58 
       
    59 procedure DrawRoundRect(rect: PSDL_Rect; BorderColor, FillColor: Longword; Surface: PSDL_Surface; Clear: boolean);
       
    60 var r: TSDL_Rect;
       
    61 begin
       
    62 r:= rect^;
       
    63 if Clear then SDL_FillRect(Surface, @r, 0);
       
    64 
       
    65 BorderColor:= SDL_MapRGB(Surface^.format, BorderColor shr 16, BorderColor shr 8, BorderColor and $FF);
       
    66 FillColor:= SDL_MapRGB(Surface^.format, FillColor shr 16, FillColor shr 8, FillColor and $FF);
       
    67 
       
    68 r.y:= rect^.y + 1;
       
    69 r.h:= rect^.h - 2;
       
    70 SDL_FillRect(Surface, @r, BorderColor);
       
    71 r.x:= rect^.x + 1;
       
    72 r.w:= rect^.w - 2;
       
    73 r.y:= rect^.y;
       
    74 r.h:= rect^.h;
       
    75 SDL_FillRect(Surface, @r, BorderColor);
       
    76 r.x:= rect^.x + 2;
       
    77 r.y:= rect^.y + 1;
       
    78 r.w:= rect^.w - 4;
       
    79 r.h:= rect^.h - 2;
       
    80 SDL_FillRect(Surface, @r, FillColor);
       
    81 r.x:= rect^.x + 1;
       
    82 r.y:= rect^.y + 2;
       
    83 r.w:= rect^.w - 2;
       
    84 r.h:= rect^.h - 4;
       
    85 SDL_FillRect(Surface, @r, FillColor)
       
    86 end;
       
    87 
       
    88 function WriteInRoundRect(Surface: PSDL_Surface; X, Y: LongInt; Color: LongWord; Font: THWFont; s: ansistring): TSDL_Rect;
       
    89 var w, h: LongInt;
       
    90     tmpsurf: PSDL_Surface;
       
    91     clr: TSDL_Color;
       
    92     finalRect: TSDL_Rect;
       
    93 begin
       
    94 w:= 0; h:= 0; // avoid compiler hints
       
    95 TTF_SizeUTF8(Fontz[Font].Handle, Str2PChar(s), w, h);
       
    96 finalRect.x:= X;
       
    97 finalRect.y:= Y;
       
    98 finalRect.w:= w + FontBorder * 2 + 4;
       
    99 finalRect.h:= h + FontBorder * 2;
       
   100 DrawRoundRect(@finalRect, cWhiteColor, endian(cNearBlackColorChannels.value), Surface, true);
       
   101 clr.r:= (Color shr 16) and $FF;
       
   102 clr.g:= (Color shr 8) and $FF;
       
   103 clr.b:= Color and $FF;
       
   104 tmpsurf:= TTF_RenderUTF8_Blended(Fontz[Font].Handle, Str2PChar(s), clr);
       
   105 finalRect.x:= X + FontBorder + 2;
       
   106 finalRect.y:= Y + FontBorder;
       
   107 SDLTry(tmpsurf <> nil, true);
       
   108 SDL_UpperBlit(tmpsurf, nil, Surface, @finalRect);
       
   109 SDL_FreeSurface(tmpsurf);
       
   110 finalRect.x:= X;
       
   111 finalRect.y:= Y;
       
   112 finalRect.w:= w + FontBorder * 2 + 4;
       
   113 finalRect.h:= h + FontBorder * 2;
       
   114 WriteInRoundRect:= finalRect;
       
   115 end;
       
   116 
    50 
   117 function WriteInRect(Surface: PSDL_Surface; X, Y: LongInt; Color: LongWord; Font: THWFont; s: ansistring): TSDL_Rect;
    51 function WriteInRect(Surface: PSDL_Surface; X, Y: LongInt; Color: LongWord; Font: THWFont; s: ansistring): TSDL_Rect;
   118 var w, h: LongInt;
    52 var w, h: LongInt;
   119     tmpsurf: PSDL_Surface;
    53     tmpsurf: PSDL_Surface;
   120     clr: TSDL_Color;
    54     clr: TSDL_Color;
   495     FreeTexture(ropeIconTex);
   429     FreeTexture(ropeIconTex);
   496     FreeTexture(HHTexture);
   430     FreeTexture(HHTexture);
   497 end;
   431 end;
   498 
   432 
   499 
   433 
   500 function CheckCJKFont(s: ansistring; font: THWFont): THWFont;
       
   501 var l, i : LongInt;
       
   502     u: WideChar;
       
   503     tmpstr: array[0..256] of WideChar;
       
   504 begin
       
   505 
       
   506 {$IFNDEF IPHONEOS}
       
   507 // remove chinese fonts for now
       
   508 if (font >= CJKfnt16) or (length(s) = 0) then
       
   509 {$ENDIF}
       
   510     exit(font);
       
   511 
       
   512 l:= Utf8ToUnicode(@tmpstr, Str2PChar(s), length(s))-1;
       
   513 i:= 0;
       
   514 while i < l do
       
   515     begin
       
   516     u:= tmpstr[i];
       
   517     if (#$2E80  <= u) and  (
       
   518                            (u <= #$2FDF )  or // CJK Radicals Supplement / Kangxi Radicals
       
   519        ((#$2FF0  <= u) and (u <= #$303F))  or // Ideographic Description Characters / CJK Radicals Supplement
       
   520        ((#$31C0  <= u) and (u <= #$31EF))  or // CJK Strokes
       
   521        ((#$3200  <= u) and (u <= #$4DBF))  or // Enclosed CJK Letters and Months / CJK Compatibility / CJK Unified Ideographs Extension A
       
   522        ((#$4E00  <= u) and (u <= #$9FFF))  or // CJK Unified Ideographs
       
   523        ((#$F900  <= u) and (u <= #$FAFF))  or // CJK Compatibility Ideographs
       
   524        ((#$FE30  <= u) and (u <= #$FE4F)))    // CJK Compatibility Forms
       
   525        then exit(THWFont( ord(font) + ((ord(High(THWFont))+1) div 2) ));
       
   526     inc(i)
       
   527     end;
       
   528 exit(font);
       
   529 (* two more to check. pascal WideChar is only 16 bit though
       
   530        ((#$20000 <= u) and (u >= #$2A6DF)) or // CJK Unified Ideographs Extension B
       
   531        ((#$2F800 <= u) and (u >= #$2FA1F)))   // CJK Compatibility Ideographs Supplement *)
       
   532 end;
       
   533 
       
   534 function  RenderStringTex(s: ansistring; Color: Longword; font: THWFont): PTexture;
       
   535 var w, h: LongInt;
       
   536     finalSurface: PSDL_Surface;
       
   537 begin
       
   538 if length(s) = 0 then s:= ' ';
       
   539 font:= CheckCJKFont(s, font);
       
   540 w:= 0; h:= 0; // avoid compiler hints
       
   541 TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(s), w, h);
       
   542 
       
   543 finalSurface:= SDL_CreateRGBSurface(SDL_SWSURFACE, w + FontBorder * 2 + 4, h + FontBorder * 2,
       
   544          32, RMask, GMask, BMask, AMask);
       
   545 
       
   546 TryDo(finalSurface <> nil, 'RenderString: fail to create surface', true);
       
   547 
       
   548 WriteInRoundRect(finalSurface, 0, 0, Color, font, s);
       
   549 
       
   550 TryDo(SDL_SetColorKey(finalSurface, SDL_SRCCOLORKEY, 0) = 0, errmsgTransparentSet, true);
       
   551 
       
   552 RenderStringTex:= Surface2Tex(finalSurface, false);
       
   553 
       
   554 SDL_FreeSurface(finalSurface);
       
   555 end;
       
   556 
       
   557 function RenderSpeechBubbleTex(s: ansistring; SpeechType: Longword; font: THWFont): PTexture;
       
   558 var textWidth, textHeight, x, y, w, h, i, j, pos, prevpos, line, numLines, edgeWidth, edgeHeight, cornerWidth, cornerHeight: LongInt;
       
   559     finalSurface, tmpsurf, rotatedEdge: PSDL_Surface;
       
   560     rect: TSDL_Rect;
       
   561     chars: TSysCharSet = [#9,' ','.',';',':','?','!',','];
       
   562     substr: shortstring;
       
   563     edge, corner, tail: TSPrite;
       
   564 begin
       
   565 
       
   566 case SpeechType of
       
   567     1: begin;
       
   568        edge:= sprSpeechEdge;
       
   569        corner:= sprSpeechCorner;
       
   570        tail:= sprSpeechTail;
       
   571        end;
       
   572     2: begin;
       
   573        edge:= sprThoughtEdge;
       
   574        corner:= sprThoughtCorner;
       
   575        tail:= sprThoughtTail;
       
   576        end;
       
   577     3: begin;
       
   578        edge:= sprShoutEdge;
       
   579        corner:= sprShoutCorner;
       
   580        tail:= sprShoutTail;
       
   581        end;
       
   582     end;
       
   583 edgeHeight:= SpritesData[edge].Height;
       
   584 edgeWidth:= SpritesData[edge].Width;
       
   585 cornerWidth:= SpritesData[corner].Width;
       
   586 cornerHeight:= SpritesData[corner].Height;
       
   587 // This one screws up WrapText
       
   588 //s:= 'This is the song that never ends.  ''cause it goes on and on my friends. Some people, started singing it not knowing what it was. And they''ll just go on singing it forever just because... This is the song that never ends...';
       
   589 // This one does not
       
   590 //s:= 'This is the song that never ends.  cause it goes on and on my friends. Some people, started singing it not knowing what it was. And they will go on singing it forever just because... This is the song that never ends... ';
       
   591 
       
   592 numLines:= 0;
       
   593 
       
   594 if length(s) = 0 then s:= '...';
       
   595 font:= CheckCJKFont(s, font);
       
   596 w:= 0; h:= 0; // avoid compiler hints
       
   597 TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(s), w, h);
       
   598 if w<8 then w:= 8;
       
   599 j:= 0;
       
   600 if (length(s) > 20) then
       
   601     begin
       
   602     w:= 0;
       
   603     i:= round(Sqrt(length(s)) * 2);
       
   604     s:= WrapText(s, #1, chars, i);
       
   605     pos:= 1; prevpos:= 0; line:= 0;
       
   606 // Find the longest line for the purposes of centring the text.  Font dependant.
       
   607     while pos <= length(s) do
       
   608         begin
       
   609         if (s[pos] = #1) or (pos = length(s)) then
       
   610             begin
       
   611             inc(numlines);
       
   612             if s[pos] <> #1 then inc(pos);
       
   613             while s[prevpos+1] = ' ' do inc(prevpos);
       
   614             substr:= copy(s, prevpos+1, pos-prevpos-1);
       
   615             i:= 0; j:= 0;
       
   616             TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(substr), i, j);
       
   617             if i > w then w:= i;
       
   618             prevpos:= pos;
       
   619             end;
       
   620         inc(pos);
       
   621         end;
       
   622     end
       
   623 else numLines := 1;
       
   624 
       
   625 textWidth:=((w-(cornerWidth-edgeWidth)*2) div edgeWidth)*edgeWidth+edgeWidth;
       
   626 textHeight:=(((numlines * h + 2)-((cornerHeight-edgeWidth)*2)) div edgeWidth)*edgeWidth;
       
   627 
       
   628 textHeight:=max(textHeight,edgeWidth);
       
   629 //textWidth:=max(textWidth,SpritesData[tail].Width);
       
   630 rect.x:= 0;
       
   631 rect.y:= 0;
       
   632 rect.w:= textWidth + (cornerWidth * 2);
       
   633 rect.h:= textHeight + cornerHeight*2 - edgeHeight + SpritesData[tail].Height;
       
   634 //s:= inttostr(w) + ' ' + inttostr(numlines) + ' ' + inttostr(rect.x) + ' '+inttostr(rect.y) + ' ' + inttostr(rect.w) + ' ' + inttostr(rect.h);
       
   635 
       
   636 finalSurface:= SDL_CreateRGBSurface(SDL_SWSURFACE, rect.w, rect.h, 32, RMask, GMask, BMask, AMask);
       
   637 
       
   638 TryDo(finalSurface <> nil, 'RenderString: fail to create surface', true);
       
   639 
       
   640 //////////////////////////////// CORNERS ///////////////////////////////
       
   641 copyToXY(SpritesData[corner].Surface, finalSurface, 0, 0); /////////////////// NW
       
   642 
       
   643 flipSurface(SpritesData[corner].Surface, true); // store all 4 versions in memory to avoid repeated flips?
       
   644 x:= 0;
       
   645 y:= textHeight + cornerHeight -1;
       
   646 copyToXY(SpritesData[corner].Surface, finalSurface, x, y); /////////////////// SW
       
   647 
       
   648 flipSurface(SpritesData[corner].Surface, false);
       
   649 x:= rect.w-cornerWidth-1;
       
   650 y:= textHeight + cornerHeight -1;
       
   651 copyToXY(SpritesData[corner].Surface, finalSurface, x, y); /////////////////// SE
       
   652 
       
   653 flipSurface(SpritesData[corner].Surface, true);
       
   654 x:= rect.w-cornerWidth-1;
       
   655 y:= 0;
       
   656 copyToXY(SpritesData[corner].Surface, finalSurface, x, y); /////////////////// NE
       
   657 flipSurface(SpritesData[corner].Surface, false); // restore original position
       
   658 //////////////////////////////// END CORNERS ///////////////////////////////
       
   659 
       
   660 //////////////////////////////// EDGES //////////////////////////////////////
       
   661 x:= cornerWidth;
       
   662 y:= 0;
       
   663 while x < rect.w-cornerWidth-1 do
       
   664     begin
       
   665     copyToXY(SpritesData[edge].Surface, finalSurface, x, y); ///////////////// top edge
       
   666     inc(x,edgeWidth);
       
   667     end;
       
   668 flipSurface(SpritesData[edge].Surface, true);
       
   669 x:= cornerWidth;
       
   670 y:= textHeight + cornerHeight*2 - edgeHeight-1;
       
   671 while x < rect.w-cornerWidth-1 do
       
   672     begin
       
   673     copyToXY(SpritesData[edge].Surface, finalSurface, x, y); ///////////////// bottom edge
       
   674     inc(x,edgeWidth);
       
   675     end;
       
   676 flipSurface(SpritesData[edge].Surface, true); // restore original position
       
   677 
       
   678 rotatedEdge:= SDL_CreateRGBSurface(SDL_SWSURFACE, edgeHeight, edgeWidth, 32, RMask, GMask, BMask, AMask);
       
   679 x:= rect.w - edgeHeight - 1;
       
   680 y:= cornerHeight;
       
   681 //// initially was going to rotate in place, but the SDL spec claims width/height are read only
       
   682 copyRotatedSurface(SpritesData[edge].Surface,rotatedEdge);
       
   683 while y < textHeight + cornerHeight do
       
   684     begin
       
   685     copyToXY(rotatedEdge, finalSurface, x, y);
       
   686     inc(y,edgeWidth);
       
   687     end;
       
   688 flipSurface(rotatedEdge, false); // restore original position
       
   689 x:= 0;
       
   690 y:= cornerHeight;
       
   691 while y < textHeight + cornerHeight do
       
   692     begin
       
   693     copyToXY(rotatedEdge, finalSurface, x, y);
       
   694     inc(y,edgeWidth);
       
   695     end;
       
   696 //////////////////////////////// END EDGES //////////////////////////////////////
       
   697 
       
   698 x:= cornerWidth;
       
   699 y:= textHeight + cornerHeight * 2 - edgeHeight - 1;
       
   700 copyToXY(SpritesData[tail].Surface, finalSurface, x, y);
       
   701 
       
   702 rect.x:= edgeHeight;
       
   703 rect.y:= edgeHeight;
       
   704 rect.w:= rect.w - edgeHeight * 2;
       
   705 rect.h:= textHeight + cornerHeight * 2 - edgeHeight * 2;
       
   706 i:= rect.w;
       
   707 j:= rect.h;
       
   708 SDL_FillRect(finalSurface, @rect, cWhiteColor);
       
   709 
       
   710 pos:= 1; prevpos:= 0; line:= 0;
       
   711 while pos <= length(s) do
       
   712     begin
       
   713     if (s[pos] = #1) or (pos = length(s)) then
       
   714         begin
       
   715         if s[pos] <> #1 then inc(pos);
       
   716         while s[prevpos+1] = ' 'do inc(prevpos);
       
   717         substr:= copy(s, prevpos+1, pos-prevpos-1);
       
   718         if Length(substr) <> 0 then
       
   719            begin
       
   720            tmpsurf:= TTF_RenderUTF8_Blended(Fontz[Font].Handle, Str2PChar(substr), cNearBlackColorChannels);
       
   721            rect.x:= edgeHeight + 1 + ((i - w) div 2);
       
   722            // trying to more evenly position the text, vertically
       
   723            rect.y:= edgeHeight + ((j-(numLines*h)) div 2) + line * h;
       
   724            SDLTry(tmpsurf <> nil, true);
       
   725            SDL_UpperBlit(tmpsurf, nil, finalSurface, @rect);
       
   726            SDL_FreeSurface(tmpsurf);
       
   727            inc(line);
       
   728            prevpos:= pos;
       
   729            end;
       
   730         end;
       
   731     inc(pos);
       
   732     end;
       
   733 
       
   734 //TryDo(SDL_SetColorKey(finalSurface, SDL_SRCCOLORKEY, 0) = 0, errmsgTransparentSet, true);
       
   735 RenderSpeechBubbleTex:= Surface2Tex(finalSurface, true);
       
   736 
       
   737 SDL_FreeSurface(rotatedEdge);
       
   738 SDL_FreeSurface(finalSurface);
       
   739 end;
       
   740 
       
   741 procedure RenderHealth(var Hedgehog: THedgehog);
   434 procedure RenderHealth(var Hedgehog: THedgehog);
   742 var s: shortstring;
   435 var s: shortstring;
   743 begin
   436 begin
   744     str(Hedgehog.Gear^.Health, s);
   437     str(Hedgehog.Gear^.Health, s);
   745     if Hedgehog.HealthTagTex <> nil then
   438     if Hedgehog.HealthTagTex <> nil then
   961     WriteLnToConsole('Freeing progress surface... ');
   654     WriteLnToConsole('Freeing progress surface... ');
   962     FreeTexture(ProgrTex);
   655     FreeTexture(ProgrTex);
   963     perfExt_FinishProgress();
   656     perfExt_FinishProgress();
   964 end;
   657 end;
   965 
   658 
   966 procedure flipSurface(Surface: PSDL_Surface; Vertical: Boolean);
       
   967 var y, x, i, j: LongInt;
       
   968     tmpPixel: Longword;
       
   969     pixels: PLongWordArray;
       
   970 begin
       
   971 TryDo(Surface^.format^.BytesPerPixel = 4, 'flipSurface failed, expecting 32 bit surface', true);
       
   972 pixels:= Surface^.pixels;
       
   973 if Vertical then
       
   974    for y := 0 to (Surface^.h div 2) - 1 do
       
   975        for x := 0 to Surface^.w - 1 do
       
   976            begin
       
   977            i:= y * Surface^.w + x;
       
   978            j:= (Surface^.h - y - 1) * Surface^.w + x;
       
   979            tmpPixel:= pixels^[i];
       
   980            pixels^[i]:= pixels^[j];
       
   981            pixels^[j]:= tmpPixel;
       
   982            end
       
   983 else
       
   984    for x := 0 to (Surface^.w div 2) - 1 do
       
   985        for y := 0 to Surface^.h -1 do
       
   986            begin
       
   987            i:= y*Surface^.w + x;
       
   988            j:= y*Surface^.w + (Surface^.w - x - 1);
       
   989            tmpPixel:= pixels^[i];
       
   990            pixels^[i]:= pixels^[j];
       
   991            pixels^[j]:= tmpPixel;
       
   992            end;
       
   993 end;
       
   994 
       
   995 procedure copyToXY(src, dest: PSDL_Surface; destX, destY: LongInt);
       
   996 var srcX, srcY, i, j, maxDest: LongInt;
       
   997     srcPixels, destPixels: PLongWordArray;
       
   998     r0, g0, b0, a0, r1, g1, b1, a1: Byte;
       
   999 begin
       
  1000 maxDest:= (dest^.pitch div 4) * dest^.h;
       
  1001 srcPixels:= src^.pixels;
       
  1002 destPixels:= dest^.pixels;
       
  1003 
       
  1004 for srcX:= 0 to src^.w - 1 do
       
  1005    for srcY:= 0 to src^.h - 1 do
       
  1006       begin
       
  1007       i:= (destY + srcY) * (dest^.pitch div 4) + destX + srcX;
       
  1008       j:= srcY * (src^.pitch div 4) + srcX;
       
  1009       if (i < maxDest) and (srcPixels^[j] and AMask <> 0) then
       
  1010          begin
       
  1011          SDL_GetRGBA(destPixels^[i], dest^.format, @r0, @g0, @b0, @a0);
       
  1012          SDL_GetRGBA(srcPixels^[j], src^.format, @r1, @g1, @b1, @a1);
       
  1013          r0:= (r0 * (255 - LongInt(a1)) + r1 * LongInt(a1)) div 255;
       
  1014          g0:= (g0 * (255 - LongInt(a1)) + g1 * LongInt(a1)) div 255;
       
  1015          b0:= (b0 * (255 - LongInt(a1)) + b1 * LongInt(a1)) div 255;
       
  1016          a0:= (a0 * (255 - LongInt(a1)) + a1 * LongInt(a1)) div 255;
       
  1017          destPixels^[i]:= SDL_MapRGBA(dest^.format, r0, g0, b0, a0);
       
  1018          end;
       
  1019       end;
       
  1020 end;
       
  1021 
       
  1022 procedure copyRotatedSurface(src, dest: PSDL_Surface); // this is necessary since width/height are read only in SDL, apparently
       
  1023 var y, x, i, j: LongInt;
       
  1024     srcPixels, destPixels: PLongWordArray;
       
  1025 begin
       
  1026 TryDo(src^.format^.BytesPerPixel = 4, 'rotateSurface failed, expecting 32 bit surface', true);
       
  1027 TryDo(dest^.format^.BytesPerPixel = 4, 'rotateSurface failed, expecting 32 bit surface', true);
       
  1028 
       
  1029 srcPixels:= src^.pixels;
       
  1030 destPixels:= dest^.pixels;
       
  1031 
       
  1032 j:= 0;
       
  1033 for x := 0 to src^.w - 1 do
       
  1034     for y := 0 to src^.h - 1 do
       
  1035         begin
       
  1036         i:= (src^.h - 1 - y) * (src^.pitch div 4) + x;
       
  1037         destPixels^[j]:= srcPixels^[i];
       
  1038         inc(j)
       
  1039         end;
       
  1040 end;
       
  1041 
       
  1042 function RenderHelpWindow(caption, subcaption, description, extra: ansistring; extracolor: LongInt; iconsurf: PSDL_Surface; iconrect: PSDL_Rect): PTexture;
   659 function RenderHelpWindow(caption, subcaption, description, extra: ansistring; extracolor: LongInt; iconsurf: PSDL_Surface; iconrect: PSDL_Rect): PTexture;
  1043 var tmpsurf: PSDL_SURFACE;
   660 var tmpsurf: PSDL_SURFACE;
  1044     w, h, i, j: LongInt;
   661     w, h, i, j: LongInt;
  1045     font: THWFont;
   662     font: THWFont;
  1046     r, r2: TSDL_Rect;
   663     r, r2: TSDL_Rect;