forked from AuroraMiddleware/gtk
Improve and simplify line segment rendering on Win32, especially the
2005-06-23 Tor Lillqvist <tml@novell.com> Improve and simplify line segment rendering on Win32, especially the implementation of GDK_CAP_NOT_LAST, and dashed lines. Fixes bug #306396. * gdk/win32/gdkprivate-win32.h (GdkGCWin32): Save the GdkGC's line_style, cap_style and join_style as such in the GdkGCWin32. Don't need to keep the pen_double_dash flag, we can check the line_style. * gdk/win32/gdkgc-win32.c (fixup_pen): New internal function. Sets up the GDI pen type, style, end cap and join attributes to use based on the pen width, GDK line style, end cap style, and join style. For a narrow (zero-width) GDK pen with the GDK_CAP_NOT_LAST end cap style, which typically are used for XOR drawing where it is essential that the last pixel is not drawn, use a GDI cosmetic pen. Only for a cosmetic pen does GDI not draw the last pixel. I deduced this by experimetation, the documentation is rather vague. For other GDK pens use a geometric GDI pen. If the width is 0 or 1 and the GDK end cap style is GDK_CAP_BUTT, and the line style is GDK_LINE_SOLID, use PS_ENDCAP_ROUND. This ensures that also single-pixel length lines are drawn. (For sngle-pixel width lines roundness as such is of course irrelevant.) For dashed lines, use PS_ENDCAP_FLAT. For wide lines use PS_ENDCAP_FLAT, _ROUND or _SQUARE, respectively, for GDK_CAP_BUTT, GDK_CAP_ROUND and GDK_CAP_PROJECTING. For one pixel on-off dashed lines, use PS_ALTERNATE, it seems to work better than PS_USERSTYLE. For other dashed lines, use PS_USERSTYLE and the dashes as set by the user (or the default four-pixel on-off style). (gdk_win32_gc_values_to_win32values, gdk_win32_gc_set_dashes): Call fixup_pen() to do the pen settings after modifying some of the GDK GC attributes that affect pens. * gdk/win32/gdkdrawable-win32.c (render_line_horizontal, render_line_vertical, draw_segments): Check GdkGCWin32::line_style instead of the the removed pen_double_dash member. Don't use PATCOPY unconditionally in the PatBlt() call, use a raster ope code that depends on the GC function in use. (draw_rectangle, draw_segments, draw_lines): Be more careful in deciding when to do the manual dash rendering. (draw_segments): Don't do any manual "last point" drawing at all. The above changes takes care of narrow line segments being drawn correctly in most cases, at least on NT-based Windows.
This commit is contained in:
parent
621f16a442
commit
baad14eee0
54
ChangeLog
54
ChangeLog
@ -1,3 +1,57 @@
|
|||||||
|
2005-06-23 Tor Lillqvist <tml@novell.com>
|
||||||
|
|
||||||
|
Improve and simplify line segment rendering on Win32, especially
|
||||||
|
the implementation of GDK_CAP_NOT_LAST, and dashed lines. Fixes
|
||||||
|
bug #306396.
|
||||||
|
|
||||||
|
* gdk/win32/gdkprivate-win32.h (GdkGCWin32): Save the GdkGC's
|
||||||
|
line_style, cap_style and join_style as such in the
|
||||||
|
GdkGCWin32. Don't need to keep the pen_double_dash flag, we can
|
||||||
|
check the line_style.
|
||||||
|
|
||||||
|
* gdk/win32/gdkgc-win32.c (fixup_pen): New internal function. Sets
|
||||||
|
up the GDI pen type, style, end cap and join attributes to use
|
||||||
|
based on the pen width, GDK line style, end cap style, and join
|
||||||
|
style.
|
||||||
|
|
||||||
|
For a narrow (zero-width) GDK pen with the GDK_CAP_NOT_LAST end
|
||||||
|
cap style, which typically are used for XOR drawing where it is
|
||||||
|
essential that the last pixel is not drawn, use a GDI cosmetic
|
||||||
|
pen. Only for a cosmetic pen does GDI not draw the last pixel. I
|
||||||
|
deduced this by experimetation, the documentation is rather vague.
|
||||||
|
|
||||||
|
For other GDK pens use a geometric GDI pen. If the width is 0 or 1
|
||||||
|
and the GDK end cap style is GDK_CAP_BUTT, and the line style is
|
||||||
|
GDK_LINE_SOLID, use PS_ENDCAP_ROUND. This ensures that also
|
||||||
|
single-pixel length lines are drawn. (For sngle-pixel width lines
|
||||||
|
roundness as such is of course irrelevant.) For dashed lines, use
|
||||||
|
PS_ENDCAP_FLAT.
|
||||||
|
|
||||||
|
For wide lines use PS_ENDCAP_FLAT, _ROUND or _SQUARE,
|
||||||
|
respectively, for GDK_CAP_BUTT, GDK_CAP_ROUND and GDK_CAP_PROJECTING.
|
||||||
|
|
||||||
|
For one pixel on-off dashed lines, use PS_ALTERNATE, it seems to
|
||||||
|
work better than PS_USERSTYLE. For other dashed lines, use
|
||||||
|
PS_USERSTYLE and the dashes as set by the user (or the default
|
||||||
|
four-pixel on-off style).
|
||||||
|
|
||||||
|
(gdk_win32_gc_values_to_win32values, gdk_win32_gc_set_dashes):
|
||||||
|
Call fixup_pen() to do the pen settings after modifying some of
|
||||||
|
the GDK GC attributes that affect pens.
|
||||||
|
|
||||||
|
* gdk/win32/gdkdrawable-win32.c (render_line_horizontal,
|
||||||
|
render_line_vertical, draw_segments): Check GdkGCWin32::line_style
|
||||||
|
instead of the the removed pen_double_dash member. Don't use
|
||||||
|
PATCOPY unconditionally in the PatBlt() call, use a raster ope
|
||||||
|
code that depends on the GC function in use.
|
||||||
|
|
||||||
|
(draw_rectangle, draw_segments, draw_lines): Be more careful in
|
||||||
|
deciding when to do the manual dash rendering.
|
||||||
|
|
||||||
|
(draw_segments): Don't do any manual "last point" drawing at
|
||||||
|
all. The above changes takes care of narrow line segments being
|
||||||
|
drawn correctly in most cases, at least on NT-based Windows.
|
||||||
|
|
||||||
2005-06-23 Matthias Clasen <mclasen@redhat.com>
|
2005-06-23 Matthias Clasen <mclasen@redhat.com>
|
||||||
|
|
||||||
* gtk/gtkfilesystemunix.c (gtk_file_system_unix_get_folder):
|
* gtk/gtkfilesystemunix.c (gtk_file_system_unix_get_folder):
|
||||||
|
@ -1,3 +1,57 @@
|
|||||||
|
2005-06-23 Tor Lillqvist <tml@novell.com>
|
||||||
|
|
||||||
|
Improve and simplify line segment rendering on Win32, especially
|
||||||
|
the implementation of GDK_CAP_NOT_LAST, and dashed lines. Fixes
|
||||||
|
bug #306396.
|
||||||
|
|
||||||
|
* gdk/win32/gdkprivate-win32.h (GdkGCWin32): Save the GdkGC's
|
||||||
|
line_style, cap_style and join_style as such in the
|
||||||
|
GdkGCWin32. Don't need to keep the pen_double_dash flag, we can
|
||||||
|
check the line_style.
|
||||||
|
|
||||||
|
* gdk/win32/gdkgc-win32.c (fixup_pen): New internal function. Sets
|
||||||
|
up the GDI pen type, style, end cap and join attributes to use
|
||||||
|
based on the pen width, GDK line style, end cap style, and join
|
||||||
|
style.
|
||||||
|
|
||||||
|
For a narrow (zero-width) GDK pen with the GDK_CAP_NOT_LAST end
|
||||||
|
cap style, which typically are used for XOR drawing where it is
|
||||||
|
essential that the last pixel is not drawn, use a GDI cosmetic
|
||||||
|
pen. Only for a cosmetic pen does GDI not draw the last pixel. I
|
||||||
|
deduced this by experimetation, the documentation is rather vague.
|
||||||
|
|
||||||
|
For other GDK pens use a geometric GDI pen. If the width is 0 or 1
|
||||||
|
and the GDK end cap style is GDK_CAP_BUTT, and the line style is
|
||||||
|
GDK_LINE_SOLID, use PS_ENDCAP_ROUND. This ensures that also
|
||||||
|
single-pixel length lines are drawn. (For sngle-pixel width lines
|
||||||
|
roundness as such is of course irrelevant.) For dashed lines, use
|
||||||
|
PS_ENDCAP_FLAT.
|
||||||
|
|
||||||
|
For wide lines use PS_ENDCAP_FLAT, _ROUND or _SQUARE,
|
||||||
|
respectively, for GDK_CAP_BUTT, GDK_CAP_ROUND and GDK_CAP_PROJECTING.
|
||||||
|
|
||||||
|
For one pixel on-off dashed lines, use PS_ALTERNATE, it seems to
|
||||||
|
work better than PS_USERSTYLE. For other dashed lines, use
|
||||||
|
PS_USERSTYLE and the dashes as set by the user (or the default
|
||||||
|
four-pixel on-off style).
|
||||||
|
|
||||||
|
(gdk_win32_gc_values_to_win32values, gdk_win32_gc_set_dashes):
|
||||||
|
Call fixup_pen() to do the pen settings after modifying some of
|
||||||
|
the GDK GC attributes that affect pens.
|
||||||
|
|
||||||
|
* gdk/win32/gdkdrawable-win32.c (render_line_horizontal,
|
||||||
|
render_line_vertical, draw_segments): Check GdkGCWin32::line_style
|
||||||
|
instead of the the removed pen_double_dash member. Don't use
|
||||||
|
PATCOPY unconditionally in the PatBlt() call, use a raster ope
|
||||||
|
code that depends on the GC function in use.
|
||||||
|
|
||||||
|
(draw_rectangle, draw_segments, draw_lines): Be more careful in
|
||||||
|
deciding when to do the manual dash rendering.
|
||||||
|
|
||||||
|
(draw_segments): Don't do any manual "last point" drawing at
|
||||||
|
all. The above changes takes care of narrow line segments being
|
||||||
|
drawn correctly in most cases, at least on NT-based Windows.
|
||||||
|
|
||||||
2005-06-23 Matthias Clasen <mclasen@redhat.com>
|
2005-06-23 Matthias Clasen <mclasen@redhat.com>
|
||||||
|
|
||||||
* gtk/gtkfilesystemunix.c (gtk_file_system_unix_get_folder):
|
* gtk/gtkfilesystemunix.c (gtk_file_system_unix_get_folder):
|
||||||
|
@ -1,3 +1,57 @@
|
|||||||
|
2005-06-23 Tor Lillqvist <tml@novell.com>
|
||||||
|
|
||||||
|
Improve and simplify line segment rendering on Win32, especially
|
||||||
|
the implementation of GDK_CAP_NOT_LAST, and dashed lines. Fixes
|
||||||
|
bug #306396.
|
||||||
|
|
||||||
|
* gdk/win32/gdkprivate-win32.h (GdkGCWin32): Save the GdkGC's
|
||||||
|
line_style, cap_style and join_style as such in the
|
||||||
|
GdkGCWin32. Don't need to keep the pen_double_dash flag, we can
|
||||||
|
check the line_style.
|
||||||
|
|
||||||
|
* gdk/win32/gdkgc-win32.c (fixup_pen): New internal function. Sets
|
||||||
|
up the GDI pen type, style, end cap and join attributes to use
|
||||||
|
based on the pen width, GDK line style, end cap style, and join
|
||||||
|
style.
|
||||||
|
|
||||||
|
For a narrow (zero-width) GDK pen with the GDK_CAP_NOT_LAST end
|
||||||
|
cap style, which typically are used for XOR drawing where it is
|
||||||
|
essential that the last pixel is not drawn, use a GDI cosmetic
|
||||||
|
pen. Only for a cosmetic pen does GDI not draw the last pixel. I
|
||||||
|
deduced this by experimetation, the documentation is rather vague.
|
||||||
|
|
||||||
|
For other GDK pens use a geometric GDI pen. If the width is 0 or 1
|
||||||
|
and the GDK end cap style is GDK_CAP_BUTT, and the line style is
|
||||||
|
GDK_LINE_SOLID, use PS_ENDCAP_ROUND. This ensures that also
|
||||||
|
single-pixel length lines are drawn. (For sngle-pixel width lines
|
||||||
|
roundness as such is of course irrelevant.) For dashed lines, use
|
||||||
|
PS_ENDCAP_FLAT.
|
||||||
|
|
||||||
|
For wide lines use PS_ENDCAP_FLAT, _ROUND or _SQUARE,
|
||||||
|
respectively, for GDK_CAP_BUTT, GDK_CAP_ROUND and GDK_CAP_PROJECTING.
|
||||||
|
|
||||||
|
For one pixel on-off dashed lines, use PS_ALTERNATE, it seems to
|
||||||
|
work better than PS_USERSTYLE. For other dashed lines, use
|
||||||
|
PS_USERSTYLE and the dashes as set by the user (or the default
|
||||||
|
four-pixel on-off style).
|
||||||
|
|
||||||
|
(gdk_win32_gc_values_to_win32values, gdk_win32_gc_set_dashes):
|
||||||
|
Call fixup_pen() to do the pen settings after modifying some of
|
||||||
|
the GDK GC attributes that affect pens.
|
||||||
|
|
||||||
|
* gdk/win32/gdkdrawable-win32.c (render_line_horizontal,
|
||||||
|
render_line_vertical, draw_segments): Check GdkGCWin32::line_style
|
||||||
|
instead of the the removed pen_double_dash member. Don't use
|
||||||
|
PATCOPY unconditionally in the PatBlt() call, use a raster ope
|
||||||
|
code that depends on the GC function in use.
|
||||||
|
|
||||||
|
(draw_rectangle, draw_segments, draw_lines): Be more careful in
|
||||||
|
deciding when to do the manual dash rendering.
|
||||||
|
|
||||||
|
(draw_segments): Don't do any manual "last point" drawing at
|
||||||
|
all. The above changes takes care of narrow line segments being
|
||||||
|
drawn correctly in most cases, at least on NT-based Windows.
|
||||||
|
|
||||||
2005-06-23 Matthias Clasen <mclasen@redhat.com>
|
2005-06-23 Matthias Clasen <mclasen@redhat.com>
|
||||||
|
|
||||||
* gtk/gtkfilesystemunix.c (gtk_file_system_unix_get_folder):
|
* gtk/gtkfilesystemunix.c (gtk_file_system_unix_get_folder):
|
||||||
|
@ -45,6 +45,12 @@
|
|||||||
#define LINE_ATTRIBUTES (GDK_GC_LINE_WIDTH|GDK_GC_LINE_STYLE| \
|
#define LINE_ATTRIBUTES (GDK_GC_LINE_WIDTH|GDK_GC_LINE_STYLE| \
|
||||||
GDK_GC_CAP_STYLE|GDK_GC_JOIN_STYLE)
|
GDK_GC_CAP_STYLE|GDK_GC_JOIN_STYLE)
|
||||||
|
|
||||||
|
#define MUST_RENDER_DASHES_MANUALLY(gcwin32) \
|
||||||
|
(gcwin32->line_style == GDK_LINE_DOUBLE_DASH || \
|
||||||
|
(gcwin32->line_style == GDK_LINE_ON_OFF_DASH && \
|
||||||
|
(gcwin32->pen_dash_offset || \
|
||||||
|
(!G_WIN32_IS_NT_BASED () && (gcwin32->pen_style & PS_STYLE_MASK) == PS_SOLID))))
|
||||||
|
|
||||||
static void gdk_win32_draw_rectangle (GdkDrawable *drawable,
|
static void gdk_win32_draw_rectangle (GdkDrawable *drawable,
|
||||||
GdkGC *gc,
|
GdkGC *gc,
|
||||||
gboolean filled,
|
gboolean filled,
|
||||||
@ -230,7 +236,51 @@ gdk_win32_set_colormap (GdkDrawable *drawable,
|
|||||||
/* Drawing
|
/* Drawing
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static DWORD default_double_dashes[] = { 3, 3 };
|
static int
|
||||||
|
rop2_to_rop3 (int rop2)
|
||||||
|
{
|
||||||
|
switch (rop2)
|
||||||
|
{
|
||||||
|
/* Oh, Microsoft's silly names for binary and ternary rops. */
|
||||||
|
#define CASE(rop2,rop3) case R2_##rop2: return rop3
|
||||||
|
CASE (BLACK, BLACKNESS);
|
||||||
|
CASE (NOTMERGEPEN, NOTSRCERASE);
|
||||||
|
CASE (MASKNOTPEN, 0x00220326);
|
||||||
|
CASE (NOTCOPYPEN, NOTSRCCOPY);
|
||||||
|
CASE (MASKPENNOT, SRCERASE);
|
||||||
|
CASE (NOT, DSTINVERT);
|
||||||
|
CASE (XORPEN, SRCINVERT);
|
||||||
|
CASE (NOTMASKPEN, 0x007700E6);
|
||||||
|
CASE (MASKPEN, SRCAND);
|
||||||
|
CASE (NOTXORPEN, 0x00990066);
|
||||||
|
CASE (NOP, 0x00AA0029);
|
||||||
|
CASE (MERGENOTPEN, MERGEPAINT);
|
||||||
|
CASE (COPYPEN, SRCCOPY);
|
||||||
|
CASE (MERGEPENNOT, 0x00DD0228);
|
||||||
|
CASE (MERGEPEN, SRCPAINT);
|
||||||
|
CASE (WHITE, WHITENESS);
|
||||||
|
#undef CASE
|
||||||
|
default: return SRCCOPY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rop2_to_patblt_rop (int rop2)
|
||||||
|
{
|
||||||
|
switch (rop2)
|
||||||
|
{
|
||||||
|
#define CASE(rop2,patblt_rop) case R2_##rop2: return patblt_rop
|
||||||
|
CASE (COPYPEN, PATCOPY);
|
||||||
|
CASE (XORPEN, PATINVERT);
|
||||||
|
CASE (NOT, DSTINVERT);
|
||||||
|
CASE (BLACK, BLACKNESS);
|
||||||
|
CASE (WHITE, WHITENESS);
|
||||||
|
#undef CASE
|
||||||
|
default:
|
||||||
|
g_warning ("Unhandled rop2 in GC to be used in PatBlt: %#x", rop2);
|
||||||
|
return PATCOPY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
align_with_dash_offset (int a, DWORD *dashes, int num_dashes, GdkGCWin32 *gcwin32)
|
align_with_dash_offset (int a, DWORD *dashes, int num_dashes, GdkGCWin32 *gcwin32)
|
||||||
@ -259,70 +309,58 @@ align_with_dash_offset (int a, DWORD *dashes, int num_dashes, GdkGCWin32 *gcwin3
|
|||||||
*/
|
*/
|
||||||
static inline gboolean
|
static inline gboolean
|
||||||
render_line_horizontal (GdkGCWin32 *gcwin32,
|
render_line_horizontal (GdkGCWin32 *gcwin32,
|
||||||
int x1,
|
int x1,
|
||||||
int x2,
|
int x2,
|
||||||
int y)
|
int y)
|
||||||
{
|
{
|
||||||
int n = 0;
|
int n = 0;
|
||||||
HDC hdc = gcwin32->hdc;
|
const int pen_width = MAX (gcwin32->pen_width, 1);
|
||||||
int pen_width = gcwin32->pen_width;
|
const int _x1 = x1;
|
||||||
DWORD *dashes;
|
|
||||||
int num_dashes;
|
|
||||||
int _x1 = x1;
|
|
||||||
|
|
||||||
if (gcwin32->pen_dashes)
|
g_assert (gcwin32->pen_dashes);
|
||||||
{
|
|
||||||
dashes = gcwin32->pen_dashes;
|
x1 = align_with_dash_offset (x1, gcwin32->pen_dashes, gcwin32->pen_num_dashes, gcwin32);
|
||||||
num_dashes = gcwin32->pen_num_dashes;
|
|
||||||
x1 = align_with_dash_offset (x1, dashes, num_dashes, gcwin32);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dashes = default_double_dashes;
|
|
||||||
num_dashes = G_N_ELEMENTS (default_double_dashes);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (n = 0; x1 < x2; n++)
|
for (n = 0; x1 < x2; n++)
|
||||||
{
|
{
|
||||||
int len = dashes[n % num_dashes];
|
int len = gcwin32->pen_dashes[n % gcwin32->pen_num_dashes];
|
||||||
if (x1 + len > x2)
|
if (x1 + len > x2)
|
||||||
len = x2 - x1;
|
len = x2 - x1;
|
||||||
|
|
||||||
if (n % 2 == 0 && x1 + len > _x1)
|
if (n % 2 == 0 && x1 + len > _x1)
|
||||||
if (!GDI_CALL (PatBlt, (hdc,
|
if (!GDI_CALL (PatBlt, (gcwin32->hdc,
|
||||||
x1 < _x1 ? _x1 : x1,
|
x1 < _x1 ? _x1 : x1,
|
||||||
y - pen_width / 2,
|
y - pen_width / 2,
|
||||||
len, pen_width,
|
len, pen_width,
|
||||||
PATCOPY)))
|
rop2_to_patblt_rop (gcwin32->rop2))))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
x1 += dashes[n % num_dashes];
|
x1 += gcwin32->pen_dashes[n % gcwin32->pen_num_dashes];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gcwin32->pen_double_dash)
|
if (gcwin32->line_style == GDK_LINE_DOUBLE_DASH)
|
||||||
{
|
{
|
||||||
HBRUSH hbr;
|
HBRUSH hbr;
|
||||||
|
|
||||||
if ((hbr = SelectObject (hdc, gcwin32->pen_hbrbg)) == HGDI_ERROR)
|
if ((hbr = SelectObject (gcwin32->hdc, gcwin32->pen_hbrbg)) == HGDI_ERROR)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
x1 = _x1;
|
x1 = _x1;
|
||||||
if (gcwin32->pen_dashes)
|
x1 += gcwin32->pen_dash_offset;
|
||||||
x1 += gcwin32->pen_dash_offset;
|
|
||||||
for (n = 0; x1 < x2; n++)
|
for (n = 0; x1 < x2; n++)
|
||||||
{
|
{
|
||||||
int len = dashes[n % num_dashes];
|
int len = gcwin32->pen_dashes[n % gcwin32->pen_num_dashes];
|
||||||
if (x1 + len > x2)
|
if (x1 + len > x2)
|
||||||
len = x2 - x1;
|
len = x2 - x1;
|
||||||
|
|
||||||
if (n % 2)
|
if (n % 2)
|
||||||
if (!GDI_CALL (PatBlt, (hdc, x1, y - pen_width / 2,
|
if (!GDI_CALL (PatBlt, (gcwin32->hdc, x1, y - pen_width / 2,
|
||||||
len, pen_width,
|
len, pen_width,
|
||||||
PATCOPY)))
|
rop2_to_patblt_rop (gcwin32->rop2))))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
x1 += dashes[n % num_dashes];
|
x1 += gcwin32->pen_dashes[n % gcwin32->pen_num_dashes];
|
||||||
}
|
}
|
||||||
if (SelectObject (hdc, hbr) == HGDI_ERROR)
|
if (SelectObject (gcwin32->hdc, hbr) == HGDI_ERROR)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,67 +369,54 @@ render_line_horizontal (GdkGCWin32 *gcwin32,
|
|||||||
|
|
||||||
static inline gboolean
|
static inline gboolean
|
||||||
render_line_vertical (GdkGCWin32 *gcwin32,
|
render_line_vertical (GdkGCWin32 *gcwin32,
|
||||||
int x,
|
int x,
|
||||||
int y1,
|
int y1,
|
||||||
int y2)
|
int y2)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
HDC hdc = gcwin32->hdc;
|
const int pen_width = MAX (gcwin32->pen_width, 1);
|
||||||
int pen_width = gcwin32->pen_width;
|
const int _y1 = y1;
|
||||||
DWORD *dashes;
|
|
||||||
int num_dashes;
|
|
||||||
int _y1 = y1;
|
|
||||||
|
|
||||||
if (gcwin32->pen_dashes)
|
g_assert (gcwin32->pen_dashes);
|
||||||
{
|
|
||||||
dashes = gcwin32->pen_dashes;
|
|
||||||
num_dashes = gcwin32->pen_num_dashes;
|
|
||||||
y1 = align_with_dash_offset (y1, dashes, num_dashes, gcwin32);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dashes = default_double_dashes;
|
|
||||||
num_dashes = G_N_ELEMENTS (default_double_dashes);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
y1 = align_with_dash_offset (y1, gcwin32->pen_dashes, gcwin32->pen_num_dashes, gcwin32);
|
||||||
for (n = 0; y1 < y2; n++)
|
for (n = 0; y1 < y2; n++)
|
||||||
{
|
{
|
||||||
int len = dashes[n % num_dashes];
|
int len = gcwin32->pen_dashes[n % gcwin32->pen_num_dashes];
|
||||||
if (y1 + len > y2)
|
if (y1 + len > y2)
|
||||||
len = y2 - y1;
|
len = y2 - y1;
|
||||||
if (n % 2 == 0 && y1 + len > _y1)
|
if (n % 2 == 0 && y1 + len > _y1)
|
||||||
if (!GDI_CALL (PatBlt, (hdc, x - pen_width / 2,
|
if (!GDI_CALL (PatBlt, (gcwin32->hdc, x - pen_width / 2,
|
||||||
y1 < _y1 ? _y1 : y1,
|
y1 < _y1 ? _y1 : y1,
|
||||||
pen_width, len,
|
pen_width, len,
|
||||||
PATCOPY)))
|
rop2_to_patblt_rop (gcwin32->rop2))))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
y1 += dashes[n % num_dashes];
|
y1 += gcwin32->pen_dashes[n % gcwin32->pen_num_dashes];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gcwin32->pen_double_dash)
|
if (gcwin32->line_style == GDK_LINE_DOUBLE_DASH)
|
||||||
{
|
{
|
||||||
HBRUSH hbr;
|
HBRUSH hbr;
|
||||||
|
|
||||||
if ((hbr = SelectObject (hdc, gcwin32->pen_hbrbg)) == HGDI_ERROR)
|
if ((hbr = SelectObject (gcwin32->hdc, gcwin32->pen_hbrbg)) == HGDI_ERROR)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
y1 = _y1;
|
y1 = _y1;
|
||||||
if (gcwin32->pen_dashes)
|
y1 += gcwin32->pen_dash_offset;
|
||||||
y1 += gcwin32->pen_dash_offset;
|
|
||||||
for (n = 0; y1 < y2; n++)
|
for (n = 0; y1 < y2; n++)
|
||||||
{
|
{
|
||||||
int len = dashes[n % num_dashes];
|
int len = gcwin32->pen_dashes[n % gcwin32->pen_num_dashes];
|
||||||
if (y1 + len > y2)
|
if (y1 + len > y2)
|
||||||
len = y2 - y1;
|
len = y2 - y1;
|
||||||
if (n % 2)
|
if (n % 2)
|
||||||
if (!GDI_CALL (PatBlt, (hdc, x - pen_width / 2, y1,
|
if (!GDI_CALL (PatBlt, (gcwin32->hdc, x - pen_width / 2, y1,
|
||||||
pen_width, len,
|
pen_width, len,
|
||||||
PATCOPY)))
|
rop2_to_patblt_rop (gcwin32->rop2))))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
y1 += dashes[n % num_dashes];
|
y1 += gcwin32->pen_dashes[n % gcwin32->pen_num_dashes];
|
||||||
}
|
}
|
||||||
if (SelectObject (hdc, hbr) == HGDI_ERROR)
|
if (SelectObject (gcwin32->hdc, hbr) == HGDI_ERROR)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,34 +510,6 @@ draw_tiles (GdkDrawable *drawable,
|
|||||||
gdk_gc_unref (gc_copy);
|
gdk_gc_unref (gc_copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
rop2_to_rop3 (int rop2)
|
|
||||||
{
|
|
||||||
switch (rop2)
|
|
||||||
{
|
|
||||||
/* Oh, Microsoft's silly names for binary and ternary rops. */
|
|
||||||
#define CASE(rop2,rop3) case R2_##rop2: return rop3
|
|
||||||
CASE (BLACK, BLACKNESS);
|
|
||||||
CASE (NOTMERGEPEN, NOTSRCERASE);
|
|
||||||
CASE (MASKNOTPEN, 0x00220326);
|
|
||||||
CASE (NOTCOPYPEN, NOTSRCCOPY);
|
|
||||||
CASE (MASKPENNOT, SRCERASE);
|
|
||||||
CASE (NOT, DSTINVERT);
|
|
||||||
CASE (XORPEN, SRCINVERT);
|
|
||||||
CASE (NOTMASKPEN, 0x007700E6);
|
|
||||||
CASE (MASKPEN, SRCAND);
|
|
||||||
CASE (NOTXORPEN, 0x00990066);
|
|
||||||
CASE (NOP, 0x00AA0029);
|
|
||||||
CASE (MERGENOTPEN, MERGEPAINT);
|
|
||||||
CASE (COPYPEN, SRCCOPY);
|
|
||||||
CASE (MERGEPENNOT, 0x00DD0228);
|
|
||||||
CASE (MERGEPEN, SRCPAINT);
|
|
||||||
CASE (WHITE, WHITENESS);
|
|
||||||
#undef CASE
|
|
||||||
default: return SRCCOPY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
generic_draw (GdkDrawable *drawable,
|
generic_draw (GdkDrawable *drawable,
|
||||||
GdkGC *gc,
|
GdkGC *gc,
|
||||||
@ -835,9 +832,7 @@ draw_rectangle (GdkGCWin32 *gcwin32,
|
|||||||
x -= x_offset;
|
x -= x_offset;
|
||||||
y -= y_offset;
|
y -= y_offset;
|
||||||
|
|
||||||
if (!filled && (gcwin32->pen_double_dash ||
|
if (!filled && MUST_RENDER_DASHES_MANUALLY (gcwin32))
|
||||||
(gcwin32->pen_dashes && (gcwin32->pen_dash_offset ||
|
|
||||||
!G_WIN32_IS_NT_BASED ()))))
|
|
||||||
{
|
{
|
||||||
render_line_vertical (gcwin32, x, y, y+height+1) &&
|
render_line_vertical (gcwin32, x, y, y+height+1) &&
|
||||||
render_line_horizontal (gcwin32, x, x+width+1, y) &&
|
render_line_horizontal (gcwin32, x, x+width+1, y) &&
|
||||||
@ -1284,9 +1279,7 @@ draw_segments (GdkGCWin32 *gcwin32,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gcwin32->pen_double_dash ||
|
if (MUST_RENDER_DASHES_MANUALLY (gcwin32))
|
||||||
(gcwin32->pen_dashes && (gcwin32->pen_dash_offset ||
|
|
||||||
!G_WIN32_IS_NT_BASED ())))
|
|
||||||
{
|
{
|
||||||
for (i = 0; i < nsegs; i++)
|
for (i = 0; i < nsegs; i++)
|
||||||
{
|
{
|
||||||
@ -1315,42 +1308,22 @@ draw_segments (GdkGCWin32 *gcwin32,
|
|||||||
else
|
else
|
||||||
GDI_CALL (MoveToEx, (hdc, segs[i].x1, segs[i].y1, NULL)) &&
|
GDI_CALL (MoveToEx, (hdc, segs[i].x1, segs[i].y1, NULL)) &&
|
||||||
GDI_CALL (LineTo, (hdc, segs[i].x2, segs[i].y2));
|
GDI_CALL (LineTo, (hdc, segs[i].x2, segs[i].y2));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (i = 0; i < nsegs; i++)
|
for (i = 0; i < nsegs; i++)
|
||||||
GDI_CALL (MoveToEx, (hdc, segs[i].x1, segs[i].y1, NULL)) &&
|
{
|
||||||
GDI_CALL (LineTo, (hdc, segs[i].x2, segs[i].y2));
|
const GdkSegment *ps = &segs[i];
|
||||||
|
const int x1 = ps->x1, y1 = ps->y1;
|
||||||
|
int x2 = ps->x2, y2 = ps->y2;
|
||||||
|
|
||||||
/* not drawing the end pixel does produce a crippled mask, look
|
GDK_NOTE (MISC, g_print (" +%d+%d..+%d+%d", x1, y1, x2, y2));
|
||||||
* e.g. at xpm icons produced with gdk_pixbuf_new_from_xpm_data trough
|
GDI_CALL (MoveToEx, (hdc, x1, y1, NULL)) &&
|
||||||
* gdk_pixbuf_render_threshold_alpha (testgtk folder icon or
|
GDI_CALL (LineTo, (hdc, x2, y2));
|
||||||
* Dia's toolbox icons) but only on win9x ... --hb
|
}
|
||||||
*
|
|
||||||
* Update : see bug #81895 and bug #126710 why this is finally
|
|
||||||
* needed on any win32 platform ;-)
|
|
||||||
*/
|
|
||||||
if (gcwin32->pen_width <= 1)
|
|
||||||
{
|
|
||||||
GdkSegment *ps = &segs[nsegs-1];
|
|
||||||
int xc = 0, yc = 0;
|
|
||||||
|
|
||||||
if (ps->y2 == ps->y1 && ps->x2 == ps->x1)
|
GDK_NOTE (MISC, g_print ("\n"));
|
||||||
xc = 1; /* just a point */
|
|
||||||
else if (ps->y2 == ps->y1)
|
|
||||||
xc = (ps->x1 < ps->x2) ? 1 : -1; /* advance x only */
|
|
||||||
else if (ps->x2 == ps->x1)
|
|
||||||
yc = (ps->y1 < ps->y2) ? 1 : -1; /* advance y only */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
xc = (ps->x1 < ps->x2) ? 1 : -1;
|
|
||||||
yc = (ps->y1 < ps->y2) ? 1 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
GDI_CALL (LineTo, (hdc, ps->x2 + xc, ps->y2 + yc));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (x_offset != 0 || y_offset != 0)
|
if (x_offset != 0 || y_offset != 0)
|
||||||
g_free (segs);
|
g_free (segs);
|
||||||
@ -1393,8 +1366,7 @@ gdk_win32_draw_segments (GdkDrawable *drawable,
|
|||||||
|
|
||||||
region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
|
region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
|
||||||
|
|
||||||
generic_draw (drawable, gc, GDK_GC_FOREGROUND | GDK_GC_FOREGROUND |
|
generic_draw (drawable, gc, GDK_GC_FOREGROUND | LINE_ATTRIBUTES,
|
||||||
LINE_ATTRIBUTES,
|
|
||||||
draw_segments, region, segs, nsegs);
|
draw_segments, region, segs, nsegs);
|
||||||
|
|
||||||
gdk_region_destroy (region);
|
gdk_region_destroy (region);
|
||||||
@ -1421,9 +1393,7 @@ draw_lines (GdkGCWin32 *gcwin32,
|
|||||||
pts[i].y -= y_offset;
|
pts[i].y -= y_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gcwin32->pen_double_dash ||
|
if (MUST_RENDER_DASHES_MANUALLY (gcwin32))
|
||||||
(gcwin32->pen_dashes && (gcwin32->pen_dash_offset ||
|
|
||||||
!G_WIN32_IS_NT_BASED ())))
|
|
||||||
{
|
{
|
||||||
for (i = 0; i < npoints - 1; i++)
|
for (i = 0; i < npoints - 1; i++)
|
||||||
{
|
{
|
||||||
|
@ -113,6 +113,115 @@ gdk_gc_win32_finalize (GObject *object)
|
|||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fixup_pen (GdkGCWin32 *win32_gc)
|
||||||
|
{
|
||||||
|
win32_gc->pen_style = 0;
|
||||||
|
|
||||||
|
/* First look at GDK width and end cap style, set GDI pen type and
|
||||||
|
* end cap.
|
||||||
|
*/
|
||||||
|
if (win32_gc->pen_width == 0 &&
|
||||||
|
win32_gc->cap_style == GDK_CAP_NOT_LAST)
|
||||||
|
{
|
||||||
|
/* Use a cosmetic pen, always width 1 */
|
||||||
|
win32_gc->pen_style |= PS_COSMETIC;
|
||||||
|
}
|
||||||
|
else if (win32_gc->pen_width <= 1 &&
|
||||||
|
win32_gc->cap_style == GDK_CAP_BUTT)
|
||||||
|
{
|
||||||
|
/* For 1 pixel wide lines PS_ENDCAP_ROUND means draw both ends,
|
||||||
|
* even for one pixel length lines. But if we are drawing dashed
|
||||||
|
* lines we can't use PS_ENDCAP_ROUND.
|
||||||
|
*/
|
||||||
|
if (win32_gc->line_style == GDK_LINE_SOLID)
|
||||||
|
win32_gc->pen_style |= PS_GEOMETRIC | PS_ENDCAP_ROUND;
|
||||||
|
else
|
||||||
|
win32_gc->pen_style |= PS_GEOMETRIC | PS_ENDCAP_FLAT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
win32_gc->pen_style |= PS_GEOMETRIC;
|
||||||
|
switch (win32_gc->cap_style)
|
||||||
|
{
|
||||||
|
/* For non-zero-width lines X11's CapNotLast works like CapButt */
|
||||||
|
case GDK_CAP_NOT_LAST:
|
||||||
|
case GDK_CAP_BUTT:
|
||||||
|
win32_gc->pen_style |= PS_ENDCAP_FLAT;
|
||||||
|
break;
|
||||||
|
case GDK_CAP_ROUND:
|
||||||
|
win32_gc->pen_style |= PS_ENDCAP_ROUND;
|
||||||
|
break;
|
||||||
|
case GDK_CAP_PROJECTING:
|
||||||
|
win32_gc->pen_style |= PS_ENDCAP_SQUARE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next look at GDK line style, set GDI pen style attribute */
|
||||||
|
switch (win32_gc->line_style)
|
||||||
|
{
|
||||||
|
case GDK_LINE_SOLID:
|
||||||
|
win32_gc->pen_style |= PS_SOLID;
|
||||||
|
break;
|
||||||
|
case GDK_LINE_ON_OFF_DASH:
|
||||||
|
case GDK_LINE_DOUBLE_DASH:
|
||||||
|
if (win32_gc->pen_dashes == NULL)
|
||||||
|
{
|
||||||
|
win32_gc->pen_dashes = g_new (DWORD, 1);
|
||||||
|
win32_gc->pen_dashes[0] = 4;
|
||||||
|
win32_gc->pen_num_dashes = 1;
|
||||||
|
}
|
||||||
|
if (G_WIN32_IS_NT_BASED ())
|
||||||
|
{
|
||||||
|
if (!(win32_gc->pen_style & PS_TYPE_MASK) == PS_GEOMETRIC &&
|
||||||
|
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_style |= PS_ALTERNATE;
|
||||||
|
else
|
||||||
|
win32_gc->pen_style |= PS_USERSTYLE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Render "short" on-off dashes drawn with R2_COPYPEN and a
|
||||||
|
* cosmetic pen using PS_DOT
|
||||||
|
*/
|
||||||
|
if (win32_gc->line_style == GDK_LINE_ON_OFF_DASH &&
|
||||||
|
win32_gc->rop2 == R2_COPYPEN &&
|
||||||
|
(win32_gc->pen_style & PS_TYPE_MASK) == PS_COSMETIC &&
|
||||||
|
win32_gc->pen_dashes[0] <= 2 &&
|
||||||
|
(win32_gc->pen_num_dashes == 1 ||
|
||||||
|
(win32_gc->pen_num_dashes == 2 && win32_gc->pen_dashes[1] <= 2)))
|
||||||
|
win32_gc->pen_style |= PS_DOT;
|
||||||
|
else
|
||||||
|
/* Otherwise render opaque lines solid, horizontal or
|
||||||
|
* vertical ones will be dashed manually, see
|
||||||
|
* gdkdrawable-win32.c.
|
||||||
|
*/
|
||||||
|
win32_gc->pen_style |= PS_SOLID;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Last, for if the GDI pen is geometric, set the join attribute */
|
||||||
|
if ((win32_gc->pen_style & PS_TYPE_MASK) == PS_GEOMETRIC)
|
||||||
|
{
|
||||||
|
switch (win32_gc->join_style)
|
||||||
|
{
|
||||||
|
case GDK_JOIN_MITER:
|
||||||
|
win32_gc->pen_style |= PS_JOIN_MITER;
|
||||||
|
break;
|
||||||
|
case GDK_JOIN_ROUND:
|
||||||
|
win32_gc->pen_style |= PS_JOIN_ROUND;
|
||||||
|
break;
|
||||||
|
case GDK_JOIN_BEVEL:
|
||||||
|
win32_gc->pen_style |= PS_JOIN_BEVEL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gdk_win32_gc_values_to_win32values (GdkGCValues *values,
|
gdk_win32_gc_values_to_win32values (GdkGCValues *values,
|
||||||
GdkGCValuesMask mask,
|
GdkGCValuesMask mask,
|
||||||
@ -217,45 +326,6 @@ gdk_win32_gc_values_to_win32values (GdkGCValues *values,
|
|||||||
{
|
{
|
||||||
if (values->stipple != NULL)
|
if (values->stipple != NULL)
|
||||||
{
|
{
|
||||||
#if 0 /* HB: this size limitation is disabled to make radio and check
|
|
||||||
* buttons work. I got the impression from the API docs, that
|
|
||||||
* it shouldn't be necessary at all, but win9x would do the clipping
|
|
||||||
*
|
|
||||||
* This code will need some work if reenabled since the stipple is
|
|
||||||
* now stored in the backend-independent code.
|
|
||||||
*/
|
|
||||||
gint sw, sh;
|
|
||||||
|
|
||||||
gdk_drawable_get_size (values->stipple, &sw, &sh);
|
|
||||||
|
|
||||||
if ( (sw != 8 || sh != 8)
|
|
||||||
&& !G_WIN32_IS_NT_BASED ()) /* HB: the MSDN says it's a Win95 limitation */
|
|
||||||
{
|
|
||||||
/* It seems that it *must* be 8x8, at least on my machine.
|
|
||||||
* Thus, tile an 8x8 bitmap with the stipple in case it is
|
|
||||||
* smaller, or simply use just the top left 8x8 in case it is
|
|
||||||
* larger.
|
|
||||||
*/
|
|
||||||
gchar dummy[8];
|
|
||||||
GdkPixmap *bm = gdk_bitmap_create_from_data (NULL, dummy, 8, 8);
|
|
||||||
GdkGC *gc = gdk_gc_new (bm);
|
|
||||||
gint i, j;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while (i < 8)
|
|
||||||
{
|
|
||||||
j = 0;
|
|
||||||
while (j < 8)
|
|
||||||
{
|
|
||||||
gdk_draw_drawable (bm, gc, values->stipple, 0, 0, i, j, sw, sh);
|
|
||||||
j += sh;
|
|
||||||
}
|
|
||||||
i += sw;
|
|
||||||
}
|
|
||||||
win32_gc->stipple = bm;
|
|
||||||
gdk_gc_unref (gc);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
win32_gc->values_mask |= GDK_GC_STIPPLE;
|
win32_gc->values_mask |= GDK_GC_STIPPLE;
|
||||||
GDK_NOTE (GC,
|
GDK_NOTE (GC,
|
||||||
(g_print ("%sstipple=%p", s,
|
(g_print ("%sstipple=%p", s,
|
||||||
@ -343,78 +413,32 @@ gdk_win32_gc_values_to_win32values (GdkGCValues *values,
|
|||||||
|
|
||||||
if (mask & GDK_GC_LINE_STYLE)
|
if (mask & GDK_GC_LINE_STYLE)
|
||||||
{
|
{
|
||||||
switch (values->line_style)
|
win32_gc->line_style = values->line_style;
|
||||||
{
|
|
||||||
case GDK_LINE_SOLID:
|
|
||||||
if (win32_gc->pen_dashes)
|
|
||||||
{
|
|
||||||
g_free (win32_gc->pen_dashes);
|
|
||||||
win32_gc->pen_dashes = NULL;
|
|
||||||
win32_gc->pen_num_dashes = 0;
|
|
||||||
}
|
|
||||||
win32_gc->pen_style &= ~(PS_STYLE_MASK);
|
|
||||||
win32_gc->pen_style |= PS_SOLID;
|
|
||||||
win32_gc->pen_double_dash = FALSE;
|
|
||||||
break;
|
|
||||||
case GDK_LINE_ON_OFF_DASH:
|
|
||||||
case GDK_LINE_DOUBLE_DASH:
|
|
||||||
if (!win32_gc->pen_dashes)
|
|
||||||
{
|
|
||||||
/* setting to PS_DASH probably isn't correct. If I understand the
|
|
||||||
* xlib docs correctly it should influence the handling of
|
|
||||||
* line endings ? --hb
|
|
||||||
*/
|
|
||||||
win32_gc->pen_style &= ~(PS_STYLE_MASK);
|
|
||||||
win32_gc->pen_style |= PS_DASH;
|
|
||||||
}
|
|
||||||
win32_gc->pen_double_dash = values->line_style == GDK_LINE_DOUBLE_DASH;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
GDK_NOTE (GC, (g_print ("%sps|=PS_STYLE_%s", s, _gdk_win32_psstyle_to_string (win32_gc->pen_style)),
|
|
||||||
s = ","));
|
|
||||||
win32_gc->values_mask |= GDK_GC_LINE_STYLE;
|
win32_gc->values_mask |= GDK_GC_LINE_STYLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mask & GDK_GC_CAP_STYLE)
|
if (mask & GDK_GC_CAP_STYLE)
|
||||||
{
|
{
|
||||||
win32_gc->pen_style &= ~(PS_ENDCAP_MASK);
|
win32_gc->cap_style = values->cap_style;
|
||||||
switch (values->cap_style)
|
|
||||||
{
|
|
||||||
case GDK_CAP_NOT_LAST: /* ??? */
|
|
||||||
case GDK_CAP_BUTT:
|
|
||||||
win32_gc->pen_style |= PS_ENDCAP_FLAT;
|
|
||||||
break;
|
|
||||||
case GDK_CAP_ROUND:
|
|
||||||
win32_gc->pen_style |= PS_ENDCAP_ROUND;
|
|
||||||
break;
|
|
||||||
case GDK_CAP_PROJECTING:
|
|
||||||
win32_gc->pen_style |= PS_ENDCAP_SQUARE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
GDK_NOTE (GC, (g_print ("%sps|=PS_ENDCAP_%s", s, _gdk_win32_psendcap_to_string (win32_gc->pen_style)),
|
|
||||||
s = ","));
|
|
||||||
win32_gc->values_mask |= GDK_GC_CAP_STYLE;
|
win32_gc->values_mask |= GDK_GC_CAP_STYLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mask & GDK_GC_JOIN_STYLE)
|
if (mask & GDK_GC_JOIN_STYLE)
|
||||||
{
|
{
|
||||||
win32_gc->pen_style &= ~(PS_JOIN_MASK);
|
win32_gc->join_style = values->join_style;
|
||||||
switch (values->join_style)
|
|
||||||
{
|
|
||||||
case GDK_JOIN_MITER:
|
|
||||||
win32_gc->pen_style |= PS_JOIN_MITER;
|
|
||||||
break;
|
|
||||||
case GDK_JOIN_ROUND:
|
|
||||||
win32_gc->pen_style |= PS_JOIN_ROUND;
|
|
||||||
break;
|
|
||||||
case GDK_JOIN_BEVEL:
|
|
||||||
win32_gc->pen_style |= PS_JOIN_BEVEL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
GDK_NOTE (GC, (g_print ("%sps|=PS_JOIN_%s", s, _gdk_win32_psjoin_to_string (win32_gc->pen_style)),
|
|
||||||
s = ","));
|
|
||||||
win32_gc->values_mask |= GDK_GC_JOIN_STYLE;
|
win32_gc->values_mask |= GDK_GC_JOIN_STYLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mask & (GDK_GC_LINE_WIDTH|GDK_GC_LINE_STYLE|GDK_GC_CAP_STYLE|GDK_GC_JOIN_STYLE))
|
||||||
|
{
|
||||||
|
fixup_pen (win32_gc);
|
||||||
|
GDK_NOTE (GC, (g_print ("%sps|=PS_STYLE_%s|PS_ENDCAP_%s|PS_JOIN_%s", s,
|
||||||
|
_gdk_win32_psstyle_to_string (win32_gc->pen_style),
|
||||||
|
_gdk_win32_psendcap_to_string (win32_gc->pen_style),
|
||||||
|
_gdk_win32_psjoin_to_string (win32_gc->pen_style)),
|
||||||
|
s = ","));
|
||||||
|
}
|
||||||
|
|
||||||
GDK_NOTE (GC, g_print ("} mask=(%s)", _gdk_win32_gcvalues_mask_to_string (win32_gc->values_mask)));
|
GDK_NOTE (GC, g_print ("} mask=(%s)", _gdk_win32_gcvalues_mask_to_string (win32_gc->values_mask)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,11 +467,17 @@ _gdk_win32_gc_new (GdkDrawable *drawable,
|
|||||||
win32_gc->subwindow_mode = GDK_CLIP_BY_CHILDREN;
|
win32_gc->subwindow_mode = GDK_CLIP_BY_CHILDREN;
|
||||||
win32_gc->graphics_exposures = TRUE;
|
win32_gc->graphics_exposures = TRUE;
|
||||||
win32_gc->pen_width = 0;
|
win32_gc->pen_width = 0;
|
||||||
win32_gc->pen_style = PS_GEOMETRIC|PS_ENDCAP_FLAT|PS_JOIN_MITER;
|
/* Don't get confused by the PS_ENDCAP_ROUND. For narrow GDI pens
|
||||||
|
* (width == 1), PS_GEOMETRIC|PS_ENDCAP_ROUND works like X11's
|
||||||
|
* CapButt.
|
||||||
|
*/
|
||||||
|
win32_gc->pen_style = PS_GEOMETRIC|PS_ENDCAP_ROUND|PS_JOIN_MITER;
|
||||||
|
win32_gc->line_style = GDK_LINE_SOLID;
|
||||||
|
win32_gc->cap_style = GDK_CAP_BUTT;
|
||||||
|
win32_gc->join_style = GDK_JOIN_MITER;
|
||||||
win32_gc->pen_dashes = NULL;
|
win32_gc->pen_dashes = NULL;
|
||||||
win32_gc->pen_num_dashes = 0;
|
win32_gc->pen_num_dashes = 0;
|
||||||
win32_gc->pen_dash_offset = 0;
|
win32_gc->pen_dash_offset = 0;
|
||||||
win32_gc->pen_double_dash = FALSE;
|
|
||||||
win32_gc->pen_hbrbg = NULL;
|
win32_gc->pen_hbrbg = NULL;
|
||||||
|
|
||||||
win32_gc->values_mask = GDK_GC_FUNCTION | GDK_GC_FILL;
|
win32_gc->values_mask = GDK_GC_FUNCTION | GDK_GC_FILL;
|
||||||
@ -522,29 +552,9 @@ gdk_win32_gc_get_values (GdkGC *gc,
|
|||||||
values->graphics_exposures = win32_gc->graphics_exposures;
|
values->graphics_exposures = win32_gc->graphics_exposures;
|
||||||
values->line_width = win32_gc->pen_width;
|
values->line_width = win32_gc->pen_width;
|
||||||
|
|
||||||
if (win32_gc->pen_style & PS_SOLID)
|
values->line_style = win32_gc->line_style;
|
||||||
values->line_style = GDK_LINE_SOLID;
|
values->cap_style = win32_gc->cap_style;
|
||||||
else if (win32_gc->pen_style & PS_DASH)
|
values->join_style = win32_gc->join_style;
|
||||||
values->line_style = win32_gc->pen_double_dash ? GDK_LINE_DOUBLE_DASH :
|
|
||||||
GDK_LINE_ON_OFF_DASH;
|
|
||||||
else
|
|
||||||
values->line_style = GDK_LINE_SOLID;
|
|
||||||
|
|
||||||
/* PS_ENDCAP_ROUND is zero */
|
|
||||||
if (win32_gc->pen_style & PS_ENDCAP_FLAT)
|
|
||||||
values->cap_style = GDK_CAP_BUTT;
|
|
||||||
else if (win32_gc->pen_style & PS_ENDCAP_SQUARE)
|
|
||||||
values->cap_style = GDK_CAP_PROJECTING;
|
|
||||||
else
|
|
||||||
values->cap_style = GDK_CAP_ROUND;
|
|
||||||
|
|
||||||
/* PS_JOIN_ROUND is zero */
|
|
||||||
if (win32_gc->pen_style & PS_JOIN_MITER)
|
|
||||||
values->join_style = GDK_JOIN_MITER;
|
|
||||||
else if (win32_gc->pen_style & PS_JOIN_BEVEL)
|
|
||||||
values->join_style = GDK_JOIN_BEVEL;
|
|
||||||
else
|
|
||||||
values->join_style = GDK_JOIN_ROUND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -573,19 +583,13 @@ gdk_win32_gc_set_dashes (GdkGC *gc,
|
|||||||
|
|
||||||
win32_gc = GDK_GC_WIN32 (gc);
|
win32_gc = GDK_GC_WIN32 (gc);
|
||||||
|
|
||||||
/* mark as set, see gdk_win32_gc_values_to_win32values () for the reason */
|
|
||||||
win32_gc->values_mask |= GDK_GC_LINE_STYLE;
|
|
||||||
|
|
||||||
win32_gc->pen_style &= ~(PS_STYLE_MASK);
|
|
||||||
|
|
||||||
win32_gc->pen_style |= (PS_GEOMETRIC | PS_USERSTYLE);
|
|
||||||
win32_gc->pen_num_dashes = n;
|
win32_gc->pen_num_dashes = n;
|
||||||
if (win32_gc->pen_dashes != NULL)
|
g_free (win32_gc->pen_dashes);
|
||||||
g_free (win32_gc->pen_dashes);
|
|
||||||
win32_gc->pen_dashes = g_new (DWORD, n);
|
win32_gc->pen_dashes = g_new (DWORD, n);
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
win32_gc->pen_dashes[i] = dash_list[i];
|
win32_gc->pen_dashes[i] = dash_list[i];
|
||||||
win32_gc->pen_dash_offset = dash_offset;
|
win32_gc->pen_dash_offset = dash_offset;
|
||||||
|
fixup_pen (win32_gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -659,13 +663,16 @@ _gdk_windowing_gc_copy (GdkGC *dst_gc,
|
|||||||
dst_win32_gc->graphics_exposures = src_win32_gc->graphics_exposures;
|
dst_win32_gc->graphics_exposures = src_win32_gc->graphics_exposures;
|
||||||
dst_win32_gc->pen_width = src_win32_gc->pen_width;
|
dst_win32_gc->pen_width = src_win32_gc->pen_width;
|
||||||
dst_win32_gc->pen_style = src_win32_gc->pen_style;
|
dst_win32_gc->pen_style = src_win32_gc->pen_style;
|
||||||
dst_win32_gc->pen_dashes = src_win32_gc->pen_dashes;
|
dst_win32_gc->line_style = src_win32_gc->line_style;
|
||||||
if (dst_win32_gc->pen_dashes)
|
dst_win32_gc->cap_style = src_win32_gc->cap_style;
|
||||||
|
dst_win32_gc->join_style = src_win32_gc->join_style;
|
||||||
|
if (src_win32_gc->pen_dashes)
|
||||||
dst_win32_gc->pen_dashes = g_memdup (src_win32_gc->pen_dashes,
|
dst_win32_gc->pen_dashes = g_memdup (src_win32_gc->pen_dashes,
|
||||||
sizeof (DWORD) * src_win32_gc->pen_num_dashes);
|
sizeof (DWORD) * src_win32_gc->pen_num_dashes);
|
||||||
|
else
|
||||||
|
dst_win32_gc->pen_dashes = NULL;
|
||||||
dst_win32_gc->pen_num_dashes = src_win32_gc->pen_num_dashes;
|
dst_win32_gc->pen_num_dashes = src_win32_gc->pen_num_dashes;
|
||||||
dst_win32_gc->pen_dash_offset = src_win32_gc->pen_dash_offset;
|
dst_win32_gc->pen_dash_offset = src_win32_gc->pen_dash_offset;
|
||||||
dst_win32_gc->pen_double_dash = src_win32_gc->pen_double_dash;
|
|
||||||
|
|
||||||
|
|
||||||
dst_win32_gc->hdc = NULL;
|
dst_win32_gc->hdc = NULL;
|
||||||
@ -825,7 +832,6 @@ gdk_win32_hdc_get (GdkDrawable *drawable,
|
|||||||
GdkDrawableImplWin32 *impl = NULL;
|
GdkDrawableImplWin32 *impl = NULL;
|
||||||
gboolean ok = TRUE;
|
gboolean ok = TRUE;
|
||||||
COLORREF fg = RGB (0, 0, 0), bg = RGB (255, 255, 255);
|
COLORREF fg = RGB (0, 0, 0), bg = RGB (255, 255, 255);
|
||||||
LOGBRUSH logbrush;
|
|
||||||
HPEN hpen;
|
HPEN hpen;
|
||||||
HBRUSH hbr;
|
HBRUSH hbr;
|
||||||
|
|
||||||
@ -858,7 +864,7 @@ gdk_win32_hdc_get (GdkDrawable *drawable,
|
|||||||
if (ok && (usage & LINE_ATTRIBUTES))
|
if (ok && (usage & LINE_ATTRIBUTES))
|
||||||
{
|
{
|
||||||
/* For drawing GDK_LINE_DOUBLE_DASH */
|
/* For drawing GDK_LINE_DOUBLE_DASH */
|
||||||
if ((usage & GDK_GC_BACKGROUND) && win32_gc->pen_double_dash)
|
if ((usage & GDK_GC_BACKGROUND) && win32_gc->line_style == GDK_LINE_DOUBLE_DASH)
|
||||||
{
|
{
|
||||||
bg = _gdk_win32_colormap_color (impl->colormap, _gdk_gc_get_bg_pixel (gc));
|
bg = _gdk_win32_colormap_color (impl->colormap, _gdk_gc_get_bg_pixel (gc));
|
||||||
if ((win32_gc->pen_hbrbg = CreateSolidBrush (bg)) == NULL)
|
if ((win32_gc->pen_hbrbg = CreateSolidBrush (bg)) == NULL)
|
||||||
@ -867,33 +873,26 @@ gdk_win32_hdc_get (GdkDrawable *drawable,
|
|||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
|
LOGBRUSH logbrush;
|
||||||
|
DWORD style_count = 0;
|
||||||
|
const DWORD *style = NULL;
|
||||||
|
|
||||||
/* Create and select pen */
|
/* Create and select pen */
|
||||||
logbrush.lbStyle = BS_SOLID;
|
logbrush.lbStyle = BS_SOLID;
|
||||||
logbrush.lbColor = fg;
|
logbrush.lbColor = fg;
|
||||||
logbrush.lbHatch = 0;
|
logbrush.lbHatch = 0;
|
||||||
|
|
||||||
if (win32_gc->pen_num_dashes > 0 && !G_WIN32_IS_NT_BASED ())
|
if ((win32_gc->pen_style & PS_STYLE_MASK) == PS_USERSTYLE)
|
||||||
{
|
{
|
||||||
/* The Win9x GDI is rather limited so we either draw dashed
|
style_count = win32_gc->pen_num_dashes;
|
||||||
* lines ourselves (only horizontal and vertical) or let them be
|
style = win32_gc->pen_dashes;
|
||||||
* drawn solid to avoid implementing a whole line renderer.
|
|
||||||
*/
|
|
||||||
if ((hpen = ExtCreatePen (
|
|
||||||
(win32_gc->pen_style & ~(PS_STYLE_MASK)) | PS_SOLID,
|
|
||||||
MAX (win32_gc->pen_width, 1),
|
|
||||||
&logbrush,
|
|
||||||
0, NULL)) == NULL)
|
|
||||||
WIN32_GDI_FAILED ("ExtCreatePen"), ok = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((hpen = ExtCreatePen (win32_gc->pen_style,
|
|
||||||
MAX (win32_gc->pen_width, 1),
|
|
||||||
&logbrush,
|
|
||||||
win32_gc->pen_num_dashes,
|
|
||||||
win32_gc->pen_dashes)) == NULL)
|
|
||||||
WIN32_GDI_FAILED ("ExtCreatePen"), ok = FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((hpen = ExtCreatePen (win32_gc->pen_style,
|
||||||
|
MAX (win32_gc->pen_width, 1),
|
||||||
|
&logbrush,
|
||||||
|
style_count, style)) == NULL)
|
||||||
|
WIN32_GDI_FAILED ("ExtCreatePen"), ok = FALSE;
|
||||||
|
|
||||||
if (ok && SelectObject (win32_gc->hdc, hpen) == NULL)
|
if (ok && SelectObject (win32_gc->hdc, hpen) == NULL)
|
||||||
WIN32_GDI_FAILED ("SelectObject"), ok = FALSE;
|
WIN32_GDI_FAILED ("SelectObject"), ok = FALSE;
|
||||||
|
@ -274,10 +274,12 @@ struct _GdkGCWin32
|
|||||||
gint graphics_exposures;
|
gint graphics_exposures;
|
||||||
gint pen_width;
|
gint pen_width;
|
||||||
DWORD pen_style;
|
DWORD pen_style;
|
||||||
|
GdkLineStyle line_style;
|
||||||
|
GdkCapStyle cap_style;
|
||||||
|
GdkJoinStyle join_style;
|
||||||
DWORD *pen_dashes; /* use for PS_USERSTYLE or step-by-step rendering */
|
DWORD *pen_dashes; /* use for PS_USERSTYLE or step-by-step rendering */
|
||||||
gint pen_num_dashes;
|
gint pen_num_dashes;
|
||||||
gint pen_dash_offset;
|
gint pen_dash_offset;
|
||||||
gboolean pen_double_dash;
|
|
||||||
HBRUSH pen_hbrbg;
|
HBRUSH pen_hbrbg;
|
||||||
|
|
||||||
/* Following fields are valid while the GC exists as a Windows DC */
|
/* Following fields are valid while the GC exists as a Windows DC */
|
||||||
|
Loading…
Reference in New Issue
Block a user