cancel
Showing results for 
Search instead for 
Did you mean: 

How can I get the width of a character in a specific font?

GS1
Senior III

I am implementing a Custom keyboard to enter text.

Now I want to have

  • a cursor to be displayed at the current location
  • reposition the cursor by touching the text
  • insert text at that position

I achieved to display a cursor, but the position has to be adapted in relation to the text length which depends on the font width of the characters in the text (I have Calibri, which is not monotype).

How can I get the font width of a single character?

And how can I insert text at the current position instead of cutting the text after that insert-position?

Thank you for any suggestions!

5 REPLIES 5
GS1
Senior III

Ok: Text width solution works:

For any one interested, here my solution to calculate the Cursor position for the current buffer position:

int CustomKeyboard::calcCursorPosition()

{

   int n=0, nPos, nCursorPos=0;

   // get font from assets

   Font* font = FontManager::getFont(Typography::CALIBRIMEDIUM);

   nPos = keyboard.getBufferPosition();

   for (n = 0; n < nPos; n++)

   {

       nCursorPos+= font->getCharWidth(buffer[n]);

   }

   return nCursorPos;

}

GS1
Senior III

Ok, and now I got the insert functionality working with following steps:

1)

Save Text of keyboard buffer to a copy buffer at startup and every time a character is inserted:

Unicode::strncpy(bufSav, buffer, BUFFER_SIZE);

2)

Adapt keyPressedhandler:

void CustomKeyboard::keyPressedhandler(Unicode::UnicodeChar keyChar)

{

   uint16_t pos = keyboard.getBufferPosition();

   int n, nSize,nSizeOld;

   nSize = Unicode::strlen(buffer);

   nSizeOld = Unicode::strlen(bufSav);

   if ((nSizeOld >= nSize) &&  (nSizeOld > 0)) 

   {

       if (bClickedSpecialKey != true)   // not Backspace/Mode/Shift?

       {

            // Restore remaining text from copy

           for (n = pos; n < BUFFER_SIZE; n++)

           {

               buffer[n] = bufSav[n-1];

           }

       }

   }

   bClickedSpecialKey = false;

   // Save current buffer for Insert-Handling

   Unicode::strncpy(bufSav, buffer, BUFFER_SIZE);

   // After the first keypress, the keyboard will shift to lowercase.

   if (firstCharacterEntry && keyChar != 0)

   {

       firstCharacterEntry = false;

       uppercaseKeys = false;

       setKeyMappingList();

   }

   setCaret(); // Cursor at current position

}

JimFouch
Associate III

This is very helpful. I'm also going to need a full keyboard for my project. I was going to write my own as I want to be able to allow users to edit better. Only allowing them to BS over the last character will not cut it for my project.

I was going to just write my own keyboard from scratch, but it looks like you have enhanced the current custom keyboard object.

Thanks for posting this.

Hi Jim,

just in case you need the cursor implementation, please see how it is done in the following link. I did take this feature from there:

https://touchgfx.zendesk.com/hc/en-us/community/posts/115002704212-Keyboard-Cursor

In my user interface I have included two buttons which process to move the cursor 1 position to the left and right so this allows to set the cursor to any character position in the edit field.

I am still working on the direct touch handling to set the cursor anywhere in the text area.

Have a Merry Christmas and a Happy New Year!

GS1
Senior III

Ok, finally I have the time to provide the last step for setting the cursor to any place within the string by clicking in the text area:

1) Forward the handleClickEvent to the CustomKeyboard form the view.

2) Handle Click Event in the CustomKeyboard:

void CustomKeyboard::handleClickEvent(const ClickEvent& evt)

{

   unsigned int x = evt.getX();

   unsigned int y = evt.getY();

   // in case clicked into text field area:

   if ((x >= TEXT_POS_X) && (x <= (TEXT_POS_X + TEXT_POS_WIDTH)) &&

       (y >= TEXT_POS_Y) && (y <= (TEXT_POS_Y + TEXT_POS_HEIGHT)))

   {

       x -= TEXT_POS_X;

   // find closest Position of click event

       m_position = findPosition(x);

       //This find the end of buffer so that the caret will not appear at a weird place

       if (m_position > BUFFER_SIZE)

       {

           m_position = BUFFER_SIZE;

       }

       keyboard.setBufferPosition(m_position);

       setCaret();

   }

}

uint16_t CustomKeyboard::findPosition(int x)

{

   int nSize, i, nTextPos=0;

   nSize = Unicode::strlen(buffer);

   for (nTextPos = 0; nTextPos <= nSize; nTextPos++)

   {

       i = calcCursorPosition(nTextPos);  

       if (i >= x)    // Beyond clicked Position

       {

           // Cursor would be set after the character which is on the right side of the click position

           if (nTextPos > 0)

               nTextPos--;    // Therefore: set to one position on the left

           return (uint16_t)nTextPos;

        }

   return (uint16_t)nTextPos;

}