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

Commit daf9762

Browse files
committed
[[ Bug 13746 ]] Ensure window mask is scaled appropriately for the stack scale & resolution scale
1 parent b6b5a99 commit daf9762

File tree

13 files changed

+197
-102
lines changed

13 files changed

+197
-102
lines changed

docs/notes/bugfix-13746.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# the shape property of stacks is broken

engine/engine.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,8 @@
553553
E8A554B81785A83A00DABC1A /* libskia.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E8AF4895174D5563000B2F9E /* libskia.a */; };
554554
E8AE876C177B3F5C0041B7E0 /* cgimageutil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8AE876B177B3F5C0041B7E0 /* cgimageutil.cpp */; };
555555
E8AF465B174CF247000B2F9E /* surface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D4F9DFA13CDE63000B9B15D /* surface.cpp */; };
556+
E8AF7D2319F7E3BF000F68E9 /* graphics_util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8AF7D2219F7E3BF000F68E9 /* graphics_util.cpp */; };
557+
E8AF7D2419F7E3BF000F68E9 /* graphics_util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8AF7D2219F7E3BF000F68E9 /* graphics_util.cpp */; };
556558
E8B5BB1416DF77DF00CA02FB /* imagelist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B5BB1216DF77DF00CA02FB /* imagelist.cpp */; };
557559
E8D1ECDD1992395A00984EFE /* sysosxrandom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4DB32230174BD08E00046FFE /* sysosxrandom.cpp */; };
558560
E8D7F8321785A88200EC051A /* imagelist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B5BB1216DF77DF00CA02FB /* imagelist.cpp */; };
@@ -1579,6 +1581,7 @@
15791581
E8A7EF0016FC98A200C39491 /* stacksecurity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stacksecurity.cpp; path = src/stacksecurity.cpp; sourceTree = "<group>"; };
15801582
E8AE876B177B3F5C0041B7E0 /* cgimageutil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cgimageutil.cpp; path = src/cgimageutil.cpp; sourceTree = "<group>"; };
15811583
E8AF4890174D5563000B2F9E /* libskia.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libskia.xcodeproj; path = ../thirdparty/libskia/libskia.xcodeproj; sourceTree = SOURCE_ROOT; };
1584+
E8AF7D2219F7E3BF000F68E9 /* graphics_util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = graphics_util.cpp; path = src/graphics_util.cpp; sourceTree = "<group>"; };
15821585
E8B5BB1216DF77DF00CA02FB /* imagelist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imagelist.cpp; path = src/imagelist.cpp; sourceTree = "<group>"; };
15831586
E8B5BB1316DF77DF00CA02FB /* imagelist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imagelist.h; path = src/imagelist.h; sourceTree = "<group>"; };
15841587
E8D7F8461785A99900EC051A /* srvtheme.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srvtheme.cpp; path = src/srvtheme.cpp; sourceTree = "<group>"; };
@@ -2543,6 +2546,7 @@
25432546
4D592DEA14EED23600EADBB6 /* fonttable.cpp */,
25442547
4DB902510DAA5C980014A170 /* gradient.cpp */,
25452548
4DB902520DAA5C980014A170 /* gradient.h */,
2549+
E8AF7D2219F7E3BF000F68E9 /* graphics_util.cpp */,
25462550
4CC55320180D546000C10387 /* graphics_util.h */,
25472551
4C10D76D16BF9BFA00D25197 /* graphicscontext.cpp */,
25482552
4C10D76E16BF9BFA00D25197 /* graphicscontext.h */,
@@ -3520,6 +3524,7 @@
35203524
4D1F9D53171C682E0091C6CB /* hndlrlst.cpp in Sources */,
35213525
4D1F9D54171C682E0091C6CB /* idraw.cpp in Sources */,
35223526
4D1F9D55171C682E0091C6CB /* ifile.cpp in Sources */,
3527+
E8AF7D2419F7E3BF000F68E9 /* graphics_util.cpp in Sources */,
35233528
4D1F9D56171C682E0091C6CB /* igif.cpp in Sources */,
35243529
4D1F9D57171C682E0091C6CB /* iimport.cpp in Sources */,
35253530
4D1F9D58171C682E0091C6CB /* ijpg.cpp in Sources */,
@@ -3864,6 +3869,7 @@
38643869
4DECCA511885958300463D52 /* osxstack.cpp in Sources */,
38653870
4DECCA5B188595F500463D52 /* desktop-menu.cpp in Sources */,
38663871
4DECD0C81886E4FD00463D52 /* mac-window.mm in Sources */,
3872+
E8AF7D2319F7E3BF000F68E9 /* graphics_util.cpp in Sources */,
38673873
4DECD1351886F0FF00463D52 /* mac-surface.mm in Sources */,
38683874
4DECD1FD1887F24E00463D52 /* platform-window.cpp in Sources */,
38693875
4DECD26E188807E400463D52 /* platform-surface.cpp in Sources */,

