#include "WindowManager.h" void TransWindow(WindowRef w, Boolean vis) { WindowTransitionAction Action; if(vis) Action = kWindowShowTransitionAction; else Action = kWindowHideTransitionAction; TransitionWindow(w, kWindowZoomTransitionEffect, Action, NULL); } #pragma mark - void SetOrtho(VWindow * w) { Rect bounds; bounds = WindowSize(w); glMatrixMode(GL_PROJECTION); glLoadIdentity(); w->Ortho = true; glDisable(GL_DEPTH_TEST); glOrtho(0, bounds.right-bounds.left, 0, bounds.bottom-bounds.top, 0, 20); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void SetPerspective(VWindow * w) { Rect bounds; GLfloat ratio; bounds = WindowSize(w); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if ((bounds.right - bounds.left) > (bounds.bottom - bounds.top)) { ratio = ((GLfloat) (bounds.right - bounds.left) / (bounds.bottom - bounds.top)); glFrustum(-ratio, ratio, -1.0, 1.0, 1.5, 10000.0); } else { ratio = ((GLfloat) (bounds.bottom - bounds.top) / (bounds.right - bounds.left)); glFrustum(-1.0, 1.0, -ratio, ratio, 1.5, 10000.0); } glScalef(10.0, 10.0, 10.0); w->Ortho = false; glEnable(GL_DEPTH_TEST); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } static void SetOGLSetttings(VWindow * w) { glLineWidth(1.0); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glEnable(GL_ALPHA_TEST); glEnable(GL_POLYGON_OFFSET_FILL); glAlphaFunc(GL_GREATER, 0.0f); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); /* Wireframe mode */ if(w->Ortho) SetOrtho(w); else SetPerspective(w); } Rect WindowSize(VWindow * w) { Rect result; GDHandle Display; if(w->FullScreen) { Display = GetMainDevice(); return (**Display).gdRect; } else { GetWindowPortBounds(w->TheWindow, &result); return result; } } void CreateWindowedContext(VWindow * w) { GLint Attribs[] = {AGL_RGBA, AGL_DOUBLEBUFFER, AGL_DEPTH_SIZE, 24, AGL_NO_RECOVERY, AGL_ACCELERATED, AGL_PIXEL_SIZE, 32, AGL_NONE}; AGLPixelFormat Format; Rect windowBounds; Format = aglChoosePixelFormat(NULL, 0, Attribs); w->Windowed = aglCreateContext(Format, w->FullScreen); if(w->FullScreen) { glClear(GL_COLOR_BUFFER_BIT); aglSwapBuffers(w->FullScreen); aglSetCurrentContext(NULL); aglSetDrawable(w->FullScreen, NULL); aglDestroyContext(w->FullScreen); w->FullScreen = NULL; } aglSetDrawable(w->Windowed, GetWindowPort(w->TheWindow)); aglSetCurrentContext(w->Windowed); aglDestroyPixelFormat(Format); GetWindowPortBounds(w->TheWindow, &windowBounds); w->IsFullScreen = false; SetOGLSetttings(w); glClear(GL_COLOR_BUFFER_BIT); if(aglGetError()) SysBeep(0); } void CreateFullScreenContext(VWindow * w) { GLint Attribs[] = {AGL_RGBA, AGL_DOUBLEBUFFER, AGL_DEPTH_SIZE, 24, AGL_FULLSCREEN, AGL_NO_RECOVERY, AGL_ACCELERATED, AGL_PIXEL_SIZE, 32, AGL_NONE}; AGLPixelFormat Format; GDHandle Display; Display = GetMainDevice(); Format = aglChoosePixelFormat(&Display, 1, Attribs); w->FullScreen = aglCreateContext(Format, w->Windowed); if(w->Windowed) { glClear(GL_COLOR_BUFFER_BIT); aglSwapBuffers(w->Windowed); aglSetCurrentContext(NULL); aglSetDrawable(w->Windowed, NULL); aglDestroyContext(w->Windowed); w->Windowed = NULL; } aglSetFullScreen(w->FullScreen, (**Display).gdRect.right, (**Display).gdRect.bottom, 0, 0); aglSetCurrentContext(w->FullScreen); aglDestroyPixelFormat(Format); w->IsFullScreen = true; SetOGLSetttings(w); glClear(GL_COLOR_BUFFER_BIT); if(aglGetError()) SysBeep(0); } static void InitWindowContext(VWindow * w) { w->FullScreen = NULL; w->Windowed = NULL; w->Ortho = false; w->Scaled = false; CreateWindowedContext(w); } #pragma mark - static pascal OSStatus WindowWasClosed(EventHandlerCallRef nextEvent, EventRef theEvent, void * userData) { #pragma unused(nextEvent, theEvent) VWindow * w; w = (VWindow *) userData; if (w->quitOnClose) QuitApplicationEventLoop(); return eventNotHandledErr; } static pascal OSStatus WindowCollapsing(EventHandlerCallRef nextEvent, EventRef theEvent, void * userData) { #pragma unused(nextEvent, theEvent) VWindow * w; w = (VWindow *) userData; w->isMinimized = 1; if (!w->IsFullScreen && w->Windowed != NULL) { PixMapHandle myPixMap; Rect windowBounds; void * imageData; GWorldPtr origGWorld; GDHandle origGDev; short currentRow; Rect srcRect, destRect; GetWindowPortBounds(w->TheWindow, &windowBounds); OffsetRect(&windowBounds, -windowBounds.left, -windowBounds.top); myPixMap = NewPixMap(); if (myPixMap == NULL) return eventNotHandledErr; imageData = NewPtr(4 * windowBounds.right * windowBounds.bottom); if (imageData == NULL) { DisposePixMap(myPixMap); return eventNotHandledErr; } glReadPixels(0, 0, windowBounds.right, windowBounds.bottom, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, imageData); (**myPixMap).baseAddr = imageData; (**myPixMap).rowBytes = ((windowBounds.right * 4) | (1 << 15)); (**myPixMap).bounds = windowBounds; (**myPixMap).pmVersion = 0; (**myPixMap).packType = 0; (**myPixMap).packSize = 0; (**myPixMap).hRes = (72 << 16); /* hRes is a Fixed */ (**myPixMap).vRes = (72 << 16); /* vRes is a Fixed */ (**myPixMap).pixelType = RGBDirect; (**myPixMap).pixelSize = 32; (**myPixMap).cmpCount = 3; /* RGB, ignore Alpha */ (**myPixMap).cmpSize = 8; (**myPixMap).pixelFormat = 0; (**myPixMap).pmExt = 0; (**myPixMap).pmTable = GetCTable(72); /* Unnecessary? */ GetGWorld(&origGWorld, &origGDev); SetPortWindowPort(w->TheWindow); srcRect = destRect = windowBounds; /* Since glReadPixels will give us an upside-down image, copy one row at a time. Not the most efficient way to do it, but it works well enough. */ for (currentRow = 0; currentRow < windowBounds.bottom; currentRow++) { srcRect.bottom = (windowBounds.bottom - currentRow); srcRect.top = (srcRect.bottom - 1); destRect.top = currentRow; destRect.bottom = (currentRow + 1); CopyBits((BitMap *) *myPixMap, GetPortBitMapForCopyBits(GetWindowPort(w->TheWindow)), &srcRect, &destRect, srcCopy, NULL); } /* Make sure the image shows up */ QDFlushPortBuffer(GetWindowPort(w->TheWindow), NULL); SetGWorld(origGWorld, origGDev); DisposePixMap(myPixMap); DisposePtr(imageData); } return eventNotHandledErr; } static pascal OSStatus WindowExpanding(EventHandlerCallRef nextEvent, EventRef theEvent, void * userData) { #pragma unused(nextEvent, theEvent) VWindow * w; w = (VWindow *) userData; w->isMinimized = 0; return eventNotHandledErr; } void InitWindow(VWindow * w) { GDHandle mainDevice; Point screenSize; Rect Bounds; EventTypeSpec eventType; mainDevice = GetMainDevice(); screenSize.h = (**mainDevice).gdRect.right; screenSize.v = (**mainDevice).gdRect.bottom; /* This will center the window onscreen. */ SetRect(&Bounds, ((screenSize.h / 2) - WINDOWH/2), ((screenSize.v / 2) - WINDOWV/2), ((screenSize.h / 2) + WINDOWH/2), ((screenSize.v / 2) + WINDOWV/2)); CreateNewWindow(kDocumentWindowClass, kWindowCloseBoxAttribute + kWindowCollapseBoxAttribute, &Bounds, &w->TheWindow); SetWindowTitleWithCFString(w->TheWindow, CFSTR("Vectorized")); InstallStandardEventHandler(GetWindowEventTarget(w->TheWindow)); eventType.eventClass = kEventClassWindow; eventType.eventKind = kEventWindowClosed; InstallWindowEventHandler(w->TheWindow, NewEventHandlerUPP(WindowWasClosed), 1, &eventType, w, NULL); eventType.eventClass = kEventClassWindow; eventType.eventKind = kEventWindowCollapsing; InstallWindowEventHandler(w->TheWindow, NewEventHandlerUPP(WindowCollapsing), 1, &eventType, w, NULL); eventType.eventClass = kEventClassWindow; eventType.eventKind = kEventWindowExpanding; InstallWindowEventHandler(w->TheWindow, NewEventHandlerUPP(WindowExpanding), 1, &eventType, w, NULL); TransWindow(w->TheWindow, true); InitWindowContext(w); w->quitOnClose = 0; w->isMinimized = 0; } void CleanUpWindow(VWindow * w) { TransWindow(w->TheWindow, false); if(w->FullScreen) { aglSetCurrentContext(NULL); aglSetDrawable(w->FullScreen, NULL); aglDestroyContext(w->FullScreen); w->FullScreen = NULL; } if(w->Windowed) { aglSetCurrentContext(NULL); aglSetDrawable(w->Windowed, NULL); aglDestroyContext(w->Windowed); w->Windowed = NULL; } DisposeWindow(w->TheWindow); w->TheWindow = NULL; }