首页 > 代码库 > skia~setDIBitsToDevice~Windows

skia~setDIBitsToDevice~Windows

问题: skia是一个图形库,本身没有在设备上作图的能力,可以通过提供的SkView类,参考实现对不同平台设备上作画。

  SkOsWindow_Win.cpp: onPaint方法中提供了在windows平台设备上作图的接口,SetDIBitsToDevice();  

 1 SetDIBitsToDevice( 2                 HDC hdc,                 // 设备环境句柄。 3                 int XDest,               // 指定目标矩形左上角的X轴坐标,按逻辑单位表示坐标。 4                 int YDest,               // 指字目标矩形左上角的Y轴坐标,按逻辑单位表示坐标。 5                 DWORD dwWidth,           // 指定DIB的宽度,按逻辑单位表示宽度。 6                 DWORD dwHeight,          // 指定DIB的高度,按逻辑单位表示高度。 7                 int XSrc,                // 指定DIB位图左下角的X轴坐标,按逻辑单位表示坐标 8                 int YSrc,                // 指定DIB位图左下角的Y轴坐标,按逻辑单位表示坐标。 9                 UINT uStartScan,         // 指定DIB中的起始扫描线。10                 UINT cScanLines,         // 指定参数lpvBits指向的数组中包含的DIB扫描线数目。11                 CONST VOID *lpvBits,     // 指向存储DIB颜色数据的字节类型数组的指针。12                 CONST BITMAPINFO *lpbmi, // 指向BITMAPINFO结构的指针,该结构包含有关DIB的信息。13                 UINT fuColorUse          // 指向BITMAPINFO结构中的成员bmiColors是否包含明确的RGB值或对调色板进行索引的值。14                 )
SetDIBitsToDevice
 1 void SkOSWindow::doPaint(void* ctx) { 2     this->update(NULL); 3  4     if (kNone_BackEndType == fAttached) 5     { 6         HDC hdc = (HDC)ctx; 7         const SkBitmap& bitmap = this->getBitmap(); 8  9         BITMAPINFO bmi;10         memset(&bmi, 0, sizeof(bmi));11         bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);12         bmi.bmiHeader.biWidth       = bitmap.width();13         bmi.bmiHeader.biHeight      = -bitmap.height(); // top-down image14         bmi.bmiHeader.biPlanes      = 1;15         bmi.bmiHeader.biBitCount    = 32;16         bmi.bmiHeader.biCompression = BI_RGB;17         bmi.bmiHeader.biSizeImage   = 0;18 19         //20         // Do the SetDIBitsToDevice.21         //22         // TODO(wjmaclean):23         //       Fix this call to handle SkBitmaps that have rowBytes != width,24         //       i.e. may have padding at the end of lines. The SkASSERT below25         //       may be ignored by builds, and the only obviously safe option26         //       seems to be to copy the bitmap to a temporary (contiguous)27         //       buffer before passing to SetDIBitsToDevice().28         SkASSERT(bitmap.width() * bitmap.bytesPerPixel() == bitmap.rowBytes());29         bitmap.lockPixels();30         int ret = SetDIBitsToDevice(hdc,31             0, 0,32             bitmap.width(), bitmap.height(),33             0, 0,34             0, bitmap.height(),35             bitmap.getPixels(),36             &bmi,37             DIB_RGB_COLORS);38         (void)ret; // we‘re ignoring potential failures for now.39         bitmap.unlockPixels();40     }41 }
SkOSWindow_win.cpp

 

 1 //建立逻辑坐标系 2         paint.setARGB(255, 255, 0, 0); 3         paint.setStrokeWidth(3); 4         canvas->drawLine(0, 0, bitmap->width(), 0, paint); 5         canvas->drawLine(0, 0, 0, bitmap->height(), paint); 6  7         paint.setARGB(255, 255, 200, 200); 8         canvas->drawText("X/2", 4, bitmap->width() / 2 + 10, 10, paint); 9         canvas->drawText("Y/2", 4, 5, bitmap->height() / 2, paint);10 11         paint.setARGB(255, 255, 200, 0);12         canvas->drawText("X", 2, bitmap->width()-10, 10, paint);13         canvas->drawText("Y", 2, 5, bitmap->height(), paint);
建立坐标系
1 //三个概念 窗口区域、画布canvas区域、位图bitmap区域2             SetDIBitsToDevice(hdc,3                 0, 0,    //指定逻辑坐标系(即:画布canavs)的坐标原点,左上角(即:右、下为正方向),4                 bitmap->width(), bitmap->height(),5                 0, 0,6                 0,            //画布中起始显示位置7                 bitmap->height(), bitmap->getPixels(), //扫描的起点与扫描的高度8                 &lpbmi, DIB_RGB_COLORS);
三个区域

 

  

   

 

 

通过设置用画笔填充真个绘制区域发现,canvas的绘制区域,一直都是bitmap的区域,而,

在位图的变换中,canvas的逻辑坐标(屏幕左上角的,右、下),而位图的逻辑坐标是左下角(右、上),所有变换在位图的显示变换中有一个倒置的操作。

即: