From c4842323e8771eca6526e3aa3c3f42ffa40921a5 Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 14 Sep 2009 03:52:44 +0000 Subject: [PATCH] use quartz for splash window --- direct/src/plugin/Sources.pp | 10 + direct/src/plugin/p3dOsxSplashWindow.cxx | 231 ++++++++++++++--------- direct/src/plugin/p3dOsxSplashWindow.h | 3 +- direct/src/plugin/p3dSplashWindow.cxx | 5 + direct/src/plugin_standalone/panda3d.cxx | 2 +- 5 files changed, 163 insertions(+), 88 deletions(-) diff --git a/direct/src/plugin/Sources.pp b/direct/src/plugin/Sources.pp index 84c251116a..7133d32198 100644 --- a/direct/src/plugin/Sources.pp +++ b/direct/src/plugin/Sources.pp @@ -174,4 +174,14 @@ #end static_lib_target + +#begin bin_target + #define BUILD_TARGET $[HAVE_WX] + #define USE_PACKAGES wx openssl + #define TARGET p3dcert + + #define SOURCES p3dCert.cxx +#end bin_target + + #include $[THISDIRPREFIX]p3d_plugin_config.h.pp diff --git a/direct/src/plugin/p3dOsxSplashWindow.cxx b/direct/src/plugin/p3dOsxSplashWindow.cxx index 130e6c9f60..8e28f4fad1 100644 --- a/direct/src/plugin/p3dOsxSplashWindow.cxx +++ b/direct/src/plugin/p3dOsxSplashWindow.cxx @@ -84,7 +84,7 @@ set_wparams(const P3DWindowParams &wparams) { EventHandlerRef application_event_ref_ref1; EventTypeSpec list1[] = { { kEventClassWindow, kEventWindowDrawContent }, - //{ kEventClassWindow, kEventWindowUpdate }, + { kEventClassWindow, kEventWindowBoundsChanged }, { kEventClassMouse, kEventMouseUp }, { kEventClassMouse, kEventMouseDown }, { kEventClassMouse, kEventMouseMoved }, @@ -242,96 +242,76 @@ paint_window() { } GrafPtr out_port = NULL; - GrafPtr portSave = NULL; - Boolean portChanged = false; - if (_toplevel_window != NULL) { GetPort(&out_port); } else { out_port = _wparams.get_parent_window()._port; - portChanged = QDSwapPort(out_port, &portSave); } - Rect r = { 0, 0, _win_height, _win_width }; - ClipRect(&r); - EraseRect(&r); + CGContextRef context; + OSStatus err = CreateCGContextForPort(out_port, &context); + if (err != noErr) { + nout << "Couldn't create CG context\n"; + return; + } - paint_image(out_port, _background_image); + // Adjust for any SetOrigin calls on out_port + SyncCGContextOriginWithPort(context, out_port); + + // Move the CG origin to the upper left of the port + Rect port_rect; + GetPortBounds(out_port, &port_rect); + CGContextTranslateCTM(context, 0, (float)(port_rect.bottom - port_rect.top)); + + // Flip the y axis so that positive Y points down + CGContextScaleCTM(context, 1.0, -1.0); + int width = port_rect.right - port_rect.left; + int height = port_rect.bottom - port_rect.top; + if (width != _win_width || height != _win_height) { + _win_width = width; + _win_height = height; + set_button_range(_button_ready_image); + } + + // Clear the whole region to white before beginning. + CGRect region = { { 0, 0 }, { _win_width, _win_height } }; + + // Clear the entire progress bar to white. + CGColorRef white = CGColorGetConstantColor(kCGColorWhite); + CGContextBeginPath(context); + CGContextSetFillColorWithColor(context, white); + CGContextAddRect(context, region); + CGContextFillPath(context); + + // Now paint in the image(s). + paint_image(context, _background_image); switch (_bstate) { case BS_hidden: break; case BS_ready: - paint_image(out_port, _button_ready_image); + paint_image(context, _button_ready_image); break; case BS_rollover: - if (!paint_image(out_port, _button_rollover_image)) { - paint_image(out_port, _button_ready_image); + if (!paint_image(context, _button_rollover_image)) { + paint_image(context, _button_ready_image); } break; case BS_click: - if (!paint_image(out_port, _button_click_image)) { - paint_image(out_port, _button_ready_image); + if (!paint_image(context, _button_click_image)) { + paint_image(context, _button_ready_image); } break; } // Draw the progress bar. We don't draw this bar at all unless we // have nonzero progress. - int bar_x, bar_y, bar_width, bar_height; - get_bar_placement(bar_x, bar_y, bar_width, bar_height); - if (_install_progress != 0.0) { - Rect rbar = { bar_y, bar_x, bar_y + bar_height, bar_x + bar_width }; - FrameRect(&rbar); - - int progress_width = (int)((bar_width - 2) * _install_progress); - if (progress_width != 0) { - int progress = bar_x + 1 + progress_width; - Rect rneed = { bar_y + 1, progress, bar_y + bar_height - 1, bar_x + bar_width - 1 }; - Rect rdone = { bar_y + 1, bar_x + 1, bar_y + bar_height - 1, progress }; - RGBColor blue = { 27756, 42405, 57568 }; - RGBForeColor(&blue); - PaintRect(&rdone); - EraseRect(&rneed); - } - - RGBColor black = { 0, 0, 0 }; - RGBForeColor(&black); - - if (!_install_label.empty()) { - // Now draw the install_label right above it. - TextFont(0); - TextFace(bold); - TextMode(srcOr); - TextSize(0); - - Point numer = { 1, 1 }; - Point denom = { 1, 1 }; - FontInfo font_info; - StdTxMeas(_install_label.size(), _install_label.data(), &numer, &denom, &font_info); - int ascent = font_info.ascent * numer.v / denom.v; - int descent = font_info.descent * numer.v / denom.v; - - int text_width = TextWidth(_install_label.data(), 0, _install_label.size()); - int text_x = (_win_width - text_width) / 2; - int text_y = bar_y - descent - 8; - - Rect rtext = { text_y - ascent - 2, text_x - 2, - text_y + descent + 2, text_x + text_width + 2 }; - EraseRect(&rtext); - - MoveTo(text_x, text_y); - DrawText(_install_label.data(), 0, _install_label.size()); - } - } - - if (_toplevel_window == NULL) { - if (portChanged) { - QDSwapPort(portSave, NULL); - } + paint_progress_bar(context); } + + CGContextRelease(context); } //////////////////////////////////////////////////////////////////// @@ -348,13 +328,15 @@ load_image(OsxImageData &image, const string &image_filename) { } // Now we need to copy from the RGB (or RGBA) source image into the - // BGRA target image. + // BGRA target image. We also flip the image upside-down here to + // compensate for the upside-down vertical scale on + // CGContextScaleCTM. int row_stride = image._width * image._num_channels; int new_row_stride = image._width * 4; image._raw_data = new char[new_row_stride * image._height]; for (int yi = 0; yi < image._height; ++yi) { char *dest = image._raw_data + yi * new_row_stride; - const char *source = string_data.data() + yi * row_stride; + const char *source = string_data.data() + (image._height - 1 - yi) * row_stride; if (image._num_channels == 3) { // Source is RGB. for (int xi = 0; xi < image._width; ++xi) { @@ -407,28 +389,16 @@ load_image(OsxImageData &image, const string &image_filename) { // is not defined. //////////////////////////////////////////////////////////////////// bool P3DOsxSplashWindow:: -paint_image(GrafPtr out_port, const OsxImageData &image) { +paint_image(CGContextRef context, const OsxImageData &image) { if (image._image == NULL) { return false; } - - CGContextRef context; - QDErr err = QDBeginCGContext(out_port, &context); - if (err != noErr) { - nout << "Error: QDBeginCGContext\n"; - return false; - } - - // We have to rely on the clipping rectangle having been set up - // correctly in order to get the proper location to draw the image. - // This isn't completely right, because if the image is slightly - // offscreen, the top left of the clipping rectangle will no longer - // correspond to the top left of the original image. - CGRect rect = CGContextGetClipBoundingBox(context); // Determine the relative size of image and window. int win_cx = _win_width / 2; int win_cy = _win_height / 2; + + CGRect rect = { { 0, 0 }, { 0, 0 } }; if (image._width <= _win_width && image._height <= _win_height) { // The bitmap fits within the window; center it. @@ -461,11 +431,92 @@ paint_image(GrafPtr out_port, const OsxImageData &image) { CGContextDrawImage(context, rect, image._image); - QDEndCGContext(out_port, &context); - return true; } +//////////////////////////////////////////////////////////////////// +// Function: P3DOsxSplashWindow::paint_progress_bar +// Access: Private +// Description: Draws the progress bar and the label within the +// window. +//////////////////////////////////////////////////////////////////// +void P3DOsxSplashWindow:: +paint_progress_bar(CGContextRef context) { + int bar_x, bar_y, bar_width, bar_height; + get_bar_placement(bar_x, bar_y, bar_width, bar_height); + + // We offset the bar by half a pixel, so we'll be drawing the + // one-pixel line through the middle of a pixel, and it won't try to + // antialias itself into a half-black two-pixel line. + float bar_xf = bar_x + 0.5; + float bar_yf = bar_y - 0.5; + + CGRect bar = { { bar_xf, bar_yf }, { bar_width, bar_height } }; + + // Clear the entire progress bar to white. + CGColorRef white = CGColorGetConstantColor(kCGColorWhite); + CGContextBeginPath(context); + CGContextSetFillColorWithColor(context, white); + CGContextAddRect(context, bar); + CGContextFillPath(context); + + // Draw the interior of the progress bar in blue. + int progress_width = (int)((bar_width - 2) * _install_progress); + if (progress_width != 0) { + CGRect prog = { { bar_xf, bar_yf }, { progress_width, bar_height } }; + CGColorRef blue = CGColorCreateGenericRGB(0.424, 0.647, 0.878, 1.0); + CGContextBeginPath(context); + CGContextSetFillColorWithColor(context, blue); + CGContextAddRect(context, prog); + CGContextFillPath(context); + CGColorRelease(blue); + } + + // Draw the black stroke around the progress bar. + CGColorRef black = CGColorGetConstantColor(kCGColorBlack); + CGContextBeginPath(context); + CGContextSetLineWidth(context, 1); + CGContextSetStrokeColorWithColor(context, black); + CGContextAddRect(context, bar); + CGContextStrokePath(context); + + if (!_install_label.empty()) { + // Now draw the install_label right above it. + + CGContextSetTextMatrix(context, CGContextGetCTM(context)); + + // Choose a suitable font. + float text_height = 15.0; + CGContextSelectFont(context, "Helvetica", text_height, kCGEncodingMacRoman); + + // Measure the text, for centering. + CGContextSetTextPosition(context, 0, 0); + CGContextSetTextDrawingMode(context, kCGTextInvisible); + CGContextShowText(context, _install_label.data(), _install_label.length()); + CGPoint end_point = CGContextGetTextPosition(context); + float text_width = end_point.x; + + int text_x = (_win_width - text_width) / 2; + int text_y = bar_y - text_height * 1.5; + + // Clear the rectangle behind the text to white. + CGRect text_rect = { { text_x - 2, text_y - 2 }, { text_width + 4, text_height + 4 } }; + + CGContextBeginPath(context); + CGContextAddRect(context, text_rect); + CGContextSetFillColorWithColor(context, white); + CGContextFillPath(context); + + // And finally, draw the text. + CGContextSetTextDrawingMode(context, kCGTextFill); + CGColorRef black = CGColorGetConstantColor(kCGColorBlack); + CGContextSetFillColorWithColor(context, black); + + CGContextShowTextAtPoint(context, text_x, text_y + text_height, + _install_label.data(), _install_label.length()); + } +} + //////////////////////////////////////////////////////////////////// // Function: P3DOsxSplashWindow::st_event_callback // Access: Private, Static @@ -495,6 +546,16 @@ event_callback(EventHandlerCallRef my_handler, EventRef event) { switch (the_class) { case kEventClassWindow: switch (kind) { + case kEventWindowBoundsChanged: + // If the window changes size, we have to repaint it. + refresh(); + + // We seem to get the mouse-down, but lose the mouse-up, event + // in this case, so infer it. + set_mouse_data(_mouse_x, _mouse_y, false); + result = noErr; + break; + case kEventWindowDrawContent: paint_window(); result = noErr; @@ -532,8 +593,6 @@ event_callback(EventHandlerCallRef my_handler, EventRef event) { set_mouse_data(point.h, point.v, _mouse_down); } break; - - break; } } diff --git a/direct/src/plugin/p3dOsxSplashWindow.h b/direct/src/plugin/p3dOsxSplashWindow.h index 0d977c16c6..d50b9e4b1f 100644 --- a/direct/src/plugin/p3dOsxSplashWindow.h +++ b/direct/src/plugin/p3dOsxSplashWindow.h @@ -49,7 +49,8 @@ private: class OsxImageData; void load_image(OsxImageData &image, const string &image_filename); - bool paint_image(GrafPtr out_port, const OsxImageData &image); + bool paint_image(CGContextRef context, const OsxImageData &image); + void paint_progress_bar(CGContextRef context); static pascal OSStatus st_event_callback(EventHandlerCallRef my_handler, EventRef event, diff --git a/direct/src/plugin/p3dSplashWindow.cxx b/direct/src/plugin/p3dSplashWindow.cxx index a8febdacc4..983fb911c0 100755 --- a/direct/src/plugin/p3dSplashWindow.cxx +++ b/direct/src/plugin/p3dSplashWindow.cxx @@ -431,6 +431,11 @@ set_mouse_data(int mouse_x, int mouse_y, bool mouse_down) { if (orig_bstate == BS_rollover || _button_depressed) { _button_depressed = true; bstate = BS_click; + } else { + // Otherwise, we're mousing over the button region with the + // button held down. Hmm, don't think the button should + // light up. + bstate = BS_ready; } } else { _button_depressed = false; diff --git a/direct/src/plugin_standalone/panda3d.cxx b/direct/src/plugin_standalone/panda3d.cxx index 2ff2812bde..c4ce3ae09c 100644 --- a/direct/src/plugin_standalone/panda3d.cxx +++ b/direct/src/plugin_standalone/panda3d.cxx @@ -973,7 +973,7 @@ URLGetter(P3D_instance *instance, int unique_id, HTTPClient *http = HTTPClient::get_global_ptr(); _channel = http->make_channel(false); - // _channel->set_download_throttle(true); + _channel->set_download_throttle(true); if (_post_data.empty()) { _channel->begin_get_document(_url); } else {