// IM-2014-01-16: [[ StackScale ]] Utility method to calculate new rects and view transform void MCStack::view_calculate_viewports(const MCRectangle &p_stack_rect, MCRectangle &r_adjusted_stack_rect, MCRectangle &r_view_rect, MCGAffineTransform &r_transform) { MCRectangle t_view_rect; MCGAffineTransform t_transform; t_transform = MCGAffineTransformMakeScale(m_view_content_scale, m_view_content_scale); MCRectangle t_stack_rect; // IM-2014-01-16: [[ StackScale ]] Constrain stack size within the min/max size t_stack_rect = constrainstackrect(p_stack_rect); // IM-2014-01-16: [[ StackScale ]] transform stack rect using scale factor // IM-2014-02-13: [[ StackScale ]] Use MCGRectangle to avoid resizing due to rounding errors MCGRectangle t_scaled_rect; t_scaled_rect = MCGRectangleApplyAffineTransform(MCRectangleToMCGRectangle(t_stack_rect), t_transform); t_scaled_rect = view_constrainstackviewport(t_scaled_rect); MCStackFullscreenMode t_mode; if (view_getfullscreen()) { t_mode = m_view_fullscreenmode; const MCDisplay *t_display; t_display = MCscreen -> getnearestdisplay(MCGRectangleGetIntegerInterior(t_scaled_rect)); t_view_rect = MCscreen->fullscreenrect(t_display); // IM-2013-12-19: [[ Bug 11590 ]] Removed adjustment of screen rect to 0,0 origin } else { t_mode = kMCStackFullscreenModeNone; t_view_rect = MCGRectangleGetIntegerInterior(t_scaled_rect); } // IM-2014-01-16: [[ StackScale ]] store adjusted rect in stack coords MCGRectangle t_adjusted; t_adjusted = MCGRectangleApplyAffineTransform(t_scaled_rect, MCGAffineTransformInvert(t_transform)); r_adjusted_stack_rect = MCGRectangleGetIntegerRect(t_adjusted); r_view_rect = t_view_rect; // IM-2014-01-16: [[ StackScale ]] append scale transform to fullscreenmode transform r_transform = MCGAffineTransformConcat(view_get_stack_transform(t_mode, MCGRectangleGetIntegerBounds(t_scaled_rect), t_view_rect), t_transform); }
MCGAffineTransform view_get_stack_transform(MCStackFullscreenMode p_mode, MCRectangle p_stack_rect, MCRectangle p_screen_rect) { MCGFloat t_scale; MCGAffineTransform t_transform; switch (p_mode) { case kMCStackFullscreenModeNone: return MCGAffineTransformMakeIdentity(); case kMCStackFullscreenResize: return MCGAffineTransformMakeIdentity(); case kMCStackFullscreenExactFit: return MCGAffineTransformMakeScale((MCGFloat)p_screen_rect.width / (MCGFloat)p_stack_rect.width, (MCGFloat)p_screen_rect.height / (MCGFloat)p_stack_rect.height); case kMCStackFullscreenLetterbox: case kMCStackFullscreenShowAll: t_scale = MCMin((MCGFloat)p_screen_rect.width / (MCGFloat)p_stack_rect.width, (MCGFloat)p_screen_rect.height / (MCGFloat)p_stack_rect.height); t_transform = MCGAffineTransformMakeTranslation(-(MCGFloat)p_stack_rect.width / 2.0, -(MCGFloat)p_stack_rect.height / 2.0); t_transform = MCGAffineTransformPreScale(t_transform, t_scale, t_scale); t_transform = MCGAffineTransformPreTranslate(t_transform, (MCGFloat)p_screen_rect.width / 2.0, (MCGFloat)p_screen_rect.height / 2.0); return t_transform; case kMCStackFullscreenNoBorder: t_scale = MCMax((MCGFloat)p_screen_rect.width / (MCGFloat)p_stack_rect.width, (MCGFloat)p_screen_rect.height / (MCGFloat)p_stack_rect.height); t_transform = MCGAffineTransformMakeTranslation(-(MCGFloat)p_stack_rect.width / 2.0, -(MCGFloat)p_stack_rect.height / 2.0); t_transform = MCGAffineTransformPreScale(t_transform, t_scale, t_scale); t_transform = MCGAffineTransformPreTranslate(t_transform, (MCGFloat)p_screen_rect.width / 2.0, (MCGFloat)p_screen_rect.height / 2.0); return t_transform; case kMCStackFullscreenNoScale: // offset so stack is centered in screen MCRectangle t_rect; t_rect = MCU_center_rect(p_screen_rect, p_stack_rect); // IM-2013-12-19: [[ Bug 11590 ]] Adjust for screen rect origins other than 0,0 return MCGAffineTransformMakeTranslation(t_rect.x - p_screen_rect.x, t_rect.y - p_screen_rect.y); default: MCUnreachableReturn(MCGAffineTransformMakeIdentity()); } }
bool MCWin32ApplyMaskToRasterRegion(MCGRaster &p_raster, uint32_t p_x_origin, uint32_t p_y_origin, const MCGRaster &p_mask, MCRegionRef p_region) { // IM-2013-09-11: [[ ResIndependence ]] reduce mask params to single MCGRaster bool t_success; t_success = true; MCGContextRef t_gcontext; t_gcontext = nil; if (t_success) t_success = MCGContextCreateWithRaster(p_raster, t_gcontext); MCGImageRef t_mask_image; t_mask_image = nil; if (t_success) t_success = MCGImageCreateWithRasterNoCopy(p_mask, t_mask_image); if (t_success) { // IM-2013-09-11: [[ ResIndependence ]] Apply scaled mask to target raster. // Drawing the mask directly will not work as the effective shape of the drawing operation // will be defined by the opaque parts of the mask - areas outside will be unaffected. Instead we // draw a solid rectangle over the intended areas using the mask as a pattern. MCGFloat t_scale; t_scale = MCResGetPixelScale(); MCGContextSetFillPattern(t_gcontext, t_mask_image, MCGAffineTransformMakeScale(t_scale, t_scale), kMCGImageFilterNearest); MCGContextTranslateCTM(t_gcontext, -(MCGFloat)p_x_origin, -(MCGFloat)p_y_origin); MCGContextSetBlendMode(t_gcontext, kMCGBlendModeDestinationIn); t_success = MCRegionForEachRect(p_region, __MCApplyMaskCallback, t_gcontext); } MCGImageRelease(t_mask_image); MCGContextRelease(t_gcontext); return t_success; }
MCPoint MCScreenDC::screentologicalpoint(const MCPoint &p_point) { MCGFloat t_scale; t_scale = 1 / MCWin32GetLogicalToScreenScale(); return MCPointTransform(p_point, MCGAffineTransformMakeScale(t_scale, t_scale)); }