zoukankan      html  css  js  c++  java
  • 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);
        
      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. 运行截图

  • 相关阅读:
    Go 语言简介(下)— 特性
    Array.length vs Array.prototype.length
    【转】javascript Object使用Array的方法
    【转】大话程序猿眼里的高并发架构
    【转】The magic behind array length property
    【转】Build Your own Simplified AngularJS in 200 Lines of JavaScript
    【转】在 2016 年做 PHP 开发是一种什么样的体验?(一)
    【转】大话程序猿眼里的高并发
    php通过token验证表单重复提交
    windows 杀进程软件
  • 原文地址:https://www.cnblogs.com/majiao61/p/15201070.html
Copyright © 2011-2022 走看看