Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit b8dcf1c

Browse files
committed
[[ Cocoa ]] Implemented window masks.
1 parent 7cd2345 commit b8dcf1c

File tree

8 files changed

+194
-11
lines changed

8 files changed

+194
-11
lines changed

engine/engine.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@
267267
4D30CB27189AC40C0034CDC6 /* mac-font.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4D30CB26189AC40C0034CDC6 /* mac-font.mm */; };
268268
4D30D1F018A152700034CDC6 /* mac-player.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4D30D1EF18A152700034CDC6 /* mac-player.mm */; };
269269
4D30D43E18A293650034CDC6 /* QTKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D30D43D18A293650034CDC6 /* QTKit.framework */; };
270+
4D30D5D218A394250034CDC6 /* desktop-image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D30D5D118A394250034CDC6 /* desktop-image.cpp */; };
270271
4D377262150785AF000B0EB0 /* fieldhtml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D377261150785AF000B0EB0 /* fieldhtml.cpp */; };
271272
4D37727E150787EA000B0EB0 /* fieldrtf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D37727D150787EA000B0EB0 /* fieldrtf.cpp */; };
272273
4D407C0C15F8D15600AA3ABC /* osxscriptold.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D407C0B15F8D15600AA3ABC /* osxscriptold.cpp */; };
@@ -907,6 +908,7 @@
907908
4D30CB26189AC40C0034CDC6 /* mac-font.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "mac-font.mm"; path = "src/mac-font.mm"; sourceTree = "<group>"; };
908909
4D30D1EF18A152700034CDC6 /* mac-player.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "mac-player.mm"; path = "src/mac-player.mm"; sourceTree = "<group>"; };
909910
4D30D43D18A293650034CDC6 /* QTKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QTKit.framework; path = System/Library/Frameworks/QTKit.framework; sourceTree = SDKROOT; };
911+
4D30D5D118A394250034CDC6 /* desktop-image.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "desktop-image.cpp"; path = "src/desktop-image.cpp"; sourceTree = "<group>"; };
910912
4D377261150785AF000B0EB0 /* fieldhtml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = fieldhtml.cpp; path = src/fieldhtml.cpp; sourceTree = "<group>"; };
911913
4D3772671507869A000B0EB0 /* textbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = textbuffer.h; path = src/textbuffer.h; sourceTree = "<group>"; };
912914
4D37727D150787EA000B0EB0 /* fieldrtf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = fieldrtf.cpp; path = src/fieldrtf.cpp; sourceTree = "<group>"; };
@@ -1856,6 +1858,7 @@
18561858
4DECC9E81885808100463D52 /* desktop-stack.cpp */,
18571859
4DECCA5A188595F500463D52 /* desktop-menu.cpp */,
18581860
4D30C37018995E840034CDC6 /* desktop-pasteboard.cpp */,
1861+
4D30D5D118A394250034CDC6 /* desktop-image.cpp */,
18591862
4DECC94218856FE000463D52 /* mac-internal.h */,
18601863
4DECC93B18856C7500463D52 /* mac-core.mm */,
18611864
4DECD0C71886E4FD00463D52 /* mac-window.mm */,
@@ -3511,6 +3514,7 @@
35113514
4D30CAF6189AC1720034CDC6 /* mac-snapshot.mm in Sources */,
35123515
4D30CB27189AC40C0034CDC6 /* mac-font.mm in Sources */,
35133516
4D30D1F018A152700034CDC6 /* mac-player.mm in Sources */,
3517+
4D30D5D218A394250034CDC6 /* desktop-image.cpp in Sources */,
35143518
);
35153519
runOnlyForDeploymentPostprocessing = 0;
35163520
};

