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

Commit 3bc83a2

Browse files
committed
[[ SVG ]] Further Integration
This patch improves the support for drawing-based images. It ensures that drawing-based images render correctly when an image has a transformation (rotation now works). It ensures that drawing-based images render correctly when used as icons (in particular, with iconGravity). It ensures that drawing-based images work when used from LCB via the 'image from data' constructor.
1 parent f5944ab commit 3bc83a2

File tree

11 files changed

+175
-56
lines changed

11 files changed

+175
-56
lines changed

engine/src/graphicscontext.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,10 +1232,6 @@ void MCGraphicsContext::fillpath(MCPath *path, bool p_evenodd)
12321232

12331233
void MCGraphicsContext::drawpict(uint1 *data, uint4 length, bool embed, const MCRectangle& drect, const MCRectangle& crect)
12341234
{
1235-
MCGContextSave(m_gcontext);
1236-
MCGContextClipToRect(m_gcontext, MCRectangleToMCGRectangle(crect));
1237-
MCGContextPlayback(m_gcontext, MCRectangleToMCGRectangle(drect), MCMakeSpan(static_cast<const byte_t*>(data), length));
1238-
MCGContextRestore(m_gcontext);
12391235
}
12401236

12411237
void MCGraphicsContext::draweps(real8 sx, real8 sy, int2 angle, real8 xscale, real8 yscale, int2 tx, int2 ty,

engine/src/idraw.cpp

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,71 @@ bool MCImage::get_rep_and_transform(MCImageRep *&r_rep, bool &r_has_transform, M
8080

8181
void MCImage::drawme(MCDC *dc, int2 sx, int2 sy, uint2 sw, uint2 sh, int2 dx, int2 dy, uint2 dw, uint2 dh)
8282
{
83-
MCRectangle drect, crect;
84-
8583
if (m_rep != nil)
8684
{
85+
/* Printer output generally requires special-casing */
86+
bool t_printer = dc->gettype() == CONTEXT_TYPE_PRINTER;
87+
88+
/* Update the transform - as necessary */
89+
bool t_update = !((state & CS_SIZE) && (state & CS_EDITED));
90+
91+
if (t_update)
92+
apply_transform();
93+
8794
if (m_rep->GetType() == kMCImageRepVector)
8895
{
89-
MCU_set_rect(drect, dx - sx, dy - sy, rect.width, rect.height);
90-
MCU_set_rect(crect, dx, dy, dw, dh);
91-
static_cast<MCVectorImageRep*>(m_rep)->Render(dc, false, drect, crect);
96+
MCGAffineTransform t_transform;
97+
if (m_has_transform)
98+
{
99+
t_transform = m_transform;
100+
}
101+
else
102+
{
103+
t_transform = MCGAffineTransformMakeIdentity();
104+
}
105+
106+
uindex_t t_rep_width, t_rep_height;
107+
m_rep->GetGeometry(t_rep_width, t_rep_height);
108+
109+
// MW-2014-06-19: [[ IconGravity ]] Scale the image appropriately.
110+
if (dw != sw || dh != sh)
111+
{
112+
t_transform = MCGAffineTransformPreScale(t_transform, dw / (float)sw, dh / (float)sh);
113+
}
114+
115+
// MW-2014-06-19: [[ IconGravity ]] Only clip if we are drawing a partial image (we need to double-check, but I don't think sx/sy are ever non-zero).
116+
MCRectangle t_old_clip;
117+
t_old_clip = dc->getclip();
118+
if (sx != 0 && sy != 0)
119+
{
120+
dc->setclip(MCRectangleMake(dx, dy, sw, sh));
121+
}
122+
123+
t_transform = MCGAffineTransformConcat(t_transform,
124+
MCGAffineTransformMakeTranslation(-(dx - sx), -(dy - sy)));
125+
t_transform = MCGAffineTransformPreTranslate(t_transform, (dx - sx), (dy - sy));
126+
127+
MCGContextRef t_gcontext;
128+
if (dc->lockgcontext(t_gcontext))
129+
{
130+
MCGContextSave(t_gcontext);
131+
132+
MCGContextConcatCTM(t_gcontext, t_transform);
133+
134+
auto t_vector_rep = static_cast<MCVectorImageRep *>(m_rep);
135+
136+
void* t_data;
137+
uindex_t t_data_size;
138+
t_vector_rep->GetData(t_data, t_data_size);
139+
140+
MCGContextPlaybackRectOfDrawing(t_gcontext, MCMakeSpan((const byte_t*)t_data, t_data_size), MCGRectangleMake(0, 0, t_rep_width, t_rep_height), MCGRectangleMake(dx - sx, dy - sy, t_rep_width, t_rep_height));
141+
142+
MCGContextRestore(t_gcontext);
143+
144+
dc->unlockgcontext(t_gcontext);
145+
}
146+
147+
dc->setclip(t_old_clip);
92148
}
93149
else
94150
{
@@ -99,12 +155,6 @@ void MCImage::drawme(MCDC *dc, int2 sx, int2 sy, uint2 sw, uint2 sh, int2 dx, in
99155
bool t_success = true;
100156

101157
MCGImageFrame t_frame;
102-
103-
bool t_printer = dc->gettype() == CONTEXT_TYPE_PRINTER;
104-
bool t_update = !((state & CS_SIZE) && (state & CS_EDITED));
105-
106-
if (t_update)
107-
apply_transform();
108158

109159
// IM-2013-11-06: [[ RefactorGraphics ]] Use common method to get image rep & transform
110160
// so imagedata & rendered image have the same appearance
@@ -201,7 +251,7 @@ void MCImage::drawme(MCDC *dc, int2 sx, int2 sy, uint2 sw, uint2 sh, int2 dx, in
201251
else
202252
{
203253
// can't get image data from rep
204-
drawnodata(dc, drect, sw, sh, dx, dy, dw, dh);
254+
drawnodata(dc, sw, sh, dx, dy, dw, dh);
205255
}
206256

207257
if (t_success)
@@ -233,12 +283,13 @@ void MCImage::drawme(MCDC *dc, int2 sx, int2 sy, uint2 sw, uint2 sh, int2 dx, in
233283
else if (!MCStringIsEmpty(filename))
234284
{
235285
// AL-2014-01-15: [[ Bug 11570 ]] Draw stippled background when referenced image file not found
236-
drawnodata(dc, rect, sw, sh, dx, dy, dw, dh);
286+
drawnodata(dc, sw, sh, dx, dy, dw, dh);
237287
}
238288
}
239289

240-
void MCImage::drawnodata(MCDC *dc, MCRectangle drect, uint2 sw, uint2 sh, int2 dx, int2 dy, uint2 dw, uint2 dh)
290+
void MCImage::drawnodata(MCDC *dc, uint2 sw, uint2 sh, int2 dx, int2 dy, uint2 dw, uint2 dh)
241291
{
292+
MCRectangle drect;
242293
MCU_set_rect(drect, dx, dy, dw, dh);
243294
setforeground(dc, DI_BACK, False);
244295
dc->setbackground(MCscreen->getwhite());

engine/src/image.cpp

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1977,6 +1977,63 @@ bool MCImage::lockbitmap(bool p_premultiplied, bool p_update_transform, const MC
19771977
else
19781978
t_size = *p_size;
19791979

1980+
/* Special case vector image reps - as they don't have pixels! */
1981+
if (t_success &&
1982+
t_rep->GetType() == kMCImageRepVector)
1983+
{
1984+
/* Start with the identity transform, if none */
1985+
if (!t_has_transform)
1986+
t_transform = MCGAffineTransformMakeIdentity();
1987+
1988+
/* Scale from the rect size to the requested size. */
1989+
MCGFloat t_x_scale, t_y_scale;
1990+
t_x_scale = (MCGFloat)t_size.width / (MCGFloat)rect.width;
1991+
t_y_scale = (MCGFloat)t_size.height / (MCGFloat)rect.height;
1992+
t_transform = MCGAffineTransformConcat(MCGAffineTransformMakeScale(t_x_scale, t_y_scale), t_transform);
1993+
1994+
MCImageBitmap *t_bitmap = nullptr;
1995+
t_success = MCImageBitmapCreate(t_size.width, t_size.height, t_bitmap);
1996+
1997+
MCGContextRef t_context = nullptr;
1998+
if (t_success)
1999+
{
2000+
MCImageBitmapClear(t_bitmap);
2001+
t_success = MCGContextCreateWithPixels(t_bitmap->width, t_bitmap->height, t_bitmap->stride, t_bitmap->data, true, t_context);
2002+
}
2003+
2004+
if (t_success)
2005+
{
2006+
MCGContextConcatCTM(t_context, t_transform);
2007+
2008+
auto t_vector_rep = static_cast<MCVectorImageRep *>(t_rep);
2009+
2010+
void* t_data;
2011+
uindex_t t_data_size;
2012+
t_vector_rep->GetData(t_data, t_data_size);
2013+
2014+
MCGContextPlaybackRectOfDrawing(t_context, MCMakeSpan((const byte_t*)t_data, t_data_size), MCGRectangleMake(0, 0, t_width, t_height), MCGRectangleMake(0, 0, t_size.width, t_size.height));
2015+
}
2016+
2017+
MCGContextRelease(t_context);
2018+
2019+
if (t_success)
2020+
{
2021+
MCImageBitmapCheckTransparency(t_bitmap);
2022+
if (!p_premultiplied)
2023+
{
2024+
MCImageBitmapUnpremultiply(t_bitmap);
2025+
}
2026+
2027+
r_bitmap = t_bitmap;
2028+
}
2029+
else
2030+
{
2031+
MCImageFreeBitmap(t_bitmap);
2032+
}
2033+
2034+
return t_success;
2035+
}
2036+
19802037
if (t_success)
19812038
{
19822039
if (!t_has_transform)
@@ -1986,7 +2043,6 @@ bool MCImage::lockbitmap(bool p_premultiplied, bool p_update_transform, const MC
19862043
MCGFloat t_x_scale, t_y_scale;
19872044
t_x_scale = (MCGFloat)t_size.width / (MCGFloat)rect.width;
19882045
t_y_scale = (MCGFloat)t_size.height / (MCGFloat)rect.height;
1989-
19902046
t_transform = MCGAffineTransformConcat(MCGAffineTransformMakeScale(t_x_scale, t_y_scale), t_transform);
19912047

19922048
t_transform_scale = MCGAffineTransformGetEffectiveScale(t_transform);

engine/src/image.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ class MCImage : public MCControl, public MCMixinObjectHandle<MCImage>
518518
// in idraw.cc
519519
void drawme(MCDC *dc, int2 sx, int2 sy, uint2 sw, uint2 sh, int2 dx, int2 dy, uint2 dw, uint2 dh);
520520
void drawcentered(MCDC *dc, int2 x, int2 y, Boolean reverse);
521-
void drawnodata(MCDC *dc, MCRectangle drect, uint2 sw, uint2 sh, int2 dx, int2 dy, uint2 dw, uint2 dh);
521+
void drawnodata(MCDC *dc, uint2 sw, uint2 sh, int2 dx, int2 dy, uint2 dw, uint2 dh);
522522

523523
void drawwithgravity(MCDC *dc, MCRectangle rect, MCGravity gravity);
524524

engine/src/image_rep.cpp

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
2424
#include "image.h"
2525
#include "image_rep.h"
2626

27+
#include "graphics_util.h"
28+
2729
////////////////////////////////////////////////////////////////////////////////
2830

2931
MCImageRep::MCImageRep()
@@ -767,7 +769,7 @@ bool MCImageRepGetResident(const void *p_data, uindex_t p_size, MCImageRep *&r_r
767769
return t_success;
768770
}
769771

770-
bool MCImageRepGetVector(void *p_data, uindex_t p_size, MCImageRep *&r_rep)
772+
bool MCImageRepGetVector(const void *p_data, uindex_t p_size, MCImageRep *&r_rep)
771773
{
772774
bool t_success = true;
773775

@@ -864,6 +866,12 @@ bool MCImageRepCreateWithPath(MCStringRef p_path, MCImageRep *&r_image_rep)
864866

865867
bool MCImageRepCreateWithData(MCDataRef p_data, MCImageRep *&r_image_rep)
866868
{
869+
if (MCDataGetLength(p_data) >= 3 &&
870+
memcmp(MCDataGetBytePtr(p_data), "LCD", 3) == 0)
871+
{
872+
return MCImageRepGetVector(MCDataGetBytePtr(p_data), MCDataGetLength(p_data), r_image_rep);
873+
}
874+
867875
return MCImageRepGetResident(MCDataGetBytePtr(p_data), MCDataGetLength(p_data), r_image_rep);
868876
}
869877

@@ -905,6 +913,37 @@ void MCImageRepUnlockRaster(MCImageRep *p_image_rep, uint32_t p_index, MCImageBi
905913
p_image_rep->UnlockBitmap(p_index, p_raster);
906914
}
907915

916+
void MCImageRepRender(MCImageRep *p_image_rep, MCGContextRef p_gcontext, uint32_t p_index, MCGRectangle p_src_rect, MCGRectangle p_dst_rect, MCGImageFilter p_filter)
917+
{
918+
if (p_image_rep->GetType() == kMCImageRepVector)
919+
{
920+
auto t_vector_rep = static_cast<MCVectorImageRep *>(p_image_rep);
921+
922+
void* t_data;
923+
uindex_t t_data_size;
924+
t_vector_rep->GetData(t_data, t_data_size);
925+
926+
MCGContextPlaybackRectOfDrawing(p_gcontext, MCMakeSpan((const byte_t*)t_data, t_data_size), p_src_rect, p_dst_rect);
927+
}
928+
else
929+
{
930+
MCGFloat t_scale;
931+
t_scale = MCGAffineTransformGetEffectiveScale(MCGContextGetDeviceTransform(p_gcontext));
932+
933+
MCGImageFrame t_frame;
934+
if (MCImageRepLock(p_image_rep, p_index, t_scale, t_frame))
935+
{
936+
MCGAffineTransform t_transform;
937+
t_transform = MCGAffineTransformMakeScale(1.0 / t_frame.x_scale, 1.0 / t_frame.y_scale);
938+
939+
MCGRectangle t_src_rect;
940+
t_src_rect = MCGRectangleScale(p_src_rect, t_frame.x_scale, t_frame.y_scale);
941+
942+
MCGContextDrawRectOfImage(p_gcontext, t_frame.image, t_src_rect, p_dst_rect, p_filter);
943+
944+
MCImageRepUnlock(p_image_rep, 0, t_frame);
945+
}
946+
}
947+
}
908948

909949
////////////////////////////////////////////////////////////////////////////////
910-

engine/src/image_rep.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -301,16 +301,14 @@ class MCVectorImageRep : public MCLoadableImageRep
301301
uint32_t GetDataCompression();
302302

303303
uindex_t GetFrameCount() { return 1; }
304-
304+
305305
//////////
306306

307307
void GetData(void *&r_data, uindex_t &r_size)
308308
{
309309
r_data = m_data, r_size = m_size;
310310
}
311311

312-
bool Render(MCDC *p_context, bool p_embed, MCRectangle &p_image_rect, MCRectangle &p_clip_rect);
313-
314312
protected:
315313
bool LoadImageFrames(MCBitmapFrame *&r_frames, uindex_t &r_frame_count, bool &r_frames_premultiplied);
316314
bool LoadHeader(uindex_t &r_width, uindex_t &r_height, uint32_t &r_frame_count);
@@ -464,7 +462,7 @@ bool MCImageRepCreateReferencedWithSearchKey(MCStringRef p_filename, MCStringRef
464462

465463
bool MCImageRepGetReferenced(MCStringRef p_filename, MCImageRep *&r_rep);
466464
bool MCImageRepGetResident(const void *p_data, uindex_t p_size, MCImageRep *&r_rep);
467-
bool MCImageRepGetVector(void *p_data, uindex_t p_size, MCImageRep *&r_rep);
465+
bool MCImageRepGetVector(const void *p_data, uindex_t p_size, MCImageRep *&r_rep);
468466
bool MCImageRepGetCompressed(MCImageCompressedBitmap *p_compressed, MCImageRep *&r_rep);
469467
bool MCImageRepGetDensityMapped(MCStringRef p_filename, MCImageRep *&r_rep);
470468

engine/src/image_rep_encoded.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -273,12 +273,6 @@ MCVectorImageRep::~MCVectorImageRep()
273273
MCMemoryDeallocate(m_data);
274274
}
275275

276-
bool MCVectorImageRep::Render(MCDC *p_context, bool p_embed, MCRectangle &p_image_rect, MCRectangle &p_clip_rect)
277-
{
278-
p_context->drawpict((uint8_t*)m_data, m_size, p_embed, p_image_rect, p_clip_rect);
279-
return true;
280-
}
281-
282276
bool MCVectorImageRep::LoadImageFrames(MCBitmapFrame *&r_frames, uindex_t &r_frame_count, bool &r_frames_premultiplied)
283277
{
284278
/* OVERHAUL - REVISIT - should be able to render into an image context

engine/src/module-canvas.cpp

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5795,23 +5795,7 @@ void MCCanvasDrawRectOfImage(MCCanvasRef p_canvas, MCCanvasImageRef p_image, con
57955795

57965796
MCCanvasApplyChanges(*t_canvas);
57975797

5798-
MCGImageFrame t_frame;
5799-
5800-
MCGFloat t_scale;
5801-
t_scale = MCGAffineTransformGetEffectiveScale(MCGContextGetDeviceTransform(t_canvas->context));
5802-
5803-
if (MCImageRepLock(t_image, 0, t_scale, t_frame))
5804-
{
5805-
MCGAffineTransform t_transform;
5806-
t_transform = MCGAffineTransformMakeScale(1.0 / t_frame.x_scale, 1.0 / t_frame.y_scale);
5807-
5808-
MCGRectangle t_src_rect;
5809-
t_src_rect = MCGRectangleScale(p_src_rect, t_frame.x_scale, t_frame.y_scale);
5810-
5811-
MCGContextDrawRectOfImage(t_canvas->context, t_frame.image, t_src_rect, p_dst_rect, t_canvas->props().image_filter);
5812-
5813-
MCImageRepUnlock(t_image, 0, t_frame);
5814-
}
5798+
MCImageRepRender(t_image, t_canvas->context, 0, p_src_rect, p_dst_rect, t_canvas->props().image_filter);
58155799
}
58165800

58175801
MC_DLLEXPORT_DEF

engine/src/module-canvas.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ void MCImageRepUnlock(MCImageRep *p_image_rep, uint32_t p_index, MCGImageFrame &
6464
bool MCImageRepLockRaster(MCImageRep *p_image_rep, uint32_t p_index, MCGFloat p_density, MCImageBitmap *&r_raster);
6565
void MCImageRepUnlockRaster(MCImageRep *p_image_rep, uint32_t p_index, MCImageBitmap *p_raster);
6666

67+
void MCImageRepRender(MCImageRep *p_image_rep, MCGContextRef p_gcontext, uint32_t p_index, MCGRectangle p_src_rect, MCGRectangle p_dst_rect, MCGImageFilter p_filter);
68+
6769
//////////
6870

6971
bool MCImageRepGetTransformed(MCImageRep *p_image_rep, const MCGAffineTransform &p_transform, const MCGSize *p_output_size, MCGImageFilter p_resize_quality, MCImageRep *&r_transformed);

libgraphics/include/graphics.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,7 @@ void MCGContextDrawPlatformText(MCGContextRef context, const unichar_t *text, ui
10231023
MCGFloat MCGContextMeasurePlatformText(MCGContextRef context, const unichar_t *text, uindex_t length, const MCGFont &p_font, const MCGAffineTransform &p_transform);
10241024
bool MCGContextMeasurePlatformTextImageBounds(MCGContextRef context, const unichar_t *text, uindex_t length, const MCGFont &p_font, const MCGAffineTransform &p_transform, MCGRectangle &r_bounds);
10251025

1026-
void MCGContextPlayback(MCGContextRef context, MCGRectangle p_dst_rect, MCSpan<const byte_t> p_drawing);
1026+
void MCGContextPlaybackRectOfDrawing(MCGContextRef context, MCSpan<const byte_t> p_drawing, MCGRectangle p_src, MCGRectangle p_dst);
10271027

10281028
////////////////////////////////////////////////////////////////////////////////
10291029

0 commit comments

Comments
 (0)