unsafe private bool CheckARGB8888_() { if (surface == IntPtr.Zero) { return(false); } SDL.SDL_Surface * surface_ = (SDL.SDL_Surface *)surface; SDL.SDL_PixelFormat *format = (SDL.SDL_PixelFormat *)surface_->format; if (format == null) { return(false); } if (SDL.SDL_BYTEORDER.Equals(SDL.SDL_BIG_ENDIAN)) { return(format->BitsPerPixel == 32 && format->Rmask == 0xff000000 && format->Gmask == 0x00ff0000 && format->Bmask == 0x0000ff00 && format->Amask == 0x000000ff ); } else { return(format->BitsPerPixel == 32 && format->Rmask == 0x000000ff && format->Gmask == 0x0000ff00 && format->Bmask == 0x00ff0000 && format->Amask == 0xff000000 ); } }
unsafe private Color4ub GetPixel_(int x, int y) { SDL.SDL_Surface * surface_ = (SDL.SDL_Surface *)surface; SDL.SDL_PixelFormat *format = (SDL.SDL_PixelFormat *)surface_->format; uint u = 0; switch (format->BitsPerPixel) { case 16: u = *(ushort *)((byte *)GetPixels_() + y * surface_->pitch + x * 2); break; case 24: byte *p = ((byte *)GetPixels_()) + (y * surface_->pitch + x * 3); u = (uint)(p[2] << 16 | p[1] << 8 | p[0]); break; case 32: u = *(uint *)((byte *)GetPixels_() + y * surface_->pitch + x * 4); break; } return(new Color4ub((byte)((u & format->Rmask) >> format->Rshift), (byte)((u & format->Gmask) >> format->Gshift), (byte)((u & format->Bmask) >> format->Bshift), (byte)((u & format->Amask) >> format->Ashift))); }
/// <summary> /// パレットから色を取得 /// </summary> /// <param name="i">パレットのインデックス</param> private unsafe Color4ub GetPaletteColor(int i) { SDL.SDL_Surface * surface_ = (SDL.SDL_Surface *)surface; SDL.SDL_PixelFormat *format = (SDL.SDL_PixelFormat *)surface_->format; SDL.SDL_Palette * palette = (SDL.SDL_Palette *)format->palette; SDL.SDL_Color * colors = (SDL.SDL_Color *)palette->colors; global::System.Diagnostics.Debug.Assert(i < palette->ncolors); return(new Color4ub(colors[i].r, colors[i].g, colors[i].b, 0xff)); }
unsafe private bool getAlpha() { if (surface == IntPtr.Zero) { return(false); } SDL.SDL_Surface * surface_ = (SDL.SDL_Surface *)surface; SDL.SDL_PixelFormat *format = (SDL.SDL_PixelFormat *)surface_->format; return(format != null && format->Amask != 0); // alpha maskを持つならば、alpha channelがあるのだろう。 }
/// <summary> /// SDL_Surfaceに設定されているカラーキーを返すためのヘルパ /// </summary> /// <returns></returns> unsafe private long?getColorKey() { SDL.SDL_Surface * surface_ = (SDL.SDL_Surface *)surface; SDL.SDL_PixelFormat *format = (SDL.SDL_PixelFormat *)surface_->format; // 転送元カラーキーが設定されていないのでnullを返す if ((surface_->flags & SDL.SDL_SRCCOLORKEY) == 0) { return(null); } uint ckey = format->colorkey; return(ckey); }
unsafe private Color4ub GetPixel_(int x, int y) { SDL.SDL_Surface * surface_ = (SDL.SDL_Surface *)surface; SDL.SDL_PixelFormat *format = (SDL.SDL_PixelFormat *)surface_->format; uint u = 0; int i; switch (format->BitsPerPixel) { /* * case 1: * i = *((byte*)GetPixels_() + y * surface_->pitch + x / 8); * return GetPaletteColor((i >> (x % 8)) & 0x01); * case 2: * i = *((byte*)GetPixels_() + y * surface_->pitch + x / 4); * return GetPaletteColor((i >> (x % 4) * 2) & 0x03); * case 4: * i = *((byte*)GetPixels_() + y * surface_->pitch + x / 2); * return GetPaletteColor((i >> (x % 2) * 4) & 0x0f); */ // ↑SDLがそもそもサポートしてないようなので要らない。 case 8: i = *((byte *)GetPixels_() + y * surface_->pitch + x); return(GetPaletteColor(i)); case 16: u = *(ushort *)((byte *)GetPixels_() + y * surface_->pitch + x * 2); break; case 24: byte *p = ((byte *)GetPixels_()) + (y * surface_->pitch + x * 3); u = (uint)(p[2] << 16 | p[1] << 8 | p[0]); break; case 32: u = *(uint *)((byte *)GetPixels_() + y * surface_->pitch + x * 4); break; } return(new Color4ub((byte)((u & format->Rmask) >> format->Rshift), (byte)((u & format->Gmask) >> format->Gshift), (byte)((u & format->Bmask) >> format->Bshift), (byte)((u & format->Amask) >> format->Ashift))); }
private static unsafe IntPtr INTERNAL_convertSurfaceFormat(IntPtr surface) { IntPtr result = surface; unsafe { SDL_Surface * surPtr = (SDL_Surface *)surface; SDL.SDL_PixelFormat *pixelFormatPtr = (SDL.SDL_PixelFormat *)surPtr->format; // SurfaceFormat.Color is SDL_PIXELFORMAT_ABGR8888 if (pixelFormatPtr->format != SDL.SDL_PIXELFORMAT_ABGR8888) { // Create a properly formatted copy, free the old surface result = SDL.SDL_ConvertSurfaceFormat(surface, SDL.SDL_PIXELFORMAT_ABGR8888, 0); SDL.SDL_FreeSurface(surface); } } return(result); }
/// <summary>サーフェースに文字列を描画します。</summary> /// <remarks> /// サーフェースをnewしたくないときは、こちらを使うよろし。 /// </remarks> public void DrawBlendedUnicode(Surface surface, string str) { CacheSystem.OnAccess(this); if (font != IntPtr.Zero) { SDL.TTF_SetFontStyle(font, style); IntPtr image = SDL.TTF_RenderUNICODE_Blended(font, str, color); RateCheck(ref image); // debug目的でsurfaceの種類を調べるためのコード unsafe { SDL.SDL_PixelFormat *format = (SDL.SDL_PixelFormat *)((SDL.SDL_Surface *)image)->format; int alpha = format->alpha; } surface.SDL_Surface = image; // setSurface(image); } else { surface.SDL_Surface = IntPtr.Zero; // setSurface(IntPtr.Zero); } }
unsafe private void RateCheck(ref IntPtr image) { // rateが1でなければ、サーフェースを縮小しなければならない。 if (rate == 1) { return; } // ok if (image == IntPtr.Zero) { return; } // surfaceの作成に失敗しちょる SDL.SDL_Surface *image_ = (SDL.SDL_Surface *)image; // 1/rateのサイズのサーフェースを作ることからはじめよう int ix, iy; ix = image_->w; iy = image_->h; ix /= rate; iy /= rate; // これが rateで割り切れない時のことは知らネ if (ix == 0 || iy == 0) { return; } SDL.SDL_PixelFormat *format = (SDL.SDL_PixelFormat *)image_->format; bool bAlpha = (format->BitsPerPixel == 32); /* * SDL_ttfの返すサーフェースは、αつきなら32bpp,αなしなら8bppと * 決まっちょる */ // SDLには縮小する関数が無いので、 // DIBを作って、それを縮小することにする // SDL_gfxを持ってきてもいいのだが、そこまで大がかりでもないので.. IntPtr image2; if (Surface.CreateDIBstatic(out image2, image_->w, image_->h, bAlpha) != 0) { return; // 作成失敗 } if (bAlpha) { // αを無効化しておかないとARGB→ARGBのbltで // αを考慮して転送しやがる SDL.SDL_SetAlpha(image, 0, 0); } if (SDL.SDL_BlitSurface(image, IntPtr.Zero, image2, IntPtr.Zero) != 0) { SDL.SDL_FreeSurface(image2); return; // 転送失敗 } IntPtr image2s; // ix,iyが2^nの場合、フォントが表示されないのでiy+1していた。 // 原因が分かったら戻すこと→わかったので戻した。 if (Surface.CreateDIBstatic(out image2s, ix, iy, bAlpha) != 0) { SDL.SDL_FreeSurface(image2); SDL.SDL_FreeSurface(image2s); return; // 作成失敗 } // 縮小するためにlockする if (SDL.SDL_LockSurface(image2) != 0) { SDL.SDL_FreeSurface(image2); SDL.SDL_FreeSurface(image2s); return; // lock失敗 } if (SDL.SDL_LockSurface(image2s) != 0) { SDL.SDL_UnlockSurface(image2s); SDL.SDL_FreeSurface(image2); SDL.SDL_FreeSurface(image2s); return; // lock失敗 } SDL.SDL_Surface *image2_, image2s_; image2_ = (SDL.SDL_Surface *)image2; image2s_ = (SDL.SDL_Surface *)image2s; // 縮小ルーチン if (bAlpha) { uint rt, gt, bt, at; uint rr = (uint)(rate * rate); uint *pixels1 = (uint *)image2_->pixels; uint *pixels2 = (uint *)image2s_->pixels; for (int y = 0; y < iy /*image2s_->h*/; ++y) { uint xx = 0; for (int x = 0; x < ix /*image2s_->w*/; ++x) { // ピクセルの平均を求める uint r, g, b, a; uint *pixels1t = pixels1; r = g = b = a = 0; for (int j = 0; j < rate; ++j) { for (int i = 0; i < rate; ++i) { uint p = pixels1t[xx + i]; format = (SDL.SDL_PixelFormat *)image2_->format; rt = p & format->Rmask; rt >>= format->Rshift; r += rt; gt = p & format->Gmask; gt >>= format->Gshift; g += gt; bt = p & format->Bmask; bt >>= format->Bshift; b += bt; at = p & format->Amask; at >>= format->Ashift; a += at; } pixels1t = (uint *)(((byte *)pixels1) + image2_->pitch); } r /= rr; g /= rr; b /= rr; a /= rr; // ↑これだと切り捨てすぎかも.. // format = (SDL.SDL_PixelFormat*)image2_->format; format = (SDL.SDL_PixelFormat *)image2s_->format; pixels2[x] = (r << format->Rshift) + (g << format->Gshift) + (b << format->Bshift) + (a << format->Ashift); xx += (uint)rate; } pixels1 = (uint *)(((byte *)pixels1) + image2_->pitch * rate); pixels2 = (uint *)(((byte *)pixels2) + image2s_->pitch); } } else { // 24bppのはず uint rr = (uint)(rate * rate); byte *pixels1 = (byte *)image2_->pixels; byte *pixels2 = (byte *)image2s_->pixels; for (int y = 0; y < image2s_->h; ++y) { uint xx, x2; xx = x2 = 0; for (int x = 0; x < image2s_->w; ++x) { // ピクセルの平均を求める uint r, g, b; byte *pixels1t = pixels1; r = g = b = 0; for (int j = 0; j < rate; ++j) { uint xxx = xx; for (int i = 0; i < rate; ++i) { r += pixels1t[xxx + i + 0]; g += pixels1t[xxx + i + 1]; b += pixels1t[xxx + i + 2]; xxx += 3; } pixels1t = pixels1 + image2_->pitch; } r /= rr; g /= rr; b /= rr; pixels2[x2 + 0] = (byte)r; pixels2[x2 + 1] = (byte)g; pixels2[x2 + 2] = (byte)b; x2 += 3; xx += (uint)(3 * rate); } pixels1 = pixels1 + image2_->pitch * rate; pixels2 = pixels2 + image2s_->pitch; } } // さすがにunlockは失敗しないでそ.. SDL.SDL_UnlockSurface(image2); SDL.SDL_UnlockSurface(image2s); SDL.SDL_FreeSurface(image); SDL.SDL_FreeSurface(image2); image = image2s; // 書き換えて返す }