0

I'm trying to render text in . The text should appear in SDL_Rect destination in the clip area SDL_Rect rcTextOutput but it returns a error. I've tried to debug this with and but I still don't see the problem.

I'll leave the entire code at the end, but here's the section where the text gets rendered:

SDL_SetRenderDrawColor(gRenderer, 0x40, 0x40, 0x40, 0x40);

gTextSurface = TTF_RenderText_Solid(gFont, "text", gTextColor);
if (gTextSurface == NULL)
{
  throw "Unable to render texture! ERROR: ";
}
gTextTexture = SDL_CreateTextureFromSurface(gRenderer, gTextSurface);
if (gTextTexture == NULL)
{
  throw "Unable to render texture! ERROR: ";
}

SDL_Rect destination;
destination.x = rcTextOutput.x + rcTextOutput.w - 800;
destination.y = rcTextOutput.y;
destination.w = 800;
destination.h = 20;

SDL_RenderSetClipRect(gRenderer, &rcTextOutput);
SDL_RenderCopy(gRenderer, gTextTexture, NULL, &destination);
SDL_RenderSetClipRect(gRenderer, NULL);

// ...

SDL_RenderPresent(gRenderer);

I took note of SDL_SetClipRect() from this answer and its example but it's not working.

I've already looked at this Lazy Foo' tutorial and the code seems to be in order. I've also run on it and it returned:

Starting program: /home/pradana/Projects/sierra/caventure/build/caventure 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
[New Thread 0x7fffeb5f1700 (LWP 25319)]
[New Thread 0x7fffeadf0700 (LWP 25320)]
terminate called after throwing an instance of 'char const*'

Thread 1 "caventure" received signal SIGABRT, Aborted.
0x00007ffff6c92a10 in raise () from /usr/lib/libc.so.6

I even tried :

==25239== Memcheck, a memory error detector
==25239== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==25239== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==25239== Command: build/./caventure
==25239== 
==25239== Syscall param writev(vector[...]) points to uninitialised byte(s)
==25239==    at 0x5CF218D: ??? (in /usr/lib/libc-2.25.so)
==25239==    by 0x8088BAC: ??? (in /usr/lib/libxcb.so.1.1.0)
==25239==    by 0x8088FAC: ??? (in /usr/lib/libxcb.so.1.1.0)
==25239==    by 0x808902C: xcb_writev (in /usr/lib/libxcb.so.1.1.0)
==25239==    by 0x7D7EF3D: _XSend (in /usr/lib/libX11.so.6.3.0)
==25239==    by 0x7D7F431: _XReply (in /usr/lib/libX11.so.6.3.0)
==25239==    by 0x7D6A2EE: XInternAtom (in /usr/lib/libX11.so.6.3.0)
==25239==    by 0x4EFB79A: ??? (in /usr/lib/libSDL2-2.0.so.0.4.1)
==25239==    by 0x4EFC694: ??? (in /usr/lib/libSDL2-2.0.so.0.4.1)
==25239==    by 0x4EEB87F: ??? (in /usr/lib/libSDL2-2.0.so.0.4.1)
==25239==    by 0x4EEB60E: ??? (in /usr/lib/libSDL2-2.0.so.0.4.1)
==25239==    by 0x4E4F1C6: ??? (in /usr/lib/libSDL2-2.0.so.0.4.1)
==25239==  Address 0x79c5573 is 35 bytes inside a block of size 16,384 alloc'd
==25239==    at 0x4C2CF35: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==25239==    by 0x7D6F385: XOpenDisplay (in /usr/lib/libX11.so.6.3.0)
==25239==    by 0x4EFA84F: ??? (in /usr/lib/libSDL2-2.0.so.0.4.1)
==25239==    by 0x4EEB5BB: ??? (in /usr/lib/libSDL2-2.0.so.0.4.1)
==25239==    by 0x4E4F1C6: ??? (in /usr/lib/libSDL2-2.0.so.0.4.1)
==25239==    by 0x4011F3: init() (in /home/pradana/Projects/sierra/caventure/build/caventure)
==25239==    by 0x40148A: main (in /home/pradana/Projects/sierra/caventure/build/caventure)
==25239== 
terminate called after throwing an instance of 'char const*'
==25239== 
==25239== Process terminating with default action of signal 6 (SIGABRT): dumping core
==25239==    at 0x5C41A10: raise (in /usr/lib/libc-2.25.so)
==25239==    by 0x5C43139: abort (in /usr/lib/libc-2.25.so)
==25239==    by 0x53ED4EC: __gnu_cxx::__verbose_terminate_handler() (vterminate.cc:95)
==25239==    by 0x53EB2A5: __cxxabiv1::__terminate(void (*)()) (eh_terminate.cc:47)
==25239==    by 0x53EB2F0: std::terminate() (eh_terminate.cc:57)
==25239==    by 0x53EB507: __cxa_throw (eh_throw.cc:87)
==25239==    by 0x4013FC: loadMedia() (in /home/pradana/Projects/sierra/caventure/build/caventure)
==25239==    by 0x40148F: main (in /home/pradana/Projects/sierra/caventure/build/caventure)
==25239== 
==25239== HEAP SUMMARY:
==25239==     in use at exit: 13,232,031 bytes in 33,989 blocks
==25239==   total heap usage: 76,191 allocs, 42,202 frees, 50,434,525 bytes allocated
==25239== 
==25239== LEAK SUMMARY:
==25239==    definitely lost: 16 bytes in 1 blocks
==25239==    indirectly lost: 176 bytes in 4 blocks
==25239==      possibly lost: 4,143,500 bytes in 29,652 blocks
==25239==    still reachable: 9,088,339 bytes in 4,332 blocks
==25239==         suppressed: 0 bytes in 0 blocks
==25239== Rerun with --leak-check=full to see details of leaked memory
==25239== 
==25239== For counts of detected and suppressed errors, rerun with: -v
==25239== Use --track-origins=yes to see where uninitialised values come from
==25239== ERROR SUMMARY: 5 errors from 1 contexts (suppressed: 0 from 0)

