BREWアプリを Windows へ移植(7)
IBitmap の実装について。
IBitmap は IDIB にキャスト出来る必要があるので、少々変則的になりますが、基本は同じです。
まず、このインターフェースは定義されていないので、定義してやります。
struct IBitmap : public IDIB{ };
IDIB は IDIBVtbl ではなくて、IBitmapVtbl へのポインタが入っているので、これで十分です。
で、次は WinBitmap の実装です。
class WinBitmap : public IBitmap{ public: WinBitmap(); ~WinBitmap(); private: static uint32 AddRef(IBitmap* po); static uint32 Release(IBitmap* po); static int QueryInterface(IBitmap* po, AEECLSID, void **); static NativeColor RGBToNative(IBitmap *po, RGBVAL rgb); static RGBVAL NativeToRGB(IBitmap *po, NativeColor clr); static int DrawPixel(IBitmap *po, unsigned x, unsigned y, NativeColor color, AEERasterOp rop); static int GetPixel(IBitmap *po, unsigned x, unsigned y, NativeColor *pColor); static int SetPixels(IBitmap *po, unsigned cnt, AEEPoint *pPoint, NativeColor color, AEERasterOp rop); static int DrawHScanline(IBitmap *po, unsigned y, unsigned xMin, unsigned xMax, NativeColor color, AEERasterOp rop); static int FillRect(IBitmap *po, const AEERect *prc, NativeColor color, AEERasterOp rop); static int BltIn(IBitmap *po, int xDst, int yDst, int dx, int dy, IBitmap *pSrc, int xSrc, int ySrc, AEERasterOp rop); static int BltOut(IBitmap *po, int xDst, int yDst, int dx, int dy, IBitmap *pDst, int xSrc, int ySrc, AEERasterOp rop); static int GetInfo(IBitmap *po, AEEBitmapInfo *pinfo, int nSize); static int CreateCompatibleBitmap(IBitmap *po, IBitmap **ppIBitmap, uint16 w, uint16 h); static int SetTransparencyColor(IBitmap *po, NativeColor color); static int GetTransparencyColor(IBitmap *po, NativeColor *pColor); private: IBitmapVtbl _vtbl; uint32 _ref; AEEDIB _dib; };
IDIB のメンバは、外部から書き換えられる可能性があるので、pBmp 等のデータは内部で持っておく必要があります。そのために、IDIB のメンバとは別に、AEEDIB をメンバに保持しておくことにします。
WinBitmap::WinBitmap(){ // これは反則かな? ::memset( this , 0 , sizeof( WinBitmap ) ); _ref = 1; _vtbl.AddRef = &AddRef; _vtbl.Release = &Release; _vtbl.QueryInterface = &QueryInterface; _vtbl.RGBToNative = &RGBToNative; _vtbl.NativeToRGB = &NativeToRGB; _vtbl.DrawPixel = &DrawPixel; _vtbl.GetPixel = &GetPixel; _vtbl.SetPixels = &SetPixels; _vtbl.DrawHScanline = &DrawHScanline; _vtbl.FillRect = &FillRect; _vtbl.BltIn = &BltIn; _vtbl.BltOut = &BltOut; _vtbl.GetInfo = &GetInfo; _vtbl.CreateCompatibleBitmap = &CreateCompatibleBitmap; _vtbl.SetTransparencyColor = &SetTransparencyColor; _vtbl.GetTransparencyColor = &GetTransparencyColor; this->pvt = &_vtbl; } WinBitmap::~WinBitmap(){ delete _dib.pBmp; } uint32 WinBitmap::AddRef(IBitmap* po){ return ++*1( | ((uint16)(g & 0xfc) << (6-3)) | (b >> 3); return nc; } RGBVAL WinBitmap::NativeToRGB(IBitmap *po, NativeColor clr){ int r = (clr & 0xf800) >> (11-3); int g = (clr & 0x07e0) >> (6-3); int b = (clr & 0x001f) << 3; return MAKE_RGB( r , g , b ); } int WinBitmap::DrawPixel(IBitmap *po, unsigned x, unsigned y, NativeColor color, AEERasterOp rop){ // 範囲外チェックは行わない。 *(uint16*)(po->pBmp + y * po->nPitch + x) = (uint16)color; return SUCCESS; } int WinBitmap::GetPixel(IBitmap *po, unsigned x, unsigned y, NativeColor *pColor){ // null チェック、範囲外チェックは行わない。 (*pColor) = *(uint16*)(po->pBmp + y * po->nPitch + x); return SUCCESS; } int WinBitmap::SetPixels(IBitmap *po, unsigned cnt, AEEPoint *pPoint, NativeColor color, AEERasterOp rop){ throw std::exception( "not implemented" ); } int WinBitmap::DrawHScanline(IBitmap *po, unsigned y, unsigned xMin, unsigned xMax, NativeColor color, AEERasterOp rop){ throw std::exception( "not implemented" ); } int WinBitmap::FillRect(IBitmap *po, const AEERect *prc, NativeColor color, AEERasterOp rop){ throw std::exception( "not implemented" ); } int WinBitmap::BltIn(IBitmap *po, int xDst, int yDst, int w, int h, IBitmap *pSrc, int xSrc, int ySrc, AEERasterOp rop){ // ここで描画処理を行う。 // 最低でも 4bit, 8bit インデックスのパレットと、RGB565 の転送処理はサポートするべきだろう。 return SUCCESS; } int WinBitmap::BltOut(IBitmap *po, int xDst, int yDst, int dx, int dy, IBitmap *pDst, int xSrc, int ySrc, AEERasterOp rop){ return IBITMAP_BltIn( pDst , xDst , yDst , dx , dy , po , xSrc , ySrc , rop ); } int WinBitmap::GetInfo(IBitmap *po, AEEBitmapInfo *pinfo, int nSize){ if( nSize == sizeof( AEEBitmapInfo ) && pinfo != NULL ){ pinfo->cx = po->cx; pinfo->cy = po->cy; pinfo->nDepth = po->nDepth; return SUCCESS; } return EUNSUPPORTED; } int WinBitmap::CreateCompatibleBitmap(IBitmap *po, IBitmap **ppIBitmap, uint16 w, uint16 h){ WinBitmap* pBmp = (WinBitmap*)(*ppIBitmap); pBmp = new WinBitmap(); const int depth = 16; // 形式は RGB565 pBmp->cx = w; pBmp->cy = h; pBmp->nDepth = depth; pBmp->nColorScheme = IDIB_COLORSCHEME_565; // pitch を求める(4byteでアラインされている) int pitch = (((w * depth + 7) >> 3) + 3) & ~3; pBmp->nPitch = pitch; if( h > 0 ){ pBmp->pBmp = new byte[ pitch * h ]; pBmp->_dib.pBmp = pBmp->pBmp; pBmp->_dib.nPitch = pitch; } (*ppIBitmap) = pBmp; return SUCCESS; } // ほんとは _dib.ncTransparent にもセットするべきかも……。 int WinBitmap::SetTransparencyColor(IBitmap *po, NativeColor color){ po->ncTransparent = color; return SUCCESS; } int WinBitmap::GetTransparencyColor(IBitmap *po, NativeColor *pColor){ (*pColor) = po->ncTransparent; return SUCCESS; }
画像の形式と NativeColor は RGB565 として作っています。これは現在の端末の多くが RGB565 であるからです。
描画処理についてはかなり長いので省略しました。
これで IBitmap の実装は終了です。次は IDisplay かな……。
*1:WinBitmap*)po)->_ref; } uint32 WinBitmap::Release(IBitmap* po){ WinBitmap* pMe = (WinBitmap*)po; if( --pMe->_ref == 0 ){ delete pMe; return 0; } return pMe->_ref; } int WinBitmap::QueryInterface(IBitmap* po, AEECLSID id, void ** pp){ if( IQI_SELF( po , id , pp , AEECLSID_DIB ) != NULL ){ IBASE_AddRef( (IBase*)(*pp) ); return SUCCESS; }else{ return ECLASSNOTSUPPORT; } } // NativeColor は RGB565 としておく NativeColor WinBitmap::RGBToNative(IBitmap *po, RGBVAL rgb){ int r,g,b; r = (rgb >> 8) & 0xff; g = (rgb >> 16) & 0xff; b = (rgb >> 24) & 0xff; NativeColor nc = )((uint16)(r & 0xf8) << (11-3