Skia绘图库

2D向量图形处理函数库


如何引入Skia项目

<p>打开VS,创建一个空项目,在项目目录中,创建“Skia”文件夹</p> <ol> <li>将Skia的include复制到“Skia”文件夹内</li> <li>将Skia的out/Static复制到“Skia”文件夹内</li> <li>项目 -&gt; VC++ 目录 -&gt; 包含目录 添加 $(ProjectDir)Skia</li> <li>项目 -&gt; 链接器 -&gt; 附加库目录 添加 $(ProjectDir)Skia\Static</li> <li>在调试时发现,Skia源码中min、max与C++内置宏冲突 解决办法:项目 -&gt; C/C++ -&gt; 预处理器 -&gt; 预处理器定义 添加 NOMINMAX 注意:在此之前,必须已添加.h或.cpp文件</li> <li>项目 -&gt; 常规 -&gt; C++ 语言标准 -&gt; C++ 17 标准以上</li> <li>项目 -&gt; C/C++ -&gt; 预处理器 -&gt; 所有命令行 -&gt; 运行库 多线程 (/MT)</li> </ol> <p><em>一个简单的例子</em></p> <pre><code class="language-cpp">#include &amp;lt;Windows.h&amp;gt; #include &amp;quot;include/core/SkSurface.h&amp;quot; #include &amp;quot;include/core/SkCanvas.h&amp;quot; #pragma comment(lib, &amp;quot;Skia.lib&amp;quot;) LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: { break; } case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &amp;amp;ps); RECT rt; GetClientRect(hWnd, &amp;amp;rt); int bmpw = rt.right - rt.left; int bmph = rt.bottom - rt.top; const size_t bmpSize = sizeof(BITMAPINFOHEADER) + bmpw * bmph * sizeof(uint32_t); BITMAPINFO* bmpInfo = (BITMAPINFO*)new BYTE[bmpSize](); bmpInfo-&amp;gt;bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmpInfo-&amp;gt;bmiHeader.biWidth = bmpw; // biHeight为正时,bmpInfo-&amp;gt;bmiColors像素是从图片的左下角开始。 // biHeight为负时,bmpInfo-&amp;gt;bmiColors像素是从图片的左上角开始。 // 这是BMP的格式中指定。而skia绘制需要从上到下。 bmpInfo-&amp;gt;bmiHeader.biHeight = -bmph; bmpInfo-&amp;gt;bmiHeader.biPlanes = 1; bmpInfo-&amp;gt;bmiHeader.biBitCount = 32; //图片每像素32位 bmpInfo-&amp;gt;bmiHeader.biCompression = BI_RGB; void* pixels = bmpInfo-&amp;gt;bmiColors; //图片像素位置指针 // kBGRA_8888_SkColorType,这参数决定SkCanvas绘图像素的格式 // BGRA,ARGB,就好象cpu大端,小端之类的。 SkImageInfo info = SkImageInfo::Make(bmpw, bmph, kBGRA_8888_SkColorType, kPremul_SkAlphaType); sk_sp&amp;lt;SkSurface&amp;gt; surface = SkSurfaces::WrapPixels(info, pixels, bmpw * sizeof(uint32_t)); SkCanvas* canvas = surface-&amp;gt;getCanvas(); canvas-&amp;gt;clear(SK_ColorWHITE); //填充白色背景 SkPaint paint; paint.setStrokeWidth(1); paint.setARGB(0xff, 0xff, 0, 0); SkRect rect = SkRect::MakeXYWH(20, 20, 80, 80); canvas-&amp;gt;drawRect(rect, paint); StretchDIBits(hdc, 0, 0, bmpw, bmph, 0, 0, bmpw, bmph, pixels, bmpInfo, DIB_RGB_COLORS, SRCCOPY); //整张图绘制到DC delete[] bmpInfo; EndPaint(hWnd, &amp;amp;ps); break; } case WM_LBUTTONDOWN: { break; } case WM_DESTROY: PostQuitMessage(0); return 0; default: break; } return DefWindowProcW(hWnd, uMsg, wParam, lParam); } int main() { // 注册窗口类 WNDCLASSEXW wcex = { 0 }; wcex.cbSize = sizeof(WNDCLASSEXW); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = [](HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -&amp;gt; LRESULT { SetWindowLongPtrW(hWnd, GWLP_WNDPROC, (LONG_PTR)WndProc); // 指向新的窗口过程 return WndProc(hWnd, uMsg, wParam, lParam); }; wcex.hInstance = GetModuleHandleW(nullptr); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.hCursor = LoadCursorW(nullptr, IDC_ARROW); wcex.lpszClassName = L&amp;quot;Window.h2Gui.123&amp;quot;; RegisterClassExW(&amp;amp;wcex); // 创建窗口 HWND hWnd = CreateWindowExW( 0, L&amp;quot;Window.h2Gui.123&amp;quot;, L&amp;quot;Window.Skia.Test&amp;quot;, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 200, 200, 800, 600, nullptr, nullptr, GetModuleHandleW(nullptr), nullptr); UpdateWindow(hWnd); // 建立消息循环 MSG msg = { 0 }; while (GetMessageW(&amp;amp;msg, nullptr, 0, 0) &amp;gt; 0) { TranslateMessage(&amp;amp;msg); DispatchMessageW(&amp;amp;msg); } return (int)msg.wParam; }</code></pre>

页面列表

ITEM_HTML