Updates to Palette rendering - Fixes bug 882.

Glenn Wurster gwurster at scs.carleton.ca
Wed Sep 29 00:26:50 CDT 2004


Authors:
  Doug Paul <doug at elemental.ath.cx>,
  Glenn Wurster <gwurster at scs.carleton.ca>

Description:
* Patch to fix bug 882 which is outstanding against Alpha Centauri.

* In addition to PALETTEINDEX(0x01) and PALETTERGB(0x00) as macros for
specifying colour through the GDI colour functions, there is also
SYSPALETTEINDEX(0x10).  0x10 as a value maps the colour to the system
palette, which is the palette used by Alpha Centauri for text.

* Changed switch of PC_EXPLICIT, PC_NOCOLLAPSE, and PC_RESERVED to an
if statement, since if multiple flags are set it is not appropriate to
act as if none were set.

* When we are working with a palette, we need to disable antialiasing.
Antialiasing results in a lot of extra colour values which are not
mapped in the palette, causing bad display artifacts.

* AnimatePalette did not check peFlags to ensure that it was set to
PC_RESERVED.

* SetPaletteEntries unrealized the palette at the end so the check at
the end of AnimatePalette would always fail, causing the new palette
to not be realized and actually be unrealized by a call to
AnimatePalette.

Changelog:
 * Bugfix: Bug 882
 * Handle SYSPALETTEINDEX(0x10) as a COLORREF high byte
 * Change reading of PC_(EXPLICIT|NOCOLLAPSE|RESERVED) to handle
   multiple values
 * Disable antialiasing when working with the palette
 * check peFlags for PC_RESERVED in AnimatePalette
 * Don't unrealize the palette in SetPaletteEntries
 * Doug Paul <doug at elemental.ath.cx>
 * Glenn Wurster <gwurster at scs.carleton.ca>

Index: dlls/gdi/palette.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/palette.c,v
retrieving revision 1.1
diff -u -u -r1.1 palette.c
--- dlls/gdi/palette.c	21 Jul 2004 04:07:28 -0000	1.1
+++ dlls/gdi/palette.c	29 Sep 2004 04:46:45 -0000
@@ -446,7 +446,41 @@
 
     if( hPal != GetStockObject(DEFAULT_PALETTE) )
     {
-        if (!SetPaletteEntries( hPal, StartIndex, NumEntries, PaletteColors )) return FALSE;
+        PALETTEOBJ * palPtr;
+        UINT pal_entries;
+        PALETTEENTRY *pptr = PaletteColors;
+
+        palPtr = (PALETTEOBJ *) GDI_GetObjPtr( hPal, PALETTE_MAGIC );
+        if (!palPtr) return 0;
+
+        pal_entries = palPtr->logpalette.palNumEntries;
+        if (StartIndex >= pal_entries)
+        {
+          GDI_ReleaseObj( hPal );
+          return 0;
+        }
+        if (StartIndex+NumEntries > pal_entries) NumEntries = pal_entries - StartIndex;
+        
+        for (NumEntries += StartIndex; StartIndex < NumEntries; StartIndex++, pptr++) {
+          /* According to MSDN, only animate PC_RESERVED colours */
+          if (palPtr->logpalette.palPalEntry[StartIndex].peFlags & PC_RESERVED) {
+            TRACE("Animating colour (%d,%d,%d) to (%d,%d,%d)\n",
+              palPtr->logpalette.palPalEntry[StartIndex].peRed,
+              palPtr->logpalette.palPalEntry[StartIndex].peGreen,
+              palPtr->logpalette.palPalEntry[StartIndex].peBlue,
+              pptr->peRed, pptr->peGreen, pptr->peBlue);
+            memcpy( &palPtr->logpalette.palPalEntry[StartIndex], pptr,
+                    sizeof(PALETTEENTRY) );
+            PALETTE_ValidateFlags(&palPtr->logpalette.palPalEntry[StartIndex], 1);
+          } else {
+            TRACE("Not animating entry %d -- not PC_RESERVED\n", StartIndex);
+          }
+        }
+        
+        GDI_ReleaseObj( hPal );
+        
+        TRACE("pLastRealizedDC %p -- pLastRealizedDC->pRealizePalette %p\n",
+          pLastRealizedDC, pLastRealizedDC ? pLastRealizedDC->pRealizePalette : 0);
 
         if (pLastRealizedDC && pLastRealizedDC->pRealizePalette)
             pLastRealizedDC->pRealizePalette( NULL, hPal, hPal == hPrimaryPalette );
@@ -669,6 +703,7 @@
     }
     if (hLastRealizedPalette == handle)
     {
+        TRACE("unrealizing palette %p\n", handle);
         hLastRealizedPalette = 0;
         pLastRealizedDC = NULL;
     }
