Compare commits

...
Author SHA1 Message Date
71fc1e9f25 gdk: fix Win32 alternating dash pens
Use PS_ALTERNATE only for cosmetic one-pixel alternating dash patterns.

Correct the pen-type test so it recognizes cosmetic pens, and inspect
the second dash length for two-element patterns instead of checking the
first entry twice. Other dash patterns continue to use PS_USERSTYLE.

This also removes the inherited boolean-precedence compiler warnings.
2026-08-18 09:35:26 +02:00
2efb07b6d4 gdk: fix Win32 HDC access for offscreen windows
Normalize public windows and pixmaps to their drawable implementations
before resolving Win32 HDC access.

This makes public GDK_WINDOW_OFFSCREEN drawables resolve through their
GdkOffscreenWindow backing drawable instead of treating the generic
offscreen implementation as a Win32 drawable.

The resulting helper removes the incompatible-pointer warning without
increasing object text size.
2026-08-18 09:35:26 +02:00
295038c456 gdk: support RGB30 Win32 pixmaps
Use 32-bit BI_BITFIELDS DIB sections for depth-30 Win32 pixmaps with
canonical 10:10:10 masks and preserve full pixel values through
GdkImage and native blit paths.

Use CAIRO_FORMAT_RGB30 when available at compile time and retain the
HDC-backed fallback for older Cairo without a runtime version branch.
Extend Win32 true-color COLORREF conversion to 10-bit channels so
private RGB30 colormaps scale channel values correctly.

Keep RGB30 visuals private and unadvertised so the system visual and
public depth enumeration remain unchanged.
2026-08-18 09:35:25 +02:00
3 changed files with 74 additions and 29 deletions

View file