engine/src/desktop-image.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/* Copyright (C) 2003-2013 Runtime Revolution Ltd.
2+
3+
This file is part of LiveCode.
4+
5+
LiveCode is free software; you can redistribute it and/or modify it under
6+
the terms of the GNU General Public License v3 as published by the Free
7+
Software Foundation.
8+
9+
LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
10+
WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
16+
17+
#include "platform.h"
18+
19+
#include "core.h"
20+
#include "globdefs.h"
21+
#include "filedefs.h"
22+
#include "osspec.h"
23+
#include "typedefs.h"
24+
#include "parsedef.h"
25+
#include "objdefs.h"
26+
27+
#include "image.h"
28+
29+
////////////////////////////////////////////////////////////////////////////////
30+
31+
extern void surface_extract_alpha(void *p_pixels, uint4 p_pixel_stride, void *p_alpha, uint4 p_alpha_stride, uint4 p_width, uint4 p_height);
32+
33+
////////////////////////////////////////////////////////////////////////////////
34+
35+
MCWindowShape *MCImage::makewindowshape(void)
36+
{
37+
bool t_success = true;
38+
39+
MCWindowShape *t_mask = nil;
40+
MCPlatformWindowMaskRef t_mask_image = nil;
41+
MCImageBitmap *t_bitmap = nil;
42+
uint8_t *t_alpha = nil;
43+
uindex_t t_alpha_stride = 0;
44+
uindex_t t_width, t_height;
45+
46+
t_success = lockbitmap(t_bitmap, true);
47+
48+
if (t_success)
49+
t_success = MCImageBitmapHasTransparency(t_bitmap);
50+
51+
if (t_success)
52+
{
53+
t_width = t_bitmap->width;
54+
t_height = t_bitmap->height;
55+
56+
t_alpha_stride = (t_width + 3) & ~3;
57+
t_success = MCMemoryAllocate(t_alpha_stride * t_height, t_alpha);
58+
}
59+
60+
if (t_success)
61+
{
62+
surface_extract_alpha(t_bitmap->data, t_bitmap->stride, t_alpha, t_alpha_stride, t_width, t_height);
63+
MCPlatformWindowMaskCreate(t_width, t_height, t_alpha_stride, t_alpha, t_mask_image);
64+
MCMemoryDeallocate(t_alpha);
65+
}
66+
67+
if (t_success)
68+
t_success = MCMemoryNew(t_mask);
69+
70+
unlockbitmap(t_bitmap);
71+
72+
if (!t_success)
73+
{
74+
MCMemoryDeallocate(t_mask);
75+
if (t_mask_image != nil)
76+
MCPlatformWindowMaskRelease(t_mask_image);
77+
return nil;
78+
}
79+
80+
t_mask->width = t_width;
81+
t_mask->height = t_height;
82+
t_mask->is_sharp = false;
83+
84+
t_mask->data = nil;
85+
t_mask->stride = t_alpha_stride;
86+
87+
t_mask->handle = t_mask_image;
88+
89+
return t_mask;
90+
}
91+
92+
////////////////////////////////////////////////////////////////////////////////

engine/src/desktop-stack.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,7 @@ void MCStack::realize(void)
172172
MCPlatformSetWindowContentRect(t_window, t_device_rect);
173173

174174
if (m_window_shape != nil)
175-
{
176-
MCPlatformWindowMaskRef t_mask;
177-
MCPlatformWindowMaskCreate(m_window_shape -> width, m_window_shape -> height, m_window_shape -> stride, m_window_shape -> data, t_mask);
178-
MCPlatformSetWindowProperty(t_window, kMCPlatformWindowPropertyMask, kMCPlatformPropertyTypeWindowMask, &t_mask);
179-
}
175+
MCPlatformSetWindowProperty(t_window, kMCPlatformWindowPropertyMask, kMCPlatformPropertyTypeWindowMask, (MCPlatformWindowMaskRef *)&m_window_shape -> handle);
180176
MCPlatformSetWindowProperty(t_window, kMCPlatformWindowPropertyStyle, kMCPlatformPropertyTypeWindowStyle, &t_window_style);
181177
MCPlatformSetWindowBoolProperty(t_window, kMCPlatformWindowPropertyHasTitleWidget, t_has_titlebox);
182178
MCPlatformSetWindowBoolProperty(t_window, kMCPlatformWindowPropertyHasCloseWidget, t_has_closebox);
@@ -490,6 +486,20 @@ void MCStack::device_updatewindowwithcallback(MCRegionRef p_region, MCStackUpdat
490486

491487
////////////////////////////////////////////////////////////////////////////////
492488

489+
void MCStack::destroywindowshape(void)
490+
{
491+
if (m_window_shape == nil)
492+
return;
493+
494+
delete[] m_window_shape -> data;
495+
if (m_window_shape -> handle != nil)
496+
MCPlatformWindowMaskRelease((MCPlatformWindowMaskRef)m_window_shape -> handle);
497+
delete m_window_shape;
498+
m_window_shape = nil;
499+
}
500+
501+
////////////////////////////////////////////////////////////////////////////////
502+
493503
class MCDesktopStackSurface: public MCStackSurface
494504
{
495505
MCPlatformSurfaceRef m_surface;

engine/src/mac-surface.mm

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
extern bool MCU_empty_rect(const MCRectangle&);
3535
extern bool MCGRasterToCGImage(const MCGRaster &p_raster, MCGRectangle p_src_rect, CGColorSpaceRef p_colorspace, bool p_copy, bool p_invert, CGImageRef &r_image);
3636
extern bool MCGImageToCGImage(MCGImageRef p_src, MCGRectangle p_src_rect, bool p_copy, bool p_invert, CGImageRef &r_image);
37+
extern MCGFloat MCResGetDeviceScale(void);
3738

3839
////////////////////////////////////////////////////////////////////////////////
3940

@@ -194,7 +195,37 @@
194195

195196
void MCMacPlatformSurface::Lock(void)
196197
{
197-
// COCOA-TODO: Implement window masks.
198+
CGImageRef t_mask;
199+
t_mask = nil;
200+
if (m_window -> m_mask != nil)
201+
t_mask = (CGImageRef)m_window -> m_mask;
202+
203+
if (t_mask != nil)
204+
{
205+
// COCOA-TODO: Getting the height to flip round is dependent on a friend.
206+
int t_surface_height;
207+
t_surface_height = m_window -> m_content . height;
208+
209+
MCRectangle t_rect;
210+
t_rect = MCRegionGetBoundingBox(m_update_rgn);
211+
CGContextClearRect(m_cg_context, CGRectMake(t_rect . x, t_surface_height - (t_rect . y + t_rect . height), t_rect . width, t_rect . height));
212+
213+
// IM-2013-08-29: [[ ResIndependence ]] scale mask to device coords
214+
MCGFloat t_scale;
215+
t_scale = MCResGetDeviceScale();
216+
217+
MCGFloat t_mask_height, t_mask_width;
218+
t_mask_width = CGImageGetWidth(t_mask) * t_scale;
219+
t_mask_height = CGImageGetHeight(t_mask) * t_scale;
220+
221+
CGRect t_dst_rect;
222+
t_dst_rect . origin . x = 0;
223+
t_dst_rect . origin . y = t_surface_height - t_mask_height;
224+
t_dst_rect . size . width = t_mask_width;
225+
t_dst_rect . size . height = t_mask_height;
226+
CGContextClipToMask(m_cg_context, t_dst_rect, t_mask);
227+
}
228+
198229
CGContextSaveGState(m_cg_context);
199230
}
200231

engine/src/mac-window.mm

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,7 @@ - (NSRect)mapMCRectangleToNSRect: (MCRectangle)r
808808
[m_window_handle setContentView: m_view];
809809

810810
[m_window_handle setLevel: t_window_level];
811-
[m_window_handle setOpaque: m_mask != nil];
811+
[m_window_handle setOpaque: m_mask == nil];
812812
[m_window_handle setHasShadow: m_has_shadow];
813813
if (!m_has_zoom_widget)
814814
[[m_window_handle standardWindowButton: NSWindowZoomButton] setEnabled: NO];
@@ -853,7 +853,7 @@ - (NSRect)mapMCRectangleToNSRect: (MCRectangle)r
853853

854854
if (m_changes . mask_changed)
855855
{
856-
[m_window_handle setOpaque: m_mask != nil];
856+
[m_window_handle setOpaque: m_mask == nil];
857857
if (m_has_shadow)
858858
m_shadow_changed = true;
859859
}
@@ -1002,18 +1002,57 @@ - (NSRect)mapMCRectangleToNSRect: (MCRectangle)r
10021002

10031003
////////////////////////////////////////////////////////////////////////////////
10041004

1005-
// COCOA-TODO: Implement window masks.
1005+
static bool MCAlphaToCGImage(uindex_t p_width, uindex_t p_height, uint8_t* p_data, uindex_t p_stride, CGImageRef &r_image)
1006+
{
1007+
bool t_success = true;
1008+
1009+
CGImageRef t_image = nil;
1010+
CGColorSpaceRef t_colorspace = nil;
1011+
CFDataRef t_data = nil;
1012+
CGDataProviderRef t_dp = nil;
1013+
1014+
if (t_success)
1015+
t_success = nil != (t_data = CFDataCreate(kCFAllocatorDefault, (uint8_t*)p_data, p_stride * p_height));
1016+
1017+
if (t_success)
1018+
t_success = nil != (t_dp = CGDataProviderCreateWithCFData(t_data));
1019+
1020+
if (t_success)
1021+
t_success = nil != (t_colorspace = CGColorSpaceCreateDeviceGray());
1022+
1023+
if (t_success)
1024+
t_success = nil != (t_image = CGImageCreate(p_width, p_height, 8, 8, p_stride, t_colorspace, kCGImageAlphaNone, t_dp, nil, false, kCGRenderingIntentDefault));
1025+
1026+
CGColorSpaceRelease(t_colorspace);
1027+
CGDataProviderRelease(t_dp);
1028+
CFRelease(t_data);
1029+
1030+
if (t_success)
1031+
r_image = t_image;
1032+
1033+
return t_success;
1034+
}
1035+
10061036
void MCPlatformWindowMaskCreate(int32_t p_width, int32_t p_height, int32_t p_stride, void *p_bits, MCPlatformWindowMaskRef& r_mask)
10071037
{
1008-
r_mask = nil;
1038+
CGImageRef t_mask;
1039+
t_mask = nil;
1040+
MCAlphaToCGImage(p_width, p_height, (uint8_t *)p_bits, p_stride, t_mask);
1041+
r_mask = (MCPlatformWindowMaskRef)t_mask;
10091042
}
10101043

10111044
void MCPlatformWindowMaskRetain(MCPlatformWindowMaskRef p_mask)
10121045
{
1046+
CGImageRef t_mask;
1047+
t_mask = (CGImageRef)p_mask;
1048+
CGImageRetain(t_mask);
10131049
}
10141050

10151051
void MCPlatformWindowMaskRelease(MCPlatformWindowMaskRef p_mask)
10161052
{
1053+
CGImageRef t_mask;
1054+
t_mask = (CGImageRef)p_mask;
1055+
CGImageRelease(t_mask);
10171056
}
10181057

10191058
////////////////////////////////////////////////////////////////////////////////

engine/src/osximage.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ CGImageRef MCImage::makeicon(uint4 p_width, uint4 p_height)
8686
return t_icon;
8787
}
8888

89+
#ifdef OLD_MAC
8990
// MW-2011-09-13: [[ Masks ]] Updated to store data in an MCWindowMask struct.
9091
MCWindowShape *MCImage::makewindowshape(void)
9192
{
@@ -145,6 +146,7 @@ MCWindowShape *MCImage::makewindowshape(void)
145146

146147
return t_mask;
147148
}
149+
#endif
148150

149151
bool MCImageBitmapToPICT(MCImageBitmap *p_bitmap, MCMacSysPictHandle &r_pict)
150152
{
@@ -298,6 +300,7 @@ bool MCImageBitmapToPICT(MCImageBitmap *p_bitmap, MCMacSysPictHandle &r_pict)
298300
#endif
299301
}
300302

303+
#ifdef OLD_MAC
301304
CGImageRef MCImage::converttodragimage(void)
302305
{
303306
CGImageRef t_image = NULL;
@@ -310,3 +313,4 @@ CGImageRef MCImage::converttodragimage(void)
310313
return t_image;
311314

312315
}
316+
#endif

engine/src/osxstack.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,7 @@ void MCStack::syncscroll(void)
704704
}
705705
#endif
706706

707+
#ifdef OLD_MAC
707708
// MW-2011-09-13: [[ Masks ]] The windowshape is now stored in a 'WindowMask'
708709
// struct. We don't distinguish between 1-bit and 8-bit masks on Mac.
709710
void MCStack::destroywindowshape()
@@ -717,6 +718,7 @@ void MCStack::destroywindowshape()
717718
m_window_shape = nil;
718719
}
719720
}
721+
#endif
720722

721723
void MCStack::getminmax(Rect *r)
722724
{ //get the min & max size of a stack

engine/src/platform-window.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,10 @@ void MCPlatformWindow::SetProperty(MCPlatformWindowProperty p_property, MCPlatfo
210210
assert(p_type == kMCPlatformPropertyTypeWindowMask);
211211
if (m_mask != nil)
212212
MCPlatformWindowMaskRelease(m_mask);
213-
m_mask = (MCPlatformWindowMaskRef)p_value;
213+
m_mask = *(MCPlatformWindowMaskRef *)p_value;
214214
if (m_mask != nil)
215215
MCPlatformWindowMaskRetain(m_mask);
216+
m_changes . mask_changed = true;
216217
break;
217218
case kMCPlatformWindowPropertyContentRect:
218219
assert(p_type == kMCPlatformPropertyTypeRectangle);

0 commit comments

Comments
 (0)