Font character width & concatenating arrays

Status
Not open for further replies.

xenington

Well-known member
Hi All,

I am trying to determine the width in screen pixels of a character array. The character array can be any length up to 25 characters and is input by the user.

The font data table contains the width information in a struct called __PRGMTAG_. The following is the data for the number "1" with the width information highlighted in red:

Code:
static const uint8_t image_data_MagUbuntuCond_36_0x31[84] __PRGMTAG_  = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x01, 0xe0, 0x07, 0xe0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f, 0xe0, 0x1f, 0xe0, 0x09, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};////character: '1'

static const tImage MagUbuntuCond_36_0x31 __PRGMTAG_ = { image_data_MagUbuntuCond_36_0x31,
    [COLOR="#FF0000"]16[/COLOR], 84};//character: '1' , height: 42, (charW,total bytes)

Here is the define for the struct (lines 48 - 52 font.h linked below):

Code:
	typedef struct __PRGMTAG_ {
			const uint8_t 	*data;
			uint8_t 		image_width;
			int				image_datalen;
} tImage;

I would like to read each character in the array and extract the width for each from the data table. Then add them together to get the total width for the array. I have been able to do the following:

Code:
  char Name[6] = {"123AB"};
  byte lengthName = strlen(Name); 
  for (byte i = 0; i < lengthName; i ++) {
    Serial.printf("MagUbuntuCond_36_0x%x", Name[i]);  
    Serial.println();
  }
    Serial.println(__PRGMTAG_ MagUbuntuCond_36_0x31.image_width);

This produces the following in the serial monitor:

MagUbuntuCond_36_0x31
MagUbuntuCond_36_0x32
MagUbuntuCond_36_0x33
MagUbuntuCond_36_0x41
MagUbuntuCond_36_0x42
16

The hex code for each character (e.g. 0x31 for "1") can be read and attached to the font name using printf. Also, the width for individual characters can be extracted (e.g. 16 for 0x31 "1"). However, I can't find a way to combine the two operations into one.

I have tried various combinations of the following examples, but none work (most don't even compile):

Code:
char widthChar = (Name[i], HEX);
char fontName[22] = "MagUbuntuCond_36_0x";
strcat(fontName, widthChar); 

char fontName = printf("MagUbuntuCond_36_0x%x", Name[i]); 
char fontName = printf("MagUbuntuCond_36_0x", (Name[i], HEX)); 

char widthChar = __PRGMTAG_ MagUbuntuCond_36_0x, Name[i].image_width; 
char widthChar = __PRGMTAG_ MagUbuntuCond_36_0x, (Name[i], HEX).image_width; 

strcat(fontName, (Name[i], HEX));

Does anyone know how I can extract the 'image_width' data on a character by character basis and use it to calculate the array width?

Thank you for any help and suggestions.

The font file is attached.

https://github.com/sumotoy/RA8875/blob/0.70/_settings/font.h
 

Attachments

  • MagUbuntuCond_36.c
    77.6 KB · Views: 56
At the end of your attached C file is an array of type tChar. You need to use that information as the link from character to the font description and image. It looks like this:

Code:
static const tChar MagUbuntuCond_36_array[] = {

  // character: ' '
  {0x20, &MagUbuntuCond_36_0x20},
  // character: '!'
  {0x21, &MagUbuntuCond_36_0x21},
  // character: '"'
  {0x22, &MagUbuntuCond_36_0x22},
  // character: '#'
  {0x23, &MagUbuntuCond_36_0x23},
  // character: '$'
  {0x24, &MagUbuntuCond_36_0x24},
  // character: '%'
  {0x25, &MagUbuntuCond_36_0x25},
  // character: '&'

You can search in that array for your character, or check if your character is greater or equal to a space and just subtract to index directly. Example:

Code:
char Name[6] = {"123AB"};
char c = Name[3];

MagUbuntuCond_36_array[c - ' '].something.something

You then need to de-reference the structures to get the width.
 
Hi

Thank you for the reply. I have tried some things based on your suggestion, but can't get it to work. Could you explain the following a bit more please?

Code:
MagUbuntuCond_36_array[c - ' '].something.something

Thanks.
 
something.something

You need to look in the header file and get the names of the structure members.

Code:
typedef struct __PRGMTAG_ {
			const uint8_t 	*data;
			uint8_t 		image_width;
			int				image_datalen;
	} tImage;

	typedef struct {
			uint8_t 		char_code;
			const tImage 	*image;
	} tChar;

So in tChar the word image is wanted and in tImage the word image_width is wanted. So you end up with something like

Code:
  int width_ = MagUbuntuCond_36_array[c - ' '].*image.image_width;     
  //  Or maybe it is
  int width_ = MagUbuntuCond_36_array[c - ' '].image->image_width;     // the other way to de-reference structures

You may have to play around with that to get it to compile. If you can't get it to work all on one line, break it down one step at a time.
 
Many, many thanks for your help.

It works! I would never have figured it out for myself. Here is what I came up with:

Code:
  byte lengthName = strlen(surveyName); 
  byte widthChar[lengthName];
  int widthName = 0;
  for (byte i = 0; i < lengthName; i ++) {
    byte codeChar = surveyName[i];
    widthChar[i] = MagUbuntuCond_36_array[codeChar - ' '].image->image_width;
    widthName += widthChar[i];  
  }
  for (byte k = lengthName - 1; k > 17; k --) {
    if (widthName <= 500) {
      break;
    }
    widthName -= widthChar[k];
    lengthName --;
  }
  char surveyNameScreen[lengthName];
  for (byte j = 0; j < lengthName; j ++) {
    surveyNameScreen[j] = surveyName[j];
  }  
  tft.setFont(&MagUbuntuCond_36);  
  tft.setCursor(pageTitleX, pageTitleY, true); 
  tft.print(surveyNameScreen);

It obtains the width of each character and adds them up. If the total is more than 500 (the available space on the screen), it removes one character at a time until the width is less than 500 and prints whats left.

Just for others looking for similar: Teensy 3.6 with RA8875 tft 800 x 480.

Thanks again.
 
Status
Not open for further replies.
Back
Top