Author Topic: Possible to get a stroke/outline around text?  (Read 842 times)

wrybread

  • Full Member
  • ***
  • Posts: 55
    • View Profile
Possible to get a stroke/outline around text?
« on: February 22, 2018, 09:36:06 PM »
In a theme I'm working on, the background snapshots sometimes overpower the text in the ROM list. Is there some way to add a stroke or outline or even shadow to the text to help it stand out?


Arcadefan1

  • Jr. Member
  • **
  • Posts: 22
    • View Profile
Re: Possible to get a stroke/outline around text?
« Reply #1 on: February 22, 2018, 10:16:59 PM »
I had the same problem. I just displayed the list twice. One time in black and one time in the desired color on top of it, just a few pixel off. That gives it a shadow effect. If you want it outlined, maybe try a different font size..

verion

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 804
    • View Profile
    • new projects
Re: Possible to get a stroke/outline around text?
« Reply #2 on: February 23, 2018, 12:53:02 AM »
Check out one of the Pandoras Box themes - IIRC it has outlined text.

zpaolo11x

  • Sr. Member
  • ****
  • Posts: 221
    • View Profile
Re: Possible to get a stroke/outline around text?
« Reply #3 on: February 23, 2018, 05:12:59 AM »
In a theme I'm working on, the background snapshots sometimes overpower the text in the ROM list. Is there some way to add a stroke or outline or even shadow to the text to help it stand out?

One solution is, as already suggested, to add a shadow, I did this in my Arcadeflow theme.

Another way is to put the text on a surface, for some reason this adds a very tiny border around the text. Since this is probably a bug and since the effect is very very very subtle I don't think it's viable

Third option, and I'm thinking of implementing something like that, is to find a font that has a "bold" sibling, so you can superimpose two fonts and use one for the outline. Of course it's very tricky to find a font that is perfectly matching its bold counterpart, in the end you'll probably have to build your one with some font editing tool

zpaolo11x

  • Sr. Member
  • ****
  • Posts: 221
    • View Profile
Re: Possible to get a stroke/outline around text?
« Reply #4 on: February 23, 2018, 05:44:56 AM »
Another trick, although a bit complex, is to add _4_ replicas of your font, each one moved to a corner. Say your font is 150 pixel tall, and you want a 5 pixel border, then add four copies of that font with positions:

5,5
5,-5
-5,5
-5,-5

Works quite well

wrybread

  • Full Member
  • ***
  • Posts: 55
    • View Profile
Re: Possible to get a stroke/outline around text?
« Reply #5 on: February 23, 2018, 04:48:33 PM »
@zpaolo11x: thank you! Masking 5 versions of the list, 4 of them offset by one pixel in each direction, works beautifully.

One small issue I'm having is that, according to the Squirrel docs, I should be able to just make one version of the stroke list and clone it 3 times:

https://developer.electricimp.com/squirrel/squirrelcrib (search for "clone")

However, when I do that, I get a segmentation fault every time. For example, here's my version without clone, which works well but is a bit verbose and hard to modify:

Code: [Select]
// first version for the stroke
local lb1 = fe.add_listbox( 0, configs["rom_list_margin_top"].tointeger(), fe.layout.width, configs["rom_list_height"].tointeger() );
lb1.charsize = configs["list_char_size"].tointeger();
lb1.set_rgb(0,0,0) // don't put stroke on non selected items
lb1.set_sel_rgb(0,0,0); // stroke color
lb1.sel_style = Style.Bold;
lb1.selbg_alpha=0;
lb1.rows = configs["list_rows"].tointeger();

// second version for the stroke
local lb2 = fe.add_listbox( 0, configs["rom_list_margin_top"].tointeger(), fe.layout.width, configs["rom_list_height"].tointeger() );
lb2.charsize = configs["list_char_size"].tointeger();
lb2.set_rgb(0,0,0) // don't put stroke on non selected items
lb2.set_sel_rgb(0,0,0); // stroke color
lb2.sel_style = Style.Bold;
lb2.selbg_alpha=0;
lb2.rows = configs["list_rows"].tointeger();

