/// <summary> /// GetTexture/GetTextureSolid用のhelper /// </summary> /// <remarks> /// isBlendedの値に応じて、DrawBlendedUnicodeとDrawTextureSolidとを切り替えて描画する。 /// </remarks> /// <param name="letter"></param> /// <param name="style"></param> /// <param name="isBlended"></param> /// <returns></returns> private ITexture GetTextureHelper(char letter, int style, bool isBlended) { if (loader == null) { return(null); // うんこーヽ(`Д´)ノ } int index = int.MaxValue; // fail safe // 探してみる for (int i = 0; i < fonts.Count; ++i) { if ((fonts[i].Letter == letter) && (fonts[i].Style == style) && (fonts[i].FontLoader == loader) && (fonts[i].FontNo == fontNo)) { // みっけ! index = i; goto Exit; } } // 見つからなかったので生成してみる ITexture texture = factory(); if (texture == null) { return(null); // factory設定されとらん(´ω`) } Font font = loader.GetFont(fontNo); if (font != null) { Surface surface = isBlended ? font.DrawBlendedUnicode(letter.ToString()) : font.DrawSolidUnicode(letter.ToString()); texture.SetSurface(surface); surface.Dispose(); // 解放しとかなきゃ } else { // なんやー。読み込まれへんかったわ return(null); // 生成失敗 } // 生成できた。次に空き場所を確定させる if (fonts.Count == max) { // 場所が空いてないので、一番最後に参照された // オブジェクトを解放する long t = long.MaxValue; for (int i = 0; i < fonts.Count; ++i) { if (fonts[i].LastAccessTime < t) { t = fonts[i].LastAccessTime; index = i; } } ITexture tt = fonts[index].Texture; if (tt != null) { tt.Dispose(); // 一応解放しておく } } else { index = fonts.Count; fonts.Add(new Info()); // ひとつ確保 } // このlocal copy、最適化で消えるやろか? Info info = new Info(); info.Letter = letter; info.FontLoader = loader; info.FontNo = fontNo; info.Style = style; info.Texture = texture; fonts[index] = info; Exit: // これ参照したので、時刻をずらしておく。 fonts[index].LastAccessTime = ++time; return(fonts[index].Texture); }
/// <summary> /// Screenの画像をサーフェスにする。 /// ただし、画面の上に載せている.NET Frameworkのコントロールは /// キャプチャできないので注意。 /// </summary> public Surface GetSurface() { Surface surface = new Surface(); if (surface.CreateDIB(Width, Height, false) != YanesdkResult.NoError) { surface.Dispose(); return(null); } // 読み出し元を設定。 // デフォルトでバックバッファだが念のため設定。 //Gl.glReadBuffer(Gl.GL_FRONT); Gl.glReadBuffer(Gl.GL_BACK); //* Gl.glReadPixels(0, 0, surface.Width, surface.Height, surface.Alpha ? Gl.GL_RGBA : Gl.GL_RGB, Gl.GL_UNSIGNED_BYTE, surface.Pixels); // glReadPixels()で取得したピクセルが上下逆で、 // 反転させる方法が分からなかったので、 // 仕方なくこちら側で反転させるコードを書いてみた。(´ω`) unsafe { int height = surface.Height; int pitch = surface.Pitch; byte *pixels = (byte *)surface.Pixels; byte *buffer = (byte *)Marshal.AllocHGlobal(pitch); for (int y = 0; y < height / 2; y++) { byte *y1 = pixels + y * pitch; byte *y2 = pixels + (height - y - 1) * pitch; CopyMemory(buffer, y1, (uint)pitch); CopyMemory(y1, y2, (uint)pitch); CopyMemory(y2, buffer, (uint)pitch); } Marshal.FreeHGlobal((IntPtr)buffer); } /*/ * * // ↓こっちの方が微妙に重い。 * // 排他処理かなにかでもしてるのかも? * unsafe { * byte* p = (byte*)surface.Pixels; * uint format = surface.Alpha ? Gl.GL_RGBA : Gl.GL_RGB; * for (int y = 0, h = surface.Height; y < h; y++) { * // 1行ずつ読む。 * Gl.glReadPixels(0, h - y - 1, surface.Width, 1, * format, Gl.GL_UNSIGNED_BYTE, (IntPtr)p); * p += surface.Pitch; * } * } * * //*/ return(surface); }
/// <summary> /// Screenの画像をサーフェスにする。 /// ただし、画面の上に載せている.NET Frameworkのコントロールは /// キャプチャできないので注意。 /// </summary> public Surface GetSurface() { Surface surface = new Surface(); if (surface.CreateDIB(Width, Height, false) != YanesdkResult.NoError) { surface.Dispose(); return null; } // 読み出し元を設定。 // デフォルトでバックバッファだが念のため設定。 //Gl.glReadBuffer(Gl.GL_FRONT); Gl.glReadBuffer(Gl.GL_BACK); //* Gl.glReadPixels(0, 0, surface.Width, surface.Height, surface.Alpha ? Gl.GL_RGBA : Gl.GL_RGB, Gl.GL_UNSIGNED_BYTE, surface.Pixels); // glReadPixels()で取得したピクセルが上下逆で、 // 反転させる方法が分からなかったので、 // 仕方なくこちら側で反転させるコードを書いてみた。(´ω`) unsafe { int height = surface.Height; int pitch = surface.Pitch; byte* pixels = (byte*)surface.Pixels; byte* buffer = (byte*)Marshal.AllocHGlobal(pitch); for (int y = 0; y < height / 2; y++) { byte* y1 = pixels + y * pitch; byte* y2 = pixels + (height - y - 1) * pitch; CopyMemory(buffer, y1, (uint)pitch); CopyMemory(y1, y2, (uint)pitch); CopyMemory(y2, buffer, (uint)pitch); } Marshal.FreeHGlobal((IntPtr)buffer); } /*/ // ↓こっちの方が微妙に重い。 // 排他処理かなにかでもしてるのかも? unsafe { byte* p = (byte*)surface.Pixels; uint format = surface.Alpha ? Gl.GL_RGBA : Gl.GL_RGB; for (int y = 0, h = surface.Height; y < h; y++) { // 1行ずつ読む。 Gl.glReadPixels(0, h - y - 1, surface.Width, 1, format, Gl.GL_UNSIGNED_BYTE, (IntPtr)p); p += surface.Pitch; } } //*/ return surface; }