engine/src/desktop-image.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ extern void surface_extract_alpha(void *p_pixels, uint4 p_pixel_stride, void *p_
3232

3333
////////////////////////////////////////////////////////////////////////////////
3434

35-
MCWindowShape *MCImage::makewindowshape(void)
35+
MCWindowShape *MCImage::makewindowshape(const MCGIntegerSize &p_size)
3636
{
3737
bool t_success = true;
3838

@@ -43,7 +43,7 @@ MCWindowShape *MCImage::makewindowshape(void)
4343
uindex_t t_alpha_stride = 0;
4444
uindex_t t_width, t_height;
4545

46-
t_success = lockbitmap(t_bitmap, true);
46+
t_success = lockbitmap(true, true, &p_size, t_bitmap);
4747

4848
if (t_success)
4949
t_success = MCImageBitmapHasTransparency(t_bitmap);

engine/src/desktop-stack.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,9 @@ void MCStack::updatewindowshape(MCWindowShape *p_shape)
340340
{
341341
destroywindowshape();
342342
m_window_shape = p_shape;
343-
MCPlatformSetWindowProperty(window, kMCPlatformWindowPropertyMask, kMCPlatformPropertyTypeWindowMask, (MCPlatformWindowMaskRef *)&m_window_shape -> handle);
343+
// IM-2014-10-22: [[ Bug 13746 ]] Check for platform window before setting mask
344+
if (window != nil)
345+
MCPlatformSetWindowProperty(window, kMCPlatformWindowPropertyMask, kMCPlatformPropertyTypeWindowMask, (MCPlatformWindowMaskRef *)&m_window_shape -> handle);
344346
dirtyall();
345347
}
346348

engine/src/graphics_util.cpp

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
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 "graphics.h"
18+
19+
#include "graphics_util.h"
20+
21+
////////////////////////////////////////////////////////////////////////////////
22+
23+
// IM-2014-10-22: [[ Bug 13746 ]] Set the given rect of the raster to transparent black
24+
void MCGRasterClearRect(MCGRaster &x_raster, const MCGIntegerRectangle &p_rect)
25+
{
26+
MCGIntegerRectangle t_coverage;
27+
t_coverage = MCGIntegerRectangleIntersection(p_rect, MCGIntegerRectangleMake(0, 0, x_raster.width, x_raster.height));
28+
29+
if (MCGIntegerRectangleIsEmpty(t_coverage))
30+
return;
31+
32+
uint8_t *t_pixel_ptr;
33+
t_pixel_ptr = (uint8_t*)x_raster.pixels;
34+
35+
if (t_coverage.origin.y > 0)
36+
t_pixel_ptr += t_coverage.origin.y * x_raster.stride;
37+
if (t_coverage.origin.x > 0)
38+
t_pixel_ptr += t_coverage.origin.x * sizeof(uint32_t);
39+
40+
uint32_t t_width;
41+
t_width = t_coverage.size.width * sizeof(uint32_t);
42+
43+
for (uint32_t y = 0; y < t_coverage.size.height; y++)
44+
{
45+
MCMemoryClear(t_pixel_ptr, t_width);
46+
t_pixel_ptr += x_raster.stride;
47+
}
48+
}
49+
50+
// IM-2014-10-03: [[ Bug 13432 ]] Set the alpha values of the opaque image from the alpha raster, premultiplying the pixels
51+
void MCGRasterApplyAlpha(MCGRaster &x_raster, const MCGRaster &p_alpha, const MCGIntegerPoint &p_offset)
52+
{
53+
MCAssert(p_alpha.format == kMCGRasterFormat_A);
54+
MCAssert(x_raster.format == kMCGRasterFormat_xRGB);
55+
56+
MCGIntegerRectangle t_coverage;
57+
t_coverage = MCGIntegerRectangleIntersection(MCGIntegerRectangleMake(0, 0, x_raster.width, x_raster.height),
58+
MCGIntegerRectangleMake(p_offset.x, p_offset.y, p_alpha.width, p_alpha.height));
59+
60+
if (MCGIntegerRectangleIsEmpty(t_coverage))
61+
{
62+
// IM-2014-10-22: [[ Bug 13746 ]] If the mask is not within the region of the raster then blank out everything
63+
MCGRasterClearRect(x_raster, MCGIntegerRectangleMake(0, 0, x_raster.width, x_raster.height));
64+
x_raster.format = kMCGRasterFormat_ARGB;
65+
return;
66+
}
67+
68+
// IM-2014-10-22: [[ Bug 13746 ]] Areas outside the mask need to be blanked out
69+
int32_t t_left, t_top, t_right, t_bottom;
70+
t_left = t_coverage.origin.x;
71+
t_top = t_coverage.origin.y;
72+
t_right = t_coverage.origin.x + t_coverage.size.width;
73+
t_bottom = t_coverage.origin.y + t_coverage.size.height;
74+
75+
MCGRasterClearRect(x_raster, MCGIntegerRectangleMakeLTRB(0, 0, x_raster.width, t_top));
76+
MCGRasterClearRect(x_raster, MCGIntegerRectangleMakeLTRB(0, t_bottom, x_raster.width, x_raster.height));
77+
MCGRasterClearRect(x_raster, MCGIntegerRectangleMakeLTRB(0, t_top, t_left, t_bottom));
78+
MCGRasterClearRect(x_raster, MCGIntegerRectangleMakeLTRB(t_right, t_top, x_raster.width, t_bottom));
79+
80+
uint8_t *t_alpha_ptr;
81+
t_alpha_ptr = (uint8_t*)p_alpha.pixels;
82+
83+
if (p_offset.y < 0)
84+
t_alpha_ptr += p_alpha.stride * (-p_offset.y);
85+
if (p_offset.x < 0)
86+
t_alpha_ptr += (-p_offset.x);
87+
88+
uint8_t *t_pixel_ptr;
89+
t_pixel_ptr = (uint8_t*)x_raster.pixels;
90+
91+
if (t_coverage.origin.y > 0)
92+
t_pixel_ptr += x_raster.stride * t_coverage.origin.y;
93+
if (t_coverage.origin.x > 0)
94+
t_pixel_ptr += t_coverage.origin.x * sizeof(uint32_t);
95+
96+
for (uint32_t y = 0; y < t_coverage.size.height; y++)
97+
{
98+
uint8_t *t_alpha_row;
99+
t_alpha_row = t_alpha_ptr;
100+
101+
uint32_t *t_pixel_row;
102+
t_pixel_row = (uint32_t*)t_pixel_ptr;
103+
104+
for (uint32_t x = 0; x < t_coverage.size.width; x++)
105+
{
106+
uint32_t t_pixel;
107+
t_pixel = *t_pixel_row;
108+
109+
uint8_t t_alpha;
110+
t_alpha = *t_alpha_row++;
111+
112+
*t_pixel_row++ = MCGPixelPreMultiplyNative(MCGPixelSetNativeAlpha(t_pixel, t_alpha));
113+
}
114+
//
115+
116+
t_alpha_ptr += p_alpha.stride;
117+
t_pixel_ptr += x_raster.stride;
118+
}
119+
120+
x_raster.format = kMCGRasterFormat_ARGB;
121+
}
122+
123+
////////////////////////////////////////////////////////////////////////////////

engine/src/graphics_util.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,4 +371,10 @@ static inline MCGFont MCFontStructToMCGFont(MCFontStruct *p_font)
371371

372372
#endif
373373

374+
////////////////////////////////////////////////////////////////////////////////
375+
376+
// IM-2014-10-22: [[ Bug 13746 ]] Raster modifying utility functions
377+
void MCGRasterClearRect(MCGRaster &x_raster, const MCGIntegerRectangle &p_rect);
378+
void MCGRasterApplyAlpha(MCGRaster &x_raster, const MCGRaster &p_alpha, const MCGIntegerPoint &p_offset);
379+
374380
#endif // __GRAPHICS_UTIL_H_

engine/src/image.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,8 @@ class MCImage : public MCControl
538538
MCSharedString *getclipboardtext(void);
539539

540540
// MW-2011-09-13: [[ Masks ]] Updated to return a 'MCWindowMask'
541-
MCWindowShape *makewindowshape(void);
541+
// IM-2014-10-22: [[ Bug 13746 ]] Add size parameter to allow scaled window shapes
542+
MCWindowShape *makewindowshape(const MCGIntegerSize &p_size);
542543

543544
#if defined(_MAC_DESKTOP)
544545
CGImageRef makeicon(uint4 p_width, uint4 p_height);

engine/src/lnximage.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
2727
#include "lnxdc.h"
2828
#include "imagebitmap.h"
2929

30+
#include "graphics.h"
31+
3032
// Linux image conversion functions
3133

3234
bool MCImageBitmapCreateWithXImage(XImage *p_image, MCImageBitmap *&r_bitmap)
@@ -186,7 +188,7 @@ bool MCPatternToX11Pixmap(MCPatternRef p_pattern, Pixmap &r_pixmap)
186188
}
187189

188190
void surface_extract_alpha(void *p_pixels, uint4 p_pixel_stride, void *p_alpha, uint4 p_alpha_stride, uint4 p_width, uint4 p_height);
189-
MCWindowShape *MCImage::makewindowshape(void)
191+
MCWindowShape *MCImage::makewindowshape(const MCGIntegerSize &p_size)
190192
{
191193
bool t_success;
192194
t_success = true;
@@ -195,15 +197,17 @@ MCWindowShape *MCImage::makewindowshape(void)
195197
if (!MCMemoryNew(t_mask))
196198
return nil;
197199

198-
// Get the width / height.
199-
t_mask -> width = rect . width;
200-
t_mask -> height = rect . height;
201-
202200
MCImageBitmap *t_bitmap = nil;
203201
bool t_has_mask = false, t_has_alpha = false;
204-
t_success = lockbitmap(t_bitmap, true);
202+
203+
t_success = lockbitmap(true, true, &p_size, t_bitmap);
204+
205205
if (t_success)
206206
{
207+
// Get the width / height.
208+
t_mask -> width = t_bitmap->width;
209+
t_mask -> height = t_bitmap->height;
210+
207211
t_has_mask = MCImageBitmapHasTransparency(t_bitmap, t_has_alpha);
208212
#ifdef LIBGRAPHICS_BROKEN
209213
if (t_has_alpha)

engine/src/mac-surface.mm

Lines changed: 5 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -282,62 +282,6 @@ CGRect MCMacFlipCGRect(const CGRect &p_rect, uint32_t p_surface_height)
282282
CGContextSaveGState(m_cg_context);
283283
}
284284

285-
// IM-2014-10-03: [[ Bug 13432 ]] Set the alpha values of the opaque image from the alpha raster, premultiplying the pixels
286-
void MCGRasterApplyAlpha(MCGRaster &x_raster, const MCGRaster &p_alpha, const MCGIntegerPoint &p_offset)
287-
{
288-
MCAssert(p_alpha.format == kMCGRasterFormat_A);
289-
MCAssert(x_raster.format == kMCGRasterFormat_xRGB);
290-
291-
MCGIntegerRectangle t_coverage;
292-
t_coverage = MCGIntegerRectangleIntersection(MCGIntegerRectangleMake(0, 0, x_raster.width, x_raster.height),
293-
MCGIntegerRectangleMake(p_offset.x, p_offset.y, p_alpha.width, p_alpha.height));
294-
295-
if (MCGIntegerRectangleIsEmpty(t_coverage))
296-
return;
297-
298-
uint8_t *t_alpha_ptr;
299-
t_alpha_ptr = (uint8_t*)p_alpha.pixels;
300-
301-
if (p_offset.y < 0)
302-
t_alpha_ptr += p_alpha.stride * (-p_offset.y);
303-
if (p_offset.x < 0)
304-
t_alpha_ptr += (-p_offset.x);
305-
306-
uint8_t *t_pixel_ptr;
307-
t_pixel_ptr = (uint8_t*)x_raster.pixels;
308-
309-
if (t_coverage.origin.y > 0)
310-
t_pixel_ptr += x_raster.stride * t_coverage.origin.y;
311-
if (t_coverage.origin.x > 0)
312-
t_pixel_ptr += t_coverage.origin.x * sizeof(uint32_t);
313-
314-
for (uint32_t y = 0; y < t_coverage.size.height; y++)
315-
{
316-
uint8_t *t_alpha_row;
317-
t_alpha_row = t_alpha_ptr;
318-
319-
uint32_t *t_pixel_row;
320-
t_pixel_row = (uint32_t*)t_pixel_ptr;
321-
322-
for (uint32_t x = 0; x < t_coverage.size.width; x++)
323-
{
324-
uint32_t t_pixel;
325-
t_pixel = *t_pixel_row;
326-
327-
uint8_t t_alpha;
328-
t_alpha = *t_alpha_row++;
329-
330-
*t_pixel_row++ = MCGPixelPreMultiplyNative(MCGPixelSetNativeAlpha(t_pixel, t_alpha));
331-
}
332-
//
333-
334-
t_alpha_ptr += p_alpha.stride;
335-
t_pixel_ptr += x_raster.stride;
336-
}
337-
338-
x_raster.format = kMCGRasterFormat_ARGB;
339-
}
340-
341285
void MCMacPlatformSurface::Unlock(void)
342286
{
343287
// MM-2014-07-31: [[ ThreadedRendering ]] Moved the drawing to the system context to unlock from unlock pixels.
@@ -356,10 +300,14 @@ void MCGRasterApplyAlpha(MCGRaster &x_raster, const MCGRaster &p_alpha, const MC
356300

357301
if (m_window->m_mask != nil)
358302
{
303+
// IM-2014-10-22: [[ Bug 13746 ]] Apply the backing scale to the mask offset
304+
MCGFloat t_scale;
305+
t_scale = GetBackingScaleFactor();
306+
359307
// IM-2014-10-03: [[ Bug 13432 ]] Set the buffer alpha directly from the mask raster.
360308
MCMacPlatformWindowMask *t_mask;
361309
t_mask = (MCMacPlatformWindowMask*)m_window->m_mask;
362-
MCGRasterApplyAlpha(m_raster, t_mask->mask, MCGIntegerPointMake(-t_bounds.origin.x, -t_bounds.origin.y));
310+
MCGRasterApplyAlpha(m_raster, t_mask->mask, MCGIntegerPointMake(-t_bounds.origin.x * t_scale, -t_bounds.origin.y * t_scale));
363311
}
364312

365313
MCMacClipCGContextToRegion(m_cg_context, m_update_rgn, t_surface_height);

engine/src/stack.cpp

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2512,22 +2512,9 @@ Exec_stat MCStack::setprop(uint4 parid, Properties which, MCExecPoint &ep, Boole
25122512
// MW-2004-04-27: [[Deep Masks]] If a window already has a mask, replace it now to avoid flicker
25132513
if (m_window_shape != NULL)
25142514
{
2515-
MCImage *t_image;
2516-
// MW-2009-02-02: [[ Improved image search ]] Search for the appropriate image object using the standard method.
2517-
t_image = resolveimageid(windowshapeid);
2518-
if (t_image != NULL)
2519-
{
2520-
MCWindowShape *t_new_mask;
2521-
setextendedstate(True, ECS_MASK_CHANGED);
2522-
t_image -> setflag(True, F_I_ALWAYS_BUFFER);
2523-
t_image -> open();
2524-
t_new_mask = t_image -> makewindowshape();
2525-
t_image -> close();
2526-
// MW-2014-06-11: [[ Bug 12495 ]] Refactored action as different whether using platform API or not.
2527-
if (t_new_mask != NULL)
2528-
updatewindowshape(t_new_mask);
2529-
break;
2530-
}
2515+
// IM-2014-10-22: [[ Bug 13746 ]] use common loadwindowshape() method
2516+
loadwindowshape();
2517+
break;
25312518
}
25322519
#endif
25332520
}

0 commit comments

Comments
 (0)