@@ -686,6 +721,7 @@
     HeapFree( GetProcessHeap(), 0, palette->mapping );
     if (hLastRealizedPalette == handle)
     {
+        TRACE("unrealizing palette %p\n", handle);
         hLastRealizedPalette = 0;
         pLastRealizedDC = NULL;
     }
Index: dlls/x11drv/palette.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/palette.c,v
retrieving revision 1.7
diff -u -u -r1.7 palette.c
--- dlls/x11drv/palette.c	11 Aug 2004 23:45:34 -0000	1.7
+++ dlls/x11drv/palette.c	29 Sep 2004 04:46:47 -0000
@@ -227,21 +227,19 @@
     {
         palette_size = 0;
     }
+
+    if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
+        X11DRV_PALETTE_BuildPrivateMap( sys_pal_template );
     else
-    {
-        if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
-            X11DRV_PALETTE_BuildPrivateMap( sys_pal_template );
-        else
-            X11DRV_PALETTE_BuildSharedMap( sys_pal_template );
+        X11DRV_PALETTE_BuildSharedMap( sys_pal_template );
 
-        /* Build free list */
+    /* Build free list */
 
-        if( X11DRV_PALETTE_firstFree != -1 )
-            X11DRV_PALETTE_FormatSystemPalette();
+    if( X11DRV_PALETTE_firstFree != -1 )
+        X11DRV_PALETTE_FormatSystemPalette();
 
-        X11DRV_PALETTE_FillDefaultColors( sys_pal_template );
-        palette_size = visual->map_entries;
-    }
+    X11DRV_PALETTE_FillDefaultColors( sys_pal_template );
+    palette_size = visual->map_entries;
 
     return palette_size;
 }
