From 2cf5b9018365cf525cd671ebc1428f22cb675a71 Mon Sep 17 00:00:00 2001 From: Francisco Ryan Tolmasky I Date: Sun, 30 Aug 2009 20:44:44 -0700 Subject: [PATCH] Fixes for uncommon drawRect: bugs. Reviewed by me. --- AppKit/CPView.j | 22 +-- AppKit/Platform/DOM/CPDOMDisplayServer.h | 131 +++++++++++++++--- AppKit/Platform/DOM/CPDOMDisplayServer.j | 165 ----------------------- AppKit/_CPDisplayServer.j | 101 ++++++++++++++ 4 files changed, 216 insertions(+), 203 deletions(-) delete mode 100644 AppKit/Platform/DOM/CPDOMDisplayServer.j create mode 100644 AppKit/_CPDisplayServer.j diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 504569d5b..c140156ff 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -27,11 +27,11 @@ @import "CGGeometry.j" @import "CPColor.j" -@import "CPDOMDisplayServer.j" @import "CPGeometry.j" @import "CPGraphicsContext.j" @import "CPResponder.j" @import "CPTheme.j" +@import "_CPDisplayServer.j" #include "Platform/Platform.h" @@ -1562,10 +1562,6 @@ setBoundsOrigin: { if (aFlag) [self setNeedsDisplayInRect:[self bounds]]; -#if PLATFORM(DOM) - else - CPDOMDisplayServerRemoveView(self); -#endif } /*! @@ -1574,22 +1570,18 @@ setBoundsOrigin: */ - (void)setNeedsDisplayInRect:(CPRect)aRect { -#if PLATFORM(DOM) if (!(_viewClassFlags & CPViewHasCustomDrawRect)) return; -#endif - + if (_CGRectIsEmpty(aRect)) return; - + if (_dirtyRect && !_CGRectIsEmpty(_dirtyRect)) _dirtyRect = CGRectUnion(aRect, _dirtyRect); else _dirtyRect = _CGRectMakeCopy(aRect); -#if PLATFORM(DOM) - CPDOMDisplayServerAddView(self); -#endif + _CPDisplayServerAddDisplayObject(self); } - (BOOL)needsDisplay @@ -1695,13 +1687,11 @@ setBoundsOrigin: - (void)setNeedsLayout { _needsLayout = YES; - -#if PLATFORM(DOM) + if (!(_viewClassFlags & CPViewHasCustomLayoutSubviews)) return; - CPDOMDisplayServerAddView(self); -#endif + _CPDisplayServerAddLayoutObject(self); } - (void)layoutIfNeeded diff --git a/AppKit/Platform/DOM/CPDOMDisplayServer.h b/AppKit/Platform/DOM/CPDOMDisplayServer.h index c094205fa..e11306aed 100644 --- a/AppKit/Platform/DOM/CPDOMDisplayServer.h +++ b/AppKit/Platform/DOM/CPDOMDisplayServer.h @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#define DOM_OPTIMIZATION 1 + #define SetStyleOrigin 0 #define SetStyleLeftTop 0 #define SetStyleRightTop 1 @@ -45,7 +47,49 @@ CPDOMDisplayServerInstructions[__index + 2] = aTransform;\ CPDOMDisplayServerInstructions[__index + 3] = x;\ CPDOMDisplayServerInstructions[__index + 4] = y; - +#if !DOM_OPTIMIZATION +#define CPDOMDisplayServerSetStyleLeftTop(aDOMElement, aTransform, aLeft, aTop) \ +if (aTransform) var ____p = _CGPointApplyAffineTransform(CGPointMake(aLeft, aTop), aTransform); \ +else var ____p = _CGPointMake(aLeft, aTop); \ +aDOMElement.style.left = ROUND(____p.x) + "px";\ +aDOMElement.style.top = ROUND(____p.y) + "px"; + +#define CPDOMDisplayServerSetStyleRightTop(aDOMElement, aTransform, aRight, aTop) \ +if (aTransform) var ____p = _CGPointApplyAffineTransform(CGPointMake(aRight, aTop), aTransform); \ +else var ____p = _CGPointMake(aRight, aTop); \ +aDOMElement.style.right = ROUND(____p.x) + "px";\ +aDOMElement.style.top = ROUND(____p.y) + "px"; + +#define CPDOMDisplayServerSetStyleLeftBottom(aDOMElement, aTransform, aLeft, aBottom) \ +if (aTransform) var ____p = _CGPointApplyAffineTransform(CGPointMake(aLeft, aBottom), aTransform); \ +else var ____p = _CGPointMake(aLeft, aBottom); \ +aDOMElement.style.left = ROUND(____p.x) + "px";\ +aDOMElement.style.bottom = ROUND(____p.y) + "px"; + +#define CPDOMDisplayServerSetStyleRightBottom(aDOMElement, aTransform, aRight, aBottom) \ +if (aTransform) var ____p = _CGPointApplyAffineTransform(CGPointMake(aRight, aBottom), aTransform); \ +else var ____p = _CGPointMake(aRight, aBottom); \ +aDOMElement.style.right = ROUND(____p.x) + "px";\ +aDOMElement.style.bottom = ROUND(____p.y) + "px"; + +#define CPDOMDisplayServerSetStyleSize(aDOMElement, aWidth, aHeight) \ + aDOMElement.style.width = MAX(0.0, ROUND(aWidth)) + "px";\ + aDOMElement.style.height = MAX(0.0, ROUND(aHeight)) + "px"; + +#define CPDOMDisplayServerSetSize(aDOMElement, aWidth, aHeight) \ + aDOMElement.width = MAX(0.0, ROUND(aWidth));\ + aDOMElement.height = MAX(0.0, ROUND(aHeight)); + +#define CPDOMDisplayServerAppendChild(aParentElement, aChildElement) aParentElement.appendChild(aChildElement) + +#define CPDOMDisplayServerInsertBefore(aParentElement, aChildElement, aBeforeElement) aParentElement.insertBefore(aChildElement, aBeforeElement) + +#define CPDOMDisplayServerRemoveChild(aParentElement, aChildElement) aParentElement.removeChild(aChildElement) + +#define PREPARE_DOM_OPTIMIZATION() +#define EXECUTE_DOM_INSTRUCTIONS() + +#else #define CPDOMDisplayServerSetStyleLeftTop(aDOMElement, aTransform, aLeft, aTop) CPDOMDisplayServerSetStyleOrigin(SetStyleLeftTop, aDOMElement, aTransform, aLeft, aTop) #define CPDOMDisplayServerSetStyleRightTop(aDOMElement, aTransform, aRight, aTop) CPDOMDisplayServerSetStyleOrigin(SetStyleRightTop, aDOMElement, aTransform, aRight, aTop) @@ -99,27 +143,70 @@ CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = RemoveChild;\ CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = aParentElement;\ CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = aChildElement; - -//#dfeine CPDOMDisplayServerCustomAction() -#define CPDOMDisplayServerAddView(aView)\ +#define PREPARE_DOM_OPTIMIZATION()\ +CPDOMDisplayServerInstructions = [];\ +CPDOMDisplayServerInstructionCount = 0; +#define EXECUTE_DOM_INSTRUCTIONS()\ + var index = 0;\ + while (index < CPDOMDisplayServerInstructionCount)\ {\ - var ___UID = [aView UID];\ - if (typeof (CPDOMDisplayServerViewsContext[___UID]) == "undefined")\ - {\ - CPDOMDisplayServerViews[CPDOMDisplayServerViewsCount++] = aView;\ - CPDOMDisplayServerViewsContext[___UID] = aView;\ + var instruction = CPDOMDisplayServerInstructions[index++];\ + try{\ + switch (instruction)\ + {\ + case SetStyleLeftTop:\ + case SetStyleRightTop:\ + case SetStyleLeftBottom:\ + case SetStyleRightBottom: var element = CPDOMDisplayServerInstructions[index],\ + style = element.style,\ + x = (instruction == SetStyleLeftTop || instruction == SetStyleLeftBottom) ? "left" : "right",\ + y = (instruction == SetStyleLeftTop || instruction == SetStyleRightTop) ? "top" : "bottom";\ + CPDOMDisplayServerInstructions[index++] = nil;\ + var transform = CPDOMDisplayServerInstructions[index++];\ + if (transform)\ + {\ + var point = _CGPointMake(CPDOMDisplayServerInstructions[index++], CPDOMDisplayServerInstructions[index++]),\ + transformed = _CGPointApplyAffineTransform(point, transform);\ + style[x] = ROUND(transformed.x) + "px";\ + style[y] = ROUND(transformed.y) + "px";\ + }\ + else\ + {\ + style[x] = ROUND(CPDOMDisplayServerInstructions[index++]) + "px";\ + style[y] = ROUND(CPDOMDisplayServerInstructions[index++]) + "px";\ + }\ + element.CPDOMDisplayContext[SetStyleOrigin] = -1;\ + break;\ + case SetStyleSize: var element = CPDOMDisplayServerInstructions[index],\ + style = element.style;\ + CPDOMDisplayServerInstructions[index++] = nil;\ + element.CPDOMDisplayContext[SetStyleSize] = -1;\ + style.width = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++])) + "px";\ + style.height = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++])) + "px";\ + break;\ + case SetSize: var element = CPDOMDisplayServerInstructions[index];\ + CPDOMDisplayServerInstructions[index++] = nil;\ + element.CPDOMDisplayContext[SetSize] = -1;\ + element.width = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++]));\ + element.height = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++]));\ + break;\ + case AppendChild: CPDOMDisplayServerInstructions[index].appendChild(CPDOMDisplayServerInstructions[index + 1]);\ + CPDOMDisplayServerInstructions[index++] = nil;\ + CPDOMDisplayServerInstructions[index++] = nil;\ + break;\ + case InsertBefore: CPDOMDisplayServerInstructions[index].insertBefore(CPDOMDisplayServerInstructions[index + 1], CPDOMDisplayServerInstructions[index + 2]);\ + CPDOMDisplayServerInstructions[index++] = nil;\ + CPDOMDisplayServerInstructions[index++] = nil;\ + CPDOMDisplayServerInstructions[index++] = nil;\ + break;\ + case RemoveChild: CPDOMDisplayServerInstructions[index].removeChild(CPDOMDisplayServerInstructions[index + 1]);\ + CPDOMDisplayServerInstructions[index++] = nil;\ + CPDOMDisplayServerInstructions[index++] = nil;\ + break;\ + }\ + }\ + catch(e) { CPLog("e " + e + " " + instruction); }\ }\ - }\ - -#define CPDOMDisplayServerRemoveView(aView)\ - {\ - var index = CPDOMDisplayServerViewsContext[[aView UID]];\ - if (typeof index != "undefined") \ - {\ - CPDOMDisplayServerViewsContext[[aView UID]];\ - CPDOMDisplayServerViews[index] = NULL;\ - }\ - }\ - - \ No newline at end of file + CPDOMDisplayServerInstructionCount = 0; +#endif diff --git a/AppKit/Platform/DOM/CPDOMDisplayServer.j b/AppKit/Platform/DOM/CPDOMDisplayServer.j deleted file mode 100644 index b4e974646..000000000 --- a/AppKit/Platform/DOM/CPDOMDisplayServer.j +++ /dev/null @@ -1,165 +0,0 @@ -/* - * CPDOMDisplayServer.j - * AppKit - * - * Created by Francisco Tolmasky. - * Copyright 2008, 280 North, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -@import - -#include "../../CoreGraphics/CGAffineTransform.h" -#include "CPDOMDisplayServer.h" - - -var CPDOMDisplayRunLoop = nil; - -CPDOMDisplayServerInstructions = []; -CPDOMDisplayServerInstructionCount = 0; - -CPDOMDisplayServerViews = []; -CPDOMDisplayServerViewsCount = 0; -CPDOMDisplayServerViewsContext = {}; - -@implementation CPDOMDisplayServer : CPObject -{ -} - -+ (void)start -{ - CPDOMDisplayRunLoop = [CPRunLoop currentRunLoop]; - - [CPDOMDisplayRunLoop performSelector:@selector(run) target:CPDOMDisplayServer argument:nil order:0 modes:[CPDefaultRunLoopMode]]; -} - -+ (void)run -{ - while (CPDOMDisplayServerInstructionCount || CPDOMDisplayServerViewsCount) - { - var index = 0; - - while (index < CPDOMDisplayServerInstructionCount) - { - var instruction = CPDOMDisplayServerInstructions[index++]; - try{ - switch (instruction) - { - case SetStyleLeftTop: - case SetStyleRightTop: - case SetStyleLeftBottom: - case SetStyleRightBottom: var element = CPDOMDisplayServerInstructions[index], - style = element.style, - x = (instruction == SetStyleLeftTop || instruction == SetStyleLeftBottom) ? "left" : "right", - y = (instruction == SetStyleLeftTop || instruction == SetStyleRightTop) ? "top" : "bottom"; - - CPDOMDisplayServerInstructions[index++] = nil; - - var transform = CPDOMDisplayServerInstructions[index++]; - - if (transform) - { - var point = _CGPointMake(CPDOMDisplayServerInstructions[index++], CPDOMDisplayServerInstructions[index++]), - transformed = _CGPointApplyAffineTransform(point, transform); - - style[x] = ROUND(transformed.x) + "px"; - style[y] = ROUND(transformed.y) + "px"; - - } - else - { - style[x] = ROUND(CPDOMDisplayServerInstructions[index++]) + "px"; - style[y] = ROUND(CPDOMDisplayServerInstructions[index++]) + "px"; - } - - element.CPDOMDisplayContext[SetStyleOrigin] = -1; - - break; - - case SetStyleSize: var element = CPDOMDisplayServerInstructions[index], - style = element.style; - - CPDOMDisplayServerInstructions[index++] = nil; - - element.CPDOMDisplayContext[SetStyleSize] = -1; - - style.width = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++])) + "px"; - style.height = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++])) + "px"; - - break; - - case SetSize: var element = CPDOMDisplayServerInstructions[index]; - - CPDOMDisplayServerInstructions[index++] = nil; - - element.CPDOMDisplayContext[SetSize] = -1; - - element.width = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++])); - element.height = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++])); - - break; - - case AppendChild: CPDOMDisplayServerInstructions[index].appendChild(CPDOMDisplayServerInstructions[index + 1]); - - CPDOMDisplayServerInstructions[index++] = nil; - CPDOMDisplayServerInstructions[index++] = nil; - - break; - - case InsertBefore: CPDOMDisplayServerInstructions[index].insertBefore(CPDOMDisplayServerInstructions[index + 1], CPDOMDisplayServerInstructions[index + 2]); - - CPDOMDisplayServerInstructions[index++] = nil; - CPDOMDisplayServerInstructions[index++] = nil; - CPDOMDisplayServerInstructions[index++] = nil; - - break; - - case RemoveChild: CPDOMDisplayServerInstructions[index].removeChild(CPDOMDisplayServerInstructions[index + 1]); - - CPDOMDisplayServerInstructions[index++] = nil; - CPDOMDisplayServerInstructions[index++] = nil; - - break; - }}catch(e) { CPLog("here?" + instruction) } - } - - CPDOMDisplayServerInstructionCount = 0; - - var views = CPDOMDisplayServerViews, - index = 0, - count = CPDOMDisplayServerViewsCount; - - // We don't reset CPDOMDisplayServerViewsContext because it can serve for displays that are coming... - CPDOMDisplayServerViews = []; - CPDOMDisplayServerViewsCount = 0; - - for (; index < count; ++index) - { - var view = views[index]; - - delete CPDOMDisplayServerViewsContext[[view UID]]; - - [view layoutIfNeeded]; - [view displayIfNeeded]; - } - } - - [CPDOMDisplayRunLoop performSelector:@selector(run) target:CPDOMDisplayServer argument:nil order:0 modes:[CPDefaultRunLoopMode]]; -} - -@end - -[CPDOMDisplayServer start]; diff --git a/AppKit/_CPDisplayServer.j b/AppKit/_CPDisplayServer.j new file mode 100644 index 000000000..fcc53002a --- /dev/null +++ b/AppKit/_CPDisplayServer.j @@ -0,0 +1,101 @@ +/* + * _CPDisplayServer.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "CoreGraphics/CGGeometry.h" +#include "CoreGraphics/CGAffineTransform.h" +#include "Platform/DOM/CPDOMDisplayServer.h" + +PREPARE_DOM_OPTIMIZATION(); + +var displayObjects = [], + displayObjectsByUID = { }, + + layoutObjects = [], + layoutObjectsByUID = { }, + + runLoop = [CPRunLoop mainRunLoop]; + +function _CPDisplayServerAddDisplayObject(anObject) +{ + var UID = [anObject UID]; + + if (typeof displayObjectsByUID[UID] !== "undefined") + return; + + var index = displayObjects.length; + + displayObjectsByUID[UID] = index; + displayObjects[index] = anObject; +} + +function _CPDisplayServerAddLayoutObject(anObject) +{ + var UID = [anObject UID]; + + if (typeof layoutObjectsByUID[UID] !== "undefined") + return; + + var index = layoutObjects.length; + + layoutObjectsByUID[UID] = index; + layoutObjects[index] = anObject; +} + +@implementation _CPDisplayServer : CPObject +{ +} + ++ (void)run +{ + var index = 0; + + for (; index < layoutObjects.length; ++index) + { + var object = layoutObjects[index]; + + delete layoutObjectsByUID[[object UID]]; + [object layoutIfNeeded]; + } + + EXECUTE_DOM_INSTRUCTIONS(); + + layoutObjects = []; + layoutObjectsByUID = { }; + + index = 0; + + var count = displayObjects.length; + + for (; index < count; ++index) + [displayObjects[index] displayIfNeeded]; + + EXECUTE_DOM_INSTRUCTIONS(); + + displayObjects = []; + displayObjectsByUID = { }; + + [runLoop performSelector:@selector(run) target:self argument:nil order:0 modes:[CPDefaultRunLoopMode]]; +} + +@end + +[_CPDisplayServer run];