问题: 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 image 14 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 below 25 // may be ignored by builds, and the only obviously safe option 26 // 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的逻辑坐标(屏幕左上角的,右、下),而位图的逻辑坐标是左下角(右、上),所有变换在位图的显示变换中有一个倒置的操作。
即:。
skia~setDIBitsToDevice~Windows,布布扣,bubuko.com
时间: 2024-10-10 03:41:08