SDL2笔记06_SDL2透明背景窗口_win10_使用cairo和sdl_texture在透明背景上绘制(偏色)

  1. 这篇git提供了简单的cairo绘制到sdlTexture上的方法
    https://gist.github.com/sprae/607305450c51ccc482b78bdadadb9af6链接

  2. 配置makefile

         cmake_minimum_required(VERSION 3.19)
         project(main)
         set(SDL2_DIR G:/Xubuntu_Work_Space/From_Xubuntu/codeTest_2019_2_21/SDL2/win/SDL2-devel-2.0.14-mingw/SDL2-2.0.14/x86_64-w64-mingw32)
         set(SDL2_IMAGE_DIR G:/Xubuntu_Work_Space/From_Xubuntu/codeTest_2019_2_21/SDL2/win/SDL2_image-devel-2.0.5-mingw/SDL2_image-2.0.5/x86_64-w64-mingw32)
    
         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -lmingw32")
         set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")
    
         # GTK3的include
         include_directories(
                 H:/mysoft/clion/clionWorkSpace/gtk+364/include
                 H:/mysoft/clion/clionWorkSpace/gtk+364/include/gtk-3.0
                 H:/mysoft/clion/clionWorkSpace/gtk+364/include/cairo
                 H:/mysoft/clion/clionWorkSpace/gtk+364/include/gdk
                 H:/mysoft/clion/clionWorkSpace/gtk+364/include/glib-2.0
                 H:/mysoft/clion/clionWorkSpace/gtk+364/include/pango-1.0
                 H:/mysoft/clion/clionWorkSpace/gtk+364/include/atk-1.0
                 H:/mysoft/clion/clionWorkSpace/gtk+364/include/gdk-pixbuf-2.0
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/glib-2.0/include
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/gtk-3.0/include
         )
    
         # SDL2的include
         include_directories(
                 ${SDL2_DIR}/include/SDL2
                 ${SDL2_IMAGE_DIR}/include/SDL2
         )
    
         link_directories(
                 ${SDL2_DIR}/lib
                 ${SDL2_IMAGE_DIR}/lib
         )
    
         link_libraries(
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libatk-1.0.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libcairo-gobject.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libcairo-script-interpreter.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libcairo.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libcroco-0.6.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libffi.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libfontconfig.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libfreetype.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libgailutil-3.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libgdk-3.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libgdk_pixbuf-2.0.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libgio-2.0.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libglib-2.0.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libgmodule-2.0.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libgobject-2.0.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libgthread-2.0.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libgtk-3.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libjasper.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libjpeg.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/liblzma.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libpango-1.0.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libpangocairo-1.0.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libpangoft2-1.0.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libpangowin32-1.0.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libpixman-1.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libpng.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libpng15.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/librsvg-2.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libtiff.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libtiffxx.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libxml2.dll.a
                 H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libz.dll.a
         )
    
         set(SOURCE_FILES main.cpp TransparentWindow.hpp)
         add_executable(main ${SOURCE_FILES})
    
         target_link_libraries(main mingw32 SDL2main SDL2 SDL2_image)
    
  3. 第一步:windows将SDL_Window背景设为透明,可直接调用windowColorKey代码

        COLORREF defaultTransparentColor = RGB(255, 0, 255);
    
         bool windowColorKey(SDL_Window *window, COLORREF colorKey) {
             SDL_SysWMinfo wmInfo;
             SDL_VERSION(&wmInfo.version);  // Initialize wmInfo
             SDL_GetWindowWMInfo(window, &wmInfo);
             HWND hWnd = wmInfo.info.win.window;
    
             // Change window type to layered
             SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
    
             // Set transparency color
             return SetLayeredWindowAttributes(hWnd, colorKey, 0, LWA_COLORKEY);
         }
  4. 第二步,绑定cairosdlTexture,有两种方式可用(缺点:当画笔大小为1的时候颜色不对,不知怎么解决

    1. 方式一 : 建立cairo, 建立texture, 在cairo上画图,然后update过去

       // 方式一 : 建立cairo, 建立texture, 在cairo上画图,然后update过去
       int windowWidth = 640, windowHeight = 480;
       surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, windowWidth, windowWidth);
       cr = cairo_create(surface);
       cairo_set_line_width(cr, 1);
       // 画个圆角矩形, 发现颜色不对
       cairo_set_source_rgba(cr, 1, 0, 0, 1);
       draw_round_rectangle(cr, 100, 100, 180, 120, 10);
      
       cairo_stroke(cr);
       unsigned char *data = cairo_image_surface_get_data(surface);
      
       SDL_Texture *texture;
       SDL_Rect rect = {.x=0, .y=0, .w=windowWidth, .h=windowHeight};
      
       texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, windowWidth,
                                   windowHeight);
       // 设置texture为混合模式
       SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
       int widthPitch = windowWidth << 2;
       // 更新过去
       SDL_UpdateTexture(texture, &rect, data, widthPitch);
      1. 方式二:直接建立sdlTexture然后从sdlTexture的像素数据建立cairo

          // 方式二 : 建立texture, 从texture的像素数据建立cairo, 直接画到texture上去
          // 可能比方式一快, 我没读过cairo_image_surface_create_for_data的源码,不敢妄下定论
          SDL_Texture *texture;
          SDL_Rect rect = {.x=0, .y=0, .w=640, .h=480};
        
          texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, rect.w, rect.h);
          SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
        
          void *pixel;
          int pitch = 4*rect.w; // 一行的像素字节  ARGB32=4 byte, w = 640
          SDL_LockTexture(texture, &rect, &pixel, &pitch);
          surface = cairo_image_surface_create_for_data(
                  (unsigned char*) pixel,
                  CAIRO_FORMAT_ARGB32, rect.w, rect.h, pitch
                  );
          SDL_UnlockTexture(texture);
          cr = cairo_create(surface);
          cairo_set_line_width(cr, 10);
          cairo_set_source_rgb(cr, 255, 0, 0);
          draw_round_rectangle(cr, 100, 100, 50, 60, 10);
          cairo_stroke(cr);
  5. 完整代码

         #include <SDL.h>
         #include <cairo.h>
         #include <SDL_syswm.h>
         #include "windows.h"
    
         COLORREF defaultTransparentColor = RGB(255, 0, 255);
    
         bool windowColorKey(SDL_Window *window, COLORREF colorKey) {
             SDL_SysWMinfo wmInfo;
             SDL_VERSION(&wmInfo.version);  // Initialize wmInfo
             SDL_GetWindowWMInfo(window, &wmInfo);
             HWND hWnd = wmInfo.info.win.window;
    
             // Change window type to layered
             SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
    
             // Set transparency color
             return SetLayeredWindowAttributes(hWnd, colorKey, 0, LWA_COLORKEY);
         }
    
         static void
         draw_round_rectangle(cairo_t *cr,
                              double x, double y,
                              double width, double height, double r) {
             cairo_move_to(cr, x + r, y);
             cairo_line_to(cr, x + width - r, y);
    
             cairo_move_to(cr, x + width, y + r);
             cairo_line_to(cr, x + width, y + height - r);
    
             cairo_move_to(cr, x + width - r, y + height);
             cairo_line_to(cr, x + r, y + height);
    
             cairo_move_to(cr, x, y + height - r);
             cairo_line_to(cr, x, y + r);
    
             cairo_arc(cr, x + r, y + r, r, M_PI, 3 * M_PI / 2.0);
             cairo_arc(cr, x + width - r, y + r, r, 3 * M_PI / 2, 2 * M_PI);
             cairo_arc(cr, x + width - r, y + height - r, r, 0, M_PI / 2);
             cairo_arc(cr, x + r, y + height - r, r, M_PI / 2, M_PI);
         }
    
         int main(int argc, char *argv[]) {
             SDL_Init(SDL_INIT_VIDEO);
    
             SDL_Window *window;
             SDL_Renderer *renderer;
             SDL_CreateWindowAndRenderer(640, 480, SDL_WINDOW_ALWAYS_ON_TOP, &window, &renderer);
             windowColorKey(window, defaultTransparentColor);
             SDL_SetWindowTitle(window, "Cairo test");
    
             cairo_surface_t *surface;
             cairo_t *cr;
         #if 1
             // 方式一 : 建立cairo, 建立texture, 在cairo上画图,然后update过去
             int windowWidth = 640, windowHeight = 480;
             surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, windowWidth, windowWidth);
             cr = cairo_create(surface);
             cairo_set_line_width(cr, 1);
             // 画个圆角矩形, 发现颜色不对
             cairo_set_source_rgba(cr, 1, 0, 0, 1);
             draw_round_rectangle(cr, 100, 100, 180, 120, 10);
    
             cairo_stroke(cr);
             unsigned char *data = cairo_image_surface_get_data(surface);
    
             SDL_Texture *texture;
             SDL_Rect rect = {.x=0, .y=0, .w=windowWidth, .h=windowHeight};
    
             texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, windowWidth,
                                         windowHeight);
             // 设置texture为混合模式
             SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
             int widthPitch = windowWidth << 2;
             // 更新过去
             SDL_UpdateTexture(texture, &rect, data, widthPitch);
         #else
             // 方式二 : 建立texture, 从texture的像素数据建立cairo, 直接画到texture上去
             // 可能比方式一快, 我没读过cairo_image_surface_create_for_data的源码,不敢妄下定论
             SDL_Texture *texture;
             SDL_Rect rect = {.x=0, .y=0, .w=640, .h=480};
    
             texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, rect.w, rect.h);
             SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
    
             void *pixel;
             int pitch = 4*rect.w; // 一行的像素字节  ARGB32=4 byte, w = 640
             SDL_LockTexture(texture, &rect, &pixel, &pitch);
             surface = cairo_image_surface_create_for_data(
                     (unsigned char*) pixel,
                     CAIRO_FORMAT_ARGB32, rect.w, rect.h, pitch
                     );
             SDL_UnlockTexture(texture);
             cr = cairo_create(surface);
             cairo_set_line_width(cr, 10);
             cairo_set_source_rgb(cr, 255, 0, 0);
             draw_round_rectangle(cr, 100, 100, 50, 60, 10);
             cairo_stroke(cr);
         #endif
    
             SDL_Event event;
             bool is_working = true;
             while (is_working) {
                 while (SDL_PollEvent(&event)) {
                     switch (event.type) {
                         case SDL_QUIT:
                             SDL_DestroyWindow(window);
                             SDL_DestroyRenderer(renderer);
                             SDL_Quit();
                             is_working = false;
                             break;
                     }
                 }
    
                 SDL_SetRenderDrawColor(renderer, 255, 0, 255, 255);
                 SDL_RenderClear(renderer);
                 SDL_RenderCopy(renderer, texture, NULL, NULL);
                 SDL_RenderPresent(renderer);
                 SDL_Delay(66);
             }
    
             return 0;
         }
    
  6. 运行截图
    在这里插入图片描述

SDL2学习笔记 文章被收录于专栏

记录个人笔记

全部评论

相关推荐

11-08 10:39
门头沟学院 C++
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务