@ -173,10 +173,10 @@ fixup_pen (GdkGCWin32 *win32_gc)
win32_gc->pen_num_dashes = 1;
}
if (!(win32_gc->pen_style & PS_TYPE_MASK) == PS_GEOMETRIC &&
if (!(win32_gc->pen_style & PS_TYPE_MASK) &&
win32_gc->pen_dashes[0] == 1 &&
(win32_gc->pen_num_dashes == 1 ||
(win32_gc->pen_num_dashes == 2 && win32_gc->pen_dashes[0] == 1)))
(win32_gc->pen_num_dashes == 2 && win32_gc->pen_dashes[1] == 1)))
win32_gc->pen_style |= PS_ALTERNATE;
else
win32_gc->pen_style |= PS_USERSTYLE;
@ -672,7 +672,8 @@ gdk_gc_get_screen (GdkGC *gc)
return _gdk_screen;
}
static guint bitmask[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
static const guint bitmask[11] =
{ 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023 };
COLORREF
_gdk_win32_colormap_color (GdkColormap *colormap,
@ -680,7 +681,7 @@ _gdk_win32_colormap_color (GdkColormap *colormap,
{
const GdkVisual *visual;
GdkColormapPrivateWin32 *colormap_private;
guchar r, g, b;
guint r, g, b;
if (colormap == NULL)
return DIBINDEX (pixel & 1);
@ -744,17 +745,21 @@ predraw (GdkGC *gc,
static GdkDrawableImplWin32 *
get_impl_drawable (GdkDrawable *drawable)
{
if (GDK_IS_OFFSCREEN_WINDOW (drawable))
return _gdk_offscreen_window_get_real_drawable (GDK_OFFSCREEN_WINDOW (drawable));
if (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable))
return GDK_DRAWABLE_IMPL_WIN32(drawable);
else if (GDK_IS_WINDOW (drawable))
return GDK_DRAWABLE_IMPL_WIN32 ((GDK_WINDOW_OBJECT (drawable))->impl);
else if (GDK_IS_PIXMAP (drawable))
return GDK_DRAWABLE_IMPL_WIN32 ((GDK_PIXMAP_OBJECT (drawable))->impl);
else
g_assert_not_reached ();
if (GDK_IS_WINDOW (drawable))
drawable = GDK_DRAWABLE ((GDK_WINDOW_OBJECT (drawable))->impl);
if (GDK_IS_OFFSCREEN_WINDOW (drawable))
drawable =
_gdk_offscreen_window_get_real_drawable
(GDK_OFFSCREEN_WINDOW (drawable));
if (GDK_IS_PIXMAP (drawable))
drawable = GDK_DRAWABLE ((GDK_PIXMAP_OBJECT (drawable))->impl);
if (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable))
return GDK_DRAWABLE_IMPL_WIN32 (drawable);
g_assert_not_reached ();
return NULL;
}

View file

@ -290,7 +290,16 @@ gdk_image_get_pixel (GdkImage *image,
return pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
case 4:
return pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
{
guint32 pixel;
pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
if (G_UNLIKELY (image->depth == 30))
pixel |= (guint32) pixelp[3] << 24;
return pixel;
}
}
g_assert_not_reached ();
return 0;
@ -340,7 +349,9 @@ gdk_image_put_pixel (GdkImage *image,
switch (image->bpp)
{
case 4:
pixelp[3] = 0;
pixelp[3] =
G_UNLIKELY (image->depth == 30) ?
(pixel >> 24) : 0;
case 3:
pixelp[2] = ((pixel >> 16) & 0xFF);
case 2:
@ -401,6 +412,7 @@ _gdk_windowing_get_bits_for_depth (GdkDisplay *display,
return 16;
case 24:
case 30:
case 32:
return 32;
}

View file

@ -206,6 +206,14 @@ _gdk_pixmap_new (GdkDrawable *drawable,
format = CAIRO_FORMAT_RGB16_565;
break;
case 30:
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 12, 0)
format = CAIRO_FORMAT_RGB30;
#else
format = CAIRO_FORMAT_RGB24;
#endif
break;
case 24:
case 32:
format = CAIRO_FORMAT_RGB24;
@ -308,24 +316,33 @@ _gdk_pixmap_new (GdkDrawable *drawable,
}
else
{
bmi.bmiHeader.biBitCount = 16;
bmi.bmiHeader.biBitCount = depth == 30 ? 32 : 16;
bmi.bmiHeader.biCompression = BI_BITFIELDS;
visual = gdk_visual_get_system ();
if (visual->depth == depth)
if (depth == 30)
{
bmi.u.bmiMasks[0] = visual->red_mask;
bmi.u.bmiMasks[1] = visual->green_mask;
bmi.u.bmiMasks[2] = visual->blue_mask;
bmi.u.bmiMasks[0] = 0x3FF00000;
bmi.u.bmiMasks[1] = 0x000FFC00;
bmi.u.bmiMasks[2] = 0x000003FF;
}
else
{
bmi.u.bmiMasks[0] =
depth == 15 ? 0x00007C00 : 0x0000F800;
bmi.u.bmiMasks[1] =
depth == 15 ? 0x000003E0 : 0x000007E0;
bmi.u.bmiMasks[2] = 0x0000001F;
visual = gdk_visual_get_system ();
if (visual->depth == depth)
{
bmi.u.bmiMasks[0] = visual->red_mask;
bmi.u.bmiMasks[1] = visual->green_mask;
bmi.u.bmiMasks[2] = visual->blue_mask;
}
else
{
bmi.u.bmiMasks[0] =
depth == 15 ? 0x00007C00 : 0x0000F800;
bmi.u.bmiMasks[1] =
depth == 15 ? 0x000003E0 : 0x000007E0;
bmi.u.bmiMasks[2] = 0x0000001F;
}
}
}
@ -421,10 +438,21 @@ _gdk_pixmap_new (GdkDrawable *drawable,
return NULL;
}
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 12, 0)
if (depth == 30)
dib_surface =
cairo_image_surface_create_for_data (
bits,
format,
width,
height,
width * 4);
else
#endif
if (depth != 16 ||
bmi.u.bmiMasks[0] != 0x0000F800 ||
bmi.u.bmiMasks[1] != 0x000007E0 ||
bmi.u.bmiMasks[2] != 0x0000001F)
bmi.u.bmiMasks[0] != 0x0000F800 ||
bmi.u.bmiMasks[1] != 0x000007E0 ||
bmi.u.bmiMasks[2] != 0x0000001F)
dib_surface =
cairo_win32_surface_create (hdc);
else