2025年7月25日 星期五

簡單利用 sdl 載入 jpeg 檔, 描繪中文字, 線/圓繪圖

// sudo apt install libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev
// g++ sdldraw.cpp -lSDL2 -lSDL2_image -lSDL2_ttf && ./a.out
// sdldraw.cpp
#include <unistd.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
void drawcircle(SDL_Renderer *renderer, float cx, float cy, float r) {
  const int max_segments = 32;// large enough to smooth circle
  const double d_theta = M_PI * 2 / max_segments;
  double theta = d_theta;// 2nd θ
  int px = cx + r;// 1st θ = 0
  int py = cy;
  int lines = max_segments - 1;// lines to draw
  while (lines -- > 0) {
    int nx = cx + r*cosf(theta);
    int ny = cy + r*sinf(theta);
    SDL_RenderDrawLine(renderer, px, py, nx , ny);
    theta += d_theta;// next θ
    px = nx;
    py = ny;
  }
  SDL_RenderDrawLine(renderer, px, py, cx + r , cy);// close loop
}
int main(int argc, char** argv) {
  if (SDL_Init(SDL_INIT_EVERYTHING) == 0) {
    SDL_Window *xwin = SDL_CreateWindow("繪圖程式", 0, 0, 800, 600, SDL_WINDOW_RESIZABLE);
    if (xwin) {
      SDL_Renderer *renderer = SDL_CreateRenderer(xwin, -1, SDL_RENDERER_ACCELERATED);
      if (renderer) {
        SDL_Texture *bgPicture = IMG_LoadTexture(renderer, "snap.jpg");
        SDL_RenderCopy(renderer, bgPicture, NULL, NULL);
        SDL_RenderPresent(renderer);// show current image        
        SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
        const char *message = "準心";
        const SDL_Color colorGreen = {.r=0, .g=255, .b=0, .a=255};
        TTF_Font *ukai = (TTF_Init() == 0) ? TTF_OpenFont("./fonts/ukai.ttc", 32) : nullptr;
        SDL_Rect target_cross;
        SDL_Surface *msgSurface = ukai ? TTF_RenderUTF8_Blended(ukai, message, colorGreen) : nullptr;
        SDL_Texture *msgTexture = SDL_CreateTextureFromSurface(renderer, msgSurface);
        int &radius = target_cross.w; // alias
        if (msgSurface) {
          target_cross.w = msgSurface->w;
          target_cross.h = msgSurface->h;
          SDL_FreeSurface(msgSurface);
        }
        SDL_Event event;
        while (true) { // event loop begin
          usleep(1000);
          SDL_PollEvent(&event);
          if (event.type == SDL_QUIT) break;
          if (event.type == SDL_MOUSEBUTTONDOWN) {
            if (event.button.button == SDL_BUTTON_LEFT) {
              SDL_RenderCopy(renderer, bgPicture, NULL, NULL);
              int px = event.button.x;
              int py = event.button.y;
              if (msgTexture) {
                target_cross.x = px - target_cross.w/2;
                target_cross.y = py - target_cross.h/2;
                drawcircle(renderer, px, py, radius);// green circle
                SDL_RenderDrawLine(renderer, px, py - radius, px, py + radius);// red cross
                SDL_RenderDrawLine(renderer, px - radius, py, px + radius, py);
                SDL_RenderCopy(renderer, msgTexture, NULL, &target_cross);
              }
              SDL_RenderPresent(renderer);
              printf("Left mouse is down @(%d,%d)\n", px, py);
            }
          } else if (event.type == SDL_WINDOWEVENT) {
            if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
              SDL_RenderCopy(renderer, bgPicture, NULL, NULL);
              SDL_RenderPresent(renderer);
            }
          }
        }
        if (bgPicture)  SDL_DestroyTexture(bgPicture);
        if (msgTexture) SDL_DestroyTexture(msgTexture);
        if (ukai) TTF_CloseFont(ukai);
        SDL_DestroyRenderer(renderer);
      }
      SDL_DestroyWindow(xwin);
      TTF_Quit();
    }
    SDL_Quit();
  }
  return 0;
}

