static bool testtilecache_sprite_renderer(void *p_context, MCContext *p_target, const MCRectangle& p_rectangle) { MCControl *t_control; t_control = (MCControl *)p_context; // A scrolling layer is an unadorned group. bool t_scrolling; t_scrolling = t_control -> layer_isscrolling(); MCRectangle t_control_rect, t_dirty_rect; if (!t_scrolling) { t_control_rect = t_control -> geteffectiverect(); t_dirty_rect = MCU_intersect_rect(t_control_rect, MCU_offset_rect(p_rectangle, t_control_rect . x, t_control_rect . y)); } else { t_control_rect = t_control -> layer_getcontentrect(); t_dirty_rect = MCU_intersect_rect(t_control_rect, MCU_offset_rect(p_rectangle, t_control_rect . x, t_control_rect . y)); } if (MCU_empty_rect(t_dirty_rect)) return true; p_target -> setorigin(t_control_rect . x + p_rectangle . x, t_control_rect . y + p_rectangle . y); p_target -> setclip(t_dirty_rect); p_target -> setfunction(GXcopy); p_target -> setopacity(255); t_control -> draw(p_target, t_dirty_rect, false, true); return true; }
void MCStack::view_update_transform(void) { MCRectangle t_view_rect; MCGAffineTransform t_transform; // IM-2014-01-16: [[ StackScale ]] Use utility method to calculate new values view_calculate_viewports(m_view_requested_stack_rect, m_view_adjusted_stack_rect, t_view_rect, t_transform); // IM-2013-12-20: [[ ShowAll ]] Calculate new stack visible rect MCRectangle t_stack_visible_rect; t_stack_visible_rect = MCRectangleGetTransformedBounds(MCRectangleMake(0, 0, t_view_rect.width, t_view_rect.height), MCGAffineTransformInvert(t_transform)); if (m_view_fullscreenmode == kMCStackFullscreenLetterbox || m_view_fullscreenmode == kMCStackFullscreenNoScale) t_stack_visible_rect = MCU_intersect_rect(t_stack_visible_rect, MCRectangleMake(0, 0, m_view_adjusted_stack_rect.width, m_view_adjusted_stack_rect.height)); // IM-2013-10-03: [[ FullscreenMode ]] if the transform has changed, redraw everything // IM-2013-12-20: [[ ShowAll ]] if the stack viewport has changed, redraw everything if (!MCU_equal_rect(t_stack_visible_rect, m_view_stack_visible_rect) || !MCGAffineTransformIsEqual(t_transform, m_view_transform)) { m_view_transform = t_transform; m_view_stack_visible_rect = t_stack_visible_rect; view_dirty_all(); } // IM-2014-01-16: [[ StackScale ]] Update view rect if needed view_setrect(t_view_rect); }
bool LockGraphics(MCRegionRef p_area, MCContext*& r_context) { MCRectangle t_actual_area; t_actual_area = MCU_intersect_rect(MCRegionGetBoundingBox(p_area), MCRegionGetBoundingBox(m_region)); if (MCU_empty_rect(t_actual_area)) return false; m_locked_pixmap = MCscreen -> createpixmap(t_actual_area . width, t_actual_area . height, 0, False); if (m_locked_pixmap != nil) { m_locked_context = MCscreen -> createcontext(m_locked_pixmap, False, False); if (m_locked_context != nil) { m_locked_context -> setorigin(t_actual_area . x, t_actual_area . y); m_locked_context -> setclip(t_actual_area); m_locked_area = t_actual_area; r_context = m_locked_context; return true; } MCscreen -> freepixmap(m_locked_pixmap); } return false; }
bool MCTileCacheSoftwareCompositor_CompositeRect(void *p_context, int32_t p_x, int32_t p_y, uint32_t p_color) { MCTileCacheSoftwareCompositorContext *self; self = (MCTileCacheSoftwareCompositorContext *)p_context; if (self -> tile_row == nil && !MCMemoryAllocate(self -> tile_size * sizeof(uint32_t), self -> tile_row)) return false; if (self -> tile_row_color != p_color) { for(int32_t i = 0; i < self -> tile_size; i++) self -> tile_row[i] = p_color; self -> tile_row_color = p_color; } MCRectangle t_dst_rect; t_dst_rect . x = p_x; t_dst_rect . y = p_y; t_dst_rect . width = self -> tile_size; t_dst_rect . height = self -> tile_size; t_dst_rect = MCU_intersect_rect(t_dst_rect, self -> clip); void *t_dst_ptr; t_dst_ptr = (uint8_t *)self -> bits + self -> stride * (t_dst_rect . y - self -> dirty . y) + (t_dst_rect . x - self -> dirty . x) * sizeof(uint32_t); for(uint32_t y = 0; y < t_dst_rect . height; y++) self -> combiner((uint8_t *)t_dst_ptr + y * self -> stride, self -> stride, self -> tile_row, self -> tile_size * sizeof(uint32_t), t_dst_rect . width, 1, self -> opacity); return true; }
bool LockPixels(MCRegionRef p_area, MCGRaster& r_raster) { if (m_bitmap == nil || m_locked) return false; MCRectangle t_bounds = MCRegionGetBoundingBox(m_region); MCRectangle t_actual_area; t_actual_area = MCU_intersect_rect(MCRegionGetBoundingBox(p_area), t_bounds); if (MCU_empty_rect(t_actual_area)) return false; /* UNCHECKED */ MCRegionIncludeRect(m_redraw_region, t_actual_area); uint8_t *t_bits = (uint8_t*)m_raster.pixels + (t_actual_area.y - t_bounds.y) * m_raster.stride + (t_actual_area.x - t_bounds.x) * sizeof(uint32_t); m_locked_area = t_actual_area; r_raster . format = kMCGRasterFormat_ARGB; r_raster . width = t_actual_area . width; r_raster . height = t_actual_area . height; r_raster . stride = m_raster.stride; r_raster . pixels = t_bits; m_locked = true; return true; }
static bool testtilecache_scenery_renderer(void *p_context, MCContext *p_target, const MCRectangle& p_rectangle) { MCControl *t_control; t_control = (MCControl *)p_context; // Don't render anything if the control is invisible. if (!t_control -> getflag(F_VISIBLE) && !MCshowinvisibles) return true; MCRectangle t_control_rect; t_control_rect = t_control -> geteffectiverect(); MCRectangle t_dirty_rect; t_dirty_rect = MCU_intersect_rect(t_control_rect, p_rectangle); if (MCU_empty_rect(t_dirty_rect)) return true; p_target -> setclip(t_dirty_rect); p_target -> setfunction(GXcopy); p_target -> setopacity(255); t_control -> draw(p_target, t_dirty_rect, false, false); return true; }
bool MCTileCacheSoftwareCompositor_BeginLayer(void *p_context, const MCRectangle& p_clip, uint32_t p_opacity, uint32_t p_ink) { MCTileCacheSoftwareCompositorContext *self; self = (MCTileCacheSoftwareCompositorContext *)p_context; self -> clip = MCU_intersect_rect(self -> dirty, p_clip); self -> opacity = p_opacity; self -> combiner = s_surface_combiners_nda[p_ink]; return true; }
bool MCStack::view_snapshottilecache(const MCRectangle &p_stack_rect, MCGImageRef &r_image) { if (m_view_tilecache == nil) return false; // MW-2013-10-29: [[ Bug 11330 ]] Transform stack to (local) view co-ords. MCRectangle t_view_rect; t_view_rect = MCRectangleGetTransformedBounds(p_stack_rect, getviewtransform()); t_view_rect = MCU_intersect_rect(t_view_rect, MCU_make_rect(0, 0, view_getrect() . width, view_getrect() . height)); // IM-2014-01-24: [[ HiDPI ]] use backing surface coords for tilecache operations MCRectangle t_device_rect; t_device_rect = MCRectangleGetScaledBounds(t_view_rect, view_getbackingscale()); return MCTileCacheSnapshot(m_view_tilecache, t_device_rect, r_image); }
void MCNativeLayerX11::updateContainerGeometry() { m_intersect_rect = MCU_intersect_rect(m_viewport_rect, m_rect); // Clear any minimum size parameters for the GTK widgets gtk_widget_set_size_request(GTK_WIDGET(m_child_window), -1, -1); // Resize by adjusting the widget's containing GtkWindow gdk_window_move_resize(gtk_widget_get_window(GTK_WIDGET(m_child_window)), m_intersect_rect.x, m_intersect_rect.y, m_intersect_rect.width, m_intersect_rect.height); // We need to set the requested minimum size in order to get in-process GTK // widgets to re-size automatically. Unfortunately, that is the only widget // category that this works for... others need to do it themselves. gtk_widget_set_size_request(GTK_WIDGET(m_child_window), m_intersect_rect.width, m_intersect_rect.height); }
bool LockPixmap(MCRegionRef p_area, Pixmap& r_pixmap) { MCRectangle t_actual_area; t_actual_area = MCU_intersect_rect(MCRegionGetBoundingBox(p_area), MCRegionGetBoundingBox(m_region)); if (MCU_empty_rect(t_actual_area)) return false; m_locked_pixmap = MCscreen -> createpixmap(t_actual_area . width, t_actual_area . height, 0, False); if (m_locked_pixmap == nil) return false; m_locked_area = t_actual_area; r_pixmap = m_locked_pixmap; return true; }
// IM-2014-01-29: [[ HiDPI ]] Apply screen workarea to given MCDisplay array bool MCScreenDC::apply_workarea(MCDisplay *p_displays, uint32_t p_display_count) { bool t_success; t_success = true; MCRectangle t_workarea; t_success = MCX11GetWindowWorkarea(dpy, getroot(), t_workarea); if (t_success) { for (uint32_t i = 0; i < p_display_count; i++) p_displays[i].workarea = MCU_intersect_rect(t_workarea, p_displays[i].viewport); } return t_success; }
const MCDisplay *MCUIDC::device_getnearestdisplay(const MCRectangle& p_rectangle) { MCDisplay const *t_displays; uint4 t_display_count; uint4 t_home; uint4 t_max_area, t_max_distance; uint4 t_max_area_index, t_max_distance_index; t_display_count = MCscreen -> getdisplays(t_displays, false); t_max_area = 0; t_max_distance = MAXUINT4; for(uint4 t_display = 0; t_display < t_display_count; ++t_display) { MCRectangle t_workarea; t_workarea = t_displays[t_display] . device_workarea; MCRectangle t_intersection; uint4 t_area, t_distance; t_intersection = MCU_intersect_rect(p_rectangle, t_workarea); t_area = t_intersection . width * t_intersection . height; uint4 t_dx, t_dy; t_dx = (t_workarea . x + t_workarea . width / 2) - (p_rectangle . x + p_rectangle . width / 2); t_dy = (t_workarea . y + t_workarea . height / 2) - (p_rectangle . y + p_rectangle . height / 2); t_distance = t_dx * t_dx + t_dy * t_dy; if (t_area > t_max_area) { t_max_area = t_area; t_max_area_index = t_display; } if (t_distance < t_max_distance) { t_max_distance = t_distance; t_max_distance_index = t_display; } } if (t_max_area == 0) t_home = t_max_distance_index; else t_home = t_max_area_index; return &t_displays[t_home]; }
bool LockPixels(MCRegionRef p_area, MCGRaster &r_raster) { m_locked_bits = m_raster.pixels; m_locked_stride = m_raster.stride; m_locked_area = MCRegionGetBoundingBox(p_area); // restrict locked area to intersection with raster m_locked_area = MCU_intersect_rect(m_locked_area, MCU_make_rect(0, 0, m_raster.width, m_raster.height)); /* UNCHECKED */ MCRegionIncludeRect(m_redraw_region, m_locked_area); r_raster.width = m_locked_area.width; r_raster.height = m_locked_area.height; r_raster.pixels = (uint8_t *)m_locked_bits + m_locked_area . y * m_locked_stride + m_locked_area . x * sizeof(uint32_t); r_raster.stride = m_locked_stride; r_raster.format = m_raster.format; return true; }
// IM-2013-10-14: [[ FullscreenMode ]] Move update region tracking into view abstraction void MCStack::view_dirty_rect(const MCRectangle &p_rect) { MCRectangle t_visible_rect = MCRectangleGetTransformedBounds(view_getstackvisiblerect(), view_getviewtransform()); MCRectangle t_dirty_rect = MCU_intersect_rect(p_rect, t_visible_rect); if (t_dirty_rect.width == 0 || t_dirty_rect.height == 0) return; // If there is no region yet, make one. if (m_view_update_region == nil) /* UNCHECKED */ MCRegionCreate(m_view_update_region); MCRegionIncludeRect(m_view_update_region, t_dirty_rect); // Mark the stack as needing a redraw and schedule an update. m_view_need_redraw = true; MCRedrawScheduleUpdateForStack(this); }
bool LockPixels(MCRegionRef p_area, void*& r_bits, uint32_t& r_stride) { MCRectangle t_actual_area; t_actual_area = MCU_intersect_rect(MCRegionGetBoundingBox(p_area), MCRegionGetBoundingBox(m_region)); if (MCU_empty_rect(t_actual_area)) return false; m_locked_bits = malloc(t_actual_area . width * t_actual_area . height * sizeof(uint32_t)); if (m_locked_bits != nil) { m_locked_area = t_actual_area; r_bits = m_locked_bits; r_stride = t_actual_area . width * sizeof(uint32_t); return true; } return false; }
void MCControl::layer_dirtycontentrect(const MCRectangle& p_updated_rect, bool p_update_card) { if (MCU_empty_rect(p_updated_rect)) return; MCRectangle t_content_rect; t_content_rect = layer_getcontentrect(); MCTileCacheRef t_tilecache; t_tilecache = getstack() -> gettilecache(); // Note that this method is only called if layer_isscrolling() is true, which is only // possible if we have a tilecache. if (m_layer_id != 0) MCTileCacheUpdateSprite(t_tilecache, m_layer_id, MCU_offset_rect(p_updated_rect, -t_content_rect . x, -t_content_rect . y)); // Add the rect to the update region - but only if instructed (update_card will be // false if the object was invisible). if (p_update_card) static_cast<MCCard *>(parent) -> layer_dirtyrect(MCU_intersect_rect(p_updated_rect, geteffectiverect())); }
void MCStack::view_render(MCGContextRef p_target, MCRectangle p_rect) { if (getextendedstate(ECS_DONTDRAW)) return; // redraw borders if visible // scale & position stack redraw rect // update stack region // IM-2014-01-16: [[ StackScale ]] Transform redraw rect to stack coords in all cases MCRectangle t_update_rect; t_update_rect = MCRectangleGetTransformedBounds(p_rect, MCGAffineTransformInvert(m_view_transform)); MCGContextSave(p_target); MCGContextConcatCTM(p_target, m_view_transform); if (view_getfullscreen()) { // IM-2013-12-19: [[ ShowAll ]] Check if the view background needs to be drawn // IM-2013-12-20: [[ ShowAll ]] Draw the stack into its viewport if (!MCU_rect_in_rect(t_update_rect, m_view_stack_visible_rect)) { // IM-2013-10-08: [[ FullscreenMode ]] draw the view backdrop if the render area // falls outside the stack rect /* OVERHAUL - REVISIT: currently just draws black behind the stack area */ MCGContextAddRectangle(p_target, MCRectangleToMCGRectangle(t_update_rect)); MCGContextSetFillRGBAColor(p_target, 0.0, 0.0, 0.0, 1.0); MCGContextFill(p_target); } t_update_rect = MCU_intersect_rect(t_update_rect, m_view_stack_visible_rect); MCGContextClipToRect(p_target, MCRectangleToMCGRectangle(t_update_rect)); } render(p_target, t_update_rect); MCGContextRestore(p_target); }
bool MCTileCacheSoftwareCompositor_CompositeTile(void *p_context, int32_t p_x, int32_t p_y, void *p_tile) { MCTileCacheSoftwareCompositorContext *self; self = (MCTileCacheSoftwareCompositorContext *)p_context; MCRectangle t_dst_rect; t_dst_rect . x = p_x; t_dst_rect . y = p_y; t_dst_rect . width = self -> tile_size; t_dst_rect . height = self -> tile_size; t_dst_rect = MCU_intersect_rect(t_dst_rect, self -> clip); MCRectangle t_src_rect; t_src_rect = MCU_offset_rect(t_dst_rect, -p_x, -p_y); void *t_dst_ptr, *t_src_ptr; t_dst_ptr = (uint8_t *)self -> bits + self -> stride * (t_dst_rect . y - self -> dirty . y) + (t_dst_rect . x - self -> dirty . x) * sizeof(uint32_t); t_src_ptr = (uint32_t *)p_tile + self -> tile_size * t_src_rect . y + t_src_rect . x; self -> combiner(t_dst_ptr, self -> stride, t_src_ptr, self -> tile_size * sizeof(uint32_t), t_src_rect . width, t_src_rect . height, self -> opacity); return true; }
void MCStack::constrain(intptr_t lp) { uint32_t wstyle, exstyle; getstyle(wstyle, exstyle); RECT wrect = getwrect(rect, wstyle, exstyle); int4 dx = wrect.right - wrect.left - rect.width; int4 dy = wrect.bottom - wrect.top - rect.height; LPMINMAXINFO mmptr = (LPMINMAXINFO)lp; const MCDisplay *t_display; t_display = MCscreen -> getnearestdisplay(rect); if (mode < WM_MODAL) { MCRectangle t_workarea, t_viewport; if (MCU_point_in_rect(t_display -> workarea, MCwbr . x, MCwbr . y)) t_workarea = MCU_intersect_rect(MCwbr, t_display -> workarea); else t_workarea = t_display -> workarea; t_viewport = t_display -> viewport; if (memcmp(&t_workarea, &t_display -> workarea, sizeof(MCRectangle))) MCU_reduce_rect(t_workarea, -dx / 2); mmptr -> ptMaxSize . x = MCU_min(maxwidth + dx, t_workarea . width); mmptr -> ptMaxSize . y = MCU_min(maxheight + dy, t_workarea . height); mmptr -> ptMaxPosition . x = t_workarea . x - t_viewport . x; mmptr -> ptMaxPosition . y = t_workarea . y - t_viewport . y; } // MW-2007-07-27: In Windows 98 we need to clamp to 32767... mmptr -> ptMinTrackSize . x = minwidth + dx; mmptr -> ptMinTrackSize . y = minheight + dy; mmptr -> ptMaxTrackSize . x = MCU_min(32767, maxwidth + dx); mmptr -> ptMaxTrackSize . y = MCU_min(32767, maxheight + dy); }
void MCControl::layer_dirtyeffectiverect(const MCRectangle& p_effective_rect, bool p_update_card) { // The dirty rect will be the input effective rect expanded by any effects // applied by the parent groups (if any). MCRectangle t_dirty_rect; t_dirty_rect = p_effective_rect; // Expand the effective rect by that of all parent groups. MCControl *t_control; t_control = this; while(t_control -> parent -> gettype() == CT_GROUP) { MCControl *t_parent_control; t_parent_control = static_cast<MCControl *>(t_control -> parent); // If the parent control is scrolling, we are done - defer to content // dirtying. if (t_parent_control -> layer_isscrolling()) { t_parent_control -> layer_dirtycontentrect(t_dirty_rect, p_update_card); return; } // Otherwise intersect the dirty rect with the parent's rect. t_dirty_rect = MCU_intersect_rect(t_dirty_rect, t_control -> parent -> getrect()); // Expand due to bitmap effects (if any). if (t_parent_control -> m_bitmap_effects != nil) MCBitmapEffectsComputeBounds(t_parent_control -> m_bitmap_effects, t_dirty_rect, t_dirty_rect); t_control = t_parent_control; } // Fetch the tilecache we are using (if any). MCTileCacheRef t_tilecache; t_tilecache = t_control -> getstack() -> gettilecache(); // Notify any tilecache of the changes. if (t_tilecache != nil) { // We must be in tile-cache mode with a top-level control, but if the layer // id is zero, there is nothing to do. if (t_control -> m_layer_id == 0) return; // How we handle the layer depends on whether it is a sprite or not. if (!t_control -> layer_issprite()) { // Non-dynamic layers are scenery in the tilecache, their rect is in // canvas co-ords. MCTileCacheUpdateScenery(t_tilecache, t_control -> m_layer_id, t_dirty_rect); } else { // Dynamic layers are sprites in the tilecache, their rect is in // sprite co-ords. MCTileCacheUpdateSprite(t_tilecache, t_control -> m_layer_id, MCU_offset_rect(t_dirty_rect, -t_control -> rect . x, -t_control -> rect . y)); } } // Add the rect to the update region - but only if instructed (update_card will be // false if the object was invisible). if (p_update_card) static_cast<MCCard *>(t_control -> parent) -> layer_dirtyrect(t_dirty_rect); }
void MCStack::effectrect(const MCRectangle& p_area, Boolean& r_abort) { // Get the list of effects. MCEffectList *t_effects = MCcur_effects; MCcur_effects = NULL; // If the window isn't opened or hasn't been attached (plugin) or if we have no // snapshot to use, this is a no-op. if (!opened || !haswindow() || m_snapshot == nil) { while(t_effects != NULL) { MCEffectList *t_effect; t_effect = t_effects; t_effects = t_effects -> next; delete t_effect; } return; } // Mark the stack as being in an effect. state |= CS_EFFECT; // Lock messages while the effect is happening. Boolean t_old_lockmessages; t_old_lockmessages = MClockmessages; MClockmessages = True; // Calculate the area of interest. MCRectangle t_effect_area; t_effect_area = curcard -> getrect(); t_effect_area . y = getscroll(); t_effect_area . height -= t_effect_area . y; t_effect_area = MCU_intersect_rect(t_effect_area, p_area); // IM-2013-08-21: [[ ResIndependence ]] Scale effect area to device coords // Align snapshot rect to device pixels // IM-2013-09-30: [[ FullscreenMode ]] Use stack transform to get device coords MCGAffineTransform t_transform; t_transform = getdevicetransform(); // MW-2013-10-29: [[ Bug 11330 ]] Make sure the effect area is cropped to the visible // area. t_effect_area = MCRectangleGetTransformedBounds(t_effect_area, getviewtransform()); t_effect_area = MCU_intersect_rect(t_effect_area, MCU_make_rect(0, 0, view_getrect() . width, view_getrect() . height)); // IM-2014-01-24: [[ HiDPI ]] scale effect region to backing surface coords MCGFloat t_scale; t_scale = view_getbackingscale(); MCRectangle t_device_rect, t_user_rect; t_device_rect = MCRectangleGetScaledBounds(t_effect_area, t_scale); t_user_rect = MCRectangleGetTransformedBounds(t_device_rect, MCGAffineTransformInvert(t_transform)); // IM-2013-08-29: [[ RefactorGraphics ]] get device height for CoreImage effects // IM-2013-09-30: [[ FullscreenMode ]] Use view rect to get device height uint32_t t_device_height; t_device_height = floor(view_getrect().height * t_scale); // Make a region of the effect area // IM-2013-08-29: [[ ResIndependence ]] scale effect region to device coords MCRegionRef t_effect_region; t_effect_region = nil; /* UNCHECKED */ MCRegionCreate(t_effect_region); /* UNCHECKED */ MCRegionSetRect(t_effect_region, t_effect_area); #ifndef FEATURE_PLATFORM_PLAYER #if defined(FEATURE_QUICKTIME) // MW-2010-07-07: Make sure QT is only loaded if we actually are doing an effect if (t_effects != nil) if (!MCdontuseQTeffects) if (!MCtemplateplayer -> isQTinitted()) MCtemplateplayer -> initqt(); #endif #endif // Lock the screen to prevent any updates occuring until we want them. MCRedrawLockScreen(); // By default, we have not aborted. r_abort = False; MCGImageRef t_initial_image; t_initial_image = MCGImageRetain(m_snapshot); while(t_effects != nil) { uint32_t t_duration; t_duration = MCU_max(1, MCeffectrate / (t_effects -> speed - VE_VERY)); if (t_effects -> type == VE_DISSOLVE) t_duration *= 2; uint32_t t_delta; t_delta = 0; // Create surface at effect_area size. // Render into surface based on t_effects -> image MCGImageRef t_final_image = nil; // If this isn't a plain effect, then we must fetch first and last images. if (t_effects -> type != VE_PLAIN) { // Render the final image. MCGContextRef t_context = nil; // IM-2014-05-20: [[ GraphicsPerformance ]] Create opaque context for snapshot /* UNCHECKED */ MCGContextCreate(t_device_rect.width, t_device_rect.height, false, t_context); MCGContextTranslateCTM(t_context, -t_device_rect.x, -t_device_rect.y); // IM-2013-10-03: [[ FullscreenMode ]] Apply device transform to context MCGContextConcatCTM(t_context, t_transform); // Configure the context. MCGContextClipToRect(t_context, MCRectangleToMCGRectangle(t_user_rect)); // Render an appropriate image switch(t_effects -> image) { case VE_INVERSE: { MCContext *t_old_context = nil; /* UNCHECKED */ t_old_context = new MCGraphicsContext(t_context); curcard->draw(t_old_context, t_user_rect, false); delete t_old_context; MCGContextSetFillRGBAColor(t_context, 1.0, 1.0, 1.0, 1.0); MCGContextSetBlendMode(t_context, kMCGBlendModeDifference); MCGContextAddRectangle(t_context, MCRectangleToMCGRectangle(t_user_rect)); MCGContextFill(t_context); } break; case VE_BLACK: MCGContextSetFillRGBAColor(t_context, 0.0, 0.0, 0.0, 1.0); MCGContextAddRectangle(t_context, MCRectangleToMCGRectangle(t_user_rect)); MCGContextFill(t_context); break; case VE_WHITE: MCGContextSetFillRGBAColor(t_context, 1.0, 1.0, 1.0, 1.0); MCGContextAddRectangle(t_context, MCRectangleToMCGRectangle(t_user_rect)); MCGContextFill(t_context); break; case VE_GRAY: MCGContextSetFillRGBAColor(t_context, 0.5, 0.5, 0.5, 1.0); MCGContextAddRectangle(t_context, MCRectangleToMCGRectangle(t_user_rect)); MCGContextFill(t_context); break; default: { MCContext *t_old_context = nil; /* UNCHECKED */ t_old_context = new MCGraphicsContext(t_context); curcard->draw(t_old_context, t_user_rect, false); delete t_old_context; } } /* UNCHECKED */ MCGContextCopyImage(t_context, t_final_image); MCGContextRelease(t_context); } MCStackEffectContext t_context; t_context.delta = t_delta; t_context.duration = t_duration; t_context.effect = t_effects; t_context.effect_area = t_device_rect; t_context.initial_image = t_initial_image; t_context.final_image = t_final_image; // MW-2011-10-20: [[ Bug 9824 ]] Make sure dst point is correct. // Initialize the destination with the start image. view_platform_updatewindowwithcallback(t_effect_region, MCStackRenderInitial, &t_context); // If there is a sound, then start playing it. if (t_effects -> sound != NULL) { MCAudioClip *acptr; MCNewAutoNameRef t_sound; /* UNCHECKED */ MCNameCreate(t_effects->sound, &t_sound); if ((acptr = (MCAudioClip *)getobjname(CT_AUDIO_CLIP, *t_sound)) == NULL) { IO_handle stream; if ((stream = MCS_open(t_effects->sound, kMCOpenFileModeRead, True, False, 0)) != NULL) { acptr = new MCAudioClip; acptr->setdisposable(); if (!acptr->import(t_effects->sound, stream)) { delete acptr; acptr = NULL; } MCS_close(stream); } } if (acptr != NULL) { MCU_play_stop(); MCacptr = acptr; MCU_play(); #ifndef FEATURE_PLATFORM_AUDIO if (MCacptr != NULL) MCscreen->addtimer(MCacptr, MCM_internal, PLAY_RATE); #endif } if (MCscreen->wait((real8)MCsyncrate / 1000.0, False, True)) { r_abort = True; break; } } // Initialize CoreImage of QTEffects if needed. if (t_effects -> type != VE_PLAIN) { MCAutoPointer<char> t_name; /* UNCHECKED */ MCStringConvertToCString(t_effects -> name, &t_name); #ifdef _MAC_DESKTOP // IM-2013-08-29: [[ ResIndependence ]] use scaled effect rect for CI effects if (t_effects -> type == VE_UNDEFINED && MCCoreImageEffectBegin(*t_name, t_initial_image, t_final_image, t_device_rect, t_device_height, t_effects -> arguments)) t_effects -> type = VE_CIEFFECT; else #endif #ifdef FEATURE_QUICKTIME_EFFECTS // IM-2013-08-29: [[ ResIndependence ]] use scaled effect rect for QT effects if (t_effects -> type == VE_UNDEFINED && MCQTEffectBegin(t_effects -> type, *t_name, t_effects -> direction, t_initial_image, t_final_image, t_device_rect)) t_effects -> type = VE_QTEFFECT; #else ; #endif } // Run effect // Now perform the effect loop, but only if there is something to do. if (t_effects -> type != VE_PLAIN || old_blendlevel != blendlevel) { // Calculate timing parameters. double t_start_time; t_start_time = 0.0; for(;;) { t_context.delta = t_delta; Boolean t_drawn = False; view_platform_updatewindowwithcallback(t_effect_region, MCStackRenderEffect, &t_context); // Now redraw the window with the new image. // if (t_drawn) { MCscreen -> sync(getw()); } // Update the window's blendlevel (if needed) if (old_blendlevel != blendlevel) { float t_fraction = float(t_delta) / t_duration; setopacity(uint1((old_blendlevel * 255 + (float(blendlevel) - old_blendlevel) * 255 * t_fraction) / 100)); } // If the start time is zero, then start counting from here. if (t_start_time == 0.0) t_start_time = MCS_time(); // If we've reached the end of the transition, we are done. if (t_delta == t_duration) { #ifdef _ANDROID_MOBILE // MW-2011-12-12: [[ Bug 9907 ]] Make sure we let the screen sync at this point MCscreen -> wait(0.01, False, False); #endif break; } // Get the time now. double t_now; t_now = MCS_time(); // Compute the new delta value. uint32_t t_new_delta; t_new_delta = (uint32_t)ceil((t_now - t_start_time) * 1000.0); // If the new value is same as the old, then advance one step. if (t_new_delta == t_delta) t_delta = t_new_delta + 1; else t_delta = t_new_delta; // If the new delta is beyond the end point, set it to the end. if (t_delta > t_duration) t_delta = t_duration; // Wait until the next boundary, making sure we break for no reason // other than abort. if (MCscreen -> wait((t_start_time + (t_delta / 1000.0)) - t_now, False, False)) r_abort = True; // If we aborted, we render the final step and are thus done. if (r_abort) t_delta = t_duration; } } #ifdef _MAC_DESKTOP if (t_effects -> type == VE_CIEFFECT) MCCoreImageEffectEnd(); else #endif #ifdef FEATURE_QUICKTIME_EFFECTS if (t_effects -> type == VE_QTEFFECT) MCQTEffectEnd(); #endif // Free initial surface. MCGImageRelease(t_initial_image); // initial surface becomes final surface. t_initial_image = t_final_image; t_final_image = nil; // Move to the next effect. MCEffectList *t_current_effect; t_current_effect = t_effects; t_effects = t_effects -> next; delete t_current_effect; } // Make sure the pixmaps are freed and any dangling effects // are cleaned up. if (t_effects != NULL) { /* OVERHAUL - REVISIT: error cleanup needs revised */ MCGImageRelease(t_initial_image); // MCGSurfaceRelease(t_final_image); while(t_effects != NULL) { MCEffectList *t_current_effect; t_current_effect = t_effects; t_effects = t_effects -> next; delete t_current_effect; } } MCRegionDestroy(t_effect_region); MCGImageRelease(m_snapshot); m_snapshot = nil; m_snapshot = t_initial_image; // Unlock the screen. MCRedrawUnlockScreen(); // Unlock messages. MClockmessages = t_old_lockmessages; // Turn off effect mode. state &= ~CS_EFFECT; // The stack's blendlevel is now the new one. old_blendlevel = blendlevel; // Finally, mark the affected area of the stack for a redraw. dirtyrect(p_area); }
void MCStack::view_update_transform(bool p_ensure_onscreen) { MCRectangle t_view_rect; MCGAffineTransform t_transform; #if defined(_MOBILE) MCOrientation t_orientation; MCSystemGetOrientation(t_orientation); MCOrientationGetRectForOrientation(t_orientation ,m_view_requested_stack_rect); #endif // IM-2014-01-16: [[ StackScale ]] Use utility method to calculate new values view_calculate_viewports(m_view_requested_stack_rect, m_view_adjusted_stack_rect, t_view_rect, t_transform); // IM-2013-12-20: [[ ShowAll ]] Calculate new stack visible rect MCRectangle t_stack_visible_rect; t_stack_visible_rect = MCRectangleGetTransformedBounds(MCRectangleMake(0, 0, t_view_rect.width, t_view_rect.height), MCGAffineTransformInvert(t_transform)); if (m_view_fullscreenmode == kMCStackFullscreenLetterbox || m_view_fullscreenmode == kMCStackFullscreenNoScale) t_stack_visible_rect = MCU_intersect_rect(t_stack_visible_rect, MCRectangleMake(0, 0, m_view_adjusted_stack_rect.width, m_view_adjusted_stack_rect.height)); // IM-2013-10-03: [[ FullscreenMode ]] if the transform has changed, redraw everything // IM-2013-12-20: [[ ShowAll ]] if the stack viewport has changed, redraw everything bool t_rect_changed, t_transform_changed; t_rect_changed = !MCU_equal_rect(t_stack_visible_rect, m_view_stack_visible_rect); t_transform_changed = !MCGAffineTransformIsEqual(t_transform, m_view_transform); if (t_rect_changed || t_transform_changed) { m_view_transform = t_transform; m_view_stack_visible_rect = t_stack_visible_rect; dirtyall(); if (t_transform_changed) this->OnViewTransformChanged(); } // PM-2015-07-17: [[ Bug 13754 ]] Make sure stack does not disappear off screen when changing the scalefactor MCRectangle t_bounded_rect; if (p_ensure_onscreen) { // AL-2015-10-01: [[ Bug 16017 ]] Remember location of stacks on a second monitor const MCDisplay* t_nearest_display; t_nearest_display = MCscreen -> getnearestdisplay(t_view_rect); if (t_nearest_display != nil) { MCRectangle t_screen_rect; t_screen_rect = t_nearest_display -> viewport; t_bounded_rect = MCU_bound_rect(t_view_rect, t_screen_rect . x, t_screen_rect . y, t_screen_rect . width, t_screen_rect . height); } else { // In noUI mode, we don't have a nearest display. t_bounded_rect = MCU_bound_rect(t_view_rect, 0, 0, MCscreen -> getwidth(), MCscreen -> getheight()); } } else { t_bounded_rect = t_view_rect; } // IM-2014-01-16: [[ StackScale ]] Update view rect if needed view_setrect(t_bounded_rect); }
// IM-2014-01-29: [[ HiDPI ]] Apply screen struts to given MCDisplay array bool MCScreenDC::apply_partial_struts(MCDisplay *p_displays, uint32_t p_display_count) { if (MCstrutpartialatom == None || MCclientlistatom == None) return false; bool t_success = true; x11::Atom t_ret; int t_format, t_status; x11::Window *t_clients = nil; unsigned long t_client_count, t_after; x11::Atom XA_WINDOW = x11::gdk_x11_atom_to_xatom_for_display(dpy, gdk_atom_intern_static_string("WINDOW")); x11::Atom XA_CARDINAL = x11::gdk_x11_atom_to_xatom_for_display(dpy, gdk_atom_intern_static_string("CARDINAL")); t_status = x11::XGetWindowProperty(x11::gdk_x11_display_get_xdisplay(dpy), x11::gdk_x11_drawable_get_xid(getroot()), x11::gdk_x11_atom_to_xatom_for_display(dpy, MCclientlistatom), 0, -1, False,XA_WINDOW, &t_ret, &t_format, &t_client_count, &t_after, (unsigned char **)&t_clients); t_success = t_status == Success && t_ret == XA_WINDOW && t_format == 32; if (t_success) { int32_t t_screenwidth, t_screenheight; t_screenwidth = device_getwidth(); t_screenheight = device_getheight(); for (uindex_t i = 0; t_success && i < t_client_count; i++) { unsigned long t_strut_count; unsigned long *t_struts = nil; t_status = x11::XGetWindowProperty(x11::gdk_x11_display_get_xdisplay(dpy), t_clients[i], x11::gdk_x11_atom_to_xatom_for_display(dpy, MCstrutpartialatom), 0, 12, False, XA_CARDINAL, &t_ret, &t_format, &t_strut_count, &t_after, (unsigned char **)&t_struts); if (t_status == Success && t_ret == XA_CARDINAL && t_format == 32 && t_strut_count == 12) { MCRectangle t_strut_rect = {0,0,0,0}; MCRectangle t_strut_test = {0,0,0,0}; if (t_struts[0] > 0) { // LEFT t_strut_rect.x = t_struts[0]; t_strut_rect.y = 0; t_strut_rect.width = t_screenwidth - t_strut_rect.x; t_strut_rect.height = t_screenheight; t_strut_test = t_strut_rect; t_strut_test.y = t_struts[4]; t_strut_test.height = t_struts[5] - t_strut_test.y; } else if (t_struts[1] > 0) { // RIGHT t_strut_rect.x = 0; t_strut_rect.y = 0; t_strut_rect.width = t_screenwidth - t_struts[1]; t_strut_rect.height = t_screenheight; t_strut_test = t_strut_rect; t_strut_test.y = t_struts[6]; t_strut_test.height = t_struts[7] - t_strut_test.y; } else if (t_struts[2] > 0) { // TOP t_strut_rect.x = 0; t_strut_rect.y = t_struts[2]; t_strut_rect.width = t_screenwidth; t_strut_rect.height = t_screenheight - t_strut_rect.y; t_strut_test = t_strut_rect; t_strut_test.x = t_struts[8]; t_strut_test.width = t_struts[9] - t_strut_test.x; } else if (t_struts[3] > 0) { // BOTTOM t_strut_rect.x = 0; t_strut_rect.y = 0; t_strut_rect.width = t_screenwidth; t_strut_rect.height = t_screenheight - t_struts[3]; t_strut_test = t_strut_rect; t_strut_test.x = t_struts[10]; t_strut_test.width = t_struts[11] - t_strut_test.x; } for (uindex_t s = 0; s < p_display_count; s++) { MCRectangle t_workarea = p_displays[s].workarea; MCRectangle t_test = MCU_intersect_rect(t_strut_test, t_workarea); if (t_test.width != 0 && t_test.height != 0) t_workarea = MCU_intersect_rect(t_strut_rect, t_workarea); p_displays[s].workarea = t_workarea; } } if (t_struts != nil) x11::XFree(t_struts); } } if (t_clients != nil) x11::XFree(t_clients); return t_success; }