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(); }
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; }
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; }
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; }
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 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; }
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 */ }
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(); }