Пример #1
0
void MCStack::setacceleratedrendering(bool p_value)
{
	// If we are turning accelerated rendering off, then destroy the tilecache.
	if (!p_value)
	{
		MCTileCacheDestroy(m_tilecache);
		m_tilecache = nil;
		
		// MW-2012-03-15: [[ Bug ]] Make sure we dirty the stack to ensure all the
		//   layer mode attrs are rest.
		dirtyall();
		
		return;
	}
	
	// If we are turning accelerated rendering on, and we already have a tile-
	// cache, then do nothing.
	if (m_tilecache != nil)
		return;
		
	// Otherwise, we configure based on platform settings.
	int32_t t_tile_size;
	int32_t t_cache_limit;
	MCTileCacheCompositorType t_compositor_type;
#ifdef _MAC_DESKTOP
	t_compositor_type = kMCTileCacheCompositorCoreGraphics;
	t_tile_size = 32;
	t_cache_limit = 32 * 1024 * 1024;
#elif defined(_WINDOWS_DESKTOP) || defined(_LINUX_DESKTOP)
	t_compositor_type = kMCTileCacheCompositorSoftware;
	t_tile_size = 32;
	t_cache_limit = 32 * 1024 * 1024;
#elif defined(_IOS_MOBILE) || defined(_ANDROID_MOBILE)
	t_compositor_type = kMCTileCacheCompositorStaticOpenGL;
	
	const MCDisplay *t_display;
	MCscreen -> getdisplays(t_display, false);
	
	MCRectangle t_viewport;
	t_viewport = t_display -> viewport;
	
	bool t_small_screen, t_medium_screen;
	t_small_screen = MCMin(t_viewport . width, t_viewport . height) <= 480 && MCMax(t_viewport . width, t_viewport . height) <= 640;
	t_medium_screen = MCMin(t_viewport . width, t_viewport . height) <= 768 && MCMax(t_viewport . width, t_viewport . height) <= 1024;

	if (t_small_screen)
		t_tile_size = 32, t_cache_limit = 16 * 1024 * 1024;
	else if (t_medium_screen)
		t_tile_size = 64, t_cache_limit = 32 * 1024 * 1024;
	else
		t_tile_size = 64, t_cache_limit = 64 * 1024 * 1024;
#endif

	MCTileCacheCreate(t_tile_size, t_cache_limit, m_tilecache);
	MCTileCacheSetViewport(m_tilecache, curcard -> getrect());
	MCTileCacheSetCompositor(m_tilecache, t_compositor_type);
	
	dirtyall();
}
Пример #2
0
bool MCStreamCache::ReadFromCache(void *p_buffer, uint32_t p_offset, uint32_t p_length, uint32_t &r_read)
{
	uint32_t t_to_read;
	if (m_cache_buffer != NULL)
	{
		r_read = MCMin(p_length, m_cache_length - p_offset);
		MCMemoryCopy(p_buffer, (uint8_t*)m_cache_buffer + p_offset, r_read);
		return true;
	}
	else if (m_cache_file != NULL)
	{
		bool t_success = true;
		
		IO_stat t_status;
		
		t_success = (IO_NORMAL == MCS_seek_set(m_cache_file, p_offset));
		if (t_success)
			t_success = (IO_ERROR != MCS_read(p_buffer, 1, p_length, m_cache_file));
		
		if (t_success)
		{
			r_read = p_length;
		}
		
		return t_success;
	}
	
	r_read = 0;
	return true;
}
Пример #3
0
bool MCStreamCache::Read(void *p_buffer, uint32_t p_offset, uint32_t p_length, uint32_t &r_read)
{
	bool t_success = true;
	
	uint32_t t_to_read;
	t_to_read = 0;
	
	uint32_t t_read;
	t_read = 0;
	
	if (p_offset < m_cache_length)
	{
		t_to_read = MCMin(m_cache_length - p_offset, p_length);
		t_success = ReadFromCache(p_buffer, p_offset, t_to_read, t_read);
	}
	
	r_read = t_read;
	
	if (t_success && t_read != t_to_read)
		return true;
	
	if (t_success)
	{
		t_to_read = p_length - t_read;
		t_read = 0;
		if (t_to_read > 0)
			t_success = ReadFromStream((uint8_t*)p_buffer + r_read, t_to_read, t_read);
		
		r_read += t_read;
	}
	
	return t_success;
}
Пример #4
0
bool MCRegionCalculateMask(MCRegionRef region, int32_t width, int32_t height, MCBitmap*& r_mask)
{
	MCRectangle t_rect;
	t_rect = MCRegionGetBoundingBox(region);
	
	MCBitmap *t_mask;
	t_mask = MCscreen -> createimage(1, width, height, True, 255, False, False);
	
	for(int y = 0; y < MCMin(t_rect . y, height); y++)
		memset(t_mask -> data + t_mask -> bytes_per_line * y, 0, t_mask -> bytes_per_line);

	if (t_rect . x > 0 || t_rect . x + t_rect . width < width)
	{
		for(int y = MCMin(t_rect . y, height); y < MCMin(t_rect . y + t_rect . height, height); y++)
		{
			char *t_row;
			t_row = t_mask -> data + t_mask -> bytes_per_line * y;
			
			for(int x = 0; x < MCMin(t_rect . x, width); x++)
				t_row[x / 8] &= ~(1 << (7 - (x & 7)));
			for(int x = MCMin(t_rect . x + t_rect . width, width); x < width; x++)
				t_row[x / 8] &= ~(1 << (7 - (x & 7)));
		}
	}
		
	for(int y = MCMin(t_rect . y + t_rect . height, height); y < height; y++)
		memset(t_mask -> data + t_mask -> bytes_per_line * y, 0, t_mask -> bytes_per_line);
		
	r_mask = t_mask;

	return true;
}
Пример #5
0
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());
	}
}
Пример #6
0
bool MCStreamCache::Ensure(uint32_t p_offset)
{
	if (p_offset <= m_cache_length)
		return true;
	
	bool t_success = true;
	
	void *t_buffer;
	
	t_success = MCMemoryAllocate(m_buffer_limit, t_buffer);
	
	while (t_success && p_offset > m_cache_length)
	{
		uint32_t t_to_read;
		uint32_t t_read;
		
		t_to_read = MCMin(p_offset - m_cache_length, m_buffer_limit);
		t_success = Read(t_buffer, m_cache_length, t_to_read, t_read) && (t_read == t_to_read);
	}
	
	MCMemoryDeallocate(t_buffer);
	
	return t_success;
}
Пример #7
0
void MCStack::view_setacceleratedrendering(bool p_value)
{
#ifdef _SERVER
    // We don't have accelerated rendering on Server
    return;
#else
    
	// If we are turning accelerated rendering off, then destroy the tilecache.
	if (!p_value)
	{
		MCTileCacheDestroy(m_view_tilecache);
		m_view_tilecache = nil;
		
		// MW-2012-03-15: [[ Bug ]] Make sure we dirty the stack to ensure all the
		//   layer mode attrs are rest.
		dirtyall();
		
		return;
	}
	
	// If we are turning accelerated rendering on, and we already have a tile-
	// cache, then do nothing.
	if (m_view_tilecache != nil)
		return;
	
	// Otherwise, we configure based on platform settings.
	int32_t t_tile_size;
	int32_t t_cache_limit;
	MCTileCacheCompositorType t_compositor_type;
#ifdef _MAC_DESKTOP
	t_compositor_type = kMCTileCacheCompositorCoreGraphics;
	t_tile_size = 32;
	t_cache_limit = 32 * 1024 * 1024;
#elif defined(_WINDOWS_DESKTOP) || defined(_LINUX_DESKTOP) || defined(__EMSCRIPTEN__)
	t_compositor_type = kMCTileCacheCompositorSoftware;
	t_tile_size = 32;
	t_cache_limit = 32 * 1024 * 1024;
#elif defined(_IOS_MOBILE) || defined(_ANDROID_MOBILE)
	t_compositor_type = kMCTileCacheCompositorStaticOpenGL;
	
	const MCDisplay *t_display;
	MCscreen -> getdisplays(t_display, false);
	
	MCRectangle t_viewport;
	t_viewport = t_display -> viewport;
	
	// IM-2014-01-30: [[ HiDPI ]] Use backing-surface size to determine small, medium, or large
	t_viewport = MCRectangleGetScaledBounds(t_viewport, view_getbackingscale());
	
	bool t_small_screen, t_medium_screen;
	t_small_screen = MCMin(t_viewport . width, t_viewport . height) <= 480 && MCMax(t_viewport . width, t_viewport . height) <= 640;
	t_medium_screen = MCMin(t_viewport . width, t_viewport . height) <= 768 && MCMax(t_viewport . width, t_viewport . height) <= 1024;
	
	if (t_small_screen)
		t_tile_size = 32, t_cache_limit = 16 * 1024 * 1024;
	else if (t_medium_screen)
		t_tile_size = 64, t_cache_limit = 32 * 1024 * 1024;
	else
		t_tile_size = 64, t_cache_limit = 64 * 1024 * 1024;
#else
#   error "No tile cache implementation defined for this platform"
#endif
	
	MCTileCacheCreate(t_tile_size, t_cache_limit, m_view_tilecache);
	view_updatetilecacheviewport();
	MCTileCacheSetCompositor(m_view_tilecache, t_compositor_type);
	
	dirtyall();
#endif /* !_SERVER */
}
Пример #8
0
void MCPlatformHandleTextInputInsertText(MCPlatformWindowRef p_window, unichar_t *p_chars, uindex_t p_char_count, MCRange p_replace_range, MCRange p_selection_range, bool p_mark)
{
	if (!MCactivefield)
		return;
	
    // SN-2014-12-04: [[ Bug 14152 ]] Locking the screen here doesn't allow the screen to refresh after
    //  text input, inside an MCWait loop
//	MCRedrawLockScreen();
	
	int32_t t_r_si, t_r_ei;
	t_r_si = 0;
	t_r_ei = INT32_MAX;
	MCactivefield -> resolvechars(0, t_r_si, t_r_ei, p_replace_range . offset, p_replace_range . length);
	
    // SN-2014-09-15: [[ Bug 13423 ]] t_was_compositing now used further in the function
    bool t_was_compositing;
    t_was_compositing = false;
	if (!p_mark)
	{
        // MW-2014-08-05: [[ Bug 13098 ]] If we have been compositing, then don't synthesise a
        //   keyDown / keyUp.
		int4 si, ei;
		if (MCactivefield -> getcompositionrange(si, ei))
		{
			if (si < t_r_si)
				t_r_si -= MCMin(t_r_si - si, ei - si);
			if (si < t_r_ei)
				t_r_ei -= MCMin(t_r_ei - si, ei - si);
			
			MCactivefield -> stopcomposition(True, False);
            
            t_was_compositing = true;
		}
        else
            t_was_compositing = false;
		
		// If the char count is 1 and the replacement range matches the current selection,
		// the char is native and the requested selection is after the char, then synthesis a
		// keydown/up pair.        
        // MW-2014-06-25: [[ Bug 12370 ]] If the char is ascii then map appropriately so we get
        //   the keycodes the engine expects.
		char_t t_char;

		if (!t_was_compositing &&
            p_char_count == 1 &&
			MCUnicodeMapToNative(p_chars, 1, t_char) &&
			p_selection_range . offset == p_replace_range . offset + 1 &&
			p_selection_range . length == 0)
		{
			int32_t t_s_si, t_s_ei;
			MCactivefield -> selectedmark(False, t_s_si, t_s_ei, False);
			if (t_s_si == t_r_si &&
				t_s_ei == t_r_ei)
			{

                // SN-2014-09-15: [[ Bug 13423 ]] Send the messages for all the characters typed
                while (s_pending_key_down != nil)
                {
                    // MW-2014-04-15: [[ Bug 12086 ]] Pass the keycode from the last event that was
                    //   passed to the IME.
                    MCAutoStringRef t_mapped_char;
                    MCPlatformKeyCode t_mapped_key_code;

                    map_key_to_engine(s_pending_key_down -> key_code, s_pending_key_down -> mapped_codepoint, s_pending_key_down -> unmapped_codepoint, t_mapped_key_code, &t_mapped_char);
                    
                    // SN-2014-11-03: [[ Bug 13832 ]] Enqueue the event, instead of firing it now (we are still in the NSApplication's keyDown).
                    // PM-2015-05-15: [[ Bug 15372]] call MCKeyMessageAppend before wkdown to prevent a crash if 'wait with messages' is used (since s_pending_key_down might become nil after wkdown
                    MCKeyMessageAppend(s_pending_key_up, s_pending_key_down -> key_code, s_pending_key_down -> mapped_codepoint, s_pending_key_down -> unmapped_codepoint);
                    
                    MCdispatcher -> wkdown(p_window, *t_mapped_char, t_mapped_key_code);
                    
                    MCKeyMessageNext(s_pending_key_down);
                
                }
				return;
			}
		}
	}
	else
	{
		if (p_char_count == 0)
			MCactivefield -> stopcomposition(True, False);
		else
		{
			int4 si, ei;
			if (MCactivefield -> getcompositionrange(si, ei))
			{
				if (si < t_r_si)
					t_r_si -= MCMin(t_r_si - si, ei - si);
				if (si < t_r_ei)
					t_r_ei -= MCMin(t_r_ei - si, ei - si);
				
				MCactivefield -> stopcomposition(True, False);
			}
		}
	}
	
    // SN-2014-09-14: [[ Bug 13423 ]] MCPlatformHandleRawKeyDown gets the US mac layout key, without any modifier included.
    // We need to update the elements:
    // if the key pressed leads to an actual char:
    //    this wrong key is replaced by this new 'combined' char
    // if the key pressed fails to generate a char:
    //    this wrong key is replaced by the dead-key char
    // SN-2015-04-10: [[ Bug 14205 ]] When using the dictation, there is no
    //  pending key down, but the composition was still on though.
    // SN-2015-06-23: [[ Bug 3537 ]] We should not cast p_char as a uint1 if it
    //  is not a native char.
    uint1 t_char[2];
    bool t_is_native_char;
    t_is_native_char = MCUnicodeMapToNative(p_chars, 1, t_char[0]);
    t_char[1] = 0;
    
    if (t_was_compositing && s_pending_key_down && t_is_native_char)
    {
        s_pending_key_down -> key_code = (uint1)*t_char;
        s_pending_key_down -> mapped_codepoint = (uint1)*t_char;
        s_pending_key_down -> unmapped_codepoint = (uint1)*t_char;
        
        // SN-2015-05-18: [[ Bug 15385 ]] Enqueue the first char in the sequence
        //  here - that will be the same as keyDown.
        // SN-2015-06-23: [[ Bug 3537 ]] In this only case, we don't want this
        //  nativised char to be mapped again in MCPlatformHandleKeyUp.
        MCKeyMessageAppend(s_pending_key_up, (uint1)*t_char, (uint1)*t_char, (uint1)*t_char, false);
    }
    
	// Set the text.	
	MCactivefield -> seltext(t_r_si, t_r_ei, False);
	
	if (p_mark)
		MCactivefield -> startcomposition();
    
    // SN-2014-09-15: [[ Bug 13423 ]] If the character typed is not Unicode and follows a dead key character, then we send
    // [Raw]KeyDown/Up and remove the first character from the sequence of keys typed.
    // If the character successfully combined with the dead char before it in a native char, we don't use finsert
    // Otherwise, we have the dead char in p_chars, we need to remove the one stored first in the sequence
    MCAutoStringRef t_string;
    
    // SN-2015-01-20: [[ Bug 14406 ]] If we have a series of pending keys, we have two possibilities:
    //   - typing IME characters: the characters are native, so we use the finsertnew
    //   - typing dead characters: the character, if we arrive here, is > 127
    // SN-2015-04-13: [[ Bug 14205 ]] Ensure that s_pending_key_down is not nil
    if (*p_chars > 127 && s_pending_key_down && s_pending_key_down -> next
            && t_is_native_char)
    {
        MCStringCreateWithNativeChars((const char_t *)t_char, 1, &t_string);
        MCdispatcher -> wkdown(p_window, *t_string, *t_char);
        
        MCKeyMessageNext(s_pending_key_down);
    }
    else
    {
        MCStringCreateWithChars(p_chars, p_char_count, &t_string);
        
        // SN-2014-12-05: [[ Bug 14162 ]] In case the character is a Unicode alphanumeric char,
        // then that's not a combining char - and it deserves its (raw)Key(Down|Up) messages
        uint32_t t_codepoint;
        t_codepoint = MCStringGetCodepointAtIndex(*t_string, 0);
        
        // SN-2015-05-18: [[ Bug 3537 ]] Use p_mark to determine whether we are
        //  in an IME state
        // SN-2015-05-05: [[ Bug 15305 ]] Check that s_pending_key_down is not
        //  nil before trying to use it, and use IME only if p_mark says so.
        if (s_pending_key_down && !p_mark)
        {
            MCAutoStringRef t_mapped_char;
            MCPlatformKeyCode t_mapped_key_code;

            map_key_to_engine(s_pending_key_down -> key_code, s_pending_key_down -> mapped_codepoint, s_pending_key_down -> unmapped_codepoint, t_mapped_key_code, &t_mapped_char);

            MCdispatcher -> wkdown(p_window, *t_string, *p_chars);

            // SN-2015-05-18: [[ Bug 3537 ]] If we were compositing, then we want
            //  to send the same message for keyUp and keyDown - which might be
            //  seeveral character-long
            if (t_was_compositing)
                MCdispatcher -> wkup(p_window, *t_string, *p_chars);
            else
                MCKeyMessageAppend(s_pending_key_up, *p_chars, s_pending_key_down -> mapped_codepoint, s_pending_key_down -> unmapped_codepoint);
            
            MCKeyMessageNext(s_pending_key_down);
        }
        else
            MCactivefield -> finsertnew(FT_IMEINSERT, *t_string, True);
    }
	
	// And update the selection range.
	int32_t t_s_si, t_s_ei;
	t_s_si = 0;
	t_s_ei = INT32_MAX;
	MCactivefield -> resolvechars(0, t_s_si, t_s_ei, p_selection_range . offset, p_selection_range . length);
	MCactivefield -> setcompositioncursoroffset(t_s_si - t_r_si);
	MCactivefield -> seltext(t_s_si, t_s_ei, True);
	
    // SN-2014-12-04: [[ Bug 14152 ]] Locking the screen here doesn't allow the screen to refresh after
    //  text input, inside an MCWait loop
//	MCRedrawUnlockScreen();
}