hedgewars/uLand.pas
changeset 12104 f61bd25b9f70
parent 12100 166725555e57
child 12592 00b539e6115d
equal deleted inserted replaced
12103:22bd1099d51f 12104:f61bd25b9f70
   163                         LandPixels[y div 2, x div 2]:= c
   163                         LandPixels[y div 2, x div 2]:= c
   164                     end;
   164                     end;
   165                 end
   165                 end
   166 end;
   166 end;
   167 
   167 
   168 procedure ColorizeLandFast(Surface: PSDL_Surface);
   168 procedure ColorizeLandFast(mapsurf: PSDL_Surface);
   169 var ltsurf: PSDL_Surface;
   169 var ltexsurf: PSDL_Surface;
   170     x, y, ltw, lth, c, modc, lastfull: LongInt;
   170     i: LongInt;
   171     srcp, dstp: Pointer;
   171     ltlnp, srcp, dstp, stopp: Pointer;
   172 begin
   172     c: SizeInt;
   173     ltsurf:= LoadDataImage(ptCurrTheme, 'LandTex', ifCritical or ifIgnoreCaps);
   173 begin
   174     ltw:= ltsurf^.w;
   174     ltexsurf:= LoadDataImage(ptCurrTheme, 'LandTex', ifCritical or ifIgnoreCaps);
   175     lth:= ltsurf^.h;
   175 
   176 
   176     // pointer to current line of ltexsurf pixels. will be moved from line to line
   177     // pointer to ltturf pixels. will be moved from line to line
   177     ltlnp:= ltexsurf^.pixels;
   178     srcp:= ltsurf^.pixels;
   178     // pointer to mapsurf pixels. will jump forward after every move()
   179     // pointer to Surface pixels. will be moved forward with every move()
   179     dstp:= mapsurf^.pixels;
   180     dstp:= Surface^.pixels;
   180 
   181 
   181     // time to get serious
   182     // amount of pixels to write per move()
   182     SDL_LockSurface(mapsurf);
   183     c:= ltsurf^.pitch;
   183     SDL_LockSurface(ltexsurf);
   184     // amount of pixels to write for line's remainer move()
   184 
   185     modc:= Surface^.pitch mod c;
   185     // for now only fill a row with the height of landtex. do vertical copies within mapsurf after
   186 
   186 
   187     SDL_LockSurface(Surface);
   187     // do this loop for each line of ltexsurf (unless we run out of map height first)
   188     SDL_LockSurface(ltsurf);
   188     for i:= 1 to min(ltexsurf^.h, mapsurf^.h) do
   189 
   189         begin
   190     y:= 0;
   190         // amount of pixels to write in first move()
   191     // last x where a full line from src may be written to
   191         c:= ltexsurf^.pitch;
   192     lastfull:= Surface^.w - ltw;
   192 
   193     // only copy in one row of landtex. do copies within Surface after
   193         // protect from odd cases where landtex wider than map
   194     while (y < lth) and (y < Surface^.h) do
   194         if c > mapsurf^.pitch then
   195         begin
   195             c:= mapsurf^.pitch;
   196         x:= 0;
   196 
   197         // fill dst line with src lines
   197         // write line of landtex to mapsurf
   198         while x <= lastfull do
   198         move(ltlnp^, dstp^, c);
   199             begin
   199 
       
   200         // fill the rest of the line by copying left-to-right until full
       
   201 
       
   202         // new src is start of line that we've just written to
       
   203         srcp:= dstp;
       
   204         // set stop pointer to start of next pixel line of mapsurf
       
   205         stopp:= dstp + mapsurf^.pitch;
       
   206         // move dst pointer to after what we've just written
       
   207         inc(dstp, c);
       
   208 
       
   209         // loop until dstp went past end of line
       
   210         while dstp < stopp do
       
   211             begin
       
   212             // copy all from left of dstp to right of it (or just fill the gap if smaller)
       
   213             c:= min(dstp-srcp, stopp-dstp);
   200             move(srcp^, dstp^, c);
   214             move(srcp^, dstp^, c);
   201             inc(dstp, c);
   215             inc(dstp, c);
   202                 inc(x, ltw);
       
   203             end;
   216             end;
   204 
   217 
   205         // if it didn't fit perfectly, copy remainder
   218         // move to next line in ltexsurf
   206         if modc > 0 then
   219         inc(ltlnp, ltexsurf^.pitch);
   207             begin
   220         end;
   208             move(srcp^, dstp^, modc);
   221 
   209             inc(dstp, modc);
   222     // we don't need ltexsurf itself anymore -> cleanup
   210             end;
   223     ltlnp:= nil;
   211 
   224     SDL_UnlockSurface(ltexsurf);
   212         // move to next line in src surface
   225     SDL_FreeSurface(ltexsurf);
   213         inc(srcp, ltsurf^.pitch);
   226     ltexsurf:= nil;
   214         inc(y);
   227 
   215         end;
   228     // from now on only copy pixels within mapsurf
   216 
   229 
   217     // we don't need ltsurf anymore -> cleanup
   230     // copy all the already written lines at once for that get number of written bytes so far
       
   231     // already written pixels are between start and current dstp
       
   232     srcp:= mapsurf^.pixels;
       
   233 
       
   234     // first byte after end of pixels
       
   235     stopp:= srcp + (mapsurf^.pitch * mapsurf^.h);
       
   236 
       
   237     while dstp < stopp do
       
   238         begin
       
   239         // copy all from before dstp to after (or just fill the gap if smaller)
       
   240         c:= min(dstp-srcp, stopp-dstp);
       
   241         // worried about size of c with humongous maps? don't be:
       
   242         //  the OS wouldn't have allowed allocation of object with size > max of SizeInt anyway
       
   243         move(srcp^, dstp^, c);
       
   244         inc(dstp, c);
       
   245         end;
       
   246 
       
   247     // cleanup
   218     srcp:= nil;
   248     srcp:= nil;
   219     SDL_UnlockSurface(ltsurf);
   249     dstp:= nil;
   220     SDL_FreeSurface(ltsurf);
   250     stopp:= nil;
   221 
   251     SDL_UnlockSurface(mapsurf);
   222     // from now on only copy pixels within Surface
       
   223 
       
   224     // start reading from position 0, but continue writing at dstp
       
   225     srcp:= Surface^.pixels;
       
   226     // copy all the already written lines at once for that get number of written bytes so far
       
   227     c:= dstp - srcp; // effectively same as c:= lth * Surface^.pitch;
       
   228     // also figure out the remainder again
       
   229     modc:= (Surface^.h mod lth) * Surface^.pitch; // effectivle same as modc:= (Surface^.pitch * Surface^.h) mod c;
       
   230 
       
   231     // last y where a full copy may be written to
       
   232     lastfull:= Surface^.h - lth;
       
   233 
       
   234     // copy filled area down
       
   235     while y <= lastfull do
       
   236         begin
       
   237         move(srcp^, dstp^, c);
       
   238         inc(srcp, c);
       
   239         inc(dstp, c);
       
   240         inc(y, lth);
       
   241         end;
       
   242 
       
   243     // if it didn't fit perfectly, copy remainder
       
   244     if modc > 0 then
       
   245         begin
       
   246         move(srcp^, dstp^, modc);
       
   247         end;
       
   248 
       
   249     SDL_UnlockSurface(Surface);
       
   250 
   252 
   251     // freed in freeModule() below
   253     // freed in freeModule() below
   252     LandBackSurface:= LoadDataImage(ptCurrTheme, 'LandBackTex', ifIgnoreCaps or ifTransparent);
   254     LandBackSurface:= LoadDataImage(ptCurrTheme, 'LandBackTex', ifIgnoreCaps or ifTransparent);
   253     if (LandBackSurface <> nil) and GrayScale then Surface2GrayScale(LandBackSurface);
   255     if (LandBackSurface <> nil) and GrayScale then Surface2GrayScale(LandBackSurface);
   254 end;
   256 end;