Trying to do a blinking text cursor

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_Windoww, SDL_Rendererrend, SDL_Rect area);

?

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

SDL_Rendererre;SDL_Windoww;TTF_Fontfont;
int drawline(char
s){
SDL_Surfacesu=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

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 DOn Sat, Aug 6, 2016 at 11:20 AM, Jack Andrews wrote:

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_Windoww, SDL_Rendererrend, SDL_Rect area);

?

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

SDL_Rendererre;SDL_Windoww;TTF_Fontfont;
int drawline(char
s){
SDL_Surfacesu=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
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

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

Hope this helps.

CB

Hey Johnny D

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:

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 <@Jack_Andrews> wrote:

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_Windoww, SDL_Rendererrend, SDL_Rect area);

?

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

SDL_Rendererre;SDL_Windoww;TTF_Fontfont;
int drawline(char
s){
SDL_Surfacesu=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
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

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:

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

Hope this helps.

CB


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

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.

CBOn 6 August 2016 at 11:55, Jack Andrews wrote:

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.

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:

On 6 August 2016 at 11:55, Jack Andrews <@Jack_Andrews> wrote:

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
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

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 DOn Sat, Aug 6, 2016 at 11:55 AM, Jack Andrews wrote:

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:

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

Hope this helps.

CB


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

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.

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:

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
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

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.

Prior rendering artifacts don’t appear if you clear the screen each frame,
before drawing. I think we’re assuming this.

Jonny DOn Sat, Aug 6, 2016 at 2:18 PM, Naith wrote:

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
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org