Rework of display* mechanism to use new MacOSX10.4 method.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@25291 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
fredkiefer 2007-06-26 16:46:50 +00:00
parent d7426f2aac
commit d8d13297cb
6 changed files with 397 additions and 368 deletions

View file

@ -1,3 +1,16 @@
2007-06-26 Fred Kiefer <FredKiefer@gmx.de>
* Headers/AppKit/NSView.h: Add new MacOSX methods.
* Source/NSView.m: Basic implementation of new MacOSX methods.
Rewrote all the display* methods to use the new method
[displayRectIgnoringOpacity:inContext] and made them more
consistent. Add some documentation for the display mechanism.
* Source/GSPDFPrintOperation.m (-_print),
* Source/GSEPSPrintOperation.m (-_print),
* Source/NSPrintOperation.m (NSView-_displayPageInRect:withInfo:):
Use new method [NSView displayRectIgnoringOpacity:inContext:].
* Source/NSView.m (-endPage): Add DPSgrestore() call.
2007-06-23 10:43-EDT Gregory John Casamento <greg_casamento@yahoo.com> 2007-06-23 10:43-EDT Gregory John Casamento <greg_casamento@yahoo.com>
* Headers/AppKit/NSObjectController.h * Headers/AppKit/NSObjectController.h

View file