// third version for the stroke
local lb3 = fe.add_listbox( 0, configs["rom_list_margin_top"].tointeger(), fe.layout.width, configs["rom_list_height"].tointeger() );
lb3.charsize = configs["list_char_size"].tointeger();
lb3.set_rgb(0,0,0) // don't put stroke on non selected items
lb3.set_sel_rgb(0,0,0); // stroke color
lb3.sel_style = Style.Bold;
lb3.selbg_alpha=0;
lb3.rows = configs["list_rows"].tointeger();

// forth version for the stroke
local lb4 = fe.add_listbox( 0, configs["rom_list_margin_top"].tointeger(), fe.layout.width, configs["rom_list_height"].tointeger() );
lb4.charsize = configs["list_char_size"].tointeger();
lb4.set_rgb(0,0,0) // don't put stroke on non selected items
lb4.set_sel_rgb(0,0,0); // stroke color
lb4.sel_style = Style.Bold;
lb4.selbg_alpha=0;
lb4.rows = configs["list_rows"].tointeger();


// the main list (no stroke)
local lb = fe.add_listbox( 0, configs["rom_list_margin_top"].tointeger(), fe.layout.width, configs["rom_list_height"].tointeger() );
lb.charsize = configs["list_char_size"].tointeger();
lb.set_sel_rgb( 200, 200, 64 );
lb.sel_style = Style.Bold;
lb.selbg_alpha=0; // this gets rid of the bar that highlights the selected game
lb.rows = configs["list_rows"].tointeger(); // the number of rows



// offset the position of the stroke'd entries
lb1.set_pos( lb.x+1, lb.y+1 )
lb2.set_pos( lb.x+1, lb.y-1 )
lb3.set_pos( lb.x-1, lb.y+1 )
lb4.set_pos( lb.x-1, lb.y-1 )

And here's the version with clone:

Code: [Select]
// this is a version of the list that will be cloned 3 times (4 total versions) that we can offset
// one pixel in each direction to build a stroke.
local lb1 = fe.add_listbox( 0, configs["rom_list_margin_top"].tointeger(), fe.layout.width, configs["rom_list_height"].tointeger() );
lb1.charsize = configs["list_char_size"].tointeger();
lb1.set_rgb(0,0,0)            // stroke of non selected items
lb1.set_sel_rgb(0,0,0);   // stroke color of selected
lb1.sel_style = Style.Bold;
lb1.selbg_alpha=0;
lb1.rows = configs["list_rows"].tointeger();

local lb2 = clone(lb1);
local lb3 = clone(lb1);
local lb4 = clone(lb1);


// the main list (no stroke)
local lb = fe.add_listbox( 0, configs["rom_list_margin_top"].tointeger(), fe.layout.width, configs["rom_list_height"].tointeger() );
lb.charsize = configs["list_char_size"].tointeger();
lb.set_sel_rgb( 200, 200, 64 );
lb.sel_style = Style.Bold;
lb.selbg_alpha=0; // this gets rid of the bar that highlights the selected game
lb.rows = configs["list_rows"].tointeger(); // the number of rows


// offset the position of the stroked versions
lb1.set_pos( lb.x+1, lb.y+1 )
lb2.set_pos( lb.x+1, lb.y-1 )
lb3.set_pos( lb.x-1, lb.y+1 )
lb4.set_pos( lb.x-1, lb.y-1 )

As soon as I try to set any properties of the cloned objects (lb1.set_pos, etc.) I get the segmentation fault.

I zipped up my Layout (wrycade) and made a version of the layout both with and without using clone if anyone is in a testing mood.

