The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
trying to do a blinking text cursor
Jack Andrews
Guest

Hi,

I'm using SDL2 as it looks like the most cross-platform UI library out there.  I don't want a GUI toolkit.


I'm writing a very simple text editor and so far, the most challenging thing has been showing a blinking cursor at the text insertion point.


I think I can work how an SDL timer works, but I can't work out how to invert the colours of a SDL_Rect at the insertion point.  How would I implement a function:


  int ColourInvert(SDL_Window*w, SDL_Renderer*rend, SDL_Rect area);


?


here's my pseudo-code for my editor (had to trim all the editor stuff out):


SDL_Renderer*re;SDL_Window*w;TTF_Font*font;

int drawline(char*s){
  SDL_Surface*su=SDL_RenderText_Shaded(font,s,a,b));

  SDL_Texture*tx=SDL_CreateTextureFromSurface,(re,su));

  SDL_RenderCopy(re,tx,0,&rect));
  SDL_DestroyTexture(tx);
  SDL_FreeSurface(su);

}
main(){
  SDL_Init(SDL_INIT_EVERYTHING);TTF_Init();
  w=SDL_CreateWindow(x,a,a,y,z,SDL_WINDOW_SHOWN);
  re=SDL_CreateRenderer(w,-1,SDL_RENDERER_ACCELERATED);
  SDL_SetRenderDrawColor(g.v,255,255,255,255);
  SDL_RenderClear(g.v);
  SDL_RenderPresent(g.v);
  //message loop
  //a keypress changes a line
  // for each line in lines{drawline(line)}
}


Thanks for all your work, guys,




Jack
trying to do a blinking text cursor
Jonny D


Joined: 12 Sep 2009
Posts: 932
To invert existing colors on a render target, you have to read the pixels first so you can calculate the inverted colors.  This is a very slow operation and should not be done lightly.

The best way to do it nowadays (i.e. without direct video memory access) is to use a shader and keep the color calculations on the GPU.  I can't help any further than that with plain SDL (is anyone using shaders with SDL_Renderer?), but I can do it all in a couple minutes with SDL_gpu.


Jonny D






On Sat, Aug 6, 2016 at 11:20 AM, Jack Andrews wrote:
Quote:
Hi,

I'm using SDL2 as it looks like the most cross-platform UI library out there.  I don't want a GUI toolkit.


I'm writing a very simple text editor and so far, the most challenging thing has been showing a blinking cursor at the text insertion point.


I think I can work how an SDL timer works, but I can't work out how to invert the colours of a SDL_Rect at the insertion point.  How would I implement a function:


  int ColourInvert(SDL_Window*w, SDL_Renderer*rend, SDL_Rect area);


?


here's my pseudo-code for my editor (had to trim all the editor stuff out):


SDL_Renderer*re;SDL_Window*w;TTF_Font*font;

int drawline(char*s){
  SDL_Surface*su=SDL_RenderText_Shaded(font,s,a,b));

  SDL_Texture*tx=SDL_CreateTextureFromSurface,(re,su));

  SDL_RenderCopy(re,tx,0,&rect));
  SDL_DestroyTexture(tx);
  SDL_FreeSurface(su);

}
main(){
  SDL_Init(SDL_INIT_EVERYTHING);TTF_Init();
  w=SDL_CreateWindow(x,a,a,y,z,SDL_WINDOW_SHOWN);
  re=SDL_CreateRenderer(w,-1,SDL_RENDERER_ACCELERATED);
  SDL_SetRenderDrawColor(g.v,255,255,255,255);
  SDL_RenderClear(g.v);
  SDL_RenderPresent(g.v);
  //message loop
  //a keypress changes a line
  // for each line in lines{drawline(line)}
}


Thanks for all your work, guys,




Jack


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

trying to do a blinking text cursor
Chris Bush
Guest

Could you re-render the glyph in the opposite color on top of the cursor?

Hope this helps.




CB
trying to do a blinking text cursor
Jack Andrews
Guest

Hey Johnny D


Quote:
SDL_gpu

I'll use SDL_gpu - it must be portable if as it has Android.mk .  But I was under the impression that SDL did gpu operations... I'm new..


