This is PXKDrawingEngine.m in view mode; [Download] [Up]
/* PXKDrawingEngine.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Pascal Forget <pascal@wsc.com> Date: March 1996 This file is part of the GNUstep GUI X/DPS Backend. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. If you are interested in a warranty or support for this source code, contact Scott Christley <scottc@net-community.com> for more information. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <gnustep/xdps/PXKit.h> LogFile *logFile; #define PXKDE_DEBUG 1 #define PXK_MAX(x,y) (x>y)?x:y // // This functions performs all backend initialization // that is required before main() is called // BOOL initialize_gnustep_backend() { // Open log file logFile = [[LogFile alloc] initFile:"NSLog.log"]; if (!logFile) abort(); // Have backend classes poseAs their super NSLog(@"Using GNUstep GUI X/DPS Backend for backend implementation.\n"); [PXKDPSContext poseAs:[NSDPSContext class]]; [PXKScreen poseAs:[NSScreen class]]; [PXKResponder poseAs:[NSResponder class]]; [PXKEvent poseAs:[NSEvent class]]; [PXKApplication poseAs:[NSApplication class]]; [PXKView poseAs:[NSView class]]; [PXKCell poseAs:[NSCell class]]; [PXKControl poseAs:[NSControl class]]; [PXKMatrix poseAs:[NSMatrix class]]; [PXKWindow poseAs:[NSWindow class]]; [PXKMenu poseAs:[NSMenu class]]; [PXKPanel poseAs:[NSPanel class]]; [PXKActionCell poseAs:[NSActionCell class]]; [PXKFontManager poseAs:[NSFontManager class]]; [PXKFont poseAs:[NSFont class]]; [PXKFontPanel poseAs:[NSFontPanel class]]; [PXKMenuCell poseAs:[NSMenuCell class]]; [PXKColor poseAs:[NSColor class]]; [PXKBox poseAs:[NSBox class]]; [PXKButtonCell poseAs:[NSButtonCell class]]; [PXKButton poseAs:[NSButton class]]; [PXKSavePanel poseAs:[NSSavePanel class]]; [PXKOpenPanel poseAs:[NSOpenPanel class]]; [PXKPopUpButton poseAs:[NSPopUpButton class]]; [PXKSliderCell poseAs:[NSSliderCell class]]; [PXKSlider poseAs:[NSSlider class]]; [PXKTextFieldCell poseAs:[NSTextFieldCell class]]; [PXKText poseAs:[NSText class]]; [PXKTextField poseAs:[NSTextField class]]; // Initialize the XWindows drawing engine NSLog(@"Initializing XWindows drawing engine\n"); initializeDrawingEngine(); // success return YES; } void pxkDebugMsg(const char *msg) { #if PXKDE_DEBUG fprintf(stderr, "%s\n", msg); #endif } #if 0 #define icon_bitmap_width 40 #define icon_bitmap_height 40 static char icon_bitmap_bits[] = { 0xc3, 0xc3, 0x7f, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x38, 0x00, 0x40, 0x00, 0x80, 0x24, 0x00, 0x00, 0x00, 0x80, 0x44, 0x00, 0x00, 0x00, 0x80, 0x44, 0x00, 0x00, 0x00, 0x80, 0x74, 0x00, 0x0f, 0x0c, 0x00, 0x7c, 0x3e, 0x41, 0x0e, 0x00, 0x44, 0x22, 0x41, 0x02, 0x00, 0x84, 0x22, 0x46, 0x02, 0x00, 0x9c, 0x26, 0xcc, 0x02, 0x00, 0x78, 0x3c, 0xcd, 0x36, 0x80, 0x00, 0x20, 0x06, 0x0c, 0x80, 0x01, 0x00, 0x00, 0x00, 0x80, 0x01, 0x02, 0x40, 0x00, 0x80, 0x01, 0x06, 0x40, 0x00, 0x80, 0x01, 0x04, 0x20, 0x00, 0x80, 0x01, 0x04, 0x20, 0x01, 0x80, 0x01, 0x04, 0x20, 0x00, 0x80, 0x01, 0x04, 0x22, 0x00, 0x80, 0x01, 0x04, 0x33, 0xf1, 0x81, 0x01, 0x88, 0x12, 0x31, 0x03, 0x01, 0x88, 0x12, 0x11, 0x02, 0x00, 0x88, 0x12, 0x11, 0x02, 0x00, 0x48, 0x1a, 0x11, 0x02, 0x00, 0x70, 0x04, 0x19, 0x82, 0x01, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x38, 0x80, 0x01, 0x00, 0x00, 0xce, 0x80, 0x01, 0x00, 0x00, 0x83, 0x81, 0x81, 0x07, 0x80, 0x01, 0x81, 0xe1, 0x04, 0xc0, 0x00, 0x83, 0x31, 0x08, 0x40, 0x00, 0x82, 0x10, 0x08, 0x20, 0x00, 0x82, 0x19, 0x10, 0x30, 0x00, 0x86, 0x0c, 0x30, 0x18, 0x00, 0x84, 0x04, 0x60, 0x0e, 0x00, 0xdc, 0x02, 0x80, 0x03, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00}; #endif static char icon_bitmap_bits2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /* * Below are declarations of the drawing engine's global variables. */ /* Contains a list of all views and windows created */ NSMutableArray *views; NSColor *currentColor; Display *pxkDisplay; /* int pxkScreen; */ /* int pxkDisplayWidth; */ int pxkDisplayHeight; GC pxkBlackGC; /* Global drawing contexts for the most commonly */ GC pxkWhiteGC; /* used colors: Black, White, Light Gray, and */ GC pxkLightgrayGC; /* Dark Gray. The drawing engine is smart */ GC pxkDarkgrayGC; /* enough to use these contexts when passed NSColors */ /* that either have grayscale or RGB backings that */ /* correspond to any of these predefined contexts. */ @interface PXKXWindow : NSObject {} @end @implementation PXKXWindow @end /* Private functions */ void load_font(XFontStruct **font_info) { char *fontname = "9x15"; /* Load font and get font information structure. */ if ((*font_info = XLoadQueryFont(pxkDisplay,fontname)) == NULL) { (void) fprintf( stderr, "Drawing Engine error: cannot open" " 9x15 font\n"); exit( -1 ); } } /* End Private Functions */ /* * initializeDrawingSystem() is called once from the NSApplication object * when the application starts */ int initializeDrawingEngine(void) { char *displayName = NULL; XGCValues values; unsigned long valuemask = (GCForeground | GCBackground); Window win; XColor c1, c2; int xscreen; NSRect r; GC xgc; if ( (pxkDisplay = XOpenDisplay(displayName)) == NULL ) { (void)fprintf(stderr, "Cannot connect to X server. exiting.\n"); exit(-1); } [(PXKDPSContext *)[NSDPSContext currentContext] setXDisplay: pxkDisplay]; // pxkScreen = DefaultScreen(pxkDisplay); [(PXKScreen *)[NSScreen mainScreen] setXScreen: DefaultScreen(pxkDisplay)]; xscreen = [(PXKScreen *)[NSScreen mainScreen] xScreen]; r = [[NSScreen mainScreen] frame]; printf("Display width: %f height: %f\n", r.size.width, r.size.height); /* createSystemImages(); */ /* * Create the standard graphic contexts */ win = RootWindow(pxkDisplay, xscreen); values.foreground = BlackPixel(pxkDisplay, xscreen); values.background = WhitePixel(pxkDisplay, xscreen); xgc = XCreateGC(pxkDisplay, win, valuemask, &values); [(PXKDPSContext *)[NSDPSContext currentContext] setGC: xgc]; values.foreground = BlackPixel(pxkDisplay, xscreen); values.background = WhitePixel(pxkDisplay, xscreen); pxkBlackGC = XCreateGC(pxkDisplay, win, valuemask, &values); values.foreground = values.background; values.background = BlackPixel(pxkDisplay, xscreen); pxkWhiteGC = XCreateGC(pxkDisplay, win, valuemask, &values); /* set drawing color to lightgray */ XAllocNamedColor(pxkDisplay, XDefaultColormap(pxkDisplay, xscreen), "light gray", &c1, &c2); values.foreground = c1.pixel; values.background = WhitePixel(pxkDisplay, xscreen); pxkLightgrayGC = XCreateGC(pxkDisplay, win, valuemask, &values); /* set drawing color to darkgray */ XAllocNamedColor(pxkDisplay, XDefaultColormap(pxkDisplay, xscreen), "dim gray", &c1, &c2); values.foreground = c1.pixel; values.background = WhitePixel(pxkDisplay, xscreen); pxkDarkgrayGC = XCreateGC(pxkDisplay, win, valuemask, &values); views = [[NSMutableArray alloc] initWithCapacity:64]; currentColor = [NSColor blackColor]; return 0; /* success */ } Window createXWindow(NSRect rect) { XColor c1, c2; Window xWindow; XWMHints *wm_hints; XFontStruct *win_font; int xscreen = [(PXKScreen *)[NSScreen mainScreen] xScreen]; if (!(wm_hints = XAllocWMHints())) { (void)fprintf(stderr, "Failure allocating memory\n"); exit(0); } /* * Get the font */ (void)load_font(&win_font); #if 1 XAllocNamedColor(pxkDisplay, XDefaultColormap(pxkDisplay, xscreen), "light gray", &c1, &c2); #else XAllocNamedColor(pxkDisplay, XDefaultColormap(pxkDisplay, xscreen), "midnight blue", &c1, &c2); #endif /* * Create a non-bordered, non-titled X window */ rect.origin.x = 0; rect.origin.y = 0; rect.size.width = 600; rect.size.height = 900; xWindow = XCreateSimpleWindow(pxkDisplay, RootWindow(pxkDisplay,xscreen), rect.origin.x, rect.origin.y, rect.size.width, rect.size.height, 1, BlackPixel(pxkDisplay,xscreen), c1.pixel); /* Set the border width */ XSetWindowBorderWidth(pxkDisplay, xWindow, 1); wm_hints->initial_state = NormalState; wm_hints->input = True; wm_hints->icon_pixmap = XCreateBitmapFromData(pxkDisplay,xWindow, icon_bitmap_bits2, 48,48); wm_hints->flags = StateHint | IconPixmapHint | InputHint; XSetWMHints(pxkDisplay, xWindow, wm_hints); // cursor = XC_top_left_arrow; XSelectInput(pxkDisplay, xWindow, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | StructureNotifyMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask | StructureNotifyMask | FocusChangeMask | PropertyChangeMask | ColormapChangeMask | KeymapStateMask | VisibilityChangeMask); #if 1 (void)fprintf(stdout, "X windows count: %i\n", [views count]); #endif return xWindow; } int numberForXWindow(Window win) { NSArray *l = [NSApp windows]; id e, o; e = [l objectEnumerator]; o = [e nextObject]; while (o) { if ([(PXKWindow *)o xWindow] == win) return [(NSWindow *)o windowNumber]; o = [e nextObject]; } NSLog(@"Could not find NSWindow for XWindow\n"); return -1; } NSWindow * nswindow_for_xwindow(Window win) { NSArray *l = [NSApp windows]; id e, o; // Is it even a valid window number if (win < 0) return nil; e = [l objectEnumerator]; o = [e nextObject]; while (o) { if ([(PXKWindow *)o xWindow] == win) return o; o = [e nextObject]; } NSLog(@"Could not find NSWindow for XWindow\n"); return nil; } Window xWindowWithId(int num) { return -1; } int uniqueWindowId() { return -1; } void closeWindow(int windowNum) { int index = indexOfViewNumber(windowNum); if (index < 0) { fprintf(stderr, "Error closing window: invalid window " "number: %i\n", windowNum); } XUnmapWindow(pxkDisplay, [[views objectAtIndex:index] xWindow]); } void setViewFrame(int viewNum, NSRect frameRect) { int index = indexOfViewNumber(viewNum); PXKXWindow *rep = (PXKXWindow *)[views objectAtIndex:index]; NSWindow *win = [(NSView *)[rep responder] window]; NSRect winRect = [win frame]; fprintf(stdout, "set frame to: %i %i %i %i\n", PXK_MAX((int)frameRect.origin.x, 0), PXK_MAX((int)winRect.size.height + (int)frameRect.origin.y - (int)frameRect.size.height, 0), (int)frameRect.size.width, (int)frameRect.size.height); XMoveResizeWindow(pxkDisplay, [[views objectAtIndex:index] xWindow], PXK_MAX((int)frameRect.origin.x, 0), PXK_MAX((int)winRect.size.height + (int)frameRect.origin.y - (int)frameRect.size.height, 0), (int)frameRect.size.width, (int)frameRect.size.height); } void setViewFrameOrigin(int viewNum, NSPoint newOrigin) { int index = indexOfViewNumber(viewNum); PXKXWindow *window; NSRect frameRect; if (index < 0) { fprintf(stderr, "setViewFrameOrigin() error: invalid view.\n"); return; } window = [views objectAtIndex:index]; frameRect = [(NSWindow *)[window responder] frame]; XMoveWindow(pxkDisplay, [window xWindow], newOrigin.x, pxkDisplayHeight - newOrigin.y - frameRect.size.height); } void setViewFrameRotation(int viewNum, float angle) { /* Not supported by this incarnation of the drawing engine. */ } void setViewFrameSize(int viewNum, NSSize newSize) { int index = indexOfViewNumber(viewNum); PXKXWindow *window; NSRect rect; if (index < 0) { fprintf(stderr, "setViewFrameSize() error: invalid view.\n"); return; } window = [views objectAtIndex:index]; rect = [(NSWindow *)[window responder] frame]; XMoveResizeWindow(pxkDisplay, [window xWindow], rect.origin.x, pxkDisplayHeight - rect.origin.y - rect.size.height, newSize.width, newSize.height); } void setWindowFrame(int windowNum, NSRect frameRect) { int index = indexOfViewNumber(windowNum); fprintf(stdout, "set frame to: %i %i %i %i\n", PXK_MAX((int)frameRect.origin.x, 0), PXK_MAX((int)pxkDisplayHeight - (int)frameRect.origin.y - (int)frameRect.size.height, 0), (int)frameRect.size.width, (int)frameRect.size.height); XMoveResizeWindow(pxkDisplay, [[views objectAtIndex:index] xWindow], PXK_MAX((int)frameRect.origin.x, 0), PXK_MAX((int)pxkDisplayHeight - (int)frameRect.origin.y - (int)frameRect.size.height, 0), (int)frameRect.size.width, (int)frameRect.size.height); } void setWindowFrameOrigin(int windowNum, NSPoint newOrigin) { setViewFrameOrigin(windowNum, newOrigin); } void setWindowFrameSize(int windowNum, NSSize newSize) { setViewFrameSize(windowNum, newSize); } /* Utility functions not part of OpenStep */ void setCurrentColor(NSColor *aColor) { currentColor = aColor; } /* Functions to be called by other elements of the drawing engine */ int indexOfViewNumber(int viewNum) { int count = [views count]; while(count > 0) { if ([[views objectAtIndex:count-1] windowNumber] == viewNum) { //fprintf(stderr,"index: %i of view number: %i\n",count-1,viewNum); return count-1; } count--; } return -1; /* not found */ } int indexOfXWindowRepresentingAView(Window xWindow) { int count = [views count]; while(count > 0) { if ([[views objectAtIndex:count-1] xWindow] == xWindow) { fprintf(stderr, "indexOfXWindowRep.... : %i\n", count-1); return count-1; } count--; } return -1; /* not found */ } int indexOfXWindowRepresentingAWindow(Window xWindow) { return indexOfXWindowRepresentingAView(xWindow); } /* These are called from NSApplication */ void miniaturizeAll(id sender) { } void preventWindowOrdering(void) { } void updateWindows(void) { } /* Application Kit Functions */ /* Rectangle Drawing Functions */ // Oops, DPS stuff still needs to be cleaned up - scott #if 0 void NSRectFill(NSRect aRect) /* Fills rect using current color */ { pxkFillRect(aRect, currentColor); } void NSRectFillList(const NSRect *rects, int count) { int i; for (i=0; i<count; i++) { pxkFillRect(rects[i], currentColor); } } /* * NSRectFillWithGrays() Fills each rectangle in the array 'rects' * with the gray whose value is stored at the corresponding location * in the array 'grays'. Both arrays must be count elements long. * Avoid overlapping rectangles, because the drawing order can't be * guaranteed. */ void NSRectFillListWithGrays(const NSRect *rects,const float *grays,int count) { } #endif /* Draw a line (private function) */ void pxkDrawLine(NSPoint a, NSPoint b, NSColor *color) { NSView *focusView = [NSView focusView]; int windowId; if (focusView != nil) { windowId = [(PXKView *)focusView viewNum]; /* Let's cheat a little in order to speed up things */ if (color == [NSColor blackColor]) { //puts("black color"); //fprintf(stdout, "windowId: %d\n", windowId); XDrawLine(pxkDisplay, xWindowWithId(windowId), pxkBlackGC, a.x,a.y,b.x,b.y); } else if (color == [NSColor whiteColor]) { XDrawLine(pxkDisplay, xWindowWithId(windowId), pxkWhiteGC, a.x,a.y,b.x,b.y); } else if (color == [NSColor darkGrayColor]) { XDrawLine(pxkDisplay, xWindowWithId(windowId), pxkDarkgrayGC, a.x,a.y,b.x,b.y); } else if (color == [NSColor lightGrayColor]) { XDrawLine(pxkDisplay, xWindowWithId(windowId), pxkLightgrayGC, a.x,a.y,b.x,b.y); } } else { puts("No view in focus!!!"); } } /* * Draw a line that's defined as an NSRect instead of 2 points */ void pxkDrawLineRect(NSRect line, NSColor *color) { NSPoint a = line.origin; NSPoint b; /* Do not display lines where width or height < 0 */ if ((line.size.width >= 0) && (line.size.height >= 0)) { b.x = line.origin.x + line.size.width; b.y = line.origin.y + line.size.height; pxkDrawLine(a, b, color); } } void pxkFillRect(NSRect rect, NSColor *color) { NSView *focusView = [NSView focusView]; int windowId; if (focusView != nil) { windowId = [(PXKView *)focusView viewNum]; /* Let's cheat a little in order to speed up things */ if (color == [NSColor blackColor]) { XFillRectangle(pxkDisplay, xWindowWithId(windowId), pxkBlackGC, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); } else if (color == [NSColor whiteColor]) { XFillRectangle(pxkDisplay, xWindowWithId(windowId), pxkWhiteGC, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); } else if (color == [NSColor darkGrayColor]) { XFillRectangle(pxkDisplay, xWindowWithId(windowId), pxkDarkgrayGC, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); } else if (color == [NSColor lightGrayColor]) { XFillRectangle(pxkDisplay, xWindowWithId(windowId), pxkLightgrayGC, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); } } else { pxkDebugMsg("No view in focus!!!"); } } /* Private functions, not part of the OpenStep specification */ NSPoint intersectionPoint(NSRect lineA, NSRect lineB) { NSPoint aPoint; float r, s; float XA = lineA.origin.x; float XB = lineA.origin.x + lineA.size.width; float XC = lineB.origin.x; float XD = lineB.origin.x + lineB.size.width; float YA = lineA.origin.y; float YB = lineA.origin.y + lineA.size.height; float YC = lineB.origin.y; float YD = lineB.origin.y + lineB.size.height; float denominator = (XB-XA)*(YD-YC)-(YB-YA)*(XD-XC); /* The following code taken from comp.graphics.algorithms FAQ. This problem can be extremely easy or extremely difficult depends on your applications. If all you want is the intersection point, the following should work: Let A,B,C,D be 2-space position vectors. Then the directed line segments AB and CD are given by: AB=A+r(B-A), r in [0,1] CD=C+s(D-C), s in [0,1] If AB and CD intersect, then A+r(B-A)=C+s(D-C) or XA+r(XB-XA)=XC+s(XD-XC) YA+r(YB-YA)=YC+s(YD-YC) for some r,s in [0,1] Solving the above for r and s yields (YA-YC)(XD-XC)-(XA-XC)(YD-YC) r = ----------------------------- (eqn 1) (XB-XA)(YD-YC)-(YB-YA)(XD-XC) (YA-YC)(XB-XA)-(XA-XC)(YB-YA) s = ----------------------------- (eqn 2) (XB-XA)(YD-YC)-(YB-YA)(XD-XC) */ if ((denominator < 0.00000001) && (denominator > -0.00000001)) { fprintf(stderr, "in function intersect(), lines are parallel.\n"); aPoint.x = -1; aPoint.y = -1; /* x and y are always positive in this toolkit */ } r = ((YA-YC)*(XD-XC)-(XA-XC)*(YD-YC)) / denominator; s = ((YA-YC)*(XB-XA)-(XA-XC)*(YB-YA)) / denominator; /* Let I be the position vector of the intersection point, then I=A+r(B-A) or XI=XA+r(XB-XA) YI=YA+r(YB-YA) */ aPoint.x = XA+r*(XB-XA); aPoint.y = YA+r*(YB-YA); /* By examining the values of r and s, you can also determine some other limiting conditions: If 0 <= r <= 1 and 0 <= s <= 1, intersection exists r < 0 or r>1 or s < 0 or s>1 line segments do not intersect If the denominator in eqn 1 is zero, AB and CD are parallel If the numerator in eqn 1 is also zero, AB and CD are coincident If the intersection point of the 2 lines are needed (lines in this context mean infinite lines) regardless whether the two line segments intersect, then If r > 1, I is located on extension of AB If r < 0, I is located on extension of BA If s > 1, I is located on extension of CD If s < 0, I is located on extension of DC Also note that the denominators of equations 1 and 2 are identical. References: [O'Rourke] pp. 249-51 [Gems3] pp. 199-202 "Faster Line Segment Intersection," */ return aPoint; } float dist2D(NSPoint a, NSPoint b) { return (a.x-b.x)*(a.x - b.x) / ((a.y-b.y)*(a.y-b.y)); } NSRect clipLineToRect(NSRect aLine, NSRect aRect) { NSRect resultLine = aLine; NSRect clipLine; NSPoint aPoint; float XA, XB, YA, YB; XA = aLine.origin.x; XB = aLine.origin.x + aLine.size.width; YA = aLine.origin.y; YB = aLine.origin.y + aLine.size.height; /* * Set height = width = -1 for lines that are totally * outside of the clipping rectangle. */ if (((XA < aRect.origin.x) && (XB < aRect.origin.x)) || ((XA > aRect.origin.x + aRect.size.width) && (XB > aRect.origin.x + aRect.size.width)) || ((YA < aRect.origin.y) && (YB < aRect.origin.y)) || ((YA > aRect.origin.x + aRect.size.width) && (YB > aRect.origin.x + aRect.size.width))) { resultLine.size.width = resultLine.size.height = -1; return resultLine; } /* clip left */ if ((XA <= aRect.origin.x) && (XB >= aRect.origin.x)) { pxkDebugMsg("clip left"); clipLine = aRect; clipLine.size.width = 0.0; aPoint = intersectionPoint(aLine, clipLine); resultLine.origin.x = aPoint.x; resultLine.origin.y = aPoint.y; resultLine.size.width = XB - aPoint.x; resultLine.size.height = YB - aPoint.y; } /* clip right */ if ((XA <= aRect.origin.x + aRect.size.width) && (XB >= aRect.origin.x + aRect.size.width)) { pxkDebugMsg("clip right"); clipLine = aRect; clipLine.origin.x += clipLine.size.width; clipLine.size.width = 0.0; aPoint = intersectionPoint(aLine, clipLine); resultLine.origin.x = aPoint.x; resultLine.origin.y = aPoint.y; resultLine.size.width = XB - aPoint.x; resultLine.size.height = YB - aPoint.y; } /* clip bottom */ if ((YA <= aRect.origin.y + aRect.size.height) && (YB >= aRect.origin.y + aRect.size.height)) { pxkDebugMsg("clip bottom"); clipLine = aRect; clipLine.size.height = 0.0; aPoint = intersectionPoint(aLine, clipLine); resultLine.origin.x = aPoint.x; resultLine.origin.y = aPoint.y; resultLine.size.width = XB - aPoint.x; resultLine.size.height = YB - aPoint.y; } /* clip top */ if ((YA <= aRect.origin.y) && (YB >= aRect.origin.y)) { pxkDebugMsg("clip top"); clipLine = aRect; clipLine.origin.x += clipLine.size.height; clipLine.size.height = 0.0; aPoint = intersectionPoint(aLine, clipLine); resultLine.origin.x = aPoint.x; resultLine.origin.y = aPoint.y; resultLine.size.width = XB - aPoint.x; resultLine.size.height = YB - aPoint.y; } return resultLine; } #if 0 /* Draw a Bordered Rectangle */ void NSDrawButton(NSRect aRect, NSRect clipRect) /* Bordered ltgray rect */ { NSRect line; /* Draw the top white line */ line = aRect; line.size.height = 0; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor whiteColor]); /* Draw the left white line */ line = aRect; line.size.width = 0; line.size.height -= 1; /* line doesn't draw down to the last pixel */ pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor whiteColor]); /* Draw the bottom black line */ line = aRect; line.origin.y += line.size.height; line.size.height = 0; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor blackColor]); /* Draw the bottom darkgray line above the black line */ line.origin.y--; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor darkGrayColor]); /* Draw the right black line */ line = aRect; line.origin.x += line.size.width; line.size.width = 0; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor blackColor]); /* Draw the right darkgray line */ line.origin.x--; line.origin.y++; line.size.height -= 2.0; /* line doesn't draw down to the last pixel */ pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor darkGrayColor]); } void NSDrawGrayBezel(NSRect aRect, NSRect clipRect) /* pushed-in button */ { /* Like the border of a TextField? */ NSRect line; /* Draw the top darkgray line */ line = aRect; line.size.height = 0; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor darkGrayColor]); /* Draw the top darkgray line below the darkgray line */ line.origin.y++; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor darkGrayColor]); /* Draw the left darkgray line */ line = aRect; line.size.width = 0; line.size.height--; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor darkGrayColor]); /* Draw the left darkgray line, besides the vertical darkgray line */ line.origin.x++; line.size.height--; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor darkGrayColor]); /* Draw the bottom white line */ line = aRect; line.origin.y += line.size.height; line.size.height = 0; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor whiteColor]); /* Draw the bottom lightgray line above the white line */ line.origin.x++; line.size.width--; line.origin.y--; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor lightGrayColor]); /* Draw the right white line */ line = aRect; line.origin.x += line.size.width; line.size.width = 0; line.origin.y++; line.size.height--; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor whiteColor]); /* Draw the right lightgray line */ line.origin.x--; line.origin.y++; line.size.height -= 2.0; /* line doesn't draw down to the last pixel */ pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor lightGrayColor]); } void NSDrawGroove(NSRect aRect, NSRect clipRect) /* like a Box */ { NSRect line; /* Draw the top darkgray line */ line = aRect; line.size.height = 0; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor darkGrayColor]); /* Draw the top white line below the darkgray line */ line.origin.y++; line.origin.x++; line.size.width--; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor whiteColor]); /* Draw the left darkgray line */ line = aRect; line.size.width = 0; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor darkGrayColor]); /* Draw the left white line, besides the vertical darkgray line */ line.origin.x++; line.origin.y++; line.size.height--; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor whiteColor]); /* Draw the bottom white line */ line = aRect; line.origin.x++; line.size.width--; line.origin.y += line.size.height; line.size.height = 0; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor whiteColor]); /* Draw the bottom darkgray line above the white line */ line.origin.x++; line.size.width--; line.origin.y--; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor darkGrayColor]); /* Draw the right white line */ line = aRect; line.origin.x += line.size.width; line.size.width = 0; line.origin.y++; line.size.height--; pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor whiteColor]); /* Draw the right darkgray line */ line.origin.x--; line.origin.y++; line.size.height -= 2.0; /* line doesn't draw down to the last pixel */ pxkDrawLineRect(clipLineToRect(line, clipRect), [NSColor darkGrayColor]); } #if 0 void NSDrawTiledRects(NSRect boundsRect, NSRect clipRect, const NSRectEdge *sides, const float *grays, int count) { } #endif void NSDrawWhiteBezel(NSRect aRect, NSRect clipRect) /* like a TextField */ { } void NSFrameRect(NSRect aRect) /* Draws a frame of width 1.0 use curr color */ { NSPoint a, b; a = aRect.origin; b.x = aRect.origin.x + aRect.size.width; b.y = aRect.origin.y; pxkDrawLine(a, b, currentColor); a.x = b.x; a.y += aRect.origin.y + aRect.size.height; pxkDrawLine(a, b, currentColor); b.x = aRect.origin.x; b.y = a.y; pxkDrawLine(a, b, currentColor); pxkDrawLine(aRect.origin, b, currentColor); } void NSFrameRectWithWidth(NSRect aRect, float frameWidth) { } #endif // More DPS garbage #if 1 void MB__rectfill(id self, float X, float Y, float WIDTH, float HEIGHT) {} void MB__set_color(id self, NSColor *c) {} void MB__rectstroke(id self, float X, float Y, float WIDTH, float HEIGHT) {} #endif Display * xDisplay(void) { return pxkDisplay; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.