@ -42,14 +42,15 @@
@class NSMutableArray; @class NSMutableArray;
@class NSString; @class NSString;
@class NSWindow; @class NSBitmapImageRep;
@class NSPasteboard;
@class NSView;
@class NSClipView; @class NSClipView;
@class NSImage;
@class NSCursor; @class NSCursor;
@class NSScrollView; @class NSImage;
@class NSMenu; @class NSMenu;
@class NSPasteboard;
@class NSScrollView;
@class NSView;
@class NSWindow;
typedef int NSTrackingRectTag; typedef int NSTrackingRectTag;
typedef int NSToolTipTag; typedef int NSToolTipTag;
@ -162,8 +163,8 @@ typedef enum _NSFocusRingType {
*/ */
- (void) addSubview: (NSView*)aView; - (void) addSubview: (NSView*)aView;
- (void) addSubview: (NSView*)aView - (void) addSubview: (NSView*)aView
positioned: (NSWindowOrderingMode)place positioned: (NSWindowOrderingMode)place
relativeTo: (NSView*)otherView; relativeTo: (NSView*)otherView;
- (NSView*) ancestorSharedWithView: (NSView*)aView; - (NSView*) ancestorSharedWithView: (NSView*)aView;
- (BOOL) isDescendantOf: (NSView*)aView; - (BOOL) isDescendantOf: (NSView*)aView;
- (NSView*) opaqueAncestor; - (NSView*) opaqueAncestor;
@ -173,7 +174,7 @@ typedef enum _NSFocusRingType {
- (void) removeSubview: (NSView*)aView; - (void) removeSubview: (NSView*)aView;
#endif #endif
- (void) replaceSubview: (NSView*)oldView - (void) replaceSubview: (NSView*)oldView
with: (NSView*)newView; with: (NSView*)newView;
- (void) sortSubviewsUsingFunction: (int (*)(id ,id ,void*))compare - (void) sortSubviewsUsingFunction: (int (*)(id ,id ,void*))compare
context: (void*)context; context: (void*)context;
- (NSArray*) subviews; - (NSArray*) subviews;
@ -281,6 +282,10 @@ typedef enum _NSFocusRingType {
- (void) displayIfNeededInRectIgnoringOpacity: (NSRect)aRect; - (void) displayIfNeededInRectIgnoringOpacity: (NSRect)aRect;
- (void) displayRect: (NSRect)aRect; - (void) displayRect: (NSRect)aRect;
- (void) displayRectIgnoringOpacity: (NSRect)aRect; - (void) displayRectIgnoringOpacity: (NSRect)aRect;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
- (void) displayRectIgnoringOpacity: (NSRect)aRect
inContext: (NSGraphicsContext *)context;
#endif
- (BOOL) needsDisplay; - (BOOL) needsDisplay;
- (void) setNeedsDisplay: (BOOL)flag; - (void) setNeedsDisplay: (BOOL)flag;
- (void) setNeedsDisplayInRect: (NSRect)invalidRect; - (void) setNeedsDisplayInRect: (NSRect)invalidRect;
@ -303,6 +308,11 @@ typedef enum _NSFocusRingType {
- (NSRect) visibleRect; - (NSRect) visibleRect;
- (BOOL) canDraw; - (BOOL) canDraw;
- (BOOL) shouldDrawColor; - (BOOL) shouldDrawColor;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
- (NSBitmapImageRep *) bitmapImageRepForCachingDisplayInRect: (NSRect)rect;
- (void) cacheDisplayInRect: (NSRect)rect
toBitmapImageRep: (NSBitmapImageRep *)bitmap;
#endif
#if OS_API_VERSION(MAC_OS_X_VERSION_10_3, GS_API_LATEST) #if OS_API_VERSION(MAC_OS_X_VERSION_10_3, GS_API_LATEST)
- (BOOL) wantsDefaultClipping; - (BOOL) wantsDefaultClipping;
- (BOOL) needsToDrawRect: (NSRect)aRect; - (BOOL) needsToDrawRect: (NSRect)aRect;
@ -365,6 +375,9 @@ typedef enum _NSFocusRingType {
slideBack: (BOOL)slideBack slideBack: (BOOL)slideBack
event: (NSEvent *)theEvent; event: (NSEvent *)theEvent;
#endif #endif
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
- (NSArray *) registeredDraggedTypes;
#endif
/** /**
* Adds a cursor rectangle. This provides for automatic update of the * Adds a cursor rectangle. This provides for automatic update of the
@ -377,7 +390,7 @@ typedef enum _NSFocusRingType {
* visible rectangle. * visible rectangle.
*/ */
- (void) addCursorRect: (NSRect)aRect - (void) addCursorRect: (NSRect)aRect
cursor: (NSCursor*)anObject; cursor: (NSCursor*)anObject;
/** /**
* Removes all the cursor rectancles which have been set up for the * Removes all the cursor rectancles which have been set up for the
@ -393,7 +406,7 @@ typedef enum _NSFocusRingType {
* rectangle and cursor. * rectangle and cursor.
*/ */
- (void) removeCursorRect: (NSRect)aRect - (void) removeCursorRect: (NSRect)aRect
cursor: (NSCursor*)anObject; cursor: (NSCursor*)anObject;
/** <override-subclass/> /** <override-subclass/>
* This is called to establish a new set of cursor rectangles whenever * This is called to establish a new set of cursor rectangles whenever
@ -408,8 +421,8 @@ typedef enum _NSFocusRingType {
* Tool Tips * Tool Tips
*/ */
- (NSToolTipTag) addToolTipRect: (NSRect)aRect - (NSToolTipTag) addToolTipRect: (NSRect)aRect
owner: (id)anObject owner: (id)anObject
userData: (void *)data; userData: (void *)data;
- (void) removeAllToolTips; - (void) removeAllToolTips;
- (void) removeToolTip: (NSToolTipTag)tag; - (void) removeToolTip: (NSToolTipTag)tag;
- (void) setToolTip: (NSString *)string; - (void) setToolTip: (NSString *)string;
@ -437,9 +450,9 @@ typedef enum _NSFocusRingType {
* if it is NO then the first event generated will be a mouse entry. * if it is NO then the first event generated will be a mouse entry.
*/ */
- (NSTrackingRectTag) addTrackingRect: (NSRect)aRect - (NSTrackingRectTag) addTrackingRect: (NSRect)aRect
owner: (id)anObject owner: (id)anObject
userData: (void*)data userData: (void*)data
assumeInside: (BOOL)flag; assumeInside: (BOOL)flag;
/* /*
* Scrolling * Scrolling
@ -449,12 +462,12 @@ typedef enum _NSFocusRingType {
- (NSScrollView*) enclosingScrollView; - (NSScrollView*) enclosingScrollView;
- (void) scrollPoint: (NSPoint)aPoint; - (void) scrollPoint: (NSPoint)aPoint;
- (void) scrollRect: (NSRect)aRect - (void) scrollRect: (NSRect)aRect
by: (NSSize)delta; by: (NSSize)delta;
- (BOOL) scrollRectToVisible: (NSRect)aRect; - (BOOL) scrollRectToVisible: (NSRect)aRect;
- (void) reflectScrolledClipView: (NSClipView*)aClipView; - (void) reflectScrolledClipView: (NSClipView*)aClipView;
- (void) scrollClipView: (NSClipView*)aClipView - (void) scrollClipView: (NSClipView*)aClipView
toPoint: (NSPoint)aPoint; toPoint: (NSPoint)aPoint;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST) #if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
/* /*
@ -467,7 +480,7 @@ typedef enum _NSFocusRingType {
/* /*
* Aiding Event Handling * Aiding Event Handling
*/ */
-(BOOL) needsPanelToBecomeKey; - (BOOL) needsPanelToBecomeKey;
- (void) setNextKeyView: (NSView*)aView; - (void) setNextKeyView: (NSView*)aView;
- (NSView*) nextKeyView; - (NSView*) nextKeyView;
- (NSView*) nextValidKeyView; - (NSView*) nextValidKeyView;
@ -485,28 +498,28 @@ typedef enum _NSFocusRingType {
- (void) print: (id)sender; - (void) print: (id)sender;
- (NSData*) dataWithEPSInsideRect: (NSRect)aRect; - (NSData*) dataWithEPSInsideRect: (NSRect)aRect;
- (void) writeEPSInsideRect: (NSRect)rect - (void) writeEPSInsideRect: (NSRect)rect
toPasteboard: (NSPasteboard*)pasteboard; toPasteboard: (NSPasteboard*)pasteboard;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST) #if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
- (NSData *)dataWithPDFInsideRect:(NSRect)aRect; - (NSData *) dataWithPDFInsideRect: (NSRect)aRect;
- (void)writePDFInsideRect:(NSRect)aRect - (void) writePDFInsideRect: (NSRect)aRect
toPasteboard:(NSPasteboard *)pboard; toPasteboard: (NSPasteboard *)pboard;
- (NSString *)printJobTitle; - (NSString *) printJobTitle;
#endif #endif
/* /*
* Pagination * Pagination
*/ */
- (void) adjustPageHeightNew: (float*)newBottom - (void) adjustPageHeightNew: (float*)newBottom
top: (float)oldTop top: (float)oldTop
bottom: (float)oldBottom bottom: (float)oldBottom
limit: (float)bottomLimit; limit: (float)bottomLimit;
- (void) adjustPageWidthNew: (float*)newRight - (void) adjustPageWidthNew: (float*)newRight
left: (float)oldLeft left: (float)oldLeft
right: (float)oldRight right: (float)oldRight
limit: (float)rightLimit; limit: (float)rightLimit;
- (float) heightAdjustLimit; - (float) heightAdjustLimit;
- (BOOL) knowsPagesFirst: (int*)firstPageNum - (BOOL) knowsPagesFirst: (int*)firstPageNum
last: (int*)lastPageNum; last: (int*)lastPageNum;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST) #if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
- (BOOL) knowsPageRange: (NSRange*)range; - (BOOL) knowsPageRange: (NSRange*)range;
#endif #endif

View file

@ -105,7 +105,7 @@
[_view beginPageInRect: _rect [_view beginPageInRect: _rect
atPlacement: NSMakePoint(0,0)]; atPlacement: NSMakePoint(0,0)];
[_view displayRectIgnoringOpacity: _rect]; [_view displayRectIgnoringOpacity: _rect inContext: [self context]];
[_view endPage]; [_view endPage];
[_view endDocument]; [_view endDocument];

View file

@ -92,13 +92,26 @@
- (NSGraphicsContext*)createContext - (NSGraphicsContext*)createContext
{ {
// FIXME NSMutableDictionary *info;
return nil;
if (_context)
return _context;
info = [[self printInfo] dictionary];
[info setObject: _path
forKey: @"NSOutputFile"];
[info setObject: NSGraphicsContextPDFFormat
forKey: NSGraphicsContextRepresentationFormatAttributeName];
_context = RETAIN([NSGraphicsContext graphicsContextWithAttributes: info]);
return _context;
} }
- (void) _print - (void) _print
{ {
[_view displayRectIgnoringOpacity: _rect]; [_view displayRectIgnoringOpacity: _rect inContext: [self context]];
} }
- (BOOL)deliverResult - (BOOL)deliverResult

View file

@ -1145,11 +1145,12 @@ scaleRect(NSRect rect, double scale)
} }
/* Do the actual drawing */ /* Do the actual drawing */
[self displayRectIgnoringOpacity: pageRect]; [self displayRectIgnoringOpacity: pageRect inContext: ctxt];
/* End a logical page */ /* End a logical page */
// Balance gsave in beginPageInRect: // FIXME: Attempt to get the coordinates of the page border correct.
DPSgrestore(ctxt); DPSgrestore(ctxt);
DPSgsave(ctxt);
[self drawPageBorderWithSize: info.paperBounds.size]; [self drawPageBorderWithSize: info.paperBounds.size];
[self endPage]; [self endPage];

View file

@ -54,6 +54,7 @@
#include "AppKit/NSAffineTransform.h" #include "AppKit/NSAffineTransform.h"
#include "AppKit/NSApplication.h" #include "AppKit/NSApplication.h"
#include "AppKit/NSBezierPath.h" #include "AppKit/NSBezierPath.h"
#include "AppKit/NSBitmapImageRep.h"
#include "AppKit/NSCursor.h" #include "AppKit/NSCursor.h"
#include "AppKit/NSDocumentController.h" #include "AppKit/NSDocumentController.h"
#include "AppKit/NSDocument.h" #include "AppKit/NSDocument.h"
@ -291,63 +292,63 @@ GSSetDragTypes(NSView* obj, NSArray *types)
{ {
_coordinates_valid = YES; _coordinates_valid = YES;
if (!_window) if (!_window)
{ {
_visibleRect = NSZeroRect; _visibleRect = NSZeroRect;
[_matrixToWindow makeIdentityMatrix]; [_matrixToWindow makeIdentityMatrix];
[_matrixFromWindow makeIdentityMatrix]; [_matrixFromWindow makeIdentityMatrix];
} }
if (!_super_view) if (!_super_view)
{ {
_visibleRect = _bounds; _visibleRect = _bounds;
[_matrixToWindow makeIdentityMatrix]; [_matrixToWindow makeIdentityMatrix];
[_matrixFromWindow makeIdentityMatrix]; [_matrixFromWindow makeIdentityMatrix];
} }
else else
{ {
NSRect superviewsVisibleRect; NSRect superviewsVisibleRect;
BOOL wasFlipped = _super_view->_rFlags.flipped_view; BOOL wasFlipped = _super_view->_rFlags.flipped_view;
NSAffineTransform *pMatrix = [_super_view _matrixToWindow]; NSAffineTransform *pMatrix = [_super_view _matrixToWindow];
NSAffineTransformStruct ts = [pMatrix transformStruct]; NSAffineTransformStruct ts = [pMatrix transformStruct];
/* prepend translation */ /* prepend translation */
ts.tX = NSMinX(_frame) * ts.m11 + NSMinY(_frame) * ts.m21 + ts.tX; ts.tX = NSMinX(_frame) * ts.m11 + NSMinY(_frame) * ts.m21 + ts.tX;
ts.tY = NSMinX(_frame) * ts.m12 + NSMinY(_frame) * ts.m22 + ts.tY; ts.tY = NSMinX(_frame) * ts.m12 + NSMinY(_frame) * ts.m22 + ts.tY;
[_matrixToWindow setTransformStruct: ts]; [_matrixToWindow setTransformStruct: ts];
/* prepend rotation */ /* prepend rotation */
if (_frameMatrix != nil) if (_frameMatrix != nil)
{ {
(*preImp)(_matrixToWindow, preSel, _frameMatrix); (*preImp)(_matrixToWindow, preSel, _frameMatrix);
} }
if (_rFlags.flipped_view != wasFlipped) if (_rFlags.flipped_view != wasFlipped)
{ {
/* /*
* The flipping process must result in a coordinate system that * The flipping process must result in a coordinate system that
* exactly overlays the original. To do that, we must translate * exactly overlays the original. To do that, we must translate
* the origin by the height of the view. * the origin by the height of the view.
*/ */
ts = [flip transformStruct]; ts = [flip transformStruct];
ts.tY = _frame.size.height; ts.tY = _frame.size.height;
[flip setTransformStruct: ts]; [flip setTransformStruct: ts];
(*preImp)(_matrixToWindow, preSel, flip); (*preImp)(_matrixToWindow, preSel, flip);
} }
(*preImp)(_matrixToWindow, preSel, _boundsMatrix); (*preImp)(_matrixToWindow, preSel, _boundsMatrix);
ts = [_matrixToWindow transformStruct]; ts = [_matrixToWindow transformStruct];
[_matrixFromWindow setTransformStruct: ts]; [_matrixFromWindow setTransformStruct: ts];
[_matrixFromWindow invert]; [_matrixFromWindow invert];
superviewsVisibleRect = [self convertRect: [_super_view visibleRect] superviewsVisibleRect = [self convertRect: [_super_view visibleRect]
fromView: _super_view]; fromView: _super_view];
_visibleRect = NSIntersectionRect(superviewsVisibleRect, _bounds); _visibleRect = NSIntersectionRect(superviewsVisibleRect, _bounds);
} }
if (_rFlags.has_tooltips != 0) if (_rFlags.has_tooltips != 0)
{ {
GSToolTips *tt = [GSToolTips tipsForView: self]; GSToolTips *tt = [GSToolTips tipsForView: self];
[tt rebuild]; [tt rebuild];
} }
} }
} }
@ -359,19 +360,40 @@ GSSetDragTypes(NSView* obj, NSArray *types)
unsigned count = [_sub_views count]; unsigned count = [_sub_views count];
if (count > 0) if (count > 0)
{ {
unsigned i; unsigned i;
NSView *array[count]; NSView *array[count];
[_sub_views getObjects: array]; [_sub_views getObjects: array];
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
{ {
[array[i] _viewDidMoveToWindow]; [array[i] _viewDidMoveToWindow];
} }
} }
} }
} }
/*
* Extend in super view covered by the frame of a view.
* When the frame is rotated, this is different from the frame.
*/
- (NSRect) _frameExtend
{
NSRect frame = _frame;
if (_frameMatrix != nil)
{
NSRect r;
r.origin = NSZeroPoint;
r.size = frame.size;
[_frameMatrix boundingRectFor: r result: &r];
frame = NSOffsetRect(r, NSMinX(frame),
NSMinY(frame));
}
return frame;
}
/* /*
* Class methods * Class methods
@ -2034,6 +2056,35 @@ convert_rect_using_matrices(NSRect aRect, NSAffineTransform *matrix1,
} }
} }
/*
* The following display* methods work based on these invariants:
* - When a view is marked as needing display, all views above it
* in the hierarchy are marked as well.
* - When a view has an invalid rectangle, all views above it up
* to the next opaque view also include this invalid rectangle.
*
* After drawing an area in a view give, subviews a chance to draw
* there too.
* When drawing a non-opaque subview we need to make sure any area
* we draw in has been drawn by the opaque superview as well.
*
* When drawing the invalid area of a view, we need to make sure
* that invalid areas in opaque subviews get drawn as well. These
* areas will not be included in the invalid area of the view.
*
* IfNeeded means we only draw if the view is marked as needing display
* and will only draw in the _invalidRect of this view and that of all
* the opaque subviews. For non-opaque subviews we need to draw where
* ever a superview has already drawn.
*
* InRect means we will only draw in this rectangle. If non is given the
* visibleRect gets used.
*
* IgnoringOpacity means we start drawing at the current view. Otherwise
* we go up to the next opaque view.
*
*/
- (void) display - (void) display
{ {
[self displayRect: [self visibleRect]]; [self displayRect: [self visibleRect]];
@ -2043,44 +2094,7 @@ convert_rect_using_matrices(NSRect aRect, NSAffineTransform *matrix1,
{ {
if (_rFlags.needs_display == YES) if (_rFlags.needs_display == YES)
{ {
if ([self isOpaque] == YES) [self displayIfNeededInRect: [self visibleRect]];
{
[self displayIfNeededIgnoringOpacity];
}
else
{
NSView *firstOpaque = [self opaqueAncestor];
NSRect rect;
if (_coordinates_valid == NO)
{
[self _rebuildCoordinates];
}
rect = NSIntersectionRect(_invalidRect, _visibleRect);
rect = [firstOpaque convertRect: rect fromView: self];
if (NSIsEmptyRect(rect) == NO)
{
[firstOpaque displayIfNeededInRectIgnoringOpacity: rect];
}
/*
* If we still need display after displaying the invalid rectangle,
* display any subviews that need display.
*/
if (_rFlags.needs_display == YES)
{
NSEnumerator *enumerator = [_sub_views objectEnumerator];
NSView *sub;
while ((sub = [enumerator nextObject]) != nil)
{
if (sub->_rFlags.needs_display)
{
[sub displayIfNeededIgnoringOpacity];
}
}
_rFlags.needs_display = NO;
}
}
} }
} }
@ -2088,35 +2102,7 @@ convert_rect_using_matrices(NSRect aRect, NSAffineTransform *matrix1,
{ {
if (_rFlags.needs_display == YES) if (_rFlags.needs_display == YES)
{ {
NSRect rect; [self displayIfNeededInRectIgnoringOpacity: [self visibleRect]];
if (_coordinates_valid == NO)
{
[self _rebuildCoordinates];
}
rect = NSIntersectionRect(_invalidRect, _visibleRect);
if (NSIsEmptyRect(rect) == NO)
{
[self displayIfNeededInRectIgnoringOpacity: rect];
}
/*
* If we still need display after displaying the invalid rectangle,
* display any subviews that need display.
*/
if (_rFlags.needs_display == YES)
{
NSEnumerator *enumerator = [_sub_views objectEnumerator];
NSView *sub;
while ((sub = [enumerator nextObject]) != nil)
{
if (sub->_rFlags.needs_display)
{
[sub displayIfNeededIgnoringOpacity];
}
}
_rFlags.needs_display = NO;
}
} }
} }
@ -2125,131 +2111,72 @@ convert_rect_using_matrices(NSRect aRect, NSAffineTransform *matrix1,
if (_rFlags.needs_display == YES) if (_rFlags.needs_display == YES)
{ {
if ([self isOpaque] == YES) if ([self isOpaque] == YES)
{ {
[self displayIfNeededInRectIgnoringOpacity: aRect]; [self displayIfNeededInRectIgnoringOpacity: aRect];
} }
else else
{ {
NSView *firstOpaque = [self opaqueAncestor]; NSView *firstOpaque = [self opaqueAncestor];
NSRect rect;
rect = [firstOpaque convertRect: aRect fromView: self]; aRect = [firstOpaque convertRect: aRect fromView: self];
[firstOpaque displayIfNeededInRectIgnoringOpacity: rect]; [firstOpaque displayIfNeededInRectIgnoringOpacity: aRect];
} }
} }
} }
- (void) displayIfNeededInRectIgnoringOpacity: (NSRect)aRect - (void) displayIfNeededInRectIgnoringOpacity: (NSRect)aRect
{ {
if (![self canDraw])
{
return;
}
if (_rFlags.needs_display == YES) if (_rFlags.needs_display == YES)
{ {
BOOL subviewNeedsDisplay = NO; NSRect rect;
NSRect neededRect;
NSRect redrawRect; /*
* Restrict the drawing of self onto the invalid rectangle.
[_window disableFlushWindow]; */
if (_coordinates_valid == NO) rect = NSIntersectionRect(aRect, _invalidRect);
{ [self displayRectIgnoringOpacity: rect];
[self _rebuildCoordinates];
}
aRect = NSIntersectionRect(aRect, _visibleRect);
redrawRect = NSIntersectionRect(aRect, _invalidRect);
neededRect = NSIntersectionRect(_visibleRect, _invalidRect);
if (NSIsEmptyRect(redrawRect) == NO)
{
[self lockFocusInRect: redrawRect];
[self drawRect: redrawRect];
[self unlockFocusNeedsFlush: YES];
}
if (_rFlags.has_subviews == YES)
{
unsigned count = [_sub_views count];
if (count > 0)
{
NSView *array[count];
unsigned i;
[_sub_views getObjects: array];
for (i = 0; i < count; i++)
{
NSRect isect;
NSView *subview = array[i];
NSRect subviewFrame = subview->_frame;
BOOL intersectCalculated = NO;
if (subview->_frameMatrix) // assume rotation
{
NSRect r;
r.origin = NSZeroPoint;
r.size = subviewFrame.size;
[subview->_frameMatrix boundingRectFor: r result: &r];
subviewFrame = NSOffsetRect(r, NSMinX(subviewFrame),
NSMinY(subviewFrame));
}
/*
* Having drawn ourself into the rect, we must make sure that
* subviews overlapping the area are redrawn.
*/
isect = NSIntersectionRect(redrawRect, subviewFrame);
if (NSIsEmptyRect(isect) == NO)
{
isect = [subview convertRect: isect
fromView: self];
intersectCalculated = YES;
/*
* hack the ivars of the subview directly for speed.
*/
subview->_rFlags.needs_display = YES;
subview->_invalidRect = NSUnionRect(subview->_invalidRect,
isect);
}
if (subview->_rFlags.needs_display == YES)
{
if (intersectCalculated == NO
|| NSEqualRects(aRect, redrawRect) == NO)
{
isect = NSIntersectionRect(aRect, subviewFrame);
isect = [subview convertRect: isect
fromView: self];
}
[subview displayIfNeededInRectIgnoringOpacity: isect];
if (subview->_rFlags.needs_display == YES)
{
subviewNeedsDisplay = YES;
}
}
}
}
}
/* /*
* If the rect we displayed contains the _invalidRect or _visibleRect * If we still need display after displaying the invalid rectangle,
* then we can empty _invalidRect. * this means, some subviews still need to display. For opaque subviews
* If all subviews have been fully displayed, we can also turn off the * there invalid rectangle may even overlap the original aRect.
* 'needs_display' flag. * Display any subview that need display.
*/ */
if (NSEqualRects(aRect, NSUnionRect(neededRect, aRect)) == YES) if (_rFlags.needs_display == YES)
{ {
_invalidRect = NSZeroRect; NSEnumerator *enumerator = [_sub_views objectEnumerator];
_rFlags.needs_display = subviewNeedsDisplay; NSView *subview;
} BOOL subviewNeedsDisplay = NO;
if (_rFlags.needs_display == YES
&& NSEqualRects(aRect, NSUnionRect(_visibleRect, aRect)) == YES) while ((subview = [enumerator nextObject]) != nil)
{ {
_rFlags.needs_display = NO; if (subview->_rFlags.needs_display)
} {
[_window enableFlushWindow]; NSRect subviewFrame = [subview _frameExtend];
[_window flushWindowIfNeeded]; NSRect isect;
isect = NSIntersectionRect(aRect, subviewFrame);
if (NSIsEmptyRect(isect) == NO)
{
isect = [subview convertRect: isect fromView: self];
[subview displayIfNeededInRectIgnoringOpacity: isect];
}
if (subview->_rFlags.needs_display)
{
subviewNeedsDisplay = YES;
}
}
}
/*
* Make sure our needs_display flag matches that of the subviews.
* Only set to NO when there is no _invalidRect.
*/
if (NSIsEmptyRect(_invalidRect))
{
_rFlags.needs_display = subviewNeedsDisplay;
}
}
} }
} }
@ -2275,113 +2202,123 @@ convert_rect_using_matrices(NSRect aRect, NSAffineTransform *matrix1,
- (void) displayRectIgnoringOpacity: (NSRect)aRect - (void) displayRectIgnoringOpacity: (NSRect)aRect
{ {
BOOL subviewNeedsDisplay = NO; [self displayRectIgnoringOpacity: aRect inContext: nil];
NSRect neededRect; }
- (void) displayRectIgnoringOpacity: (NSRect)aRect
inContext: (NSGraphicsContext *)context
{
NSGraphicsContext *wContext;
BOOL flush = NO;
BOOL subviewNeedsDisplay = NO;
if (![self canDraw]) if (![self canDraw])
{ {
return; return;
} }
[_window disableFlushWindow]; wContext = [_window graphicsContext];
if (_coordinates_valid == NO) if (context == nil)
{ {
[self _rebuildCoordinates]; context = wContext;
} }
aRect = NSIntersectionRect(aRect, _visibleRect);
neededRect = NSIntersectionRect(_invalidRect, _visibleRect);
if (context == wContext)
{
NSRect neededRect;
flush = YES;
[_window disableFlushWindow];
if (_coordinates_valid == NO)
{
[self _rebuildCoordinates];
}
aRect = NSIntersectionRect(aRect, _visibleRect);
neededRect = NSIntersectionRect(_invalidRect, _visibleRect);
/*
* If the rect we are going to display contains the _invalidRect
* then we can empty _invalidRect. Do this before the drawing, as drawRect:
* may change this value.
* FIXME: If the drawn rectangle cuts of a complete part of the _invalidRect,
* we should try to reduce this.
*/
if (NSEqualRects(aRect, NSUnionRect(neededRect, aRect)) == YES)
{
_invalidRect = NSZeroRect;
_rFlags.needs_display = NO;
}
}
if (NSIsEmptyRect(aRect) == NO) if (NSIsEmptyRect(aRect) == NO)
{ {
/* /*
* Now we draw this view. * Now we draw this view.
*/ */
[self lockFocusInRect: aRect]; [self _lockFocusInContext: context inRect: aRect];
[self drawRect: aRect]; [self drawRect: aRect];
[self unlockFocusNeedsFlush: YES]; [self unlockFocusNeedsFlush: flush];
}
if (_rFlags.has_subviews == YES)
{
unsigned count = [_sub_views count];
if (count > 0)
{
NSView *array[count];
unsigned i;
[_sub_views getObjects: array];
for (i = 0; i < count; ++i)
{
NSView *subview = array[i];
NSRect subviewFrame = subview->_frame;
NSRect isect;
BOOL intersectCalculated = NO;
if (subview->_frameMatrix != nil)
{
NSRect r;
r.origin = NSZeroPoint;
r.size = subviewFrame.size;
[subview->_frameMatrix boundingRectFor: r result: &r];
subviewFrame = NSOffsetRect(r, NSMinX(subviewFrame),
NSMinY(subviewFrame));
}
/*
* Having drawn ourself into the rect, we must make sure that
* subviews overlapping the area are redrawn.
*/
isect = NSIntersectionRect(aRect, subviewFrame);
if (NSIsEmptyRect(isect) == NO)
{
isect = [subview convertRect: isect
fromView: self];
intersectCalculated = YES;
/*
* hack the ivars of the subview directly for speed.
*/
subview->_rFlags.needs_display = YES;
subview->_invalidRect = NSUnionRect(subview->_invalidRect,
isect);
}
if (subview->_rFlags.needs_display == YES)
{
if (intersectCalculated == NO)
{
isect = [subview convertRect: isect
fromView: self];
}
[subview displayIfNeededInRectIgnoringOpacity: isect];
if (subview->_rFlags.needs_display == YES)
{
subviewNeedsDisplay = YES;
}
}
}
}
} }
/* /*
* If the rect we displayed contains the _invalidRect or _visibleRect * Even when aRect is empty we need to loop over the subviews to see,
* then we can empty _invalidRect. If all subviews have been * if there is anything left to draw.
* fully displayed, we can also turn off the 'needs_display' flag.
*/ */
if (NSEqualRects(aRect, NSUnionRect(neededRect, aRect)) == YES) if (_rFlags.has_subviews == YES)
{ {
_invalidRect = NSZeroRect; unsigned count = [_sub_views count];
_rFlags.needs_display = subviewNeedsDisplay;
if (count > 0)
{
NSView *array[count];
unsigned i;
[_sub_views getObjects: array];
for (i = 0; i < count; ++i)
{
NSView *subview = array[i];
NSRect subviewFrame = [subview _frameExtend];
NSRect isect;
/*
* Having drawn ourself into the rect, we must make sure that
* subviews overlapping the area are redrawn.
*/
isect = NSIntersectionRect(aRect, subviewFrame);
if (NSIsEmptyRect(isect) == NO)
{
isect = [subview convertRect: isect fromView: self];
[subview displayRectIgnoringOpacity: isect inContext: context];
}
/*
* Is there still something to draw in the subview?
* This keeps the invariant that views further up are marked for redraw
* when ever a view further down needs to redraw.
*/
if (subview->_rFlags.needs_display == YES)
{
subviewNeedsDisplay = YES;
}
}
}
} }
if (_rFlags.needs_display == YES
&& NSEqualRects(aRect, NSUnionRect(_visibleRect, aRect)) == YES) if (context == wContext)
{ {
_rFlags.needs_display = NO; if (subviewNeedsDisplay)
{
/*
* If not all subviews have been fully displayed, we cannot turn off
* the 'needs_display' flag. This is to keep the invariant that when
* a view is marked as needing to display, all its ancestors will be
* marked too.
*/
_rFlags.needs_display = YES;
}
[_window enableFlushWindow];
[_window flushWindowIfNeeded];
} }
[_window enableFlushWindow];
[_window flushWindowIfNeeded];
} }
/** /**
@ -2453,6 +2390,50 @@ convert_rect_using_matrices(NSRect aRect, NSAffineTransform *matrix1,
} }
} }
- (NSBitmapImageRep *) bitmapImageRepForCachingDisplayInRect: (NSRect)rect
{
NSBitmapImageRep *bitmap;
NSDictionary *dict;
int bps, spp, alpha;
NSString *space;
dict = [_window deviceDescription];
bps = [[dict objectForKey: NSDeviceBitsPerSample] intValue];
if (bps == 0)
bps = 8;
// spp = [[dict objectForKey: @"SamplesPerPixel"] intValue];
spp = 4;
// alpha = [[dict objectForKey: @"HasAlpha"] intValue];
alpha = 1;
space = [dict objectForKey: NSDeviceColorSpaceName];
bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
pixelsWide: rect.size.width
pixelsHigh: rect.size.height
bitsPerSample: bps
samplesPerPixel: spp
hasAlpha: (alpha) ? YES : NO
isPlanar: NO
colorSpaceName: space
bytesPerRow: 0
bitsPerPixel: 0];
[self cacheDisplayInRect: rect toBitmapImageRep: bitmap];
return bitmap;
}
- (void) cacheDisplayInRect: (NSRect)rect
toBitmapImageRep: (NSBitmapImageRep *)bitmap
{
NSDictionary *dict;
NSData *imageData;
dict = [GSCurrentContext() GSReadRect: rect];
imageData = RETAIN([dict objectForKey: @"Data"]);
// FIXME: Copy the image data to the bitmap
memcpy([bitmap bitmapData], [imageData bytes], [imageData length]);
}
extern NSThread *GSAppKitThread; /* TODO */ extern NSThread *GSAppKitThread; /* TODO */
/* /*
@ -2489,8 +2470,8 @@ in the main thread.
if (GSCurrentThread() != GSAppKitThread) if (GSCurrentThread() != GSAppKitThread)
{ {
[self performSelectorOnMainThread: @selector(_setNeedsDisplay_real:) [self performSelectorOnMainThread: @selector(_setNeedsDisplay_real:)
withObject: n withObject: n
waitUntilDone: NO]; waitUntilDone: NO];
} }
else else
{ {
@ -2519,14 +2500,14 @@ in the main thread.
_rFlags.needs_display = YES; _rFlags.needs_display = YES;
_invalidRect = invalidRect; _invalidRect = invalidRect;
if (firstOpaque == self) if (firstOpaque == self)
{ {
[_window setViewsNeedDisplay: YES]; [_window setViewsNeedDisplay: YES];
} }
else else
{ {
invalidRect = [firstOpaque convertRect: _invalidRect fromView: self]; invalidRect = [firstOpaque convertRect: _invalidRect fromView: self];
[firstOpaque setNeedsDisplayInRect: invalidRect]; [firstOpaque setNeedsDisplayInRect: invalidRect];
} }
} }
/* /*
* Must make sure that superviews know that we need display. * Must make sure that superviews know that we need display.
@ -3548,6 +3529,11 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
} }
} }
- (NSArray *) registeredDraggedTypes
{
return GSGetDragTypes(self);
}
- (BOOL) dragPromisedFilesOfTypes: (NSArray *)typeArray - (BOOL) dragPromisedFilesOfTypes: (NSArray *)typeArray
fromRect: (NSRect)aRect fromRect: (NSRect)aRect
source: (id)sourceObject source: (id)sourceObject
@ -3887,6 +3873,7 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
- (void) drawPageBorderWithSize: (NSSize)borderSize - (void) drawPageBorderWithSize: (NSSize)borderSize
{ {
NSFrameRect(NSMakeRect(0, 0, borderSize.width, borderSize.height));
} }
- (void) drawSheetBorderWithSize: (NSSize)borderSize - (void) drawSheetBorderWithSize: (NSSize)borderSize
@ -3932,6 +3919,9 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
NSGraphicsContext *ctxt = [printOp context]; NSGraphicsContext *ctxt = [printOp context];
NSDictionary *dict = [[printOp printInfo] dictionary]; NSDictionary *dict = [[printOp printInfo] dictionary];
// Balance gsave in beginPageInRect:
DPSgrestore(ctxt);
nup = [[dict objectForKey: NSPrintPagesPerSheet] intValue]; nup = [[dict objectForKey: NSPrintPagesPerSheet] intValue];
if (nup > 1) if (nup > 1)
{ {
@ -4036,7 +4026,7 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
} }
- (void) beginPageInRect: (NSRect)aRect - (void) beginPageInRect: (NSRect)aRect
atPlacement: (NSPoint)location atPlacement: (NSPoint)location
{ {
int nup; int nup;
NSRect bounds; NSRect bounds;
@ -4080,7 +4070,6 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
DPSscale(ctxt, scale, scale); DPSscale(ctxt, scale, scale);
} }
// FIXME: This needs to be balanced explicitly
DPSgsave(ctxt); DPSgsave(ctxt);
/* Translate to placement */ /* Translate to placement */