Beispiel #1
0
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;
}
Beispiel #2
0
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);
}
Beispiel #3
0
	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;
	}
Beispiel #4
0
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;
}
Beispiel #5
0
	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;
	}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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);
}
Beispiel #9
0
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);
}
Beispiel #10
0
	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;	
	}
Beispiel #11
0
// 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;
}
Beispiel #12
0
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];
}
Beispiel #13
0
	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;
	}
Beispiel #14
0
// 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);
}
Beispiel #15
0
	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;
	}
Beispiel #16
0
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()));
}
Beispiel #17
0
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);
	}
Beispiel #18
0
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;
}
Beispiel #19
0
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);

}
Beispiel #20
0
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);
}
Beispiel #21
0
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);
}
Beispiel #22
0
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);
}
Beispiel #23
0
// 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;
}