Skip to content
This repository was archived by the owner on Mar 7, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/GdiPlusFlat.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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"
Expand Down
3 changes: 3 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
10 changes: 10 additions & 0 deletions src/cachedbitmap-private.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef __CACHEDBITMAP_PRIVATE_H__
#define __CACHEDBITMAP_PRIVATE_H__

typedef struct _CachedBitmap {
cairo_surface_t *surface;
} CachedBitmap;

#include "cachedbitmap.h"

#endif
59 changes: 59 additions & 0 deletions src/cachedbitmap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#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_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);

surface = cairo_surface_create_similar (bitmap->surface, CAIRO_CONTENT_COLOR_ALPHA, bitmap->active_bitmap->width, bitmap->active_bitmap->height);

ct = cairo_create (surface);

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)
{
cairo_surface_destroy(surface);
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;
}
8 changes: 8 additions & 0 deletions src/cachedbitmap.h
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions src/gdiplus-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
17 changes: 17 additions & 0 deletions src/graphics.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <cairo-features.h>
Expand Down Expand Up @@ -1361,6 +1362,22 @@ 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;
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;
}

/*
* Fills
*/
Expand Down
2 changes: 2 additions & 0 deletions src/graphics.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 10 additions & 0 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ noinst_PROGRAMS = \
testbits \
testbmpcodec \
testbrush \
testcachedbitmap \
testclip \
testcodecs \
testcustomlinecap \
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -283,6 +291,7 @@ EXTRA_DIST = \
$(testbits_SOURCES) \
$(testbmpcodec_SOURCES) \
$(testbrush_SOURCES) \
$(testcachedbitmap_SOURCES) \
$(testclip_SOURCES) \
$(test_codecs_SOURCES) \
$(testcustomlinecap_SOURCES) \
Expand Down Expand Up @@ -339,6 +348,7 @@ TESTS = \
testbits \
testbmpcodec \
testbrush \
testcachedbitmap \
testclip \
testcodecs \
testcustomlinecap \
Expand Down
130 changes: 130 additions & 0 deletions tests/testcachedbitmap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#ifdef WIN32
#ifndef __cplusplus
#error Please compile with a C++ compiler.
#endif
#endif

#if defined(USE_WINDOWS_GDIPLUS)
#include <Windows.h>
#include <GdiPlus.h>

#pragma comment(lib, "gdiplus.lib")
#else
#include <GdiPlusFlat.h>
#endif

#if defined(USE_WINDOWS_GDIPLUS)
using namespace Gdiplus;
using namespace DllExports;
#endif

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "testhelpers.h"

#define C(func) assert (func == Ok)

static GpGraphics *getImageGraphics (GpImage **image)
{
WCHAR *filePath;
GpGraphics *graphics;

filePath = createWchar ("test.bmp");
C (GdipLoadImageFromFile (filePath, image));

freeWchar (filePath);

C (GdipGetImageGraphicsContext (*image, &graphics));

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");

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 ()
{
GpImage *image;
GpGraphics *graphics;
GpCachedBitmap* cachedBitmap;

graphics = getImageGraphics (&image);

C (GdipCreateCachedBitmap(image, graphics, &cachedBitmap));

// 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);

C (GdipDeleteGraphics(graphics));
C (GdipDisposeImage(image));
}

int main (int argc, char**argv)
{
STARTUP;

test_create ();
test_roundtrip ();

SHUTDOWN;
return 0;
}