Please share your solution (or we can discuss it in SDL_gpu forum if it's off topic for the list)


Thanks
Jack.












On 7 August 2016 at 01:43, Jonathan Dearborn wrote:
Quote:
To invert existing colors on a render target, you have to read the pixels first so you can calculate the inverted colors.  This is a very slow operation and should not be done lightly.

The best way to do it nowadays (i.e. without direct video memory access) is to use a shader and keep the color calculations on the GPU.  I can't help any further than that with plain SDL (is anyone using shaders with SDL_Renderer?), but I can do it all in a couple minutes with SDL_gpu.


Jonny D






On Sat, Aug 6, 2016 at 11:20 AM, Jack Andrews wrote:


Quote:
Hi,

I'm using SDL2 as it looks like the most cross-platform UI library out there.  I don't want a GUI toolkit.


I'm writing a very simple text editor and so far, the most challenging thing has been showing a blinking cursor at the text insertion point.


I think I can work how an SDL timer works, but I can't work out how to invert the colours of a SDL_Rect at the insertion point.  How would I implement a function:


  int ColourInvert(SDL_Window*w, SDL_Renderer*rend, SDL_Rect area);


?


here's my pseudo-code for my editor (had to trim all the editor stuff out):


SDL_Renderer*re;SDL_Window*w;TTF_Font*font;

int drawline(char*s){
  SDL_Surface*su=SDL_RenderText_Shaded(font,s,a,b));

  SDL_Texture*tx=SDL_CreateTextureFromSurface,(re,su));

  SDL_RenderCopy(re,tx,0,&rect));
  SDL_DestroyTexture(tx);
  SDL_FreeSurface(su);

}
main(){
  SDL_Init(SDL_INIT_EVERYTHING);TTF_Init();
  w=SDL_CreateWindow(x,a,a,y,z,SDL_WINDOW_SHOWN);
  re=SDL_CreateRenderer(w,-1,SDL_RENDERER_ACCELERATED);
  SDL_SetRenderDrawColor(g.v,255,255,255,255);
  SDL_RenderClear(g.v);
  SDL_RenderPresent(g.v);
  //message loop
  //a keypress changes a line
  // for each line in lines{drawline(line)}
}


Thanks for all your work, guys,




Jack




_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org





_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

trying to do a blinking text cursor
Jack Andrews
Guest

Quote:
glyph opposite color


Thanks Chris.  That would work, but for the default, I'd like a browser-like blinking "I" cursor between pos-1 and pos.I kinda thought SDL was low level and so changing pixels in a window wouldn't be a big deal.


Best,
Jack.


On 7 August 2016 at 01:50, Chris Bush wrote:
Quote:
Could you re-render the glyph in the opposite color on top of the cursor?

Hope this helps.




CB



_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

trying to do a blinking text cursor
Chris Bush
Guest

On 6 August 2016 at 11:55, Jack Andrews wrote:
Quote:


for the default, I'd like a browser-like blinking "I" cursor between pos-1 and pos.




My initial thought: would it be enough to skip rendering the cursor entirely on the blink-off phases?


If you just want to invert the render draw color for a rect, would something like this work?


Uint8 r, g, b, a;

SDL_GetRenderDrawColor(renderer, &r, &g, &b, &a);

SDL_SetRenderDrawColor(renderer, 255 - r, 255 - g, 255 - b, a);


Since the rect only defines the draw area, you'd want to update the render draw color.


If your cursor is a fancy image or something, you may want to store an inverted version and alternate between on and off.


Getting into fancier territory (altering pixels under the rect, etc.), follow Jonathan's lead.


Hope this helps.


CB
Naith


Joined: 03 Jul 2014
Posts: 158
If all you want is a blinking cursor you can do it like this:

Code:

float g_Timer = 1.0f;

// How fast the cursor blinks
float g_BlinkSpeed   = 2.0f;

// The blinking cursor
SDL_Rect CursorQuad = {200, 200, 10, 20};

int main(int argc, char* argv[])
{
   while(g_Running)
   {
      g_Timer -= g_BlinkSpeed * (float)g_DeltaTime;

      if(g_Timer <= 0.0f)
         g_Timer = 2.0f;

      //////////////////////////////////////////////////////////////////////////

      // The cursor quad will be black
      SDL_SetRenderDrawColor(g_pRenderer, 0, 0, 0, SDL_ALPHA_OPAQUE);

      // Whenever the g_Timer value is even (even/odd), render the cursor
      if(((int)g_Timer & 1) == 0)
      {
         // Render the cursor quad
         SDL_RenderFillRect(g_pRenderer, &CursorQuad);

         /*
         If you want to use a font for rendering instead,
         remove 'SDL_RenderFillRect' above and use the code below
         For simplicity I've not done any error checking,
         i.e, checking that the surface and texture was successfully created and such
         */

         SDL_Surface*   pSurface   = TTF_RenderText_Blended(Myfont, "|", CursorColor);
         SDL_Texture*   pTexture   = SDL_CreateTextureFromSurface(MyRenderer, pSurface);
         int            TexWidth   = 0;
         int            TexHeight   = 0;

         SDL_QueryTexture(pTexture, NULL, NULL, &TexWidth, &TexHeight);

         SDL_Rect PositionQuad = {200, 200, TexWidth, TexHeight};

         SDL_RenderCopy(MyRenderer, pTexture, NULL, &PositionQuad);

         SDL_DestroyTexture(pTexture);
         SDL_FreeSurface(pSurface);
      }
   }

   return 0;
}



Hope it helps.
trying to do a blinking text cursor
Jack Andrews
Guest

Quote:
  skip rendering the cursor entirely on the blink-off phases?

So would I have a texture which is the text without the cursor, and a texture with only cursor then


SDL_Texture ts[2];SDL_Rect*rs[2]={NULL,&cursor_rect};