@@ -869,6 +867,29 @@
 
 	switch(spec_type)
         {
+          case 0x10: /* SYSPALETTEINDEX */
+            
+            if( (idx = color & 0xffff) >= palette_size)
+            {
+                WARN("SYSPALETTEINDEX(%lx) : idx %d is out of bounds, assuming black\n", color, idx);
+		GDI_ReleaseObj( hPal );
+                return 0;
+            }
+
+            if (X11DRV_PALETTE_PaletteToXPixel) {
+              GDI_ReleaseObj( hPal );
+              return X11DRV_PALETTE_PaletteToXPixel[idx];
+            }
+              
+	    if (COLOR_sysPal) {
+	      color = *(COLORREF*)&COLOR_sysPal[idx];
+	    } else {
+	      TRACE("System palette not allocated, assuming black\n");
+	      color = 0;
+	    }
+	    
+	    break;
+
           case 1: /* PALETTEINDEX */
 
             if( (idx = color & 0xffff) >= palPtr->logpalette.palNumEntries)
@@ -958,11 +979,19 @@
 		/* TRACE(palette,"RGB(%lx) -> pixel %i\n", color, index);
 		 */
 	    	break;
+       	    case 0x10:  /* SYSPALETTEINDEX */
+		index = color & 0xffff;
+
+	        if( index >= palette_size )
+		    WARN("SYSPALETTEINDEX(%lx) : index %i is out of bounds\n", color, index);
+		else if( X11DRV_PALETTE_PaletteToXPixel ) 
+		    index = X11DRV_PALETTE_PaletteToXPixel[index];
+		break;
        	    case 1:  /* PALETTEINDEX */
 		index = color & 0xffff;
 
 	        if( index >= palPtr->logpalette.palNumEntries )
-		    WARN("RGB(%lx) : index %i is out of bounds\n", color, index);
+		    WARN("PALETTEINDEX(%lx) : index %i is out of bounds\n", color, index);
 		else if( palPtr->mapping ) index = palPtr->mapping[index];
 
 		/*  TRACE(palette,"PALETTEINDEX(%04x) -> pixel %i\n", (WORD)color, index);
@@ -1107,28 +1136,32 @@
         index = -1;
         flag = PC_SYS_USED;
 
-        switch( palPtr->logpalette.palPalEntry[uStart].peFlags & 0x07 )
-        {
-	case PC_EXPLICIT:   /* palette entries are indices into system palette */
+        /* Even though the docs say that only one flag is to be set,
+         * they are a bitmask. At least one app sets more than one at
+         * the same time. */
+	if ( palPtr->logpalette.palPalEntry[uStart].peFlags & PC_EXPLICIT ) {
+	    /* palette entries are indices into system palette */
             index = *(WORD*)(palPtr->logpalette.palPalEntry + uStart);
             if( index > 255 || (index >= COLOR_gapStart && index <= COLOR_gapEnd) )
             {
                 WARN("PC_EXPLICIT: idx %d out of system palette, assuming black.\n", index);
                 index = 0;
             }
-            break;
-
-	case PC_RESERVED:   /* forbid future mappings to this entry */
-            flag |= PC_SYS_RESERVED;
+            if( X11DRV_PALETTE_PaletteToXPixel ) index = X11DRV_PALETTE_PaletteToXPixel[index];
+        } else {
+	    if ( palPtr->logpalette.palPalEntry[uStart].peFlags & PC_RESERVED ) {
+	        /* forbid future mappings to this entry */
+                flag |= PC_SYS_RESERVED;
+            }
+            
+	    if (! (palPtr->logpalette.palPalEntry[uStart].peFlags & PC_NOCOLLAPSE) ) {
+	        /* try to collapse identical colors */
+                index = X11DRV_LookupSysPaletteExact(*(COLORREF*)(palPtr->logpalette.palPalEntry + uStart));
+            }
 
-            /* fall through */
-	default:	    /* try to collapse identical colors */
-            index = X11DRV_LookupSysPaletteExact(*(COLORREF*)(palPtr->logpalette.palPalEntry + uStart));
-            /* fall through */
-	case PC_NOCOLLAPSE:
             if( index < 0 )
             {
-                if( X11DRV_PALETTE_firstFree > 0 && !(X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_FIXED) )
+                if( X11DRV_PALETTE_firstFree > 0 )
                 {
                     XColor color;
                     index = X11DRV_PALETTE_firstFree;  /* ought to be available */
@@ -1139,22 +1172,59 @@
                     color.green = palPtr->logpalette.palPalEntry[uStart].peGreen << 8;
                     color.blue = palPtr->logpalette.palPalEntry[uStart].peBlue << 8;
                     color.flags = DoRed | DoGreen | DoBlue;
-                    wine_tsx11_lock();
-                    XStoreColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &color);
-                    wine_tsx11_unlock();
+                    
+                    if (!(X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL)) {
+                        wine_tsx11_lock();
+                        XStoreColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &color);
+                        wine_tsx11_unlock();
+                    }
 
                     COLOR_sysPal[index] = palPtr->logpalette.palPalEntry[uStart];
                     COLOR_sysPal[index].peFlags = flag;
 		    X11DRV_PALETTE_freeList[index] = 0;
 
+                    if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_FIXED) {
+                        if (!XAllocColor( gdi_display, X11DRV_PALETTE_PaletteXColormap, &color ))
+                        {
+                            unsigned int diff, best, cntr;
+                            unsigned int r, g, b;
+                            XColor colours[256];
+
+                            /* reinit color (XAllocColor() may change it)
+                             * and map to the best shared colorcell */
+
+                            color.red = palPtr->logpalette.palPalEntry[uStart].peRed << 8;
+                            color.green = palPtr->logpalette.palPalEntry[uStart].peGreen << 8;
+                            color.blue = palPtr->logpalette.palPalEntry[uStart].peBlue << 8;
+
+                            for( cntr = 0; cntr < 256; cntr++ )
+                                colours[cntr].pixel = cntr;
+
+                            XQueryColors(gdi_display, X11DRV_PALETTE_PaletteXColormap, colours, 256 );
+
+                            r = colours[0].red >> 8;
+                            g = colours[0].green >> 8;
+                            b = colours[0].blue >> 8;
+
+                            diff = r*r + g*g + b*b;
+                            best = 0;
+                            for( cntr = 1; cntr < 256; cntr++ )	
+                            {
+                                r = (colours[cntr].red - colours[best].red)>>8;
+                                g = (colours[cntr].green - colours[best].green)>>8;
+                                b = (colours[cntr].blue - colours[best].blue)>>8;	
+                                r = r*r + g*g + b*b;
+                                if( r < diff ) { best = cntr; diff = r; }
+                            }
+
+                            if( XAllocColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &colours[best]) )
+                                color.pixel = colours[best].pixel;
+                        }
+
+                        X11DRV_PALETTE_PaletteToXPixel[index] = color.pixel;
+                     }
+
                     if( X11DRV_PALETTE_PaletteToXPixel ) index = X11DRV_PALETTE_PaletteToXPixel[index];
