U8g2_for_Adafruit_GFX icon indicating copy to clipboard operation
U8g2_for_Adafruit_GFX copied to clipboard

Problem with "u8g2_font_unifont_t_bengali"

Open muhit313 opened this issue 3 years ago • 74 comments

Thanks for your big library support. But I had some problem with "u8g2_font_unifont_t_bengali" this font. I want to show Bengali word "আমার" on my ST7735 display. But it show me the output আম ার and want to show Bengali word "মুহিত" on my ST7735 display but it show me the output ম ুহ িত . I can't understand where is the wrong ? How can I solved it?

#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <U8g2_for_Adafruit_GFX.h>

#define TFT_CS   8
#define TFT_RST  7
#define TFT_DC   6

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
U8G2_FOR_ADAFRUIT_GFX u8g2_for_adafruit_gfx;

void setup(void) {
  tft.initR(INITR_BLACKTAB);      // Init ST7735S chip, black tab
  tft.setRotation(0);
  tft.fillScreen(ST77XX_BLACK);
  u8g2_for_adafruit_gfx.begin(tft);
}

void loop() {
  u8g2_for_adafruit_gfx.setFontMode(0);                 
  u8g2_for_adafruit_gfx.setFontDirection(0);
  u8g2_for_adafruit_gfx.setForegroundColor(ST77XX_YELLOW);
  u8g2_for_adafruit_gfx.setFont(u8g2_font_unifont_t_bengali);
  u8g2_for_adafruit_gfx.setCursor(20, 20);
  u8g2_for_adafruit_gfx.print("আমার"); 
}

muhit313 avatar Nov 16 '21 09:11 muhit313

This is not supported due to missing kerning support. There is an idea of a local kerning table implemented in u8g2 (https://github.com/olikraus/u8g2/issues/42), but not in this library.

olikraus avatar Nov 16 '21 20:11 olikraus

I read your kernel table implementation algorithm. I am a begainer. So I don't have enough idea. This is a nice library for Bengali support with st7735 display. But other library may not. Please suggest me how can I do this.... with st7735 and your library.

muhit313 avatar Nov 17 '21 19:11 muhit313

Not possible with this library

olikraus avatar Nov 17 '21 20:11 olikraus

Not possible with this library

This is a sad news for me....... Please suggest me another library where I can do same things. Many thanks for your nice support.

muhit313 avatar Nov 18 '21 09:11 muhit313

This is a sad news for me.......

You could still output each unicode individually, char by char with the correct distance to the previous char.

Please suggest me another library where I can do same things.

I have created a lib because there is nothing else out there ;-)

In other words: I do not know. Especially for a RGB display like the ST7735 i think there is not even unicode support in any other lib.

olikraus avatar Nov 18 '21 13:11 olikraus

You could still output each unicode individually, char by char with the correct distance to the previous char.

This idea isn't bad.... But the problem is when I need to print big text with scrolling than may be I can't manage it.

muhit313 avatar Nov 18 '21 16:11 muhit313

But the problem is when I need to print big text with scrolling than may be I can't manage it.

You could automate the process of outputting char by char, by creating a distance table for each char. Something like this: struct chardistance { unsigned firstchar; unsigned secondchar; int distance; }

