QB64Team / qb64

BASIC for the modern era.
https://www.qb64.org
Other
671 stars 96 forks source link

Improvements to print unicode content #71

Open douyuan opened 4 years ago

douyuan commented 4 years ago

Is your feature request related to a problem? Please describe.

  1. PRINT without _MAPUNICODE is currently coercing Unicode character > 255 into ASCII;
    
    SCREEN 12
    f = _LOADFONT("cyberbit.ttf", 32, "MONOSPACE,UNICODE")
    _FONT f
    S$ = STRING$(16, 0)
    ASC(S$, 5) = 65
    ASC(S$, 9) = 78
    ASC(S$, 13) = 67

_MAPUNICODE 78 * 256 + 78 TO 128 ASC(S$, 1) = 128 PRINT S$

_FONT 16

Output "乎ANC";

SCREEN 12 f = _LOADFONT("cyberbit.ttf", 32, "MONOSPACE,UNICODE") _FONT f S$ = STRING$(16, 0) ASC(S$, 5) = 65 ASC(S$, 9) = 78 ASC(S$, 13) = 67

ASC(S$, 1) = 78 ASC(S$, 2) = 78 PRINT S$

_FONT 16

Output "NANC";

2. _PRINTWIDTH with "MONOSPACE,UNICODE" font is 4 times large than the correct value;
ASCII string is 1 byte per character;
Unicode string is UTF-32LE, UTF-32LE is 4 bytes per character;

3. internal/c/libqb.cpp is not well formatted;

**Describe the solution you'd like**
```diff
--- internal/c/libqb.cpp.original   2020-02-13 23:09:47.000000000 +0800
+++ internal/c/libqb.cpp    2020-02-13 23:09:47.000000000 +0800
@@ -10303,6 +10303,10 @@ void printchr(int32 character){
             static int32 rt_w,rt_h,rt_pre_x,rt_post_x;
             //int32 FontRenderTextASCII(int32 i,uint8*codepoint,int32 codepoints,int32 options,
             //                          uint8**out_data,int32*out_x,int32 *out_y,int32*out_x_pre_increment,int32*out_x_post_increment){
+            if (fontflags[f]&32)
+            ok=FontRenderTextUTF32(font[f],(uint32*)&character,1,1,
+            &rt_data,&rt_w,&rt_h,&rt_pre_x,&rt_post_x);
+            else
             ok=FontRenderTextASCII(font[f],(uint8*)&character,1,1,
             &rt_data,&rt_w,&rt_h,&rt_pre_x,&rt_post_x);
             if (!ok) return;
@@ -10349,6 +10353,10 @@ void printchr(int32 character){
         static int32 rt_w,rt_h,rt_pre_x,rt_post_x;
         //int32 FontRenderTextASCII(int32 i,uint8*codepoint,int32 codepoints,int32 options,
         //                          uint8**out_data,int32*out_x,int32 *out_y,int32*out_x_pre_increment,int32*out_x_post_increment){
+        if (fontflags[f]&32)
+        ok=FontRenderTextUTF32(font[f],(uint32*)&character,1,0,
+        &rt_data,&rt_w,&rt_h,&rt_pre_x,&rt_post_x);
+        else
         ok=FontRenderTextASCII(font[f],(uint8*)&character,1,0,
         &rt_data,&rt_w,&rt_h,&rt_pre_x,&rt_post_x);
         if (!ok) return;
@@ -19271,7 +19279,7 @@ void sub_put2(int32 i,int64 offset,void
             if (text->len == 0) return 0; //No point calculating an empty string
             int32 fonthandle = img[screenhandle].font; //Get the font used in screenhandle
             int32 fwidth = func__fontwidth(fonthandle, 1); //Try and get the font width
-            if (fwidth != 0) return fwidth*(text->len); //if it's not a variable width font, return the width * the letter count
+            if (fwidth != 0) return fwidth*(text->len)/(fontflags[fonthandle]&32 ? 4 : 1); //if it's not a variable width font, return the width * the letter count
             int32 fheight = func__fontheight(fonthandle, 1); //Height of the font used in screenhandle
             int32 tempscreen = func__newimage(65535, fheight, 32, 1); //Just like calling _NEWIMAGE
             int32 oldwritepage = func__dest();
  1. Add call to FontRenderTextUTF32 in printchr;
  2. Divide by 4 with monospace Unicode font in func__printwidth;
  3. Maybe GNU indent with "indent --k-and-r-style --no-tabs --ignore-newlines --break-after-boolean-operator --line-length256" is good enough;

Describe alternatives you've considered Not found.

Additional context No Additional context.

FellippeHeitor commented 4 years ago

@flukiluke thoughts?

FellippeHeitor commented 3 years ago

@douyuan does your proposed fix seem to solve the issue without affecting regular text output?

Are you willing to make a pull request?