BRT Community

Please login or register.

Login with username, password and session length
Advanced search  

News:

Welcome to the Bridgetek Community!

Please read our Welcome Note

Technical Support enquires
please contact the team
@ Bridgetek Support

Please refer to our website for detailed information on all our products - Bridgetek - Bridging Technology

Author Topic: Stencils with Fonts  (Read 20141 times)

mmottola

  • Newbie
  • *
  • Posts: 5
    • View Profile
Stencils with Fonts
« on: February 02, 2023, 06:40:04 PM »

I'm trying to use the stencil buffer to mask text outside of a set region. Below are the commands run in ESE. My intuition was that the text could be treated as a rectangular box which appears incorrect. I'm assuming the issue is related to how the font's bitmap cells may be overlapping?
  • Any explanation of how the stencil buffer is being incremented with regards to a font's bitmap cells and why there appears to be artifacts from some of these cells?
  • How can I achieve the desired effect shown in RECTS Ref 1 but with text?

Code: [Select]
CLEAR_COLOR_RGB(128,128,128)
CLEAR(1, 1, 1)

STENCIL_OP(INCR, INCR)
COLOR_A(128)
BEGIN(RECTS)
VERTEX2F(720, 576)
VERTEX2F(16383, 9600)
END()
COLOR_A(255)
STENCIL_FUNC(GEQUAL, 0, 255) // Ref 0-4
COLOR_RGB(96,96,96)
BEGIN(RECTS)
VERTEX2F(720, 0)
VERTEX2F(1504, 1152)
END()
COLOR_RGB(255,255,255)

//BEGIN(RECTS)
//VERTEX2F(0, 768)
//VERTEX2F(1504, 960)
//END()

CMD_TEXT(0, 36, 30, 0, "TESTS")
« Last Edit: February 02, 2023, 09:27:34 PM by mmottola »
Logged

BRT Community

  • Administrator
  • Hero Member
  • *****
  • Posts: 756
    • View Profile
Re: Stencils with Fonts
« Reply #1 on: February 03, 2023, 12:21:04 PM »

Hello,

We will look into your questions,

Could you also advise what your overall intended purpose for the stencil operation was within your application? Was it to do a highlight effect or a background on a string or on only certain characters of the text? We may also be able to suggest alternative ways.

Best Regards, BRT Community
Logged

mmottola

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Stencils with Fonts
« Reply #2 on: February 06, 2023, 07:10:51 PM »

Hello,

We will look into your questions,

Could you also advise what your overall intended purpose for the stencil operation was within your application? Was it to do a highlight effect or a background on a string or on only certain characters of the text? We may also be able to suggest alternative ways.

Best Regards, BRT Community

I'm creating a custom textbox widget. I have most of the functionality already developed, but it is currently limited to displaying full font characters. Since variable-width fonts can be used this creates odd gaps around the borders of the text where a full character can't fit within the box. Ideally I'd like to use something to mask the characters so only a portion of them would be shown, hence the use of the stencil operation. Attached is an image of how the textbox is currently displaying text and how I'd like it to display text. The input string is the following for reference.
Code: [Select]
"The quick brown fox\n"
"jumps over the lazy dog.\n"
"`1234567890-=[]\\;',./\n"
"This is another test\n"
"sentence to check the fit\n"
"of text in the textbox.\n"
"~!@#$%^&*()_+{}|:\"<>?"

In some cases the text within the box will accept user input and be editable so ideally I'd like to be able to highlight text as well to indicate the position of the cursor.
« Last Edit: February 06, 2023, 10:07:50 PM by mmottola »
Logged

BRT Community

  • Administrator
  • Hero Member
  • *****
  • Posts: 756
    • View Profile
Re: Stencils with Fonts
« Reply #3 on: February 07, 2023, 11:58:40 AM »

Hi,

For the partial characters, one way may be to reverse your operation and print text only where the stencil is a certain value. For example here the text is only visible in the grey box area where the stencil is 1.

Code: [Select]
CLEAR_COLOR_RGB(128,128,128)
CLEAR(1, 1, 1)

// increment stencil where the box is drawn
STENCIL_OP(INCR, INCR)
COLOR_A(128)
BEGIN(RECTS)
VERTEX2F(2144, 1728)
VERTEX2F(8000, 4800)
END()
// Stop the stencil incrementing
STENCIL_OP(KEEP, KEEP)

// Text only where the stencil is 1
COLOR_A(255)
STENCIL_FUNC(EQUAL, 1, 255)

CMD_TEXT(107, 144, 30, 0, "TESTS")

