[gtk+] Fix rendering of theme parts on Windows XP



commit f4a68dff88f242845ab96ad9e40ba22f96b394df
Author: Alexander Larsson <alexl redhat com>
Date:   Fri Mar 9 16:37:11 2012 +0100

    Fix rendering of theme parts on Windows XP
    
    It seems XP doesn't handle drawing non-alpha theme parts
    on alpha destinations. We fix this by using alpha bitmaps only when
    needed.
    
    However this means any non-drawn area by the theme part is now draw
    black, so we must take more care to only draw where the theme part draws,
    so we find the theme part size when available.

 gtk/gtkcssimagewin32.c     |   12 +++++----
 gtk/gtkwin32theme.c        |   55 ++++++++++++++++++++++++++++++++++++++-----
 gtk/gtkwin32themeprivate.h |    4 ++-
 3 files changed, 58 insertions(+), 13 deletions(-)
---
diff --git a/gtk/gtkcssimagewin32.c b/gtk/gtkcssimagewin32.c
index 8c79fd6..ca82a08 100644
--- a/gtk/gtkcssimagewin32.c
+++ b/gtk/gtkcssimagewin32.c
@@ -33,21 +33,23 @@ gtk_css_image_win32_draw (GtkCssImage        *image,
 {
   GtkCssImageWin32 *wimage = GTK_CSS_IMAGE_WIN32 (image);
   cairo_surface_t *surface;
+  int dx, dy;
 
   surface = _gtk_win32_theme_part_create_surface (wimage->theme, wimage->part, wimage->state, wimage->margins,
-						  width, height);
+						  width, height, &dx, &dy);
   
   if (wimage->state2 >= 0)
     {
       cairo_surface_t *surface2;
       cairo_t *cr;
+      int dx2, dy2;
 
       surface2 = _gtk_win32_theme_part_create_surface (wimage->theme, wimage->part2, wimage->state2, wimage->margins,
-						       width, height);
+						       width, height, &dx2, &dy2);
 
       cr = cairo_create (surface);
 
-      cairo_set_source_surface (cr, surface2, 0, 0);
+      cairo_set_source_surface (cr, surface2, dx2 - dx, dy2-dy);
       cairo_paint_with_alpha (cr, wimage->over_alpha);
       
       cairo_destroy (cr);
@@ -55,8 +57,8 @@ gtk_css_image_win32_draw (GtkCssImage        *image,
       cairo_surface_destroy (surface2);
     }
 
-  cairo_set_source_surface (cr, surface, 0, 0);
-  cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_PAD);
+  cairo_set_source_surface (cr, surface, dx, dy);
+  cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_NONE);
   cairo_rectangle (cr, 0, 0, width, height);
   cairo_fill (cr);
 
diff --git a/gtk/gtkwin32theme.c b/gtk/gtkwin32theme.c
index 35fd5db..b2931ed 100644
--- a/gtk/gtkwin32theme.c
+++ b/gtk/gtkwin32theme.c
@@ -184,27 +184,65 @@ _gtk_win32_theme_part_create_surface (HTHEME theme,
 				      int    state,
 				      int    margins[4],
 				      int    width,
-                                      int    height)
+                                      int    height,
+				      int   *x_offs_out,
+				      int   *y_offs_out)
 {
   cairo_surface_t *surface;
   GdkRGBA color;
   cairo_t *cr;
+  int x_offs;
+  int y_offs;
 #ifdef G_OS_WIN32
   HDC hdc;
   RECT rect;
+  SIZE size;
   HRESULT res;
+#endif
 
-  surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, width, height);
-  hdc = cairo_win32_surface_get_dc (surface);
+  x_offs = margins[3];
+  y_offs = margins[0];
+
+  width -= margins[3] + margins[1];
+  height -= margins[0] + margins[2];
+
+#ifdef G_OS_WIN32
+  rect.left = 0;
+  rect.top = 0;
+  rect.right = width;
+  rect.bottom = height;
+
+  hdc = GetDC (NULL);
+  res = get_theme_part_size (theme, hdc, xp_part, state, &rect, 2, &size);
+  ReleaseDC (NULL, hdc);
+
+  if (res == S_OK)
+    {
+      x_offs += (width - size.cx) / 2;
+      y_offs += (height - size.cy) / 2;
   
-  rect.left = margins[3];
-  rect.top = margins[0];
-  rect.right = width - margins[1];
-  rect.bottom = height - margins[2];
+      width = size.cx;
+      height = size.cy;
+
+      rect.right = width;
+      rect.bottom = height;
+    }
+
+  if (is_theme_partially_transparent (theme, xp_part, state))
+    surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, width, height);
+  else
+    surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_RGB24, width, height);
+
+  hdc = cairo_win32_surface_get_dc (surface);
 
   res = draw_theme_background (theme, hdc, xp_part, state, &rect, &rect);
+
+  *x_offs_out = x_offs;
+  *y_offs_out = y_offs;
+
   if (res == S_OK)
     return surface;
+
 #else /* !G_OS_WIN32 */
   surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
 #endif /* G_OS_WIN32 */
@@ -218,6 +256,9 @@ _gtk_win32_theme_part_create_surface (HTHEME theme,
 
   cairo_destroy (cr);
   
+  *x_offs_out = x_offs;
+  *y_offs_out = y_offs;
+
   return surface;
 }
 
diff --git a/gtk/gtkwin32themeprivate.h b/gtk/gtkwin32themeprivate.h
index 4445f2d..309c53c 100644
--- a/gtk/gtkwin32themeprivate.h
+++ b/gtk/gtkwin32themeprivate.h
@@ -44,7 +44,9 @@ cairo_surface_t *  _gtk_win32_theme_part_create_surface  (HTHEME       theme,
                                                           int          state,
                                                           int          margins[4],
                                                           int          width,
-                                                          int          height);
+                                                          int          height,
+							  int         *x_offs_out,
+							  int         *y_offs_out);
 
 int                _gtk_win32_theme_int_parse     (GtkCssParser      *parser,
 						   GFile             *base,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]