後記. 2025.07.29 改用 sdl3, 程式庫事先要從原始碼編譯並安裝, 上述程式修改並重新編譯:
// g++ sdl3draw.cpp -lSDL3 -lSDL3_image -lSDL3_ttf && ./a.out
// sdl3draw.cpp
#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include <SDL3/SDL.h>
#include <SDL3_image/SDL_image.h>
#include <SDL3_ttf/SDL_ttf.h>
void drawcircle(SDL_Renderer *renderer, float cx, float cy, float r) {
  const int max_segments = 32;
  const double d_theta = M_PI * 2 / max_segments;
  double theta = d_theta;
  int px = cx + r;
  int py = cy;
  int lines = max_segments - 1;
  while (lines -- > 0) {
    int nx = cx + r*cosf(theta);
    int ny = cy + r*sinf(theta);
    SDL_RenderLine(renderer, px, py, nx , ny);
    theta += d_theta;
    px = nx;
    py = ny;
  }
  SDL_RenderLine(renderer, px, py, cx + r , cy);// close loop
}
int main(int argc, char** argv) {
  if (SDL_Init(SDL_INIT_EVENTS)) {
    SDL_Window *xwin = SDL_CreateWindow("繪圖程式", 800, 600, SDL_WINDOW_RESIZABLE);
    if (xwin) {
      SDL_Renderer *renderer = SDL_CreateRenderer(xwin, nullptr);
      if (renderer) {
        SDL_Texture *bgPicture = IMG_LoadTexture(renderer, "snap.jpg");
        SDL_RenderTexture(renderer, bgPicture, NULL, NULL);
        SDL_RenderPresent(renderer);
        SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
        const char *message = "準心";
        const SDL_Color colorGreen = {.r=0, .g=255, .b=0, .a=255};
        TTF_Font *ukai = (TTF_Init()) ? TTF_OpenFont("./fonts/ukai.ttc", 32) : nullptr;
        SDL_FRect target_cross;
        SDL_Surface *msgSurface = ukai ? TTF_RenderText_Blended(ukai, message, 0, colorGreen) : nullptr;
        SDL_Texture *msgTexture = SDL_CreateTextureFromSurface(renderer, msgSurface);
        float &radius = target_cross.w; // alias
        if (msgSurface) {
          target_cross.w = msgSurface->w;
          target_cross.h = msgSurface->h;
          SDL_DestroySurface(msgSurface);
        }
        SDL_Event event;
        while (true) {
          usleep(1000);
          SDL_PollEvent(&event);
          if (event.type == SDL_EVENT_QUIT) break;
          if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
            if (event.button.button == SDL_BUTTON_LEFT) {
              SDL_RenderTexture(renderer, bgPicture, NULL, NULL);
              int px = event.button.x;
              int py = event.button.y;
              if (msgTexture) {
                target_cross.x = px - target_cross.w/2;
                target_cross.y = py - target_cross.h/2;
                drawcircle(renderer, px, py, radius);// green circle
                SDL_RenderLine(renderer, px, py - radius, px, py + radius);// red cross
                SDL_RenderLine(renderer, px - radius, py, px + radius, py);
                SDL_RenderTexture(renderer, msgTexture, NULL, &target_cross);
              }
              SDL_RenderPresent(renderer);
              printf("Left mouse is down @(%d,%d)\n", px, py);
            }
          } else if (event.window.type == SDL_EVENT_WINDOW_RESIZED) {
            SDL_RenderTexture(renderer, bgPicture, NULL, NULL);
            SDL_RenderPresent(renderer);
          }
        }
        if (bgPicture)  SDL_DestroyTexture(bgPicture);
        if (msgTexture) SDL_DestroyTexture(msgTexture);
        if (ukai) TTF_CloseFont(ukai);
        SDL_DestroyRenderer(renderer);
      }
      SDL_DestroyWindow(xwin);
      TTF_Quit();
    }
    SDL_Quit();
  }
  return 0;
}

沒有留言:

張貼留言

使用 vscode 時, 改善滑鼠反應遲鈍的問題

按下 Manage 按鈕 Settings, 輸入 server, 儘量避免選項被啟用, 讓選項儘量 disable 或 off 例如: Http: Proxy Strict SSL 不要勾選 C_Cpp: Code Folding  選擇 disable  C_Cpp: Sug...