// return the function
STENCIL_FUNC(ALWAYS, 0, 255)

We have some explanation on using character widths for things like drawing highlighting using efficient rectangles, which are part of appnotes in development, and so we'll post some snippets from those here too.

Best Regards, BRT Community
Logged

mmottola

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Stencils with Fonts
« Reply #4 on: February 07, 2023, 04:28:02 PM »

Hi,

For the partial characters, one way may be to reverse your operation and print text only where the stencil is a certain value. For example here the text is only visible in the grey box area where the stencil is 1.

Code: [Select]
CLEAR_COLOR_RGB(128,128,128)
CLEAR(1, 1, 1)

// increment stencil where the box is drawn
STENCIL_OP(INCR, INCR)
COLOR_A(128)
BEGIN(RECTS)
VERTEX2F(2144, 1728)
VERTEX2F(8000, 4800)
END()
// Stop the stencil incrementing
STENCIL_OP(KEEP, KEEP)

// Text only where the stencil is 1
COLOR_A(255)
STENCIL_FUNC(EQUAL, 1, 255)

CMD_TEXT(107, 144, 30, 0, "TESTS")

// return the function
STENCIL_FUNC(ALWAYS, 0, 255)

We have some explanation on using character widths for things like drawing highlighting using efficient rectangles, which are part of appnotes in development, and so we'll post some snippets from those here too.

Best Regards, BRT Community

Thanks, that approach appears to produce the desired results. Looking forward to the additional snippets.
Logged

BRT Community

  • Administrator
  • Hero Member
  • *****
  • Posts: 756
    • View Profile
Re: Stencils with Fonts
« Reply #5 on: February 09, 2023, 04:38:40 PM »

Hi,

Glad to hear that it helped,

Here is a very rough beta of one way to do highlighting of a block of text and also to do a cursor (by highlighting one character in a similar way)

It needs more testing and optimisation before we publish it officially but hope it helps in the meantime,

The main idea is to get the widths of each character and then add them up to work out where the highlighting rectangle should begin and how wide it should be.

Then, you can draw the rectangle either using a rectangle primitive or via efficient rectangles (see the Gameduino 2 cookbook by James Bowman available on the web as a PDF)

Finally, the text can be placed on top.

The same idea can be used to re-size shapes etc. based on the text within them or if you wanted to write a string and snapshot it etc. or any other case where you need to know the character widths.

This example uses built in fonts but you can also use widths for custom fonts.

In the code, the following lines set which char has the cursor and which chars have the highlight.

   Cursor_Position = 10;

   FirstCharToHighlight = 20;   // highlight 20th-30th characters
   LastCharToHighlight = 30;

The output looks like the attached file,

Best Regards, BRT Community


 
Code: [Select]
   
#define Handle_Highlight 7
#define Handle_Cursor 8

char message[] = "Built-In Font with Highlighting";


// Variables for the built-in font properties
    uint32_t FontByte;
    uint16_t FontIndexCounter;
    uint32_t FontTableAddress = 0;
    uint32_t X = 0;
    uint32_t Y = 0;
#define BuiltInFont 30

    // ###################################################################################################################################
    // Get font properties for a built-in font
    // ###################################################################################################################################

    // ------------------------- Get font properties for a built-in font --------------------
    // This shows how to get the width and properties of internal fonts. We need to read the
    // properties from EVE as the data is not currently in the MCU

    EVE_GPU_FONT_HEADER BuiltInFont_props; // Structure defined in the header file to hold font data

    FontTableAddress = ((HAL_MemRead32(EVE_ROMFONT_TABLEADDRESS)) + ((BuiltInFont-16) * FT_GPU_FONT_TABLE_SIZE));
    // Note that font table starts at font 16
    // EVE_ROMFONT_TABLEADDRESS is equivalent to ROM_FONTROOT
    // Font Table Address = [address at ROM_FONTROOT] + ((font required - 16) * 148)

    FontIndexCounter = 0;
    while(FontIndexCounter < 128)
    {
    FontByte = HAL_MemRead8(FontTableAddress + FontIndexCounter);
    BuiltInFont_props.FontWidth[FontIndexCounter] = FontByte;
    FontIndexCounter ++;
    }
    FontByte = HAL_MemRead32(FontTableAddress + FontIndexCounter);
    BuiltInFont_props.FontBitmapFormat = FontByte;
    FontIndexCounter = FontIndexCounter + 4;

    FontByte = HAL_MemRead32(FontTableAddress + FontIndexCounter);
    BuiltInFont_props.FontLineStride = FontByte;
    FontIndexCounter = FontIndexCounter + 4;

    FontByte = HAL_MemRead32(FontTableAddress + FontIndexCounter);
    BuiltInFont_props.FontWidthInPixels = FontByte;
    FontIndexCounter = FontIndexCounter + 4;

    FontByte = HAL_MemRead32(FontTableAddress + FontIndexCounter);
    BuiltInFont_props.FontHeightInPixels = FontByte;
    FontIndexCounter = FontIndexCounter + 4;

    FontByte = HAL_MemRead32(FontTableAddress + FontIndexCounter);
    BuiltInFont_props.PointerToFontGraphicsData = FontByte;


    // ###################################################################################################################################
    // Calculate the length of the characters to highlight or to select with cursor
    // ###################################################################################################################################

