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