Here's the rest of the script (irrelevant code is removed):

#include <stdio.h>
#include <string>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>

// Screen dimensions, constants
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 900; // 600 for ground, 280 for output, 20 for input

SDL_Surface* gScreenSurface = NULL; // The surface contained by the window
SDL_Surface* gCurrentSurface = NULL; // Current displayed image
SDL_Surface* gTextSurface = NULL; // SDL_Surface for the text.
SDL_Texture* gTextTexture = NULL; // SDL_Texture for the text.
TTF_Font* gFont = NULL; // Font pointer.
SDL_Color gTextColor = { 0, 0, 0, 0xFF }; // Text color, white.


SDL_Renderer* gRenderer = NULL; // The renderer we'll be using
SDL_Rect rcGround, rcSprite, rcTextInput, rcTextOutput;

void init();
void loadMedia();
void quit();

void init()
{
  if (SDL_Init(SDL_INIT_VIDEO) > 0)
  {
    throw "SDL failed to initialise! ERROR: ";
  }
  else
  {
    // CODE REDACTED: gWindow and gRenderer is initialised
    if (TTF_Init() > 0)
    {
      throw "TTF could not be initialised! ERROR: ";
    }
  }
}

void loadMedia()
{
  // Ground rendering
  rcGround.x = 0;
  rcGround.y = 0;
  rcGround.w = 800;
  rcGround.h = 600;

  // Sprite rendering
  rcSprite.x = 400;
  rcSprite.y = 300;
  rcSprite.w = 4;
  rcSprite.h = 4;

  // TextOutput box rendering
  rcTextOutput.x = 0;
  rcTextOutput.y = 600;
  rcTextOutput.w = 800;
  rcTextOutput.h = 280;

  // TextInput box rendering
  rcTextInput.x = 0;
  rcTextInput.y = 880;
  rcTextInput.w = 800;
  rcTextInput.h = 20;

  gFont = TTF_OpenFont("resources/consolas.ttf", 14);
  if (gFont == NULL)
  {
    throw "Font load error";
  }
}

