From 1edd1ffbf1af3ce444ad83e3ace21be149ede515 Mon Sep 17 00:00:00 2001 From: reflectronic Date: Thu, 25 Jun 2020 16:31:17 -0400 Subject: [PATCH 01/16] Define CachedBitmap and implmement creation of CachedBitmap --- src/GdiPlusFlat.h | 2 ++ src/cachedbitmap-private.h | 10 +++++++++ src/cachedbitmap.c | 44 ++++++++++++++++++++++++++++++++++++++ src/cachedbitmap.h | 8 +++++++ src/gdiplus-private.h | 1 + src/graphics.c | 10 ++++++++- src/graphics.h | 2 ++ 7 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 src/cachedbitmap-private.h create mode 100644 src/cachedbitmap.c create mode 100644 src/cachedbitmap.h diff --git a/src/GdiPlusFlat.h b/src/GdiPlusFlat.h index e967f71db..23cbc7843 100644 --- a/src/GdiPlusFlat.h +++ b/src/GdiPlusFlat.h @@ -52,6 +52,7 @@ extern "C" typedef void GpAdjustableArrowCap; typedef void GpBitmap; typedef void GpBrush; +typedef void GpCachedBitmap; typedef void GpCustomLineCap; typedef void GpFont; typedef void GpFontCollection; @@ -87,6 +88,7 @@ typedef void GpTexture; #include "adjustablearrowcap.h" #include "bitmap.h" #include "brush.h" +#include "cachedbitmap.h" #include "customlinecap.h" #include "font.h" #include "fontcollection.h" diff --git a/src/cachedbitmap-private.h b/src/cachedbitmap-private.h new file mode 100644 index 000000000..67fb38e64 --- /dev/null +++ b/src/cachedbitmap-private.h @@ -0,0 +1,10 @@ +#ifndef __CACHEDBITMAP_PRIVATE_H__ +#define __CACHEDBITMAP_PRIVATE_H__ + +typedef struct _CachedBitmap { + cairo_surface_t *surface; +} CachedBitmap; + +#include "cachedbitmap.h" + +#endif \ No newline at end of file diff --git a/src/cachedbitmap.c b/src/cachedbitmap.c new file mode 100644 index 000000000..4158afd7f --- /dev/null +++ b/src/cachedbitmap.c @@ -0,0 +1,44 @@ +#include "general-private.h" +#include "bitmap-private.h" +#include "graphics-private.h" +#include "cachedbitmap-private.h" + +GpStatus WINGDIPAPI GdipCreateCachedBitmap (GpBitmap *bitmap, GpGraphics *graphics, GpCachedBitmap **cachedBitmap) +{ + cairo_surface_t *surface; + GpCachedBitmap *newCachedBitmap; + cairo_status_t status; + + if (!bitmap || !graphics || !cachedBitmap) + return InvalidParameter; + if (bitmap->type != ImageTypeBitmap) + return InvalidParameter; + + surface = cairo_surface_create_similar_image(bitmap->surface, bitmap->cairo_format, bitmap->active_bitmap->width, bitmap->active_bitmap->height) + + status = cairo_surface_status (surface); + if (status != CAIRO_STATUS_SUCCESS) { + cairo_surface_destroy (surface); + return gdip_get_status (status); + } + + newCachedBitmap = GdipAlloc (sizeof (GpCachedBitmap)); + if (!newCachedBitmap) + return OutOfMemory; + + newCachedBitmap->surface = surface; + + *cachedBitmap = newCachedBitmap; + return Ok; +} + +GpStatus WINGDIPAPI GdipDeleteCachedBitmap (GpCachedBitmap *cachedBitmap) +{ + if (!cachedBitmap) + return InvalidParameter; + + cairo_surface_destroy(cachedBitmap->surface); + GdipFree(cachedBitmap); + + return Ok; +} \ No newline at end of file diff --git a/src/cachedbitmap.h b/src/cachedbitmap.h new file mode 100644 index 000000000..4c8e63385 --- /dev/null +++ b/src/cachedbitmap.h @@ -0,0 +1,8 @@ +#ifndef __CACHEDBITMAP_H__ +#define __CACHEDBITMAP_H__ + +GpStatus WINGDIPAPI GdipCreateCachedBitmap (GpBitmap *bitmap, GpGraphics *graphics, GpCachedBitmap **cachedBitmap); + +GpStatus WINGDIPAPI GdipDeleteCachedBitmap (GpCachedBitmap *cachedBitmap); + +#endif \ No newline at end of file diff --git a/src/gdiplus-private.h b/src/gdiplus-private.h index 00c2cc1ce..f6a39cc81 100644 --- a/src/gdiplus-private.h +++ b/src/gdiplus-private.h @@ -80,6 +80,7 @@ typedef struct _AdjustableArrowCap GpAdjustableArrowCap; typedef struct _Brush GpBrush; +typedef struct _CachedBitmap GpCachedBitmap; typedef struct _CustomLineCap GpCustomLineCap; typedef struct _Font GpFont; typedef struct _FontCollection GpFontCollection; diff --git a/src/graphics.c b/src/graphics.c index 340629099..c0533763d 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -35,6 +35,7 @@ #include "brush-private.h" #include "matrix-private.h" #include "bitmap-private.h" +#include "cachedbitmap-private.h" #include "metafile-private.h" #include @@ -1361,6 +1362,13 @@ GdipDrawCurve3I (GpGraphics *graphics, GpPen* pen, GDIPCONST GpPoint *points, IN return status; } +GpStatus WINGDIPAPI +GdipDrawCachedBitmap (GpGraphics *graphics, GpCachedBitmap *cachedBitmap, INT x, INT y) +{ + if (!graphics || !cachedBitmap) + return InvalidParameter; +} + /* * Fills */ @@ -2073,7 +2081,7 @@ GdipSetClipRect (GpGraphics *graphics, REAL x, REAL y, REAL width, REAL height, } status = GdipSetClipRegion (graphics, region, combineMode); - GdipDeleteRegion (region); + GdipDeleteRe gion (region); return status; } diff --git a/src/graphics.h b/src/graphics.h index 716fa0189..4e06f4286 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -115,6 +115,8 @@ GpStatus WINGDIPAPI GdipFillPieI( GpGraphics *graphics, GpBrush *brush, INT x, I GpStatus WINGDIPAPI GdipFillRegion (GpGraphics *graphics, GpBrush *brush, GpRegion *region); GpStatus WINGDIPAPI GdipGraphicsClear (GpGraphics *graphics, ARGB color); +GpStatus WINGDIPAPI GdipDrawCachedBitmap (GpGraphics *graphics, GpCachedBitmap *cachedBitmap, INT x, INT y); + GpStatus WINGDIPAPI GdipGetDpiX( GpGraphics *graphics, REAL *dpi); GpStatus WINGDIPAPI GdipGetDpiY (GpGraphics *graphics, REAL *dpi); GpStatus WINGDIPAPI GdipGetNearestColor (GpGraphics *graphics, ARGB *argb); From 214944c8d3af58e7e4d1509c7494b66fe613f101 Mon Sep 17 00:00:00 2001 From: reflectronic Date: Thu, 25 Jun 2020 17:01:23 -0400 Subject: [PATCH 02/16] Initial implementation of drawing --- src/graphics.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/graphics.c b/src/graphics.c index c0533763d..73c9fb307 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1367,6 +1367,9 @@ GdipDrawCachedBitmap (GpGraphics *graphics, GpCachedBitmap *cachedBitmap, INT x, { if (!graphics || !cachedBitmap) return InvalidParameter; + + cairo_set_source_surface(graphics->ct, cachedBitmap->surface, x, y); + cairo_paint(graphics->ct); } /* From 8d93375d2d0d1013c0174653ad23f0293f9486e0 Mon Sep 17 00:00:00 2001 From: reflectronic Date: Thu, 25 Jun 2020 18:40:06 -0400 Subject: [PATCH 03/16] Fix build --- src/Makefile.am | 3 +++ src/cachedbitmap.c | 2 +- src/graphics.c | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 3d3de32f8..bfd343350 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,6 +11,9 @@ libgdiplus_la_SOURCES = \ brush.c \ brush.h \ brush-private.h \ + cachedbitmap.c \ + cachedbitmap.h \ + cachedbitmap-private.h \ carbon-private.c \ carbon-private.h \ codecs.h \ diff --git a/src/cachedbitmap.c b/src/cachedbitmap.c index 4158afd7f..bbccf1193 100644 --- a/src/cachedbitmap.c +++ b/src/cachedbitmap.c @@ -14,7 +14,7 @@ GpStatus WINGDIPAPI GdipCreateCachedBitmap (GpBitmap *bitmap, GpGraphics *graphi if (bitmap->type != ImageTypeBitmap) return InvalidParameter; - surface = cairo_surface_create_similar_image(bitmap->surface, bitmap->cairo_format, bitmap->active_bitmap->width, bitmap->active_bitmap->height) + surface = cairo_surface_create_similar_image(bitmap->surface, bitmap->cairo_format, bitmap->active_bitmap->width, bitmap->active_bitmap->height); status = cairo_surface_status (surface); if (status != CAIRO_STATUS_SUCCESS) { diff --git a/src/graphics.c b/src/graphics.c index 73c9fb307..aba7aba0b 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -2084,7 +2084,7 @@ GdipSetClipRect (GpGraphics *graphics, REAL x, REAL y, REAL width, REAL height, } status = GdipSetClipRegion (graphics, region, combineMode); - GdipDeleteRe gion (region); + GdipDeleteRegion (region); return status; } From 1b50fd32f1031035de2ce9b5d58ed073ab678688 Mon Sep 17 00:00:00 2001 From: reflectronic Date: Fri, 26 Jun 2020 02:59:38 -0400 Subject: [PATCH 04/16] Copy image to surface --- src/cachedbitmap.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/cachedbitmap.c b/src/cachedbitmap.c index bbccf1193..27e1100ba 100644 --- a/src/cachedbitmap.c +++ b/src/cachedbitmap.c @@ -5,6 +5,7 @@ GpStatus WINGDIPAPI GdipCreateCachedBitmap (GpBitmap *bitmap, GpGraphics *graphics, GpCachedBitmap **cachedBitmap) { + cairo_t *ct; cairo_surface_t *surface; GpCachedBitmap *newCachedBitmap; cairo_status_t status; @@ -12,16 +13,25 @@ GpStatus WINGDIPAPI GdipCreateCachedBitmap (GpBitmap *bitmap, GpGraphics *graphi if (!bitmap || !graphics || !cachedBitmap) return InvalidParameter; if (bitmap->type != ImageTypeBitmap) - return InvalidParameter; + return InvalidParameter; + + gdip_bitmap_ensure_surface(bitmap); + + surface = cairo_surface_create_similar(bitmap->surface, CAIRO_CONTENT_COLOR_ALPHA, bitmap->active_bitmap->width, bitmap->active_bitmap->height); + + ct = cairo_create(surface); - surface = cairo_surface_create_similar_image(bitmap->surface, bitmap->cairo_format, bitmap->active_bitmap->width, bitmap->active_bitmap->height); + cairo_set_source_surface (ct, bitmap->surface, 0, 0); + cairo_paint (ct); + cairo_destroy(ct); + status = cairo_surface_status (surface); if (status != CAIRO_STATUS_SUCCESS) { cairo_surface_destroy (surface); return gdip_get_status (status); } - + newCachedBitmap = GdipAlloc (sizeof (GpCachedBitmap)); if (!newCachedBitmap) return OutOfMemory; @@ -29,6 +39,8 @@ GpStatus WINGDIPAPI GdipCreateCachedBitmap (GpBitmap *bitmap, GpGraphics *graphi newCachedBitmap->surface = surface; *cachedBitmap = newCachedBitmap; + + return Ok; } From df4953974c0155ecbdaf68b3e94ae913b918e4ed Mon Sep 17 00:00:00 2001 From: reflectronic Date: Fri, 26 Jun 2020 02:59:54 -0400 Subject: [PATCH 05/16] Small fixes --- src/graphics.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/graphics.c b/src/graphics.c index aba7aba0b..b264a1e23 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1367,9 +1367,15 @@ GdipDrawCachedBitmap (GpGraphics *graphics, GpCachedBitmap *cachedBitmap, INT x, { if (!graphics || !cachedBitmap) return InvalidParameter; + if (graphics->state == GraphicsStateBusy) + return ObjectBusy; + cairo_identity_matrix(graphics->ct); + cairo_set_source_surface(graphics->ct, cachedBitmap->surface, x, y); cairo_paint(graphics->ct); + + return Ok; } /* From 90c8c1f51ea184f3fb62cb665c9785430a496f3e Mon Sep 17 00:00:00 2001 From: reflectronic Date: Fri, 26 Jun 2020 02:59:58 -0400 Subject: [PATCH 06/16] Add tests --- tests/Makefile.am | 10 ++ tests/testcachedbitmap | 210 +++++++++++++++++++++++++++++++++++++++ tests/testcachedbitmap.c | 140 ++++++++++++++++++++++++++ 3 files changed, 360 insertions(+) create mode 100755 tests/testcachedbitmap create mode 100644 tests/testcachedbitmap.c diff --git a/tests/Makefile.am b/tests/Makefile.am index baa00c658..ad99a71f5 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -22,6 +22,7 @@ noinst_PROGRAMS = \ testbits \ testbmpcodec \ testbrush \ + testcachedbitmap \ testclip \ testcodecs \ testcustomlinecap \ @@ -91,6 +92,13 @@ testbrush_SOURCES = \ testbrush_DEPENDENCIES = $(TEST_DEPS) testbrush_LDADD = $(LDADDS) + +testcachedbitmap_SOURCES = \ + testcachedbitmap.c + +testcachedbitmap_DEPENDENCIES = $(TEST_DEPS) +testcachedbitmap_LDADD = $(LDADDS) + testclip_SOURCES = \ testclip.c @@ -283,6 +291,7 @@ EXTRA_DIST = \ $(testbits_SOURCES) \ $(testbmpcodec_SOURCES) \ $(testbrush_SOURCES) \ + $(testcachedbitmap_SOURCES) $(testclip_SOURCES) \ $(test_codecs_SOURCES) \ $(testcustomlinecap_SOURCES) \ @@ -339,6 +348,7 @@ TESTS = \ testbits \ testbmpcodec \ testbrush \ + testcachedbitmap \ testclip \ testcodecs \ testcustomlinecap \ diff --git a/tests/testcachedbitmap b/tests/testcachedbitmap new file mode 100755 index 000000000..10fd12838 --- /dev/null +++ b/tests/testcachedbitmap @@ -0,0 +1,210 @@ +#! /bin/sh + +# testcachedbitmap - temporary wrapper script for .libs/testcachedbitmap +# Generated by libtool (GNU libtool) 2.4.6 +# +# The testcachedbitmap program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command="" + +# This environment variable determines our operation mode. +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then + # install mode needs the following variables: + generated_by_libtool_version='2.4.6' + notinst_deplibs=' ../src/libgdiplus.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + file="$0" + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + ECHO="printf %s\\n" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string --lt- +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's ../libtool value, followed by no. +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=$0 + shift + for lt_opt + do + case "$lt_opt" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` + test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. + lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'` + cat "$lt_dump_D/$lt_dump_F" + exit 0 + ;; + --lt-*) + $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n "$lt_option_debug"; then + echo "testcachedbitmap:testcachedbitmap:$LINENO: libtool wrapper (GNU libtool) 2.4.6" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + $ECHO "testcachedbitmap:testcachedbitmap:$LINENO: newargv[$lt_dump_args_N]: $lt_arg" + lt_dump_args_N=`expr $lt_dump_args_N + 1` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ + + if test -n "$lt_option_debug"; then + $ECHO "testcachedbitmap:testcachedbitmap:$LINENO: newargv[0]: $progdir/$program" 1>&2 + func_lt_dump_args ${1+"$@"} 1>&2 + fi + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from $@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case " $* " in + *\ --lt-*) + for lt_wr_arg + do + case $lt_wr_arg in + --lt-*) ;; + *) set x "$@" "$lt_wr_arg"; shift;; + esac + shift + done ;; + esac + func_exec_program_core ${1+"$@"} +} + + # Parse options + func_parse_lt_options "$0" ${1+"$@"} + + # Find the directory that this script lives in. + thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` + test "x$thisdir" = "x$file" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'` + while test -n "$file"; do + destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` + + # If there was a directory component, then change thisdir. + if test "x$destdir" != "x$file"; then + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; + *) thisdir="$thisdir/$destdir" ;; + esac + fi + + file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'` + file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no + if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then + # special case for '.' + if test "$thisdir" = "."; then + thisdir=`pwd` + fi + # remove .libs from thisdir + case "$thisdir" in + *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program='testcachedbitmap' + progdir="$thisdir/.libs" + + + if test -f "$progdir/$program"; then + # Add our own library path to DYLD_LIBRARY_PATH + DYLD_LIBRARY_PATH="/Users/reflectronic/Repos/libgdiplus/src/.libs:$DYLD_LIBRARY_PATH" + + # Some systems cannot cope with colon-terminated DYLD_LIBRARY_PATH + # The second colon is a workaround for a bug in BeOS R4 sed + DYLD_LIBRARY_PATH=`$ECHO "$DYLD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'` + + export DYLD_LIBRARY_PATH + + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + # Run the actual program with our arguments. + func_exec_program ${1+"$@"} + fi + else + # The program doesn't exist. + $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2 + $ECHO "This script is just a wrapper for $program." 1>&2 + $ECHO "See the libtool documentation for more information." 1>&2 + exit 1 + fi +fi diff --git a/tests/testcachedbitmap.c b/tests/testcachedbitmap.c new file mode 100644 index 000000000..9219289cb --- /dev/null +++ b/tests/testcachedbitmap.c @@ -0,0 +1,140 @@ +#ifdef WIN32 +#ifndef __cplusplus +#error Please compile with a C++ compiler. +#endif +#endif + +#if defined(USE_WINDOWS_GDIPLUS) +#include +#include + +#pragma comment(lib, "gdiplus.lib") +#else +#include +#endif + +#if defined(USE_WINDOWS_GDIPLUS) +using namespace Gdiplus; +using namespace DllExports; +#endif + +#include +#include +#include +#include "testhelpers.h" + +static GpGraphics *getImageGraphics (GpImage **image) +{ + GpStatus status; + WCHAR *filePath; + GpGraphics *graphics; + + filePath = createWchar ("test.bmp"); + status = GdipLoadImageFromFile (filePath, image); + assertEqualInt (status, Ok); + + freeWchar (filePath); + + status = GdipGetImageGraphicsContext (*image, &graphics); + assertEqualInt (status, Ok); + + return graphics; +} + +static GpImage* getImage (const char* fileName) +{ + GpStatus status; + WCHAR *wFileName = wcharFromChar (fileName); + GpImage *image; + + status = GdipLoadImageFromFile (wFileName, &image); + assertEqualInt (status, Ok); + + freeWchar (wFileName); + + return image; +} + +static void test_roundtrip () +{ + UINT width; + UINT height; + GpBitmap *originalBitmap; + GpBitmap *surface; + GpGraphics *graphics; + GpCachedBitmap *cached; + + originalBitmap = getImage("test.bmp"); + + + assertEqualInt(GdipGetImageWidth(originalBitmap, &width), Ok); + assertEqualInt(GdipGetImageHeight(originalBitmap, &height), Ok); + + assertEqualInt(GdipCreateBitmapFromScan0(width, height, 0, PixelFormat32bppARGB, 0, &surface), Ok); + assertEqualInt(GdipGetImageGraphicsContext(surface, &graphics), Ok); + + GpRect rect = { + .X = 0, + .Y = 0, + .Width = width, + .Height = height + }; + + + assertEqualInt(GdipSetVisibleClip_linux(graphics, &rect), Ok); + assertEqualInt(GdipCreateCachedBitmap(originalBitmap, graphics, &cached), Ok); + assertEqualInt(GdipDrawCachedBitmap(graphics, cached, 0, 0), Ok); + + CLSID png_clsid = { 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }; + WCHAR *filePath = createWchar ("HELP.png"); + GdipSaveImageToFile (surface, filePath, &png_clsid, NULL); + + for (int x = 0; x < width; x++) + { + for (int y = 0; y < height; y++) + { + ARGB drawn, original; + assertEqualInt(GdipBitmapGetPixel(originalBitmap, x, y, &original), Ok); + + assertEqualInt(GdipBitmapGetPixel(surface, x, y, &drawn), Ok); + + assertEqualInt(drawn, original); + } + } +} + +static void test_create () +{ + GpStatus status; + GpImage *image; + GpGraphics *graphics; + GpCachedBitmap* cachedBitmap; + + graphics = getImageGraphics (&image); + + assertEqualInt(GdipCreateCachedBitmap(image, graphics, &cachedBitmap), Ok); + + // Negative tests. + image = getImage ("test.wmf"); + status = GdipCreateCachedBitmap(image, graphics, &cachedBitmap); + assertEqualInt(status, InvalidParameter); + + assertEqualInt(GdipCreateCachedBitmap(image, graphics, NULL), InvalidParameter); + assertEqualInt(GdipCreateCachedBitmap(image, NULL, &cachedBitmap), InvalidParameter); + assertEqualInt(GdipCreateCachedBitmap(NULL, graphics, &cachedBitmap), InvalidParameter); + + GdipDeleteGraphics(graphics); + GdipDisposeImage(image); +} + +int +main (int argc, char**argv) +{ + STARTUP; + + test_create (); + test_roundtrip (); + + SHUTDOWN; + return 0; +} From 9604d0a757b2ecc769dc9ee3f14839df0fefa9c3 Mon Sep 17 00:00:00 2001 From: reflectronic Date: Fri, 26 Jun 2020 03:23:40 -0400 Subject: [PATCH 07/16] Use correct formatting --- src/Makefile.am | 4 +- src/cachedbitmap-private.h | 4 +- src/cachedbitmap.c | 72 ++++++------- src/cachedbitmap.h | 2 +- src/graphics.c | 6 +- tests/Makefile.am | 2 +- tests/testcachedbitmap | 210 ------------------------------------- tests/testcachedbitmap.c | 127 +++++++++++----------- 8 files changed, 104 insertions(+), 323 deletions(-) delete mode 100755 tests/testcachedbitmap diff --git a/src/Makefile.am b/src/Makefile.am index bfd343350..80f10e15a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,8 +11,8 @@ libgdiplus_la_SOURCES = \ brush.c \ brush.h \ brush-private.h \ - cachedbitmap.c \ - cachedbitmap.h \ + cachedbitmap.c \ + cachedbitmap.h \ cachedbitmap-private.h \ carbon-private.c \ carbon-private.h \ diff --git a/src/cachedbitmap-private.h b/src/cachedbitmap-private.h index 67fb38e64..d8262f9ed 100644 --- a/src/cachedbitmap-private.h +++ b/src/cachedbitmap-private.h @@ -2,9 +2,9 @@ #define __CACHEDBITMAP_PRIVATE_H__ typedef struct _CachedBitmap { - cairo_surface_t *surface; + cairo_surface_t *surface; } CachedBitmap; #include "cachedbitmap.h" -#endif \ No newline at end of file +#endif diff --git a/src/cachedbitmap.c b/src/cachedbitmap.c index 27e1100ba..c5339594b 100644 --- a/src/cachedbitmap.c +++ b/src/cachedbitmap.c @@ -3,54 +3,54 @@ #include "graphics-private.h" #include "cachedbitmap-private.h" -GpStatus WINGDIPAPI GdipCreateCachedBitmap (GpBitmap *bitmap, GpGraphics *graphics, GpCachedBitmap **cachedBitmap) +GpStatus WINGDIPAPI +GdipCreateCachedBitmap (GpBitmap *bitmap, GpGraphics *graphics, GpCachedBitmap **cachedBitmap) { - cairo_t *ct; - cairo_surface_t *surface; - GpCachedBitmap *newCachedBitmap; - cairo_status_t status; + cairo_t *ct; + cairo_surface_t *surface; + GpCachedBitmap *newCachedBitmap; + cairo_status_t status; - if (!bitmap || !graphics || !cachedBitmap) - return InvalidParameter; - if (bitmap->type != ImageTypeBitmap) - return InvalidParameter; - - gdip_bitmap_ensure_surface(bitmap); + if (!bitmap || !graphics || !cachedBitmap) + return InvalidParameter; + if (bitmap->type != ImageTypeBitmap) + return InvalidParameter; - surface = cairo_surface_create_similar(bitmap->surface, CAIRO_CONTENT_COLOR_ALPHA, bitmap->active_bitmap->width, bitmap->active_bitmap->height); + gdip_bitmap_ensure_surface (bitmap); - ct = cairo_create(surface); + surface = cairo_surface_create_similar (bitmap->surface, CAIRO_CONTENT_COLOR_ALPHA, bitmap->active_bitmap->width, bitmap->active_bitmap->height); - cairo_set_source_surface (ct, bitmap->surface, 0, 0); - cairo_paint (ct); + ct = cairo_create (surface); - cairo_destroy(ct); - - status = cairo_surface_status (surface); - if (status != CAIRO_STATUS_SUCCESS) { - cairo_surface_destroy (surface); - return gdip_get_status (status); - } - - newCachedBitmap = GdipAlloc (sizeof (GpCachedBitmap)); - if (!newCachedBitmap) - return OutOfMemory; + cairo_set_source_surface (ct, bitmap->surface, 0, 0); + cairo_paint (ct); + + cairo_destroy (ct); - newCachedBitmap->surface = surface; + status = cairo_surface_status (surface); + if (status != CAIRO_STATUS_SUCCESS) { + cairo_surface_destroy (surface); + return gdip_get_status (status); + } - *cachedBitmap = newCachedBitmap; + newCachedBitmap = GdipAlloc (sizeof (GpCachedBitmap)); + if (!newCachedBitmap) + return OutOfMemory; + newCachedBitmap->surface = surface; + *cachedBitmap = newCachedBitmap; - return Ok; + return Ok; } -GpStatus WINGDIPAPI GdipDeleteCachedBitmap (GpCachedBitmap *cachedBitmap) +GpStatus WINGDIPAPI +GdipDeleteCachedBitmap (GpCachedBitmap *cachedBitmap) { - if (!cachedBitmap) - return InvalidParameter; + if (!cachedBitmap) + return InvalidParameter; - cairo_surface_destroy(cachedBitmap->surface); - GdipFree(cachedBitmap); + cairo_surface_destroy (cachedBitmap->surface); + GdipFree (cachedBitmap); - return Ok; -} \ No newline at end of file + return Ok; +} diff --git a/src/cachedbitmap.h b/src/cachedbitmap.h index 4c8e63385..627a308e5 100644 --- a/src/cachedbitmap.h +++ b/src/cachedbitmap.h @@ -5,4 +5,4 @@ GpStatus WINGDIPAPI GdipCreateCachedBitmap (GpBitmap *bitmap, GpGraphics *graphi GpStatus WINGDIPAPI GdipDeleteCachedBitmap (GpCachedBitmap *cachedBitmap); -#endif \ No newline at end of file +#endif diff --git a/src/graphics.c b/src/graphics.c index b264a1e23..808a3096b 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1370,10 +1370,10 @@ GdipDrawCachedBitmap (GpGraphics *graphics, GpCachedBitmap *cachedBitmap, INT x, if (graphics->state == GraphicsStateBusy) return ObjectBusy; - cairo_identity_matrix(graphics->ct); + cairo_identity_matrix (graphics->ct); - cairo_set_source_surface(graphics->ct, cachedBitmap->surface, x, y); - cairo_paint(graphics->ct); + cairo_set_source_surface (graphics->ct, cachedBitmap->surface, x, y); + cairo_paint (graphics->ct); return Ok; } diff --git a/tests/Makefile.am b/tests/Makefile.am index ad99a71f5..e1b69972d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -291,7 +291,7 @@ EXTRA_DIST = \ $(testbits_SOURCES) \ $(testbmpcodec_SOURCES) \ $(testbrush_SOURCES) \ - $(testcachedbitmap_SOURCES) + $(testcachedbitmap_SOURCES) \ $(testclip_SOURCES) \ $(test_codecs_SOURCES) \ $(testcustomlinecap_SOURCES) \ diff --git a/tests/testcachedbitmap b/tests/testcachedbitmap deleted file mode 100755 index 10fd12838..000000000 --- a/tests/testcachedbitmap +++ /dev/null @@ -1,210 +0,0 @@ -#! /bin/sh - -# testcachedbitmap - temporary wrapper script for .libs/testcachedbitmap -# Generated by libtool (GNU libtool) 2.4.6 -# -# The testcachedbitmap program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s|\([`"$\\]\)|\\\1|g' - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -relink_command="" - -# This environment variable determines our operation mode. -if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then - # install mode needs the following variables: - generated_by_libtool_version='2.4.6' - notinst_deplibs=' ../src/libgdiplus.la' -else - # When we are sourced in execute mode, $file and $ECHO are already set. - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - file="$0" - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} - ECHO="printf %s\\n" - fi - -# Very basic option parsing. These options are (a) specific to -# the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ that is used only on -# windows platforms, and (c) all begin with the string --lt- -# (application programs are unlikely to have options that match -# this pattern). -# -# There are only two supported options: --lt-debug and -# --lt-dump-script. There is, deliberately, no --lt-help. -# -# The first argument to this parsing function should be the -# script's ../libtool value, followed by no. -lt_option_debug= -func_parse_lt_options () -{ - lt_script_arg0=$0 - shift - for lt_opt - do - case "$lt_opt" in - --lt-debug) lt_option_debug=1 ;; - --lt-dump-script) - lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` - test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. - lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'` - cat "$lt_dump_D/$lt_dump_F" - exit 0 - ;; - --lt-*) - $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 - exit 1 - ;; - esac - done - - # Print the debug banner immediately: - if test -n "$lt_option_debug"; then - echo "testcachedbitmap:testcachedbitmap:$LINENO: libtool wrapper (GNU libtool) 2.4.6" 1>&2 - fi -} - -# Used when --lt-debug. Prints its arguments to stdout -# (redirection is the responsibility of the caller) -func_lt_dump_args () -{ - lt_dump_args_N=1; - for lt_arg - do - $ECHO "testcachedbitmap:testcachedbitmap:$LINENO: newargv[$lt_dump_args_N]: $lt_arg" - lt_dump_args_N=`expr $lt_dump_args_N + 1` - done -} - -# Core function for launching the target application -func_exec_program_core () -{ - - if test -n "$lt_option_debug"; then - $ECHO "testcachedbitmap:testcachedbitmap:$LINENO: newargv[0]: $progdir/$program" 1>&2 - func_lt_dump_args ${1+"$@"} 1>&2 - fi - exec "$progdir/$program" ${1+"$@"} - - $ECHO "$0: cannot exec $program $*" 1>&2 - exit 1 -} - -# A function to encapsulate launching the target application -# Strips options in the --lt-* namespace from $@ and -# launches target application with the remaining arguments. -func_exec_program () -{ - case " $* " in - *\ --lt-*) - for lt_wr_arg - do - case $lt_wr_arg in - --lt-*) ;; - *) set x "$@" "$lt_wr_arg"; shift;; - esac - shift - done ;; - esac - func_exec_program_core ${1+"$@"} -} - - # Parse options - func_parse_lt_options "$0" ${1+"$@"} - - # Find the directory that this script lives in. - thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` - test "x$thisdir" = "x$file" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'` - while test -n "$file"; do - destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` - - # If there was a directory component, then change thisdir. - if test "x$destdir" != "x$file"; then - case "$destdir" in - [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; - *) thisdir="$thisdir/$destdir" ;; - esac - fi - - file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'` - file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'` - done - - # Usually 'no', except on cygwin/mingw when embedded into - # the cwrapper. - WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no - if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then - # special case for '.' - if test "$thisdir" = "."; then - thisdir=`pwd` - fi - # remove .libs from thisdir - case "$thisdir" in - *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;; - .libs ) thisdir=. ;; - esac - fi - - # Try to get the absolute directory name. - absdir=`cd "$thisdir" && pwd` - test -n "$absdir" && thisdir="$absdir" - - program='testcachedbitmap' - progdir="$thisdir/.libs" - - - if test -f "$progdir/$program"; then - # Add our own library path to DYLD_LIBRARY_PATH - DYLD_LIBRARY_PATH="/Users/reflectronic/Repos/libgdiplus/src/.libs:$DYLD_LIBRARY_PATH" - - # Some systems cannot cope with colon-terminated DYLD_LIBRARY_PATH - # The second colon is a workaround for a bug in BeOS R4 sed - DYLD_LIBRARY_PATH=`$ECHO "$DYLD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'` - - export DYLD_LIBRARY_PATH - - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - # Run the actual program with our arguments. - func_exec_program ${1+"$@"} - fi - else - # The program doesn't exist. - $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2 - $ECHO "This script is just a wrapper for $program." 1>&2 - $ECHO "See the libtool documentation for more information." 1>&2 - exit 1 - fi -fi diff --git a/tests/testcachedbitmap.c b/tests/testcachedbitmap.c index 9219289cb..fd70e0794 100644 --- a/tests/testcachedbitmap.c +++ b/tests/testcachedbitmap.c @@ -23,20 +23,19 @@ using namespace DllExports; #include #include "testhelpers.h" +#define C(func) assert (func == Ok) + static GpGraphics *getImageGraphics (GpImage **image) { - GpStatus status; WCHAR *filePath; GpGraphics *graphics; filePath = createWchar ("test.bmp"); - status = GdipLoadImageFromFile (filePath, image); - assertEqualInt (status, Ok); + C (GdipLoadImageFromFile (filePath, image)); freeWchar (filePath); - status = GdipGetImageGraphicsContext (*image, &graphics); - assertEqualInt (status, Ok); + C (GdipGetImageGraphicsContext (*image, &graphics), Ok); return graphics; } @@ -57,84 +56,76 @@ static GpImage* getImage (const char* fileName) static void test_roundtrip () { - UINT width; - UINT height; - GpBitmap *originalBitmap; - GpBitmap *surface; - GpGraphics *graphics; - GpCachedBitmap *cached; - - originalBitmap = getImage("test.bmp"); - - - assertEqualInt(GdipGetImageWidth(originalBitmap, &width), Ok); - assertEqualInt(GdipGetImageHeight(originalBitmap, &height), Ok); - - assertEqualInt(GdipCreateBitmapFromScan0(width, height, 0, PixelFormat32bppARGB, 0, &surface), Ok); - assertEqualInt(GdipGetImageGraphicsContext(surface, &graphics), Ok); - - GpRect rect = { - .X = 0, - .Y = 0, - .Width = width, - .Height = height - }; - - - assertEqualInt(GdipSetVisibleClip_linux(graphics, &rect), Ok); - assertEqualInt(GdipCreateCachedBitmap(originalBitmap, graphics, &cached), Ok); - assertEqualInt(GdipDrawCachedBitmap(graphics, cached, 0, 0), Ok); - - CLSID png_clsid = { 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }; - WCHAR *filePath = createWchar ("HELP.png"); - GdipSaveImageToFile (surface, filePath, &png_clsid, NULL); - - for (int x = 0; x < width; x++) - { - for (int y = 0; y < height; y++) - { - ARGB drawn, original; - assertEqualInt(GdipBitmapGetPixel(originalBitmap, x, y, &original), Ok); - - assertEqualInt(GdipBitmapGetPixel(surface, x, y, &drawn), Ok); - - assertEqualInt(drawn, original); - } - } + UINT width; + UINT height; + GpBitmap *originalBitmap; + GpBitmap *surface; + GpGraphics *graphics; + GpCachedBitmap *cached; + + originalBitmap = getImage ("test.bmp"); + + C (GdipGetImageWidth (originalBitmap, &width)); + C (GdipGetImageHeight (originalBitmap, &height)); + + C (GdipCreateBitmapFromScan0 (width, height, 0, PixelFormat32bppARGB, 0, &surface)); + C (GdipGetImageGraphicsContext (surface, &graphics)); + + GpRect rect = { + .X = 0, + .Y = 0, + .Width = width, + .Height = height + }; + + C (GdipSetVisibleClip_linux (graphics, &rect)); + C (GdipCreateCachedBitmap (originalBitmap, graphics, &cached)); + C (GdipDrawCachedBitmap (graphics, cached, 0, 0)); + + for (int x = 0; x < width; x++) + { + for (int y = 0; y < height; y++) + { + ARGB drawn, original; + + C (GdipBitmapGetPixel (originalBitmap, x, y, &original)); + C (GdipBitmapGetPixel (surface, x, y, &drawn)); + + assertEqualInt (drawn, original); + } + } } static void test_create () { - GpStatus status; + GpStatus status; GpImage *image; GpGraphics *graphics; - GpCachedBitmap* cachedBitmap; + GpCachedBitmap* cachedBitmap; graphics = getImageGraphics (&image); - assertEqualInt(GdipCreateCachedBitmap(image, graphics, &cachedBitmap), Ok); + C (GdipCreateCachedBitmap(image, graphics, &cachedBitmap)); - // Negative tests. - image = getImage ("test.wmf"); - status = GdipCreateCachedBitmap(image, graphics, &cachedBitmap); - assertEqualInt(status, InvalidParameter); + // Negative tests. + image = getImage ("test.wmf"); + assertEqualInt (GdipCreateCachedBitmap(image, graphics, &cachedBitmap), InvalidParameter); - assertEqualInt(GdipCreateCachedBitmap(image, graphics, NULL), InvalidParameter); - assertEqualInt(GdipCreateCachedBitmap(image, NULL, &cachedBitmap), InvalidParameter); - assertEqualInt(GdipCreateCachedBitmap(NULL, graphics, &cachedBitmap), InvalidParameter); + assertEqualInt (GdipCreateCachedBitmap(image, graphics, NULL), InvalidParameter); + assertEqualInt (GdipCreateCachedBitmap(image, NULL, &cachedBitmap), InvalidParameter); + assertEqualInt (GdipCreateCachedBitmap(NULL, graphics, &cachedBitmap), InvalidParameter); - GdipDeleteGraphics(graphics); - GdipDisposeImage(image); + C (GdipDeleteGraphics(graphics)); + C (GdipDisposeImage(image)); } -int -main (int argc, char**argv) +int main (int argc, char**argv) { - STARTUP; + STARTUP; - test_create (); - test_roundtrip (); + test_create (); + test_roundtrip (); - SHUTDOWN; - return 0; + SHUTDOWN; + return 0; } From 09d203c0080c1ea242664ed95fba64bdd678bd87 Mon Sep 17 00:00:00 2001 From: reflectronic Date: Fri, 26 Jun 2020 03:58:29 -0400 Subject: [PATCH 08/16] Free surface when out of memory --- src/cachedbitmap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cachedbitmap.c b/src/cachedbitmap.c index c5339594b..09c2af596 100644 --- a/src/cachedbitmap.c +++ b/src/cachedbitmap.c @@ -35,7 +35,10 @@ GdipCreateCachedBitmap (GpBitmap *bitmap, GpGraphics *graphics, GpCachedBitmap * newCachedBitmap = GdipAlloc (sizeof (GpCachedBitmap)); if (!newCachedBitmap) + { + cairo_surface_destroy(surface); return OutOfMemory; + } newCachedBitmap->surface = surface; *cachedBitmap = newCachedBitmap; From 25def1a71866e2038d12da71857f434162262d23 Mon Sep 17 00:00:00 2001 From: reflectronic Date: Fri, 26 Jun 2020 04:02:01 -0400 Subject: [PATCH 09/16] Fix build error --- tests/testcachedbitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testcachedbitmap.c b/tests/testcachedbitmap.c index fd70e0794..c130e7889 100644 --- a/tests/testcachedbitmap.c +++ b/tests/testcachedbitmap.c @@ -35,7 +35,7 @@ static GpGraphics *getImageGraphics (GpImage **image) freeWchar (filePath); - C (GdipGetImageGraphicsContext (*image, &graphics), Ok); + C (GdipGetImageGraphicsContext (*image, &graphics)); return graphics; } From 74dcbabe531a88df616024684cac489d85ea4a90 Mon Sep 17 00:00:00 2001 From: reflectronic Date: Fri, 26 Jun 2020 04:06:30 -0400 Subject: [PATCH 10/16] Remove unused variable --- tests/testcachedbitmap.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/testcachedbitmap.c b/tests/testcachedbitmap.c index c130e7889..d0d60d089 100644 --- a/tests/testcachedbitmap.c +++ b/tests/testcachedbitmap.c @@ -98,7 +98,6 @@ static void test_roundtrip () static void test_create () { - GpStatus status; GpImage *image; GpGraphics *graphics; GpCachedBitmap* cachedBitmap; From e55ff2a7e311912bbfdbaad86dfecc9a90781cca Mon Sep 17 00:00:00 2001 From: reflectronic Date: Wed, 1 Jul 2020 00:33:04 -0400 Subject: [PATCH 11/16] Add .NET foundation license headers --- src/cachedbitmap-private.h | 4 ++++ src/cachedbitmap.c | 4 ++++ src/cachedbitmap.h | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/src/cachedbitmap-private.h b/src/cachedbitmap-private.h index d8262f9ed..5db06d4a8 100644 --- a/src/cachedbitmap-private.h +++ b/src/cachedbitmap-private.h @@ -1,3 +1,7 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + #ifndef __CACHEDBITMAP_PRIVATE_H__ #define __CACHEDBITMAP_PRIVATE_H__ diff --git a/src/cachedbitmap.c b/src/cachedbitmap.c index 09c2af596..26b114380 100644 --- a/src/cachedbitmap.c +++ b/src/cachedbitmap.c @@ -1,3 +1,7 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + #include "general-private.h" #include "bitmap-private.h" #include "graphics-private.h" diff --git a/src/cachedbitmap.h b/src/cachedbitmap.h index 627a308e5..259b8029f 100644 --- a/src/cachedbitmap.h +++ b/src/cachedbitmap.h @@ -1,3 +1,7 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + #ifndef __CACHEDBITMAP_H__ #define __CACHEDBITMAP_H__ From 84efade0c29c4fc76aefb6909dc2851c63e142f7 Mon Sep 17 00:00:00 2001 From: reflectronic Date: Wed, 1 Jul 2020 00:40:17 -0400 Subject: [PATCH 12/16] Add delete test --- tests/testcachedbitmap.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/testcachedbitmap.c b/tests/testcachedbitmap.c index d0d60d089..41e9cfd72 100644 --- a/tests/testcachedbitmap.c +++ b/tests/testcachedbitmap.c @@ -118,12 +118,26 @@ static void test_create () C (GdipDisposeImage(image)); } +static void test_delete () +{ + GpCachedBitmap *cachedBitmap; + GpBitmap *image; + GpGraphics *graphics = getImageGraphics (); + + C (GdipCreateCachedBitmap(image, graphics, &cachedBitmap)); + C (GdipDeleteCachedBitmap(cachedBitmap)); + + // Negative tests. + assertEqualInt (GdipDeleteCachedBitmap (NULL), InvalidParameter); +} + int main (int argc, char**argv) { STARTUP; test_create (); test_roundtrip (); + test_delete (); SHUTDOWN; return 0; From e335c2fceddc704d743f16356107d59870e3eeab Mon Sep 17 00:00:00 2001 From: reflectronic Date: Wed, 1 Jul 2020 00:40:49 -0400 Subject: [PATCH 13/16] Fix formatting --- tests/testcachedbitmap.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/testcachedbitmap.c b/tests/testcachedbitmap.c index 41e9cfd72..c80e6520d 100644 --- a/tests/testcachedbitmap.c +++ b/tests/testcachedbitmap.c @@ -104,15 +104,15 @@ static void test_create () graphics = getImageGraphics (&image); - C (GdipCreateCachedBitmap(image, graphics, &cachedBitmap)); + C (GdipCreateCachedBitmap (image, graphics, &cachedBitmap)); // Negative tests. image = getImage ("test.wmf"); - assertEqualInt (GdipCreateCachedBitmap(image, graphics, &cachedBitmap), InvalidParameter); + assertEqualInt (GdipCreateCachedBitmap (image, graphics, &cachedBitmap), InvalidParameter); - assertEqualInt (GdipCreateCachedBitmap(image, graphics, NULL), InvalidParameter); - assertEqualInt (GdipCreateCachedBitmap(image, NULL, &cachedBitmap), InvalidParameter); - assertEqualInt (GdipCreateCachedBitmap(NULL, graphics, &cachedBitmap), InvalidParameter); + assertEqualInt (GdipCreateCachedBitmap (image, graphics, NULL), InvalidParameter); + assertEqualInt (GdipCreateCachedBitmap (image, NULL, &cachedBitmap), InvalidParameter); + assertEqualInt (GdipCreateCachedBitmap (NULL, graphics, &cachedBitmap), InvalidParameter); C (GdipDeleteGraphics(graphics)); C (GdipDisposeImage(image)); From bc6ab5cceb331f65587bf8276154174fac13f6f8 Mon Sep 17 00:00:00 2001 From: reflectronic Date: Wed, 1 Jul 2020 00:46:16 -0400 Subject: [PATCH 14/16] Fix tests --- tests/testcachedbitmap.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/testcachedbitmap.c b/tests/testcachedbitmap.c index c80e6520d..fbea92656 100644 --- a/tests/testcachedbitmap.c +++ b/tests/testcachedbitmap.c @@ -120,9 +120,11 @@ static void test_create () static void test_delete () { - GpCachedBitmap *cachedBitmap; - GpBitmap *image; - GpGraphics *graphics = getImageGraphics (); + GpImage *image; + GpGraphics *graphics; + GpCachedBitmap* cachedBitmap; + + graphics = getImageGraphics (&image); C (GdipCreateCachedBitmap(image, graphics, &cachedBitmap)); C (GdipDeleteCachedBitmap(cachedBitmap)); From d2f545a2dd02970c6719cd25605a27b5f44407c5 Mon Sep 17 00:00:00 2001 From: reflectronic Date: Wed, 1 Jul 2020 13:43:15 -0400 Subject: [PATCH 15/16] Add support for translation matrices for Windows compat --- src/cachedbitmap.c | 2 +- src/graphics.c | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/cachedbitmap.c b/src/cachedbitmap.c index 26b114380..452a0c2af 100644 --- a/src/cachedbitmap.c +++ b/src/cachedbitmap.c @@ -53,7 +53,7 @@ GdipCreateCachedBitmap (GpBitmap *bitmap, GpGraphics *graphics, GpCachedBitmap * GpStatus WINGDIPAPI GdipDeleteCachedBitmap (GpCachedBitmap *cachedBitmap) { - if (!cachedBitmap) + if (!cachedBitmap) return InvalidParameter; cairo_surface_destroy (cachedBitmap->surface); diff --git a/src/graphics.c b/src/graphics.c index 808a3096b..f8645195d 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1370,7 +1370,15 @@ GdipDrawCachedBitmap (GpGraphics *graphics, GpCachedBitmap *cachedBitmap, INT x, if (graphics->state == GraphicsStateBusy) return ObjectBusy; - cairo_identity_matrix (graphics->ct); + // For compat with Windows, only support translation matrices. + // Return WrongState otherwise. + + cairo_matrix_t matrix; + cairo_get_matrix (graphics->ct, &matrix); + if (matrix.xx != 1 || matrix.yx != 0 || matrix.xy != 0 || matrix.yy != 1) + { + return WrongState; + } cairo_set_source_surface (graphics->ct, cachedBitmap->surface, x, y); cairo_paint (graphics->ct); From f0d57001eed4cc0da197755601fa88f3ca0cca8a Mon Sep 17 00:00:00 2001 From: reflectronic Date: Wed, 1 Jul 2020 13:43:30 -0400 Subject: [PATCH 16/16] Test clip regions and translation matrices --- tests/test-clipped.png | Bin 0 -> 1194 bytes tests/test-translated.png | Bin 0 -> 5864 bytes tests/testcachedbitmap.c | 100 +++++++++++++++++++++++++++++--------- 3 files changed, 76 insertions(+), 24 deletions(-) create mode 100644 tests/test-clipped.png create mode 100644 tests/test-translated.png diff --git a/tests/test-clipped.png b/tests/test-clipped.png new file mode 100644 index 0000000000000000000000000000000000000000..729e67be6b8ef9428c0baccd5d7faba4d3eb0f2d GIT binary patch literal 1194 zcmeAS@N?(olHy`uVBq!ia0vp^DM0MP!3HGD{U#&vz{TViY3rgXz5G|g{S;098xumUmiGdWfe1b zlH*_YU5cT9*>426ZeP_?l8~@K(A8^ohsMdj9yKR#ZalwlIkVEM^Sb-24}MpT+@$mR z;_+W6>f~-Kv@Kz zx{9Bl+j#x{QMqipom-l6Z}%Ke<~gju2`TYA3 z#cLn=GdFGA=(zjtvit8BZ+-S^>iHGdXRZ1Bt0{ba+(ULo{rc$imxnhm@G09RyM^&} z{U5(+sXNx4K6Hrb{oefre?F$oi9E94ZP{#_^O+`6CQ`hQES^0&+P!AoI-%o+4AYic z*!awxy*hE0nzgmHP4%~)zkh3Y-PP-tw@5fjW`CR)(GXW101Ti1(k>iK6%S%q`vuMenX&P^@#>Nz-*_jM`}**{fev7%y*dpZ0URujcHB25df; zOb&mp$-DETY3fu_GjsEkn|OLV6QeSGri3bW3HziPUweP0hEK$#{ZHt$)RaiKdCx<% zL=PFHWM+1<^UHmB8Xlj#o3HucgBLPuO)KXKA2;0hUR?J5+vWcieS_C-y>|QdZTI7B z&5hThUaNS1xvD+?)ugp0x$73a-nuI8-w)-#2X7kRD)#<$Ch2#)_lxbZ56e$TpG}+G z+{}E*MD?_h)m*-5sfFL)#jcCp-F9u3il>E*&5`f5Ik(eHqb` zt?z%UcslKkORuZ@_qFK9B~`oqb+W0EGrTUo{VL%m_|>gh=X`gcc`=v%kwTd**Lc{N zc@8g#(F3|SDjUeU{yK2=RgXz6MLT^&T)+ITwK<<`AR!`~|4d}x8`g}iQSQIJG;Pj1 zXZOC|Wl`2yS3W&$@6imCMPX|vFVkfI{rgPl>LZ2eLW1eXjy#+2fAVw7r$sZ}7CQ>C z08>ZY4tJU3H@4Zntq?Z<>g3gT_~+;6mW7X4*xA`7+78B)@}2*DmdKI;Vst E03aGVt^fc4 literal 0 HcmV?d00001 diff --git a/tests/test-translated.png b/tests/test-translated.png new file mode 100644 index 0000000000000000000000000000000000000000..b551ecf07395a28f05897fabbf5df2f7ea462fdf GIT binary patch literal 5864 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 Lu}-6wW9 #include "testhelpers.h" -#define C(func) assert (func == Ok) +#define C(func) assertEqualInt (func, Ok) static GpGraphics *getImageGraphics (GpImage **image) { @@ -54,7 +54,35 @@ static GpImage* getImage (const char* fileName) return image; } -static void test_roundtrip () +static void createBitmaps (GpBitmap **originalBitmap, GpBitmap **blankBitmap, GpGraphics **blankGraphics, UINT *width, UINT *height) +{ + *originalBitmap = getImage ("test.bmp"); + C (GdipGetImageWidth (*originalBitmap, width)); + C (GdipGetImageHeight (*originalBitmap, height)); + + C (GdipCreateBitmapFromScan0 (*width, *height, 0, PixelFormat32bppARGB, 0, blankBitmap)); + C (GdipGetImageGraphicsContext (*blankBitmap, blankGraphics)); +} + +static void compareEqual (GpBitmap *expected, GpBitmap *actual, UINT width, UINT height) +{ + for (int x = 0; x < width; x++) + { + for (int y = 0; y < height; y++) + { + ARGB expectedColor, actualColor; + + C (GdipBitmapGetPixel (expected, x, y, &expectedColor)); + C (GdipBitmapGetPixel (actual, x, y, &actualColor)); + + assertEqualInt (expectedColor, actualColor); + } + } +} + +CLSID png_clsid = { 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }; + +static void test_clip () { UINT width; UINT height; @@ -63,37 +91,59 @@ static void test_roundtrip () GpGraphics *graphics; GpCachedBitmap *cached; - originalBitmap = getImage ("test.bmp"); + createBitmaps(&originalBitmap, &surface, &graphics, &width, &height); + + C (GdipSetClipRect (graphics, 20, 20, 20, 20, CombineModeReplace)); - C (GdipGetImageWidth (originalBitmap, &width)); - C (GdipGetImageHeight (originalBitmap, &height)); + C (GdipCreateCachedBitmap (originalBitmap, graphics, &cached)); + C (GdipDrawCachedBitmap (graphics, cached, 0, 0)); - C (GdipCreateBitmapFromScan0 (width, height, 0, PixelFormat32bppARGB, 0, &surface)); - C (GdipGetImageGraphicsContext (surface, &graphics)); + GpImage *expected = getImage("test-clipped.png"); + compareEqual(expected, surface, width, height); +} - GpRect rect = { - .X = 0, - .Y = 0, - .Width = width, - .Height = height - }; +static void test_matrix () +{ + UINT width; + UINT height; + GpBitmap *originalBitmap; + GpBitmap *surface; + GpGraphics *graphics; + GpCachedBitmap *cached; + + createBitmaps(&originalBitmap, &surface, &graphics, &width, &height); + + C (GdipTranslateWorldTransform(graphics, 30, 30, MatrixOrderAppend)); - C (GdipSetVisibleClip_linux (graphics, &rect)); C (GdipCreateCachedBitmap (originalBitmap, graphics, &cached)); C (GdipDrawCachedBitmap (graphics, cached, 0, 0)); - for (int x = 0; x < width; x++) - { - for (int y = 0; y < height; y++) - { - ARGB drawn, original; + GpImage *expected = getImage("test-translated.png"); + compareEqual(expected, surface, width, height); - C (GdipBitmapGetPixel (originalBitmap, x, y, &original)); - C (GdipBitmapGetPixel (surface, x, y, &drawn)); + // Negative tests. + C (GdipScaleWorldTransform(graphics, 30, 30, MatrixOrderAppend)); + assertEqualInt (GdipDrawCachedBitmap(graphics, cached, 0, 0), WrongState); + C (GdipRotateWorldTransform(graphics, 30, MatrixOrderAppend)); + assertEqualInt (GdipDrawCachedBitmap(graphics, cached, 0, 0), WrongState); +} - assertEqualInt (drawn, original); - } - } + +static void test_roundtrip () +{ + UINT width; + UINT height; + GpBitmap *originalBitmap; + GpBitmap *surface; + GpGraphics *graphics; + GpCachedBitmap *cached; + + createBitmaps(&originalBitmap, &surface, &graphics, &width, &height); + + C (GdipCreateCachedBitmap (originalBitmap, graphics, &cached)); + C (GdipDrawCachedBitmap (graphics, cached, 0, 0)); + + compareEqual(originalBitmap, surface, width, height); } static void test_create () @@ -139,6 +189,8 @@ int main (int argc, char**argv) test_create (); test_roundtrip (); + test_clip (); + test_matrix (); test_delete (); SHUTDOWN;