[cairo-commit] [cairo-www] src/dotnet-gdi-rendering.mdwn
Carl Worth
cworth at freedesktop.org
Fri May 28 05:59:55 PDT 2010
src/dotnet-gdi-rendering.mdwn | 46 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
New commits:
commit b36f736dbdb69da2e8d365f1151dbbad89c9b096
Author: MikeLischke <MikeLischke at web>
Date: Fri May 28 05:59:55 2010 -0700
Created a new example.
diff --git a/src/dotnet-gdi-rendering.mdwn b/src/dotnet-gdi-rendering.mdwn
new file mode 100644
index 0000000..43b278e
--- /dev/null
+++ b/src/dotnet-gdi-rendering.mdwn
@@ -0,0 +1,46 @@
+Using GDI+ Bitmap as surface can be as simple as that (given in managed C++):
+
+ // Create the target bitmap to draw to.
+ Drawing::Bitmap contentBitmap= new Drawing::Bitmap(Width, Height);
+
+ // Create a Graphics object to have a device context we can pass to cairo.
+ Graphics^ g = Graphics::FromImage(contentBitmap);
+ g->SmoothingMode = SmoothingMode::HighQuality;
+
+ // Do some drawing in GDI+ to have some initial content, like:
+ // Fill interior.
+ Brush^ brush = gcnew SolidBrush(Color::FromArgb(191, 1, 0, 0));
+ g->FillPath(brush, innerPath);
+ delete brush;
+
+ // Get the device context handle from this graphics object and create a Win32 cairo surface from it.
+ IntPtr hdc= g->GetHdc();
+ cairo_surface_t* surface= cairo_win32_surface_create((HDC) hdc.ToPointer());
+
+ // For drawing we need a cairo context.
+ cairo_t* cr= cairo_create(surface);
+
+ // Now you are ready to draw to that using any of the cairo calls.
+ ...
+
+ // Don't forget the cleanup.
+ cairo_destroy(cr);
+ cairo_surface_destroy(surface);
+
+ g->ReleaseHdc(hdc);
+
+This works quite well but has one big disadvantage: cairo_win32_surface_create always returns a 24bit surface. So what if we have a bitmap with an alpha channel (like a png image we loaded and want to add something to it)? With the code above the alpha channel used in your cairo commands is lost.
+
+One could create a 32bit DIB surface (using cairo_win32_surface_create_with_dib), but that creates a *separate* surface, which needs to be merged later to your actual target. Using an API like AlphaBlend (via pinvoke) produces exactly the same result as in the code above.
+
+The solution to this dilemma is an image surface (e.g. you get an image surface when you load png images in cairo).
+
+ // Instead of getting an HDC and and use cairo_win32_surface we get directly
+ // to the pixels in the bitmap and create the image surface from that.
+ Imaging::BitmapData^ bitmapData= contentBitmap->LockBits(Drawing::Rectangle(0, 0, Width, Height),
+ Imaging::ImageLockMode::ReadWrite, contentBitmap->PixelFormat);
+ unsigned char* data= (unsigned char*) bitmapData->Scan0.ToPointer();
+ cairo_surface_t* surface= cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, Width, Height, bitmapData->Stride);
+
+ // The rest is the same as above, except we have to unlock the bits after we finished drawing.
+ contentBitmap->UnlockBits(bitmapData);
More information about the cairo-commit
mailing list