-                    break;
-                }
-                else if ( X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL )
-                {
-                    index = X11DRV_PALETTE_ToPhysical( NULL, 0x00ffffff &
-                             *(COLORREF*)(palPtr->logpalette.palPalEntry + uStart));
-                    break;
                 }
 
                 /* we have to map to existing entry in the system palette */
@@ -1164,7 +1234,6 @@
 	    palPtr->logpalette.palPalEntry[uStart].peFlags |= PC_SYS_USED;
 
             if( X11DRV_PALETTE_PaletteToXPixel ) index = X11DRV_PALETTE_PaletteToXPixel[index];
-            break;
         }
 
         if( !prevMapping || palPtr->mapping[uStart] != index ) iRemapped++;
@@ -1249,7 +1318,7 @@
     UINT ret;
     PALETTEOBJ *palPtr;
 
-    if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) return 0;
+    /* if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) return 0; */
 
     if (!(palPtr = GDI_GetObjPtr( hpal, PALETTE_MAGIC ))) return 0;
     ret = X11DRV_PALETTE_SetMapping( palPtr, 0, palPtr->logpalette.palNumEntries, !primary );
Index: dlls/x11drv/xrender.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/xrender.c,v
retrieving revision 1.47
diff -u -u -r1.47 xrender.c
--- dlls/x11drv/xrender.c	11 Aug 2004 23:45:34 -0000	1.47
+++ dlls/x11drv/xrender.c	29 Sep 2004 04:46:49 -0000
@@ -981,10 +981,38 @@
     HRGN saved_region = 0;
     UINT align = GetTextAlign( hdc );
     COLORREF textColor = GetTextColor( hdc );
-
+    BOOL antialias_disabled = FALSE;
+    AA_Type backup_aa;
+    
+    textColor = X11DRV_PALETTE_ToPhysical( physDev, textColor );
+    textColor = ((textColor & 0xFF0000) >> 16) |
+                (textColor & 0xFF00) |
+                ((textColor & 0xFF) << 16);
+    
     TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
 	  lprect, debugstr_wn(wstr, count), count, lpDx);
 
+    do {
+        BITMAPOBJ *bmp;
+        HBITMAP hBitmap;
+        
+        hBitmap = GetCurrentObject( physDev->hdc, OBJ_BITMAP );
+        bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC );
+        if (!(bmp && bmp->dib)) {
+          TRACE("bitmap is not a DIB\n");
+          GDI_ReleaseObj( hBitmap );
+          break;
+        }
+
+        if (bmp->dib->dsBmih.biBitCount <= 8 && antialias) {
+          TRACE("Disabling antialiasing\n");
+          antialias = 0;
+          antialias_disabled = TRUE;
+        }
+        
+        GDI_ReleaseObj( hBitmap );
+    } while (0);  
+        
     if(flags & ETO_GLYPH_INDEX)
         glyphs = (LPWORD)wstr;
     else {
@@ -1020,7 +1048,7 @@
 
     if(flags & (ETO_CLIPPED | ETO_OPAQUE)) {
         if(!lprect) {
-	    if(flags & ETO_CLIPPED) return FALSE;
+	    if(flags & ETO_CLIPPED) { retv = FALSE; goto done2; }
 	        GetTextExtentPointI(hdc, glyphs, count, &sz);
 		done_extents = TRUE;
 		rc.left = x;
@@ -1267,6 +1295,10 @@
 
     EnterCriticalSection(&xrender_cs);
     entry = glyphsetCache + physDev->xrender->cache_index;
+    if (antialias_disabled) {
+      backup_aa = entry->aa;
+      entry->aa = AA_None;
+    }
 
     for(idx = 0; idx < count; idx++) {
         if(glyphs[idx] >= entry->nrealized || entry->realized[glyphs[idx]] == FALSE) {
@@ -1274,6 +1306,9 @@
 	}
     }
 
+    if (antialias_disabled) {
+      entry->aa = backup_aa;
+    }
 
     TRACE("Writing %s at %ld,%ld\n", debugstr_wn(wstr,count),
           physDev->org.x + x, physDev->org.y + y);
@@ -1516,6 +1551,8 @@
 done:
     X11DRV_UnlockDIBSection( physDev, TRUE );
     if(glyphs != wstr) HeapFree(GetProcessHeap(), 0, glyphs);
+done2:
+    if (antialias_disabled == TRUE) antialias = 1;
     return retv;
 }
 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://www.winehq.org/pipermail/wine-patches/attachments/20040929/cb7f366d/attachment.pgp


More information about the wine-patches mailing list