SDL2笔记06_SDL2透明背景窗口_windows10_使用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);
      
    2. 方式二:直接建立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. 运行截图
    在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值