id=SDL_AddTimer(500,ontimer,(V*)1);ie=SDL_AddTimer(500,ontimer,(V*)2);


int ontimer(V*x)
{
  t=(int)x;
  for(int i=0;i<t;i++)
    SDL_RenderCopy(renderer,ts[i],0,rs[i]);
}
    

or something like that...?




On 7 August 2016 at 02:12, Chris Bush wrote:
Quote:
On 6 August 2016 at 11:55, Jack Andrews wrote:
Quote:


for the default, I'd like a browser-like blinking "I" cursor between pos-1 and pos.




My initial thought: would it be enough to skip rendering the cursor entirely on the blink-off phases?


If you just want to invert the render draw color for a rect, would something like this work?


Uint8 r, g, b, a;

SDL_GetRenderDrawColor(renderer, &r, &g, &b, &a);

SDL_SetRenderDrawColor(renderer, 255 - r, 255 - g, 255 - b, a);


Since the rect only defines the draw area, you'd want to update the render draw color.


If your cursor is a fancy image or something, you may want to store an inverted version and alternate between on and off.


Getting into fancier territory (altering pixels under the rect, etc.), follow Jonathan's lead.


Hope this helps.


CB




_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

trying to do a blinking text cursor
Jonny D


Joined: 12 Sep 2009
Posts: 932
Well, it would be simple to just draw a cursor without inverting the colors of the underlying pixels.  If you know the color of the background, you can do that.  It's a good first step.  Porting to SDL_gpu is easy, but still takes a few additional changes.  If SDL_Renderer satisfies your needs, stick with it.

SDL is quite low level and can change the color of pixels only by drawing over them.  The trouble is reading the color of the underlying pixels.  That is a different matter.


But I realized inverting the color doesn't require a shader, only a subtractive blend mode.  Still, SDL doesn't have one.




If inverted color is what you really need, you can set the shape blend equation to subtract the RGB color values (and add alpha values):


GPU_SetShapeBlendEquation(GPU_EQ_SUBTRACT, GPU_EQ_ADD);



Then set the shape blend function to use all of the RGB values and ignore the source alpha:


GPU_SetShapeBlendFunction(GPU_FUNC_ONE, GPU_FUNC_ONE, GPU_FUNC_ZERO, GPU_FUNC_ONE);


Lastly, draw a white rectangle to invert the color under it (1.0 - R = R'):



GPU_RectangleFilled(screen, x, y, x + w-1, y + h-1, GPU_MakeColor(255,255,255,255));




Jonny D




On Sat, Aug 6, 2016 at 11:55 AM, Jack Andrews wrote:
Quote:
> glyph opposite color


Thanks Chris.  That would work, but for the default, I'd like a browser-like blinking "I" cursor between pos-1 and pos.I kinda thought SDL was low level and so changing pixels in a window wouldn't be a big deal.


Best,
Jack.


On 7 August 2016 at 01:50, Chris Bush wrote:


Quote:
Could you re-render the glyph in the opposite color on top of the cursor?

Hope this helps.




CB





_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org





_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Re: trying to do a blinking text cursor
Naith


Joined: 03 Jul 2014
Posts: 158
Jack Andrews wrote:

So would I have a texture which is the text without the cursor, and a texture with only cursor then


See my answer above for a simple solution on how you can do it.
trying to do a blinking text cursor
Jack Andrews
Guest

Quote:
See my answer above for a simple solution on how you can do it.


thanks for your code, naith.  i see my error in my proposed code - having two timers.
but where do you erase the cursor?  what if the position changes and the text is not re-rendered (hold down SDLK_RIGHT) - couldn't you end up with cursor phantoms left in places when it was not invisible?



On 7 August 2016 at 03:22, Naith wrote:
Quote:



Jack Andrews wrote:


So would I have a texture which is the text without the cursor, and a texture with only cursor then





See my answer above for a simple solution on how you can do it.


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Re: trying to do a blinking text cursor
Naith


Joined: 03 Jul 2014
Posts: 158
Jack Andrews wrote:

but where do you erase the cursor?  what if the position changes and the text is not re-rendered (hold down SDLK_RIGHT) - couldn't you end up with cursor phantoms left in places when it was not invisible?

Not sure I understand. Please elaborate more on what you mean.
The cursor is never erased. It is rendered whenever the timer value is an even number and not rendered elsewhere.
trying to do a blinking text cursor
Jonny D


Joined: 12 Sep 2009
Posts: 932
Prior rendering artifacts don't appear if you clear the screen each frame, before drawing.  I think we're assuming this.

Jonny D




On Sat, Aug 6, 2016 at 2:18 PM, Naith wrote:
Quote:



Jack Andrews wrote:


but where do you erase the cursor?  what if the position changes and the text is not re-rendered (hold down SDLK_RIGHT) - couldn't you end up with cursor phantoms left in places when it was not invisible?




Not sure I understand. Please elaborate more on what you mean.
The cursor is never erased. It is rendered whenever the timer value is an even number and not rendered elsewhere.


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org