[cairo-bugs] [Bug 28541] New: No drwing after InvalidRect for partial window content

bugzilla-daemon at freedesktop.org bugzilla-daemon at freedesktop.org
Mon Jun 14 14:36:03 PDT 2010


https://bugs.freedesktop.org/show_bug.cgi?id=28541

           Summary: No drwing after InvalidRect for partial window content
           Product: cairo
           Version: 1.9.8
          Platform: x86 (IA32)
        OS/Version: Windows (All)
            Status: NEW
          Severity: critical
          Priority: medium
         Component: win32 backend
        AssignedTo: cairo-bugs at cairographics.org
        ReportedBy: tim at framstag.com
         QAContact: cairo-bugs at cairographics.org


I now started using cairo not only under X11 but also under Windows. My code is
designed that way, that I only draw within the WM_PAINT event, creating a cairo
surface using the HDC returned by BeginPaint (AFAIK this is the recommended
way). For getting parts of the windows repainted because of changes (in
reaction to user input) I call InvalidateRect (I also tried RedrawWindow with
same results) with the RECT to get redrawn to trigger WM_PAINT message for the
given region (AFAIK this is also the recommended way).

This works fine for WM_PAINT messages created by the system (initial WM_PAINT
on window open, WM_PAINT messages on window resize) but it fails for WM_PAINT
messages created by InvalidateRect - if a valid RECT* is handed over. While the
content of WM_PAINT is correct and cairo_clip_extents() on the temporary
surface shows reasonable values in all cases (while having the coordinate
origin obviously in lower left, instead upper left) , nothing gets drawn at
all. As soon as I pass NULL as RECT*, redraw works like a charm. However doing
full screen refresh on every redraw is obviously not a long term solution ;-) I
assume that cases where the cliping reagion on the HDC is not the full window
are differently (and possibly wrongly?) handled or I'm doing something wrong
(e.g. are there any coordinate system transformations necessary on the Windows
or cairo side I'm missing?).

I'm using cairo-1.9.6 together with pixmap-0.18.2, the bug also occurs unde
1.9.8, but not under 1.8.10!

For a demo compile below program and press a key in the window. It show do a
InvalidRect for a part of the window, switch alternate to "true" and then draw
in a different color over the fulkl window size. I you now see a red rectangle
on a green background everything is fine, if you only see the initial green
background, the second draw did nothing! I assume that something is wrong witht
he handling of DC that have a cliping rectangle attached. If you change the
InvalidRect rectangle to the full window size (0,0-256,256), everything works
again.

You can compile the application undermingw using the following command line:
g++ cairo-gdi-demo.cpp `pkg-config.exe --cflags cairo
` `pkg-config.exe --libs cairo` -o cairo-gdi-demo.exe

As you can see from the copyright, this is a modified exampl by Andrew Lim.

/**
cairo-gdi-demo.cpp

Demonstrates how to get Cairo Graphics working with the Windows API and GDI.

Author: Andrew Lim
Email:  danteshamest at gmail.com
Site: windrealm.com
*/

#include <windows.h>
#include <cmath>
#include <cairo.h>
#include <cairo-win32.h>

#include <iostream>

static bool alternative=false;

/**
  Gradient demonstration.
  Taken from http://cairographics.org/samples/
*/
void gradientExample( cairo_t* cr ) {
  if (!alternative) {
    cairo_set_source_rgb(cr,0,1,0);
    cairo_rectangle (cr, 0, 0, 256, 256);
    cairo_fill (cr);
  }
  else {
    cairo_set_source_rgb(cr,1,0,0);
    cairo_rectangle (cr, 0, 0, 256, 256);
    cairo_fill (cr);
  }
}

/**
  Changes the dimensions of a window's client area.
*/
void SetClientSize( HWND hwnd, int clientWidth, int clientHeight ) {
  if ( IsWindow( hwnd ) ) {
    DWORD dwStyle = GetWindowLongPtr( hwnd, GWL_STYLE ) ;
    DWORD dwExStyle = GetWindowLongPtr( hwnd, GWL_EXSTYLE ) ;
    HMENU menu = GetMenu( hwnd ) ;
    RECT rc = { 0, 0, clientWidth, clientHeight } ;
    AdjustWindowRectEx( &rc, dwStyle, menu ? TRUE : FALSE, dwExStyle );
    SetWindowPos( hwnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
                  SWP_NOZORDER | SWP_NOMOVE ) ;
  }
}

/**
  Handles WM_PAINT.
*/
LRESULT onPaint( HWND hwnd, WPARAM wParam, LPARAM lParam ) {
  PAINTSTRUCT ps ;
  HDC hdc = BeginPaint( hwnd, &ps );

  // Create the cairo surface and context.
  cairo_surface_t *surface = cairo_win32_surface_create (hdc);
  cairo_t *cr = cairo_create (surface);

  // Draw on the cairo context.
  gradientExample( cr );

  // Cleanup.
  cairo_destroy (cr);
  cairo_surface_destroy (surface);

  EndPaint( hwnd, &ps );
  return 0 ;
}

LRESULT onKey( HWND hwnd, WPARAM wParam, LPARAM lParam ) {
  RECT rect;

  rect.left=128;
  rect.top=128;
  rect.right=64;
  rect.bottom=64;

  alternative=true;

  InvalidateRect(hwnd,&rect,false);
}
/**
  Handles WM_CLOSE.
*/
LRESULT onClose( HWND hwnd, WPARAM wParam, LPARAM lParam ) {
  PostQuitMessage( 0 );
  return 0 ;
}

/**
  Handles our window's messages.
*/
LRESULT CALLBACK WndProc( HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam ) {
  switch(msg) {
    case WM_PAINT:
      return onPaint( hwnd, wParam, lParam );
    case WM_CLOSE:
      return onClose( hwnd, wParam, lParam );
    case WM_KEYDOWN:
      std::cout << "Key down!" << std::endl;
      return onKey( hwnd, wParam, lParam );
      break;
    default:
      return DefWindowProc(hwnd,msg,wParam,lParam);
  }
}

int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrev, LPSTR args, int nShow ) {
  MSG  msg ;
  WNDCLASS wc = {0};
  wc.lpszClassName = TEXT( "CairoGdiWndClass" );
  wc.hInstance     = hInst ;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc ;
  wc.hCursor       = LoadCursor(0,IDC_ARROW);

  RegisterClass(&wc);
  HWND hwnd = CreateWindow( wc.lpszClassName,TEXT("Cairo & GDI Demo"),
                            WS_OVERLAPPEDWINDOW, 0,0,256,256,0,0,hInst,0);
  SetClientSize( hwnd, 256, 256 );
  ShowWindow( hwnd, SW_SHOWNORMAL );

  while( GetMessage(&msg,0,0,0) > 0 ) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return (int)msg.wParam;
}

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.


More information about the cairo-bugs mailing list