rotateSurface90Degrees function

Pointer<SdlSurface> rotateSurface90Degrees(
  1. Pointer<SdlSurface> src,
  2. int numClockwiseTurns
)

Implementation

Pointer<SdlSurface> rotateSurface90Degrees(
    Pointer<SdlSurface> src, int numClockwiseTurns) {
  int row, col, newWidth, newHeight;
  int bpp, bpr;
  Pointer<SdlSurface> dst;
  int normalizedClockwiseTurns;
  /* Has to be a valid surface pointer and be a Nbit surface where n is divisible by 8 */
  if (src == nullptr) {
    print('NULL source surface');
    return nullptr;
  }
  var details = sdlGetPixelFormatDetails(src.ref.format);
  if (details == nullptr) {
    print('NULL source surface format');
    return nullptr;
  }
  if ((details.ref.bitsPerPixel % 8) != 0) {
//  if ((src.ref.format.ref.bitsPerPixel % 8) != 0) {
    print('Invalid source surface bit depth');
    return nullptr;
  }

  /* normalize numClockwiseTurns */
  normalizedClockwiseTurns = (numClockwiseTurns % 4);
  if (normalizedClockwiseTurns < 0) {
    normalizedClockwiseTurns += 4;
  }

  /* If turns are even, our new width/height will be the same as the source surface */
  if (normalizedClockwiseTurns % 2 != 0) {
    newWidth = src.ref.h;
    newHeight = src.ref.w;
  } else {
    newWidth = src.ref.w;
    newHeight = src.ref.h;
  }
  dst = sdlCreateSurface(newWidth, newHeight, 0);
  //dst = sdlCreateRgbSurface(
  //    src.ref.flags,
  //    newWidth,
  //    newHeight,
  //    src.ref.format.ref.bitsPerPixel,
  //    src.ref.format.ref.rmask,
  //    src.ref.format.ref.gmask,
  //    src.ref.format.ref.bmask,
  //    src.ref.format.ref.amask);
  if (dst == nullptr) {
    print('Could not create destination surface');
    return nullptr;
  }

  //if (SDL_MUSTLOCK(src)) {
  sdlLockSurface(src);
  //}
  //if (SDL_MUSTLOCK(dst)) {
  sdlLockSurface(dst);
  //}

  /* Calculate byte-per-pixel */
  bpp = details.ref.bitsPerPixel ~/ 8;
//  bpp = src.ref.format.ref.bitsPerPixel ~/ 8;

  Pointer<Pointer<Uint8>> srcBuf = calloc<Pointer<Uint8>>();
  Pointer<Pointer<Uint8>> dstBuf = calloc<Pointer<Uint8>>();

  print(normalizedClockwiseTurns);
  switch (normalizedClockwiseTurns) {
    case 0: /* Make a copy of the surface */
      {
        /* Unfortunately SDL_BlitSurface cannot be used to make a copy of the surface
			since it does not preserve alpha. */

        if (src.ref.pitch == dst.ref.pitch) {
          /* If the pitch is the same for both surfaces, the memory can be copied all at once. */
          sdlMemcpy(
              dst.ref.pixels, src.ref.pixels, (src.ref.h * src.ref.pitch));
        } else {
          /* If the pitch differs, copy each row separately */
          srcBuf.value = src.ref.pixels.cast<Uint8>();
          dstBuf.value = dst.ref.pixels.cast<Uint8>();
          bpr = src.ref.w * bpp;
          for (row = 0; row < src.ref.h; row++) {
            sdlMemcpy(dstBuf.value, srcBuf.value, bpr);
            srcBuf.value = srcBuf.value + src.ref.pitch;
            dstBuf.value = dstBuf.value + dst.ref.pitch;
          }
        }
      }
      break;

    /* rotate clockwise */
    case 1: /* rotated 90 degrees clockwise */
      {
        for (row = 0; row < src.ref.h; ++row) {
          srcBuf.value = src.ref.pixels.cast<Uint8>();
          srcBuf.value = srcBuf.value + row * src.ref.pitch;
          dstBuf.value = dst.ref.pixels.cast<Uint8>();
          dstBuf.value = dstBuf.value + (dst.ref.w - row - 1) * bpp;
          for (col = 0; col < src.ref.w; ++col) {
            sdlMemcpy(dstBuf.value, srcBuf.value, bpp);
            srcBuf.value = srcBuf.value + bpp;
            dstBuf.value = dstBuf.value + dst.ref.pitch;
          }
        }
      }
      break;

    case 2: /* rotated 180 degrees clockwise */
      {
        for (row = 0; row < src.ref.h; ++row) {
          srcBuf.value = src.ref.pixels.cast<Uint8>();
          srcBuf.value = srcBuf.value + row * src.ref.pitch;
          dstBuf.value = dst.ref.pixels.cast<Uint8>();
          dstBuf.value = dstBuf.value +
              (dst.ref.h - row - 1) * dst.ref.pitch +
              (dst.ref.w - 1) * bpp;
          for (col = 0; col < src.ref.w; ++col) {
            sdlMemcpy(dstBuf.value, srcBuf.value, bpp);
            srcBuf.value = srcBuf.value + bpp;
            dstBuf.value = dstBuf.value - bpp;
          }
        }
      }
      break;

    case 3: /* rotated 270 degrees clockwise */
      {
        for (row = 0; row < src.ref.h; ++row) {
          srcBuf.value = src.ref.pixels.cast<Uint8>();
          srcBuf.value = srcBuf.value + row * src.ref.pitch;
          dstBuf.value = dst.ref.pixels.cast<Uint8>();
          dstBuf.value =
              dstBuf.value + (row * bpp) + ((dst.ref.h - 1) * dst.ref.pitch);
          for (col = 0; col < src.ref.w; ++col) {
            sdlMemcpy(dstBuf.value, srcBuf.value, bpp);
            srcBuf.value = srcBuf.value + bpp;
            dstBuf.value = dstBuf.value - dst.ref.pitch;
          }
        }
      }
      break;
  }
  /* end switch */

  //if (SDL_MUSTLOCK(src)) {
  sdlUnlockSurface(src);
  //}
  //if (SDL_MUSTLOCK(dst)) {
  sdlUnlockSurface(dst);
  //}
  calloc.free(srcBuf);
  calloc.free(dstBuf);
  return dst;
}