uint8_t CurrentCharIndex = 0;
volatile char CurrentChar;
volatile uint8_t CurrentCharWidth;
volatile uint8_t CurrentCharHex;
uint32_t MessageSize = (sizeof(message) -1);
uint32_t TotalStringWidth = 0;

// For highlighting a block of text, here we highlight 18th-30th
uint32_t FirstCharXCoord = 0;
uint8_t FirstCharToHighlight = 0;
uint8_t LastCharToHighlight = 0;
uint32_t HighlightStringWidth = 0;
uint8_t Highlight_Enable = 0x00;

// For a cursor highlighting one character, here we select the 10th
uint8_t Cursor_Position = 0; //10
uint8_t CursorCharWidth = 0;
uint32_t CursorCharXCoord = 0;
uint8_t Cursor_Enable = 0x00;


// ######################################## Highlight ##########################################

FirstCharToHighlight = 20; // highlight 20th-30th characters
LastCharToHighlight = 30;

// --------------------- For the highlight -------------------------
// Pass in index to FirstCharToHighlight and LastCharToHighlight
// Provides output of FirstCharXCoord and HighlightStringWidth which are X coordinates to be used to draw a rectangle
CurrentCharIndex = 0;
HighlightStringWidth = 0;
TotalStringWidth = 0;
Highlight_Enable = 0xFF;

// Do not render highlight if values out of range
if((FirstCharToHighlight < 0) || (LastCharToHighlight <= FirstCharToHighlight) )
{
FirstCharXCoord = 0;
HighlightStringWidth = 0;
Highlight_Enable = 0x00;
}
else
{
// Correct any other out of range values
if(FirstCharToHighlight > (MessageSize-1))
{
FirstCharToHighlight =  (MessageSize-1);
}
if(LastCharToHighlight > (MessageSize))
{
LastCharToHighlight =  (MessageSize);
}

do
{
// Sum up the widths of the characters beginning with the first (index 0 in message)
CurrentChar = message[CurrentCharIndex];
CurrentCharHex = (uint8_t) (CurrentChar);
CurrentCharWidth = (uint8_t) BuiltInFont_props.FontWidth[CurrentCharHex];

// Record the total when we reach the START of the highlight. This becomes the width of the string up to the
// left-hand side of the FIRST character to be highlighted, allowing us to work out its coordinate
// Note that the index is 0-based and so 9 would be the 10th character.
if(CurrentCharIndex == FirstCharToHighlight)
{
FirstCharXCoord = TotalStringWidth;
}

// Record the total when we reach the END of the highlight. This becomes the width of the string up to the
// right-hand side of the LAST character to be highlighted, allowing us to work out its coordinate.
if((CurrentCharIndex >= (FirstCharToHighlight)) && (CurrentCharIndex <= (LastCharToHighlight)))
{
HighlightStringWidth += CurrentCharWidth;
}

CurrentCharIndex ++;
TotalStringWidth += CurrentCharWidth;

} while(CurrentCharIndex <= MessageSize);
}


// ######################################## Cursor ##########################################

Cursor_Position = 10;

// --------------------- For the cursor -------------------------
// Pass in index to Cursor_Position
// Provides output of CursorCharXCoord and CursorCharWidth which are X coordinates to be used to draw a rectangle
CurrentCharIndex = 0;
TotalStringWidth = 0;
Cursor_Enable = 0xFF;

// Correct any invalid inputs
if(Cursor_Position < 0)
Cursor_Position = 0;
if(Cursor_Position > MessageSize)
Cursor_Position = MessageSize;

