From 34c6043014527747dcc3fee65f66d0686a74f3fd Mon Sep 17 00:00:00 2001 From: jacksonmj Date: Thu, 19 Jan 2012 22:00:49 +0000 Subject: transform_save should check wall coordinates against size in blocks, not the actual size Fixes crash when rotating a section of wall that is wider than YRES Conflicts: src/save.c diff --git a/src/save.c b/src/save.c index a73440c..ffd2605 100644 --- a/src/save.c +++ b/src/save.c @@ -2170,3 +2170,139 @@ void *build_thumb(int *size, int bzip2) *size = j; return d; } + +void *transform_save(void *odata, int *size, matrix2d transform, vector2d translate) +{ + void *ndata; + unsigned char (*bmapo)[XRES/CELL] = calloc((YRES/CELL)*(XRES/CELL), sizeof(unsigned char)); + unsigned char (*bmapn)[XRES/CELL] = calloc((YRES/CELL)*(XRES/CELL), sizeof(unsigned char)); + particle *partst = calloc(sizeof(particle), NPART); + sign *signst = calloc(MAXSIGNS, sizeof(sign)); + unsigned (*pmapt)[XRES] = calloc(YRES*XRES, sizeof(unsigned)); + float (*fvxo)[XRES/CELL] = calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); + float (*fvyo)[XRES/CELL] = calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); + float (*fvxn)[XRES/CELL] = calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); + float (*fvyn)[XRES/CELL] = calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); + float (*vxo)[XRES/CELL] = calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); + float (*vyo)[XRES/CELL] = calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); + float (*vxn)[XRES/CELL] = calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); + float (*vyn)[XRES/CELL] = calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); + float (*pvo)[XRES/CELL] = calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); + float (*pvn)[XRES/CELL] = calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); + int i, x, y, nx, ny, w, h, nw, nh; + vector2d pos, tmp, ctl, cbr; + vector2d cornerso[4]; + unsigned char *odatac = odata; + if (parse_save(odata, *size, 0, 0, 0, bmapo, vxo, vyo, pvo, fvxo, fvyo, signst, partst, pmapt)) + { + free(bmapo); + free(bmapn); + free(partst); + free(signst); + free(pmapt); + free(fvxo); + free(fvyo); + free(fvxn); + free(fvyn); + free(vxo); + free(vyo); + free(vxn); + free(vyn); + free(pvo); + free(pvn); + return odata; + } + w = odatac[6]*CELL; + h = odatac[7]*CELL; + // undo any translation caused by rotation + cornerso[0] = v2d_new(0,0); + cornerso[1] = v2d_new(w-1,0); + cornerso[2] = v2d_new(0,h-1); + cornerso[3] = v2d_new(w-1,h-1); + for (i=0; i<4; i++) + { + tmp = m2d_multiply_v2d(transform,cornerso[i]); + if (i==0) ctl = cbr = tmp; // top left, bottom right corner + if (tmp.xcbr.x) cbr.x = tmp.x; + if (tmp.y>cbr.y) cbr.y = tmp.y; + } + // casting as int doesn't quite do what we want with negative numbers, so use floor() + tmp = v2d_new(floor(ctl.x+0.5f),floor(ctl.y+0.5f)); + translate = v2d_sub(translate,tmp); + nw = floor(cbr.x+0.5f)-floor(ctl.x+0.5f)+1; + nh = floor(cbr.y+0.5f)-floor(ctl.y+0.5f)+1; + if (nw>XRES) nw = XRES; + if (nh>YRES) nh = YRES; + // rotate and translate signs, parts, walls + for (i=0; i=nw || ny<0 || ny>=nh) + { + signst[i].text[0] = 0; + continue; + } + signst[i].x = nx; + signst[i].y = ny; + } + for (i=0; i=nw || ny<0 || ny>=nh) + { + partst[i].type = PT_NONE; + continue; + } + partst[i].x = nx; + partst[i].y = ny; + } + for (y=0; y=nw/CELL || ny<0 || ny>=nh/CELL) + continue; + if (bmapo[y][x]) + { + bmapn[ny][nx] = bmapo[y][x]; + if (bmapo[y][x]==WL_FAN) + { + fvxn[ny][nx] = fvxo[y][x]; + fvyn[ny][nx] = fvyo[y][x]; + } + } + vxn[ny][nx] = vxo[y][x]; + vyn[ny][nx] = vyo[y][x]; + pvn[ny][nx] = pvo[y][x]; + } + ndata = build_save(size,0,0,nw,nh,bmapn,vxn,vyn,pvn,fvxn,fvyn,signst,partst); + free(bmapo); + free(bmapn); + free(partst); + free(signst); + free(pmapt); + free(fvxo); + free(fvyo); + free(fvxn); + free(fvyn); + free(vxo); + free(vyo); + free(vxn); + free(vyn); + free(pvo); + free(pvn); + return ndata; +} \ No newline at end of file -- cgit v0.9.2-21-gd62e