struct chardistance distancetable[] = { { 'a', 'b', 4} // distance between a and b are 4 pixel };

So you create your own string output: Output the first char of the string while there are chars in the string get the distance to the second char by looking up the distance in your distance table advance by the distance found output second char. fist char = second char

olikraus avatar Nov 18 '21 17:11 olikraus

Thanks again for your reply by wasting time for me.

I am really sorry for distrubing you again and again.

May be I understood your concept almost.
If I am not wrong, I have a String str = "আমার সোনার বাংলা আমি তোমায় ভালোবাসি। চিরদিন তোমার আকাশ, তোমার বাতাস...." or more big than that. First I need to split the string into char array. Then placed all of them char by char in a distance that I need.

I am right?

But as a newbie I am little bit confessed how to implement this using Structure. But I am trying to do this still now.

If you feel free and have enough time then can you help me by giving an example for this string "আমার সোনার বাংলা আমি তোমায় ভালোবাসি। চিরদিন তোমার আকাশ, তোমার বাতাস…." to implement.

muhit313 avatar Nov 19 '21 14:11 muhit313

First I need to split the string into char array.

In C / C++ strings and char arrays are the same. But actually you need to specify the distance between each char. Let's take the first word: "আমার" It contains three chars, right? 1: আ 2: মা 3: র As a preparation you need to tell the distance between আ and মা --> 4 pixel distance মা and র --> 4 pixel distance

The 4 pixel distance is just an example. This is somehting you need to figure out.

Then you take the string "আমার" You print আ Then you look for the distance between আ and মা Then you move to the next position specified by the distance then you print মা Then you look for the distance between মা and র Then you move to the next position specified by the distance then you print র

The result shell look like "আমার"

olikraus avatar Nov 19 '21 16:11 olikraus

@olikraus nice explanation ...Ok I will try to my best to implement this.

But if you give a code example for me it will more better for understanding ...

I am ashamed for this type of help.

Thank you.

muhit313 avatar Nov 19 '21 18:11 muhit313

/*

  Bengali.ino
  
  List of all U8g2 fonts: https://github.com/olikraus/u8g2/wiki/fntlistall
      
*/
#include <Adafruit_SSD1306.h>
#include <U8g2_for_Adafruit_GFX.h>

const uint16_t distance_adjust_table[] = 
{
  /* first char, second char, gap reduction value */
  0x09AE, 0x9BE, 12, /* reduce distance between ম  and া  by 12 */
        /* add more pairs here... */
  
  /* this line terminates the table */
  0xffff, 0xffff, 0xffff
};

/* get distance from the distance table */
uint16_t get_distance_adjust(uint16_t e1, uint16_t e2)
{
  uint16_t i;
  i = 0;
  for(;;)
  {
    if ( distance_adjust_table[i] == 0x0ffff )
      break;
    if ( distance_adjust_table[i] == e1 && distance_adjust_table[i+1] == e2 )
      return distance_adjust_table[i+2];
    i+=3;
  }
  return 0;
}

int16_t draw_string(U8G2_FOR_ADAFRUIT_GFX &u8g2, int16_t x, int16_t y, const char *str)
{
  uint16_t e_prev = 0x0ffff;
  uint16_t e;
  uint16_t delta, adjust, sum;
  
  delta = 0;
  adjust = 0;
  u8g2.utf8_state = 0;
  
  sum = 0;
  for(;;)
  {
    e = u8g2.utf8_next((uint8_t)*str);
    if ( e == 0x0ffff )
      break;
    str++;
    if ( e != 0x0fffe )
    {
      delta = u8g2_GetGlyphWidth(&(u8g2.u8g2), e);      
      adjust = get_distance_adjust(e_prev, e);
      e_prev = e;
      u8g2_DrawGlyph(&(u8g2.u8g2), x-adjust, y, e);
      x += delta-adjust;
      sum += delta-adjust;    
    }
  }
  return sum;
}


Adafruit_SSD1306 display(/*MOSI*/ 11, /*CLK*/ 13, /*DC*/ 9, /*RESET*/ 8, /*CS*/ 10);
U8G2_FOR_ADAFRUIT_GFX u8g2_for_adafruit_gfx;

void setup() {
  display.begin(SSD1306_SWITCHCAPVCC);
  u8g2_for_adafruit_gfx.begin(display);                 // connect u8g2 procedures to Adafruit GFX
}

void loop() {  
  display.clearDisplay();                               // clear the graphcis buffer  
  u8g2_for_adafruit_gfx.setFont(u8g2_font_helvR14_tf);  // select u8g2 font from here: https://github.com/olikraus/u8g2/wiki/fntlistall
  u8g2_for_adafruit_gfx.setFontMode(1);                 // use u8g2 transparent mode (this is default)
  u8g2_for_adafruit_gfx.setFontDirection(0);            // left to right (this is default)
  u8g2_for_adafruit_gfx.setForegroundColor(WHITE);      // apply Adafruit GFX color
  u8g2_for_adafruit_gfx.setCursor(0,20);                // start writing at this position
  u8g2_for_adafruit_gfx.print("Hello World");
  u8g2_for_adafruit_gfx.setCursor(0,40);                // start writing at this position
  u8g2_for_adafruit_gfx.print("Umlaut ÄÖÜ");            // UTF-8 string with german umlaut chars
  u8g2_for_adafruit_gfx.setFont(u8g2_font_unifont_t_bengali);  // select Bengali font
  draw_string(u8g2_for_adafruit_gfx, 0,60, "আমার");          // draw Bengali string

  display.display();                                    // make everything visible
  delay(2000);
} 

NOT TESTED!

olikraus avatar Nov 19 '21 20:11 olikraus

NOT TESTED!

No problem. You give me an example by wasting your time and its enough. I will test it myself and give you feedback if it works or not. Many thanks to you for your support. You are really a helpful man.

muhit313 avatar Nov 19 '21 23:11 muhit313

@olikraus Many many thanks for your example. Your example works fine.

May be this is the last request to you. After this I will close this issue. Because I disturb you many time. I am really sorry for that.

Now I want to show a full sentence like ""আমার সোনার বাংলা আমি". So I added some line in your example.

const uint16_t distance_adjust_table[] = 
{
  /* first char, second char, gap reduction value */
  0x09AE, 0x9BE, 12, /* reduce distance between ম  and া  by 12 */
 /* add more pairs here... */
  0x09B8, 0x09CB, 12, //for স and ো
  0x09A8, 0x09BE, 12, //for ন and া
  0x09AE, 0x09BF, 14, //for ম and ি
  0x09AC, 0x09BE, 12, //for ব and া
  0x09BE, 0x0982, 12, //for া and ং
  0x09B2, 0x09BE, 12, //for ল and া
  0x09AE, 0x09BF, 4, //for ম and ই
  /* this line terminates the table */
  0xffff, 0xffff, 0xffff
};

I want to print "সোনার" , "আমি" and আব্দ so I add 0x09B8, 0x09CB, 12 //for স and ো and 0x09AE, 0x09BF, 14, //for ম and ি in distance_adjust_table. But the out put is not expected. I changed the distance value 12 to 14/10/8..... and many more but can't saw any change. ো hide the স and ি hide the ম char.

**Without ো , ি and ব্দ all works fine. **

Where is the problem with this type of char? How can I overcome this?

Here is the full code:

#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <U8g2_for_Adafruit_GFX.h>

#define TFT_CS   8
#define TFT_RST  7
#define TFT_DC   6

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
U8G2_FOR_ADAFRUIT_GFX u8g2_for_adafruit_gfx;

const uint16_t distance_adjust_table[] = 
{
  /* first char, second char, gap reduction value */
  0x09AE, 0x9BE, 12, /* reduce distance between ম  and া  by 12 */
 /* add more pairs here... */
  0x09B8, 0x09CB, 12, //for স and ো
  0x09A8, 0x09BE, 12, //for ন and া
  0x09AE, 0x09BF, 14, //for ম and ি
  0x09AC, 0x09BE, 12, //for ব and া
  0x09BE, 0x0982, 12, //for া and ং
  0x09B2, 0x09BE, 12, //for ল and া
  0x09AC, 0x09CD, 12, //for ব and ্
  0x09CD, 0x09A6, 12, //for ্ and দ
  /* this line terminates the table */
  0xffff, 0xffff, 0xffff
};

/* get distance from the distance table */
uint16_t get_distance_adjust(uint16_t e1, uint16_t e2)
{
  uint16_t i;
  i = 0;
  for(;;)
  {
    if ( distance_adjust_table[i] == 0x0ffff )
      break;
    if ( distance_adjust_table[i] == e1 && distance_adjust_table[i+1] == e2 )
      return distance_adjust_table[i+2];
    i+=3;
  }
  return 0;
}

int16_t draw_string(U8G2_FOR_ADAFRUIT_GFX &u8g2, int16_t x, int16_t y, const char *str)
{
  uint16_t e_prev = 0x0ffff;
  uint16_t e;
  uint16_t delta, adjust, sum;
  
  delta = 0;
  adjust = 0;
  u8g2.utf8_state = 0;
  
  sum = 0;
  for(;;)
  {
    e = u8g2.utf8_next((uint8_t)*str);
    if ( e == 0x0ffff )
      break;
    str++;
    if ( e != 0x0fffe )
    {
      delta = u8g2_GetGlyphWidth(&(u8g2.u8g2), e);      
      adjust = get_distance_adjust(e_prev, e);
      e_prev = e;
      u8g2_DrawGlyph(&(u8g2.u8g2), x-adjust, y, e);
      x += delta-adjust;
      sum += delta-adjust;    
    }
  }
  return sum;
}

void setup(void) {
  tft.initR(INITR_BLACKTAB);      // Init ST7735S chip, black tab
  tft.setRotation(0);
  tft.fillScreen(ST77XX_BLACK);
  u8g2_for_adafruit_gfx.begin(tft);
}

void loop() {
  u8g2_for_adafruit_gfx.setFont(u8g2_font_helvR14_tf);  // select u8g2 font from here: https://github.com/olikraus/u8g2/wiki/fntlistall
  u8g2_for_adafruit_gfx.setFontMode(1);                 // use u8g2 transparent mode (this is default)
  u8g2_for_adafruit_gfx.setFontDirection(0);            // left to right (this is default)
  u8g2_for_adafruit_gfx.setForegroundColor(ST77XX_WHITE);      // apply Adafruit GFX color
  u8g2_for_adafruit_gfx.setCursor(0,20);                // start writing at this position
  u8g2_for_adafruit_gfx.setFont(u8g2_font_unifont_t_bengali);  // select Bengali font
  draw_string(u8g2_for_adafruit_gfx, 0,20, "আমার সোনার");
  draw_string(u8g2_for_adafruit_gfx, 0,40, "বাংলা আমি");          // draw Bengali string
  draw_string(u8g2_for_adafruit_gfx, 0,60, "আব্দ");
  delay(2000); 
}

Here is the output:

20211121_115910

muhit313 avatar Nov 21 '21 06:11 muhit313

Good question, but I don't know the answer. Maybe there is still a bug in the code?

olikraus avatar Nov 21 '21 08:11 olikraus

Maybe there is still a bug in the code?

In which part of the code have bug? I can see all is ok. May be I had made some mistook when add char in in code ..... If you see the last code I post where I add some pair of char to reduce distance may be here is the bug? I am a not an professional programmer. As you are an expert you can find out the bug easily. If you can please tell me where are the bug.

muhit313 avatar Nov 21 '21 17:11 muhit313

Maybe there is no bug. I also don't understand your problem clearly. Anyhow, I can give hints and maybe examples, but I can not solve your problems.

olikraus avatar Nov 21 '21 17:11 olikraus

Maybe there is no bug. I also don't understand your problem clearly.

Yes you are right. I am not good at English too. That's why may be I fail to explain my problem. Sorry for that.

Anyhow, I can give hints and maybe examples, but I can not solve your problems.

Thanks for your continuous help by giving hints and examples. I am sorry for disturb you. You are right, I should solve my problem myself. Actually I am a learner that's why all things are not clear to me. Now I will try to solve it. But there is no good teacher besides me. I think you are really a good teacher for me.

There is no problem at all with your example.