void quit()
{
  // Destroy window
    SDL_DestroyWindow(gWindow);
    SDL_DestroyRenderer(gRenderer);
  SDL_DestroyTexture(gTextTexture);
  SDL_FreeSurface(gTextSurface);
  TTF_CloseFont(gFont);
    gWindow = NULL;
  gRenderer = NULL;
  gFont = NULL;

    // Quit SDL subsystems
  TTF_Quit();
    SDL_Quit();
}

int main()
{
  try
  {
    init();
    loadMedia();

    bool quit = false;
    SDL_Event event;

    while(!quit)
    {
      // CODE REDACTED: event & sprite movement
      }
      if (rcSprite.x < 0 || rcSprite.y < 0 || rcSprite.y > rcGround.h || rcSprite.x > rcGround.w)
      {
        rcSprite.x = 400;
        rcSprite.y = 300;
      }

      SDL_SetRenderDrawColor(gRenderer, 0x00, 0x00, 0x00, 0x00);
      SDL_RenderClear(gRenderer);

      SDL_RenderFillRect(gRenderer, &rcGround);
      SDL_BlitSurface(gCurrentSurface, NULL, gScreenSurface, &rcGround);

      SDL_RenderFillRect(gRenderer, &rcTextInput);
      SDL_BlitSurface(gCurrentSurface, NULL, gScreenSurface, &rcTextInput);

      SDL_SetRenderDrawColor(gRenderer, 0x40, 0x40, 0x40, 0x40);

      gTextSurface = TTF_RenderText_Solid(gFont, "text", gTextColor);
      if (gTextSurface == NULL)
      {
        throw "Unable to render texture! ERROR: ";
      }
      gTextTexture = SDL_CreateTextureFromSurface(gRenderer, gTextSurface);
      if (gTextTexture == NULL)
      {
        throw "Unable to render texture! ERROR: ";
      }

      SDL_Rect destination;
      destination.x = rcTextOutput.x + rcTextOutput.w - 800;
      destination.y = rcTextOutput.y;
      destination.w = 800;
      destination.h = 20;

      SDL_RenderSetClipRect(gRenderer, &rcTextOutput);
      SDL_RenderCopy(gRenderer, gTextTexture, NULL, &destination);
      SDL_RenderSetClipRect(gRenderer, NULL);

      SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);

      SDL_RenderDrawLine(gRenderer, 0, 600, 800, 600);
      SDL_RenderDrawLine(gRenderer, 0, 880, 800, 880);

      SDL_RenderFillRect(gRenderer, &rcSprite);
      SDL_BlitSurface(gCurrentSurface, NULL, gScreenSurface, &rcSprite);

      SDL_RenderPresent(gRenderer);
    }
  }
  catch (const std::string& msg)
    {
        printf("%s", msg.c_str());
        if (SDL_GetError() != NULL)
        {
            printf("%s", SDL_GetError());
        }
    else if (TTF_GetError() != NULL)
        {
            printf("%s", TTF_GetError());
        }
    else
    {
      printf("%s", "NULL");
    }
    quit();
        exit(EXIT_FAILURE);
    }
  quit();
  return 0;
}

1 Answer 1

1

You throw a pointer to array of chars but try to catch a reference to ::std::string. That obviously does not work and your program gets terminated because of uncaught exception. You should explicitly construct a string when throwing or actually you should throw and catch an instance of std::runtime_error which can contain description.

throw(::std::runtime_error("Unable to render texture!"));
...
catch(::std::runtime_error const & exception)
{
    printf("%s", exception.what());
Sign up to request clarification or add additional context in comments.

1 Comment

Huh. Apparently that was the problem. Well, thank you. I actually found the error, the file path for TTF_OpenFont() was wrong then it worked. Funny enough when I ran it, rcTextOutput went black and I can't see any text.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.