Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: Font character width & concatenating arrays

  1. #1
    Junior Member
    Join Date
    Oct 2018
    Posts
    10

    Font character width & concatenating arrays

    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,
        16, 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/bl...ettings/font.h
    Attached Files Attached Files

  2. #2
    Senior Member
    Join Date
    May 2017
    Posts
    202
    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.

  3. #3
    Junior Member
    Join Date
    Oct 2018
    Posts
    10
    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.

  4. #4
    Senior Member
    Join Date
    May 2017
    Posts
    202
    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.

  5. #5
    Junior Member
    Join Date
    Oct 2018
    Posts
    10
    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •