Author: mlytwyn
Date: Sun Apr  3 22:59:32 2016
New Revision: 39615

URL: http://svn.gna.org/viewcvs/gnustep?rev=39615&view=rev
Log:
Set clipping region on cairo surface HDC to clean up drawing problems

Modified:
    libs/back/branches/gnustep_testplant_branch/Headers/cairo/Win32CairoGState.h
    libs/back/branches/gnustep_testplant_branch/Source/cairo/Win32CairoGState.m

Modified: 
libs/back/branches/gnustep_testplant_branch/Headers/cairo/Win32CairoGState.h
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/back/branches/gnustep_testplant_branch/Headers/cairo/Win32CairoGState.h?rev=39615&r1=39614&r2=39615&view=diff
==============================================================================
--- 
libs/back/branches/gnustep_testplant_branch/Headers/cairo/Win32CairoGState.h    
    (original)
+++ 
libs/back/branches/gnustep_testplant_branch/Headers/cairo/Win32CairoGState.h    
    Sun Apr  3 22:59:32 2016
@@ -24,10 +24,12 @@
 #define Win32CairoGState_h
 
 #include "cairo/CairoGState.h"
+#include <AppKit/NSBezierPath.h>
 
 
 @interface Win32CairoGState : CairoGState
 {
+  NSBezierPath *_lastPath;
 }
 
 - (HDC) getHDC;

Modified: 
libs/back/branches/gnustep_testplant_branch/Source/cairo/Win32CairoGState.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/back/branches/gnustep_testplant_branch/Source/cairo/Win32CairoGState.m?rev=39615&r1=39614&r2=39615&view=diff
==============================================================================
--- libs/back/branches/gnustep_testplant_branch/Source/cairo/Win32CairoGState.m 
(original)
+++ libs/back/branches/gnustep_testplant_branch/Source/cairo/Win32CairoGState.m 
Sun Apr  3 22:59:32 2016
@@ -28,8 +28,23 @@
 #include "cairo/CairoSurface.h"
 #include <cairo-win32.h>
 
+@interface CairoGState (Private)
+- (void) _setPath;
+@end
+
 @implementation Win32CairoGState 
 
+static inline
+POINT GSWindowPointToMS(GSGState *s, NSPoint p)
+{
+  POINT p1;
+  
+  p1.x = p.x - s->offset.x;
+  p1.y = s->offset.y - p.y;
+  
+  return p1;
+}
+
 + (void) initialize
 {
   if (self == [Win32CairoGState class])
@@ -41,12 +56,33 @@
 {
   if (_surface)
     {
+      cairo_surface_flush([_surface surface]);
       HDC hdc = cairo_win32_surface_get_dc([_surface surface]);
       NSDebugLLog(@"CairoGState",
                   @"%s:_surface: %p hdc: %p\n", __PRETTY_FUNCTION__,
                   _surface, hdc);
-      cairo_surface_flush([_surface surface]);
+      
+      // The WinUXTheme (and maybe others in the future?) draw directly into 
the HDC...
+      // Controls are always given the _bounds to draw into regardless of the 
actual invalid
+      // rectangle requested.  NSView only locks the focus for the invalid 
rectangle given,
+      // which in the failure case, is a partial rectangle for the control.
+      
+      // This drawing outside of cairo seems to bypass the clipping area, 
causing controls
+      // drawn using MSDN theme button backgrounds OUTSIDE of the actual 
invalid rectangle
+      // when they happen to intersect THRU a control rather than including 
the entire control.
+      // This is an unfortunate side effect of using unions i.e. NSUnionRect 
for the invalid rectangle,
+      // which causes this problem.
+      
+      // As a side note, it turns out that Apple Cocoa keeps individual 
rectangles and invokes the
+      // drawRect for each rectangle in turn.
+      
+      // Save the HDC...
       SaveDC(hdc);
+      
+      // and setup the clipping path region if we have one...
+      [self _clipRegionForHDC: hdc];
+      
+      // Return the HDC...
       return hdc;
     }
   NSLog(@"%s:_surface is NULL\n", __PRETTY_FUNCTION__);
@@ -63,10 +99,102 @@
       }
       else
       {
+        // Restore the HDC...
         RestoreDC(hdc, -1);
+        
+        // and inform cairo that we modified it...
         cairo_surface_mark_dirty([_surface surface]);
       }
     }
 }
 
+- (void) _clipRegionForHDC: (HDC)hDC
+{
+  if (!hDC)
+  {
+    return;
+  }
+  
+  if (_lastPath == nil)
+  {
+    return;
+  }
+  
+  unsigned count = [_lastPath elementCount];
+  if (count)
+  {
+    NSBezierPathElement type;
+    NSPoint   points[3];
+    unsigned   j, i = 0;
+    POINT p;
+    
+    BeginPath(hDC);
+    
+    for (j = 0; j < count; j++)
+    {
+      type = [_lastPath elementAtIndex: j associatedPoints: points];
+      switch(type)
+      {
+        case NSMoveToBezierPathElement:
+          p = GSWindowPointToMS(self, points[0]);
+          MoveToEx(hDC, p.x, p.y, NULL);
+          break;
+        case NSLineToBezierPathElement:
+          p = GSWindowPointToMS(self, points[0]);
+          // FIXME This gives one pixel too few
+          LineTo(hDC, p.x, p.y);
+          break;
+        case NSCurveToBezierPathElement:
+        {
+          POINT bp[3];
+          
+          for (i = 0; i < 3; i++)
+          {
+            bp[i] = GSWindowPointToMS(self, points[i]);
+          }
+          PolyBezierTo(hDC, bp, 3);
+        }
+          break;
+        case NSClosePathBezierPathElement:
+          CloseFigure(hDC);
+          break;
+        default:
+          break;
+      }
+    }
+    EndPath(hDC);
+    
+    // Select the clip path...
+    SelectClipPath(hDC, RGN_AND);
+  }
+  
+  // Clear the used clip path...
+  DESTROY(_lastPath);
+}
+
+- (void) DPSinitclip
+{
+  // Destroy any clipping path we're holding...
+  DESTROY(_lastPath);
+  
+  // and invoke super...
+  [super DPSinitclip];
+}
+
+- (void) DPSclip
+{
+  // Invoke super...
+  [super DPSclip];
+  
+  // Keep a copy for ourselves for theme drawing directly to HDC...
+  if (_lastPath == nil)
+  {
+    _lastPath = [path copy];
+  }
+  else
+  {
+    [_lastPath appendBezierPath: path];
+  }
+}
+
 @end


_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs

Reply via email to