do
{
// Sum up the widths of the characters beginning with the first (index 0 in message)
CurrentChar = message[CurrentCharIndex];
CurrentCharHex = (uint8_t) (CurrentChar);
CurrentCharWidth = (uint8_t) BuiltInFont_props.FontWidth[CurrentCharHex];

// when we reach the selected character where the cursor should go record the values to
// specify where the rectangle should begin and end
if(CurrentCharIndex == Cursor_Position)
{
CursorCharXCoord = TotalStringWidth;
CursorCharWidth = CurrentCharWidth;
}

TotalStringWidth += CurrentCharWidth;
CurrentCharIndex ++;

} while(CurrentCharIndex < MessageSize);


// ###################################################################################################################################
    // Using the font in a display list
    // ###################################################################################################################################


EVE_LIB_BeginCoProList();
EVE_CMD_DLSTART();
EVE_CLEAR_COLOR_RGB(0, 0, 0);
EVE_CLEAR(1,1,1);
EVE_COLOR_RGB(255, 255, 255);

X = 50;
Y = 100;

// ----- add a highlight -----

if(Highlight_Enable == 0xFF)
{
// Draw a rectangle using the efficient rectangles method (see Gameduino 2 cookbook), this is for the highlight
EVE_SAVE_CONTEXT(); // Save details such as current color
EVE_BEGIN(EVE_BEGIN_BITMAPS);
EVE_COLOR_RGB(0, 0, 128); // Set a blue color for the highlight
EVE_BITMAP_HANDLE(Handle_Highlight); // Set the handle
EVE_BITMAP_LAYOUT(EVE_FORMAT_L8, 1, 1); // Set an L8 bitmap 1 x 1
EVE_BLEND_FUNC(EVE_BLEND_ONE, EVE_BLEND_ZERO); // Set the blend function
// Set the size of the rectangle to be the width of the area to be highlighted and the height of the font
EVE_BITMAP_SIZE(EVE_FILTER_NEAREST, EVE_WRAP_REPEAT, EVE_WRAP_REPEAT, HighlightStringWidth, BuiltInFont_props.FontHeightInPixels);
EVE_VERTEX2F((X+FirstCharXCoord)*16, Y*16); // Place the top-left of the rectangle at the same coordinate as the character to be highlighted
EVE_RESTORE_CONTEXT(); // Restore the settings such as text colour for the next characters

// You could also use a standard rectangle here instead of the efficient rectangles
//EVE_COLOR_RGB(0, 0, 128); // Set a blue color for the highlight
//EVE_BEGIN(EVE_BEGIN_RECTS);
//EVE_VERTEX2F((X+FirstCharXCoord)*16, Y*16); // Top-left coordinate
//EVE_VERTEX2F((X+FirstCharXCoord + HighlightStringWidth)*16, (Y+BuiltInFont_props.FontHeightInPixels)*16); // Bottom right coordinate
}

// ----- add a cursor -----

if(Cursor_Enable == 0xFF)
{
// Draw a rectangle using the efficient rectangles method, this is for the cursor
// You could also use a standard rectangle here instead
EVE_SAVE_CONTEXT(); // Save details such as current color
EVE_BEGIN(EVE_BEGIN_BITMAPS);
EVE_COLOR_RGB(0, 0, 128); // Set a blue color for the highlight
EVE_BITMAP_HANDLE(Handle_Cursor); // Set the handle
EVE_BITMAP_LAYOUT(EVE_FORMAT_L8, 1, 1); // Set an L8 bitmap 1 x 1
EVE_BLEND_FUNC(EVE_BLEND_ONE, EVE_BLEND_ZERO); // Set the blend function
// Set the size of the rectangle to be the width of the current character and the height of the font
EVE_BITMAP_SIZE(EVE_FILTER_NEAREST, EVE_WRAP_REPEAT, EVE_WRAP_REPEAT, CursorCharWidth, BuiltInFont_props.FontHeightInPixels);
EVE_VERTEX2F((X+CursorCharXCoord)*16, Y*16); // Place the top-left of the rectangle at the same coordinate as the character to be highlighted
EVE_RESTORE_CONTEXT(); // Restore the settings such as text colour for the next characters
}

EVE_BLEND_FUNC(EVE_BLEND_SRC_ALPHA, EVE_BLEND_ONE_MINUS_SRC_ALPHA); // Set the blend function back to default to avoid affecting rest of screen content

EVE_COLOR_RGB(255, 255, 255); // Color white
EVE_CMD_TEXT(X, Y, BuiltInFont, 0, message); // Write the text itself

EVE_DISPLAY();
EVE_CMD_SWAP();
EVE_LIB_EndCoProList();
EVE_LIB_AwaitCoProEmpty();

    while(1)
    {
    }
« Last Edit: February 09, 2023, 08:42:56 PM by BRT Community »
Logged