9#include "DrawUtils.hpp" 
   10#include "RootDisplay.hpp" 
   12char* musicData = NULL;
 
   16    int sdl2Flags = SDL_INIT_GAMECONTROLLER;
 
   18    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | sdl2Flags) < 0)
 
   20        printf(
"Failed to initialize SDL2 drawing library: %s\n", SDL_GetError());
 
   24    CST_SetQualityHint(
"linear");
 
   27        printf(
"Failed to initialize TTF font library: %s\n", SDL_GetError());
 
   34    SDLFlags |= SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;
 
   35    windowFlags |= SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
 
   37    root->window = SDL_CreateWindow(
 
   38        NULL, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
 
   39        SCREEN_WIDTH, SCREEN_HEIGHT, windowFlags);
 
   40    root->renderer = SDL_CreateRenderer(root->window, -1, SDLFlags);
 
   42    SDL_SetRenderTarget(root->renderer, NULL);
 
   44    if (root->renderer == NULL || root->window == NULL)
 
   50    RootDisplay::mainDisplay = root;
 
   52    for (
int i = 0; i < SDL_NumJoysticks(); i++)
 
   54        if (SDL_JoystickOpen(i) == NULL)
 
   56            printf(
"SDL_JoystickOpen: %s\n", SDL_GetError());
 
   63    root->needsRender.type = SDL_USEREVENT;
 
   73    SDL_DestroyWindow(RootDisplay::mainDisplay->window);
 
   74    SDL_QuitSubSystem(SDL_INIT_VIDEO);
 
   77    auto root = RootDisplay::mainDisplay;
 
   78    if (root->music != NULL)
 
   80        Mix_FreeMusic(root->music);
 
   83    if (musicData != NULL)
 
   95#if !defined(SIMPLE_SDL2) 
   96    Mix_Init(MIX_INIT_MP3);
 
   97    if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 4096) != 0) {
 
   98        printf(
"Failed to initialize SDL2 mixer: %s\n", Mix_GetError());
 
  103    const char* filename = 
"background.mp3";
 
  104    FILE* f = fopen(filename, 
"rb");
 
  108    fseek(f, 0, SEEK_END);
 
  109    long fsize = ftell(f);
 
  115    fseek(f, 0, SEEK_SET);
 
  117    musicData = (
char*)(malloc(fsize + 1));
 
  118    fread(musicData, fsize, 1, f);
 
  121    musicData[fsize] = 0;
 
  123    root->music = Mix_LoadMUS_RW(SDL_RWFromMem(musicData, fsize), 1);
 
  128void CST_GetRGBA(Uint32 pixel, SDL_PixelFormat* format, CST_Color* cstColor)
 
  130    SDL_GetRGBA(pixel, format, &cstColor->r, &cstColor->g, &cstColor->b, &cstColor->a);
 
  134bool CST_SavePNG(CST_Texture* texture, 
const char* file_name)
 
  136    auto renderer = RootDisplay::mainDisplay->renderer;
 
  137    SDL_Texture* target = SDL_GetRenderTarget(renderer);
 
  138    SDL_SetRenderTarget(renderer, texture);
 
  139    printf(
"Error: %s\n", SDL_GetError());
 
  141    SDL_QueryTexture(texture, NULL, NULL, &width, &height);
 
  142    SDL_Surface* surface = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0);
 
  143    SDL_RenderReadPixels(renderer, NULL, surface->format->format, surface->pixels, surface->pitch);
 
  144    IMG_SavePNG(surface, file_name);
 
  145    SDL_FreeSurface(surface);
 
  146    SDL_SetRenderTarget(renderer, target);
 
  152#if !defined(SIMPLE_SDL2) 
  155        Mix_VolumeMusic(0.85 *  MIX_MAX_VOLUME);
 
  156        Mix_PlayMusic(root->music, -1);
 
  157        Mix_VolumeMusic(0.85 *  MIX_MAX_VOLUME);
 
  162void CST_RenderPresent(CST_Renderer* renderer)
 
  166    CST_SetDrawColorRGBA(renderer, 0, 0, 0, 255);
 
  167    CST_Rect rect = { 0, 240, 40, 240 };
 
  168    CST_FillRect(renderer, &rect);
 
  169    CST_Rect rect2 = { 360, 240, 40, 240 };
 
  170    CST_FillRect(renderer, &rect2);
 
  171    CST_Rect rect3 = { 0, 240, 400, 240 };
 
  172    CST_DrawRect(renderer, &rect3);
 
  175    SDL_RenderPresent(renderer);
 
  178void CST_FreeSurface(CST_Surface* surface)
 
  180    SDL_FreeSurface(surface);
 
  183void CST_RenderCopy(CST_Renderer* dest, CST_Texture* src, CST_Rect* src_rect, CST_Rect* dest_rect)
 
  185    SDL_RenderCopy(dest, src, src_rect, dest_rect);
 
  188void CST_RenderCopyRotate(CST_Renderer* dest, CST_Texture* src, CST_Rect* src_rect, CST_Rect* dest_rect, 
int angle)
 
  190    SDL_RenderCopyEx(dest, src, src_rect, dest_rect, angle, NULL, SDL_FLIP_NONE);
 
  193void CST_SetDrawColor(CST_Renderer* renderer, CST_Color c)
 
  195    CST_SetDrawColorRGBA(renderer, c.r, c.g, c.b, c.a);
 
  198void CST_SetDrawColorRGBA(CST_Renderer* renderer, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
 
  200    SDL_SetRenderDrawColor(renderer, r, g, b, a);
 
  203void CST_FillRect(CST_Renderer* renderer, CST_Rect* dimens)
 
  205    SDL_RenderFillRect(renderer, dimens);
 
  208void CST_DrawRect(CST_Renderer* renderer, CST_Rect* dimens)
 
  210    SDL_RenderDrawRect(renderer, dimens);
 
  213void CST_DrawLine(CST_Renderer* renderer, 
int x, 
int y, 
int w, 
int h)
 
  215    SDL_RenderDrawLine(renderer, x, y, w, h);
 
  218void CST_SetDrawBlend(CST_Renderer* renderer, 
bool enabled)
 
  220    SDL_BlendMode mode = enabled ? SDL_BLENDMODE_BLEND : SDL_BLENDMODE_NONE;
 
  221    SDL_SetRenderDrawBlendMode(renderer, mode);
 
  224void CST_QueryTexture(CST_Texture* texture, 
int* w, 
int* h)
 
  226    SDL_QueryTexture(texture, 
nullptr, 
nullptr, w, h);
 
  229CST_Texture* CST_CreateTextureFromSurface(CST_Renderer* renderer, CST_Surface* surface, 
bool isAccessible )
 
  231    return SDL_CreateTextureFromSurface(renderer, surface); 
 
  234void CST_SetQualityHint(
const char* quality)
 
  236    SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, quality);
 
  239void CST_filledCircleRGBA(CST_Renderer* renderer, uint32_t x, uint32_t y, uint32_t radius, uint32_t r, uint32_t g, uint32_t b, uint32_t a)
 
  241    #if !defined(SIMPLE_SDL2) 
  243    filledCircleRGBA(renderer, x, y, radius, r, g, b, a);
 
  247void CST_SetWindowSize(CST_Window* window, 
int w, 
int h)
 
  250    SDL_SetWindowSize(window, w, h);
 
  254void CST_Delay(
int time)
 
  261    return SDL_GetTicks();
 
  266    auto joystick = SDL_JoystickFromInstanceID(event->event.jdevice.which);
 
  267    if (joystick && SDL_JoystickGetAttached(joystick)) {
 
  268        SDL_JoystickRumble(joystick, 0x400, 0x400, 200);
 
  272void CST_SetCursor(
int cursor)
 
  274    if (cursor == CST_CURSOR_NONE) {
 
  275        SDL_ShowCursor(SDL_DISABLE);
 
  279    SDL_ShowCursor(SDL_ENABLE);
 
  280    auto sdlCursor = SDL_SYSTEM_CURSOR_ARROW;
 
  281    if (cursor == CST_CURSOR_HAND) {
 
  282        sdlCursor = SDL_SYSTEM_CURSOR_HAND;
 
  283    } 
else if (cursor == CST_CURSOR_TEXT) {
 
  284        sdlCursor = SDL_SYSTEM_CURSOR_IBEAM;
 
  285    } 
else if (cursor == CST_CURSOR_SPINNER) {
 
  286        sdlCursor = SDL_SYSTEM_CURSOR_WAIT;
 
  289    SDL_SetCursor(SDL_CreateSystemCursor(sdlCursor));
 
  292bool CST_isRectOffscreen(CST_Rect* rect)
 
  295    if (rect->x > SCREEN_WIDTH + 10 || rect->y > SCREEN_HEIGHT + 10)
 
  300    if (rect->x + rect->w < -10 || rect->y + rect->h < -10)
 
  307float CST_GetDpiScale()
 
  310    SDL_GetWindowSize(RootDisplay::window, &w, &h);
 
  312    SDL_GL_GetDrawableSize(RootDisplay::window, &dw, &dh);
 
  313    return (dw / (
float) w);
 
  316void CST_SetWindowTitle(
const char* title)
 
  318    SDL_SetWindowTitle(RootDisplay::mainDisplay->window, title);
 
  321void CST_roundedBoxRGBA (
 
  322    CST_Renderer *renderer,
 
  323    Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
 
  324    Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a
 
  326    #if !defined(SIMPLE_SDL2) 
  328    roundedBoxRGBA(renderer, x1, y1, x2, y2, rad, r, g, b, a);
 
  332void CST_roundedRectangleRGBA (
 
  333    CST_Renderer *renderer,
 
  334    Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
 
  335    Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a
 
  337    #if !defined(SIMPLE_SDL2) 
  339    roundedRectangleRGBA(renderer, x1, y1, x2, y2, rad, r, g, b, a);
 
  343void CST_rectangleRGBA (
 
  344    CST_Renderer *renderer,
 
  345    Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
 
  346    Uint8 r, Uint8 g, Uint8 b, Uint8 a
 
  348    #if !defined(SIMPLE_SDL2) 
  350    rectangleRGBA(renderer, x1, y1, x2, y2, r, g, b, a);
 
  357std::vector<std::string> CST_GetMusicInfo(CST_Music* music) {
 
  358    std::vector<std::string> info;
 
  367    auto m = mpg123_new(NULL, NULL);
 
  368    mpg123_open(m, 
"./background.mp3");
 
  369    mpg123_seek(m, 0, SEEK_SET);
 
  370    auto meta = mpg123_meta_check(m);
 
  375    if (meta == MPG123_ID3 && mpg123_id3(m, &v1, &v2) == MPG123_OK) {
 
  378            info.push_back(v2->title && v2->title->p  ? v2->title->p  : 
"");
 
  379            info.push_back(v2->artist && v2->artist->p ? v2->artist->p : 
"");
 
  380            info.push_back(v2->album && v2->album->p  ? v2->album->p  : 
"");
 
  386            info.push_back(v1->title[0]  ? v1->title  : 
"");
 
  387            info.push_back(v1->artist[0] ? v1->artist : 
"");
 
  388            info.push_back(v1->album[0]  ? v1->album  : 
"");
 
  405void chdirForPlatform()
 
  407    auto basePath = SDL_GetBasePath();
 
  408    if (basePath != NULL) {
 
  414std::string replaceAll(std::string str, 
const std::string& from, 
const std::string& to) {
 
  415    size_t start_pos = 0;
 
  416    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
 
  417        str.replace(start_pos, from.length(), to);
 
  418        start_pos += to.length();