[Edited to fix the coordinates of the stroke. And as of now the layout files I included don't work, will fix later.]
« Last Edit: February 25, 2018, 01:06:41 AM by wrybread »

wrybread

  • Full Member
  • ***
  • Posts: 55
    • View Profile
Re: Possible to get a stroke/outline around text?
« Reply #6 on: February 23, 2018, 05:03:30 PM »
I just posted a video of the stroke effect:

https://www.youtube.com/watch?v=mstfDKev-XA

(Which also shows my cabinet's newfound ability to play videos, especially random episodes of South Park and Jackass. Whoohoo!)

« Last Edit: February 23, 2018, 05:14:46 PM by wrybread »

zpaolo11x

  • Sr. Member
  • ****
  • Posts: 221
    • View Profile
Re: Possible to get a stroke/outline around text?
« Reply #7 on: February 24, 2018, 01:27:26 AM »
@zpaolo11x: thank you! Masking 5 versions of the list, 4 of them offset by one pixel in each direction, works beautifully.

One small issue I'm having is that, according to the Squirrel docs, I should be able to just make one version of the stroke list and clone it 3 times:

Well from this knowledge base https://github.com/mickelson/attract/blob/master/Layouts.md#add_clone it seems that add_clone can be used only for images, artworks and surfaces.

I watched the video and the effect is super neat, I'llhave to implement it in my theme too :D

wrybread

  • Full Member
  • ***
  • Posts: 55
    • View Profile
Re: Possible to get a stroke/outline around text?
« Reply #8 on: February 24, 2018, 10:52:43 PM »
I don't think add_clone() and clone() are the same functions. From the Squirrel reference manual I'm reading (https://developer.electricimp.com/squirrel/squirrelcrib), clone() specifically says it can clone an object.

Code: [Select]
Duplicating Objects

Squirrel provides a keyword, clone, to duplicate entities — objects, tables or arrays — which are usually accessed by reference rather than value. Any such entities nested within the clone’d object will not by copied, but accessed by reference. However, they themselves may be clone’d separately — and, indeed, any objects, tables arrays nested within them — and added to the clone.

In the Attract Mode Programming Reference, though, it documents add_clone() as:

Code: [Select]
fe.add_clone( img )

Clone an image, artwork or surface object and add the clone to the back of Attract-Mode's draw list. The texture pixel data of the original and clone is shared as a result.

Parameters:

img - the image, artwork or surface object to clone. This needs to be an instance of the class fe.Image.
Return Value:

An instance of the class fe.Image which can be used to interact with the added clone.

Dunno. No biggie of course, but it would sure be a lot cleaner when adding strokes if we could simply clone one of the 4 text objects, instead of writing it out 4 times.

And oops, I had a math error in the way I was generating the stroke. I modified the code above to fix it:

// offset the position of the stroked versions
lb1.set_pos( lb.x+1, lb.y+1 )
lb2.set_pos( lb.x+1, lb.y-1 )
lb3.set_pos( lb.x-1, lb.y+1 )
lb4.set_pos( lb.x-1, lb.y-1 )


And I see that the zipped layout I included doesn't work, oops again, I'll fix that one later.
« Last Edit: February 25, 2018, 01:07:04 AM by wrybread »

zpaolo11x

  • Sr. Member
  • ****
  • Posts: 221
    • View Profile
Re: Possible to get a stroke/outline around text?
« Reply #9 on: February 25, 2018, 05:21:41 AM »
I don't think add_clone() and clone() are the same functions. From the Squirrel reference manual I'm reading (https://developer.electricimp.com/squirrel/squirrelcrib), clone() specifically says it can clone an object.

I think that's the elctric imp fork of Squirrel, not the "vanilla" one. There is a "clone" in Squirrel language reference but it works for tables, array or classes. I'm not a programmer but I don't think it will work with text objects. The squirrel reference I'm using is this: http://www.squirrel-lang.org/doc/squirrel3.html

wrybread

  • Full Member
  • ***
  • Posts: 55
    • View Profile
Re: Possible to get a stroke/outline around text?
« Reply #10 on: February 25, 2018, 07:02:39 PM »
From those docs (http://www.squirrel-lang.org/doc/squirrel3.html#d0e1274):

Code: [Select]
exp:= ‘clone’ exp

Clone performs shallow copy of a table, array or class instance (copies all slots in the new object without recursion). If the source table has a delegate, the same delegate will be assigned as delegate (not copied) to the new table (see Delegation).

After the new object is ready the “_cloned” meta method is called (see Metamethods).

When a class instance is cloned the constructor is not invoked (initializations must rely on _cloned instead

Unless I'm missing something (which is possible!) a "class instance" and an object are the same thing. So clone() should work on the text object here. Or maybe I'm just not initing the cloned object properly?

I found someone else with the same problem here:

http://forum.squirrel-lang.org/default.aspx?g=posts&t=3029

As with me, there was no problem cloning the object, but there was a segmentation fault when accessing any property of the cloned object.

And on a sidenote, I can only see that it's a segmentation fault when running this code in Linux. When I run it in Windows it simply crashes, on my computer at least.