  1. But when I want to show this word "সোনার" then স is hide. Only " োনার" is shown.
  2. And when I want to show this word "আব্দ" then ব is hide. Only "আদ" is shown.

Basically I don't know why it occurs.

Ok..... You should close this issue. Because I disturb you many times. Thanks you so much again.

muhit313 avatar Nov 21 '21 18:11 muhit313

Did you use u8g2_for_adafruit_gfx.setFontMode(1); ? It is important to use the transparent mode.

olikraus avatar Nov 21 '21 21:11 olikraus

Did you use u8g2_for_adafruit_gfx.setFontMode(1); ?

Yes, I used u8g2_for_adafruit_gfx.setFontMode(1);

You can see this in the code of the previous post.

I have a ssd1306 display too. Should I try it in ssd1306 display?

Or Is this two value is correct 0x09B8, 0x09CB, 12 //reduce distance between স and ো 0x09AE, 0x09BF, 10, //reduce distance between ম and ি May be here I had made a mistook.

muhit313 avatar Nov 22 '21 00:11 muhit313

u8g2_for_adafruit_gfx.setFontMode(1); You can see this in the code of the previous post.

Yes, but it did work correctly when I tested this, so I think there is an issue with the font mode.

olikraus avatar Nov 22 '21 06:11 olikraus

my test happend here: https://github.com/olikraus/u8g2/blob/0c82f8cc5ec5cd4dd791e7df5a82f264ee44da3b/sys/sdl/text_kerning_manual/main.c#L92-L99

olikraus avatar Nov 22 '21 06:11 olikraus

my test happend here: https://github.com/olikraus/u8g2/blob/0c82f8cc5ec5cd4dd791e7df5a82f264ee44da3b/sys/sdl/text_kerning_manual/main.c#L92-L99

You did it using c programming and may be compile with c compiler. I will test it in Arduino IDE. May I need to add some line from this code to previous code.

And that is:

do
    {
      k = u8g_sdl_get_key();
    } while( k < 0 );
    
