GDI+ line drawing and clipping bug

Tech-Archive recommends: Fix windows errors by optimizing your registry

From: Chris Hill (Chris244_at_aol.com)
Date: 08/20/04


Date: Fri, 20 Aug 2004 02:36:25 GMT

When I draw a one pixel thick line without antialiasing and the line
intersects the boundary of a clip rectangle that I have set, the line
doesn't always draw all the way to the clip rectangle boundary. It
may stop well (dozens of pixels) short of the clip rectangle. It
appears that the missing portion of the line starts at the last place
that the line changes pixel row or column.

This doesn't happen if:
- Antialiasing is enabled
- The pen is more than one pixel thick
- The line is perfectly horizontal or vertical
- The clipping is against the window boundaries rather than a clip
rectangle

Is this a bug in GDI+? This makes GDI+ very difficult to use for line
drawing in my application since it appears to be unreliable.

I have attached a small sample program demonstrating the issue I am
seeing. The nearly vertical line is drawn from the top of the window
to the bottom, advancing one pixel in the x direction. The horizontal
line represents the bottom of the clip rectangle. The vertical line
should always touch the horizonal line, but it doesn't when the mouse
is positioned slightly more than halfway down the window.

Chris

#include <windows.h>
#include <windowsx.h>
#include <gdiplus.h>
using namespace Gdiplus;

static char BUG_WINDOW_CLASS[] = "GDI+ Bug Window";
HINSTANCE hinst;

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
        switch(uMsg)
        {
        case WM_MOUSEMOVE:
                {
                Gdiplus::Graphics g(hwnd);
                Gdiplus::SolidBrush wb(Gdiplus::Color::White);
                Gdiplus::Pen bp(Gdiplus::Color::Black, 1.5);
                g.SetPageUnit(Gdiplus::UnitPixel);

//g.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
                RECT cr;
                GetClientRect(hwnd, &cr);
                Gdiplus::Rect pcr(cr.left, cr.top, cr.right-cr.left,
cr.bottom-cr.top);
                g.FillRectangle(&wb, pcr);
                int clipy = GET_Y_LPARAM(lParam);
                int centerx = cr.right/2;
                pcr.Height = clipy;
                g.DrawLine(&bp,cr.left,clipy,cr.right,clipy);
                g.SetClip(pcr);
                    g.DrawLine(&bp,centerx,cr.top,centerx+1,cr.bottom);
                break;
                }
        }
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

HWND MakeWindow()
{
        WNDCLASS wc;
        
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = WindowProc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hInstance = hinst;
        wc.hIcon = LoadIcon(NULL,IDI_EXCLAMATION);
        wc.hCursor = LoadCursor(NULL, IDC_CROSS);
        wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
        wc.lpszMenuName = NULL;
        wc.lpszClassName = BUG_WINDOW_CLASS;

        RegisterClass(&wc);

        return
CreateWindow(BUG_WINDOW_CLASS,BUG_WINDOW_CLASS,WS_VISIBLE|WS_TILEDWINDOW,
                     CW_USEDEFAULT, CW_USEDEFAULT, 500, 500, NULL,
NULL, hinst, 0);
}

int CALLBACK WinMain(HINSTANCE h, HINSTANCE prev, LPSTR cmdline, int
cmdshow)
{
        HWND win;
        MSG msg;
        GdiplusStartupInput gdiplusStartupInput;
        ULONG_PTR gdiplusToken;

        GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

        hinst = h;
        win = MakeWindow();
        while(GetMessage(&msg, win, 0, 0) > 0)
        {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
        }
        
        GdiplusShutdown(gdiplusToken);

        return 0;
}



Relevant Pages

  • Re: GDI+ line drawing and clipping bug
    ... >doesn't always draw all the way to the clip rectangle boundary. ... >that the line changes pixel row or column. ... >- The clipping is against the window boundaries rather than a clip ... The nearly vertical line is drawn from the top of the window ...
    (microsoft.public.win32.programmer.gdi)
  • Re: GDI+ line drawing and clipping bug
    ... Is there a public list of known GDI+ bugs? ... >doesn't always draw all the way to the clip rectangle boundary. ... >that the line changes pixel row or column. ... The nearly vertical line is drawn from the top of the window ...
    (microsoft.public.win32.programmer.gdi)
  • Re: [solved] Cant make fonts look any better
    ... arbitrarily choosing a value black or white for the pixel, ... a blurred glyph, one subdivides the pixel into smaller squares ... blur the boundaries which are horizontal or vertical. ... Practically this works better with TTF fonts that with ...
    (comp.unix.bsd.freebsd.misc)
  • Re: colortbl query | output differences...
    ... This seems to be a pixel rounding problem. ... dot that it can print or display. ... dvips -D 7200 ... ... the algorithm for rounding rule boundaries to pixel boundaries. ...
    (comp.text.tex)
  • Re: colortbl query | output differences...
    ... This seems to be a pixel rounding problem. ... dot that it can print or display. ... dvips -D 7200 ... ... the algorithm for rounding rule boundaries to pixel boundaries. ...
    (comp.text.tex)