FLTK logo

[branch-1.3] 20138be - macOS: Fix color component mixup in gl_draw text rendering #947

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Library      Forums      Links      Apps     Login 
 All Forums  |  Back to fltk.commit  ]
 
Previous Message ]Next Message ]

[branch-1.3] 20138be - macOS: Fix color component mixup in gl_draw text rendering #947 "Matthias Melcher" Apr 05, 2024  
 
commit 20138be66be721405b142d13cab4dbd37c425d4f
Author:     Matthias Melcher <github@matthiasm.com>
AuthorDate: Fri Apr 5 18:02:39 2024 +0200
Commit:     Matthias Melcher <github@matthiasm.com>
CommitDate: Fri Apr 5 18:02:39 2024 +0200

    macOS: Fix color component mixup in gl_draw text rendering #947

 src/gl_draw.cxx | 40 +++++++++++++++++++++++++++++++++-------
 1 file changed, 33 insertions(+), 7 deletions(-)

diff --git src/gl_draw.cxx src/gl_draw.cxx
index 1c120d9..d4914c9 100644
--- src/gl_draw.cxx
+++ src/gl_draw.cxx
@@ -365,6 +365,7 @@ private:
     int width; // its width
     float ratio; // used without rectangle texture
     int scale; // 1 or 2 for low/high resolution
+    Fl_Color color;
   } data;
   data *fifo; // array of pile elements
   int size_; // pile height
@@ -415,7 +416,7 @@ void gl_texture_fifo::display_texture(int rank)
   glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT);
   glDisable (GL_DEPTH_TEST); // ensure text is not removed by depth buffer test.
   glEnable (GL_BLEND); // for text fading
-  glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // ditto
+  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // ditto
   glDisable(GL_LIGHTING);
   GLfloat pos[4];
   glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
@@ -426,6 +427,10 @@ void gl_texture_fifo::display_texture(int rank)
   glScalef (R/winw, R/winh, 1.0f);
   glTranslatef (-winw/R, -winh/R, 0.0f);
   if (has_texture_rectangle) {
+    // The texture map is already colored, but we still need to apply alpha.
+    GLfloat colors[4];
+    glGetFloatv(GL_CURRENT_COLOR, colors);
+    glColor4f(1.0f, 1.0f, 1.0f, colors[3]);
     glEnable (GL_TEXTURE_RECTANGLE_ARB);
     glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fifo[rank].texName);
     GLint height;
@@ -444,6 +449,8 @@ void gl_texture_fifo::display_texture(int rank)
 
     glTexCoord2f (fifo[rank].width, 0.0f); // draw lower right in world coordinates
     glVertex2f (bounds.origin.x + bounds.size.width, bounds.origin.y);
+    // Restore the current color value.
+    glColor4fv(colors);
     glEnd ();
   } else {
     glTranslatef(pos[0]*2/R, pos[1]*2/R, 0.0);
@@ -492,12 +499,19 @@ int gl_texture_fifo::compute_texture(const char* str, int n)
     void *base = NULL;
     if (fl_mac_os_version < 100600) base = calloc(4*fifo[current].width, h);
     CGContextRef save_gc = fl_gc;
-    fl_gc = CGBitmapContextCreate(base, fifo[current].width, h, 8, fifo[current].width*4, lut,
-                                  (CGBitmapInfo)(kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
+    // Create our bitmap in RGBA order (no matter what the host byte order is)
+    fl_gc = CGBitmapContextCreate(base, fifo[current].width, h, 8, fifo[current].width*4, lut, kCGImageAlphaPremultipliedLast);
     CGColorSpaceRelease(lut);
+    // Note that glyphs in macOS can be colorful (Emojis, for example). So
+    // instead of caching a mask, we store the text in RGB plus A for
+    // antialiasing. Draw the text in the requested color, but don't apply user
+    // alpha yet. It is applied later at render time so it's mixed correctly
+    // with the background.
     GLfloat colors[4];
     glGetFloatv(GL_CURRENT_COLOR, colors);
-    fl_color((uchar)(colors[0]*255), (uchar)(colors[1]*255), (uchar)(colors[2]*255));
+    Fl_Color color = ((uchar)(colors[0]*255)<<24) | ((uchar)(colors[1]*255)<<16) | ((uchar)(colors[2]*255)<<8);
+    fifo[current].color = color;
+    fl_color(color);
     CGContextTranslateCTM(fl_gc, 0, h - gl_scale*fl_descent());
     CGContextScaleCTM(fl_gc, gl_scale, gl_scale);
     fl_draw(str, n, 0, 0);
@@ -506,7 +520,8 @@ int gl_texture_fifo::compute_texture(const char* str, int n)
     glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fifo[current].texName);
     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     glPixelStorei(GL_UNPACK_ROW_LENGTH, fifo[current].width);
-    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, fifo[current].width, h, 0,  GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, CGBitmapContextGetData(fl_gc));
+    // Convert the created text bitmap into an RGBA OpenGL texture map.
+    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, fifo[current].width, h, 0,  GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, CGBitmapContextGetData(fl_gc));
     glPopAttrib();
     CGContextRelease(fl_gc);
     fl_gc = save_gc;
@@ -521,9 +536,20 @@ int gl_texture_fifo::compute_texture(const char* str, int n)
 int gl_texture_fifo::already_known(const char *str, int n)
 {
   int rank;
+  GLfloat colors[4];
+  glGetFloatv(GL_CURRENT_COLOR, colors);
+  Fl_Color color = ((uchar)(colors[0]*255)<<24) | ((uchar)(colors[1]*255)<<16) | ((uchar)(colors[2]*255)<<8);
   for ( rank = 0; rank <= last; rank++) {
-    if ( memcmp(str, fifo[rank].utf8, n) == 0 && fifo[rank].utf8[n] == 0 &&
-      fifo[rank].fdesc == gl_fontsize && fifo[rank].scale == gl_scale) return rank;
+    const data &ff = fifo[rank];
+    if (   (ff.fdesc == gl_fontsize)
+        && (ff.scale == gl_scale)
+        && (ff.color == color)
+        && (ff.utf8 != NULL)
+        && (memcmp(str, ff.utf8, n) == 0)
+        && (ff.utf8[n] == 0))
+    {
+      return rank;
+    }
   }
   return -1;
 }
Direct Link to Message ]
 
     
Previous Message ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2025 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.