    if ( k == 273 ) y -= 7;
    if ( k == 274 ) y += 7;
    if ( k == 276 ) x -= 7;
    if ( k == 275 ) x += 7;
    
    if ( k == 'e' ) y -= 1;
    if ( k == 'x' ) y += 1;
    if ( k == 's' ) x -= 1;
    if ( k == 'd' ) x += 1;
    if ( k == 'q' ) break;   
  }
  do
    {
      k = u8g_sdl_get_key();
    } while( k < 0 );
    
    if ( k == 273 ) y -= 7;
    if ( k == 274 ) y += 7;
    if ( k == 276 ) x -= 7;
    if ( k == 275 ) x += 7;
    
    if ( k == 'e' ) y -= 1;
    if ( k == 'x' ) y += 1;
    if ( k == 's' ) x -= 1;
    if ( k == 'd' ) x += 1;
    if ( k == 'q' ) break;  
}

This line are missing in previous code. Am I right?

But I am confused about u8g_sdl_get_key(); method. It made error when I compiled the code. Do I need to add the same method is arduino code?

muhit313 avatar Nov 22 '21 14:11 muhit313

No, no, you can't takeover something. My test is u8g2 with SDL under Linux.

olikraus avatar Nov 22 '21 17:11 olikraus

No, no, you can't takeover something. My test is u8g2 with SDL under Linux.

You mean that I don't need to add this line of code. Previous code are correct and work perfectly in you Linux SDL. And no need to add any extra line for "সোনার" this word?

muhit313 avatar Nov 23 '21 03:11 muhit313

I am really happy to meet a such helpful man like you. May be I can't solve it without your example and continuous help. You are really a great man for me. Thank you so much.

Finally I got the problem. When I remove u8g2_for_adafruit_gfx.setFont(u8g2_font_helvR14_tf); this line the code work perfectly for all word.

But In Bengali letter there are some compound letter like " ব্দ " which formed from "ব+্+দ" , and letter "ম্ম" is formed "ম+্+ম" . If this type of compound letter work then I can complete my main project perfectly.

Now I need to search for how to solve this " ব্দ " , "ম্ম" type of compound letter . I think this is difficult task than the previous one. But don't know how to do this.

muhit313 avatar Nov 23 '21 04:11 muhit313

Now I need to search for how to solve this " ব্দ " , "ম্ম" type of compound letter . I think this is difficult task than the previous one. But don't know how to do this.

You might be used to enter "ম্ম" directly, but the problem is, that you do not know what character numbers are used by your editor (or Arduino IDE). It might be usefull to use the hex name of the intended letter, something like "\U00000444". This will not be readable, but you will have full control.

olikraus avatar Nov 23 '21 08:11 olikraus

@olikraus After searching for longtime I saw that many people like david_prentice in Arduino forum suggest Oliver for help.

One person said that " ব্দ " , "ম্ম", "ল্ল", "স্ব" these are trigrams. So I need an additional table for trigrams. But don't know how to make a additional table for trigrams.

I think as an expert you know how to make additional table for trigrams for letter like " ব্দ " , "ম্ম", "ল্ল", "স্ব".

muhit313 avatar Nov 25 '21 08:11 muhit313

One person suggested this:

I think you have 2 options.

Either you create a table with trigrams and distance adjustment, with '+্+' as the middle character, and also search through this table.

Or you create a table for trigrams, containing only the characters to combine with distance adjustment, and search through it whenever you encounter a '+্+'. In this case you draw the symbol for '+্+' if the adjacent characters are not found in the table.

This will terminate my effort to try to support you, as I have other pending work to do.

Jean-Marc

This forum section might be for you: Jobs and Paid Consultancy

in https://forum.arduino.cc/t/problem-with-utf8-or-unicode-support-in-any-display/928000/12?u=zinggjm

ZinggJM avatar Nov 25 '21 09:11 ZinggJM

@ZinggJM Yes your are the person who suggest me this.

Can you give An example for trigram table for one compound letter?

muhit313 avatar Nov 25 '21 09:11 muhit313

Yes, I could. Maybe next week.

ZinggJM avatar Nov 25 '21 09:11 ZinggJM