⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cairo-win32-surface.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Cairo - a vector graphics library with display and print output * * Copyright © 2005 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public * License version 2.1 as published by the Free Software Foundation * (the "LGPL") or, at your option, under the terms of the Mozilla * Public License Version 1.1 (the "MPL"). If you do not alter this * notice, a recipient may use your version of this file under either * the MPL or the LGPL. * * You should have received a copy of the LGPL along with this library * in the file COPYING-LGPL-2.1; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * You should have received a copy of the MPL along with this library * in the file COPYING-MPL-1.1 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY * OF ANY KIND, either express or implied. See the LGPL or the MPL for * the specific language governing rights and limitations. * * The Original Code is the cairo graphics library. * * The Initial Developer of the Original Code is Red Hat, Inc. * * Contributor(s): *	Owen Taylor <otaylor@redhat.com> *	Stuart Parmenter <stuart@mozilla.com> *	Vladimir Vukicevic <vladimir@pobox.com> */#include <stdio.h>#include "cairoint.h"#include "cairo-clip-private.h"#include "cairo-win32-private.h"/* for older SDKs */#ifndef SHADEBLENDCAPS#define SHADEBLENDCAPS  120#endif#ifndef SB_NONE#define SB_NONE         0x00000000#endifstatic const cairo_surface_backend_t cairo_win32_surface_backend;/** * _cairo_win32_print_gdi_error: * @context: context string to display along with the error * * Helper function to dump out a human readable form of the * current error code. * * Return value: A cairo status code for the error code **/cairo_status_t_cairo_win32_print_gdi_error (const char *context){    void *lpMsgBuf;    DWORD last_error = GetLastError ();    if (!FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |			 FORMAT_MESSAGE_FROM_SYSTEM,			 NULL,			 last_error,			 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),			 (LPTSTR) &lpMsgBuf,			 0, NULL)) {	fprintf (stderr, "%s: Unknown GDI error", context);    } else {	fprintf (stderr, "%s: %s", context, (char *)lpMsgBuf);	LocalFree (lpMsgBuf);    }    /* We should switch off of last_status, but we'd either return     * CAIRO_STATUS_NO_MEMORY or CAIRO_STATUS_UNKNOWN_ERROR and there     * is no CAIRO_STATUS_UNKNOWN_ERROR.     */    return CAIRO_STATUS_NO_MEMORY;}static cairo_status_t_create_dc_and_bitmap (cairo_win32_surface_t *surface,		       HDC                    original_dc,		       cairo_format_t         format,		       int                    width,		       int                    height,		       char                 **bits_out,		       int                   *rowstride_out){    cairo_status_t status;    BITMAPINFO *bitmap_info = NULL;    struct {	BITMAPINFOHEADER bmiHeader;	RGBQUAD bmiColors[2];    } bmi_stack;    void *bits;    int num_palette = 0;	/* Quiet GCC */    int i;    surface->dc = NULL;    surface->bitmap = NULL;    switch (format) {    case CAIRO_FORMAT_ARGB32:    case CAIRO_FORMAT_RGB24:	num_palette = 0;	break;    case CAIRO_FORMAT_A8:	num_palette = 256;	break;    case CAIRO_FORMAT_A1:	num_palette = 2;	break;    }    if (num_palette > 2) {	bitmap_info = malloc (sizeof (BITMAPINFOHEADER) + num_palette * sizeof (RGBQUAD));	if (!bitmap_info)	    return CAIRO_STATUS_NO_MEMORY;    } else {	bitmap_info = (BITMAPINFO *)&bmi_stack;    }    bitmap_info->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);    bitmap_info->bmiHeader.biWidth = width == 0 ? 1 : width;    bitmap_info->bmiHeader.biHeight = height == 0 ? -1 : - height; /* top-down */    bitmap_info->bmiHeader.biSizeImage = 0;    bitmap_info->bmiHeader.biXPelsPerMeter = 72. / 0.0254; /* unused here */    bitmap_info->bmiHeader.biYPelsPerMeter = 72. / 0.0254; /* unused here */    bitmap_info->bmiHeader.biPlanes = 1;    switch (format) {    /* We can't create real RGB24 bitmaps because something seems to     * break if we do, especially if we don't set up an image     * fallback.  It could be a bug with using a 24bpp pixman image     * (and creating one with masks).  So treat them like 32bpp.     */    case CAIRO_FORMAT_RGB24:    case CAIRO_FORMAT_ARGB32:	bitmap_info->bmiHeader.biBitCount = 32;	bitmap_info->bmiHeader.biCompression = BI_RGB;	bitmap_info->bmiHeader.biClrUsed = 0;	/* unused */	bitmap_info->bmiHeader.biClrImportant = 0;	break;    case CAIRO_FORMAT_A8:	bitmap_info->bmiHeader.biBitCount = 8;	bitmap_info->bmiHeader.biCompression = BI_RGB;	bitmap_info->bmiHeader.biClrUsed = 256;	bitmap_info->bmiHeader.biClrImportant = 0;	for (i = 0; i < 256; i++) {	    bitmap_info->bmiColors[i].rgbBlue = i;	    bitmap_info->bmiColors[i].rgbGreen = i;	    bitmap_info->bmiColors[i].rgbRed = i;	    bitmap_info->bmiColors[i].rgbReserved = 0;	}	break;    case CAIRO_FORMAT_A1:	bitmap_info->bmiHeader.biBitCount = 1;	bitmap_info->bmiHeader.biCompression = BI_RGB;	bitmap_info->bmiHeader.biClrUsed = 2;	bitmap_info->bmiHeader.biClrImportant = 0;	for (i = 0; i < 2; i++) {	    bitmap_info->bmiColors[i].rgbBlue = i * 255;	    bitmap_info->bmiColors[i].rgbGreen = i * 255;	    bitmap_info->bmiColors[i].rgbRed = i * 255;	    bitmap_info->bmiColors[i].rgbReserved = 0;	    break;	}    }    surface->dc = CreateCompatibleDC (original_dc);    if (!surface->dc)	goto FAIL;    surface->bitmap = CreateDIBSection (surface->dc,			                bitmap_info,			                DIB_RGB_COLORS,			                &bits,			                NULL, 0);    if (!surface->bitmap)	goto FAIL;    GdiFlush();    surface->saved_dc_bitmap = SelectObject (surface->dc,					     surface->bitmap);    if (!surface->saved_dc_bitmap)	goto FAIL;    if (bitmap_info && num_palette > 2)	free (bitmap_info);    if (bits_out)	*bits_out = bits;    if (rowstride_out) {	/* Windows bitmaps are padded to 32-bit (dword) boundaries */	switch (format) {	case CAIRO_FORMAT_ARGB32:	case CAIRO_FORMAT_RGB24:	    *rowstride_out = 4 * width;	    break;	case CAIRO_FORMAT_A8:	    *rowstride_out = (width + 3) & ~3;	    break;	case CAIRO_FORMAT_A1:	    *rowstride_out = ((width + 31) & ~31) / 8;	    break;	}    }    return CAIRO_STATUS_SUCCESS; FAIL:    status = _cairo_win32_print_gdi_error ("_create_dc_and_bitmap");    if (bitmap_info && num_palette > 2)	free (bitmap_info);    if (surface->saved_dc_bitmap) {	SelectObject (surface->dc, surface->saved_dc_bitmap);	surface->saved_dc_bitmap = NULL;    }    if (surface->bitmap) {	DeleteObject (surface->bitmap);	surface->bitmap = NULL;    }    if (surface->dc) { 	DeleteDC (surface->dc);	surface->dc = NULL;    }    return status;}static cairo_surface_t *_cairo_win32_surface_create_for_dc (HDC             original_dc,				    cairo_format_t  format,				    int	            width,				    int	            height){    cairo_status_t status;    cairo_win32_surface_t *surface;    char *bits;    int rowstride;    surface = malloc (sizeof (cairo_win32_surface_t));    if (surface == NULL) {	_cairo_error (CAIRO_STATUS_NO_MEMORY);	return &_cairo_surface_nil;    }    status = _create_dc_and_bitmap (surface, original_dc, format,				    width, height,				    &bits, &rowstride);    if (status)	goto FAIL;    surface->image = cairo_image_surface_create_for_data (bits, format,							  width, height, rowstride);    if (surface->image->status) {	status = CAIRO_STATUS_NO_MEMORY;	goto FAIL;    }    surface->format = format;    surface->clip_rect.x = 0;    surface->clip_rect.y = 0;    surface->clip_rect.width = width;    surface->clip_rect.height = height;    surface->saved_clip = CreateRectRgn (0, 0, 0, 0);    if (GetClipRgn (surface->dc, surface->saved_clip) == 0) {        DeleteObject(surface->saved_clip);        surface->saved_clip = NULL;    }    surface->extents = surface->clip_rect;    _cairo_surface_init (&surface->base, &cairo_win32_surface_backend,			 _cairo_content_from_format (format));    return (cairo_surface_t *)surface; FAIL:    if (surface->bitmap) {	SelectObject (surface->dc, surface->saved_dc_bitmap);  	DeleteObject (surface->bitmap);        DeleteDC (surface->dc);    }    if (surface)	free (surface);    if (status == CAIRO_STATUS_NO_MEMORY) {	_cairo_error (CAIRO_STATUS_NO_MEMORY);	return &_cairo_surface_nil;    } else {	_cairo_error (status);	return &_cairo_surface_nil;    }}static cairo_surface_t *_cairo_win32_surface_create_similar (void	    *abstract_src,				     cairo_content_t content,				     int	     width,				     int	     height){    cairo_win32_surface_t *src = abstract_src;    cairo_format_t format = _cairo_format_from_content (content);    return _cairo_win32_surface_create_for_dc (src->dc, format, width, height);}static cairo_status_t_cairo_win32_surface_finish (void *abstract_surface){    cairo_win32_surface_t *surface = abstract_surface;    if (surface->image)	cairo_surface_destroy (surface->image);    if (surface->saved_clip)	DeleteObject (surface->saved_clip);    /* If we created the Bitmap and DC, destroy them */    if (surface->bitmap) {	SelectObject (surface->dc, surface->saved_dc_bitmap);  	DeleteObject (surface->bitmap);        DeleteDC (surface->dc);    }    return CAIRO_STATUS_SUCCESS;}static cairo_status_t_cairo_win32_surface_get_subimage (cairo_win32_surface_t  *surface,				   int                     x,				   int                     y,				   int                     width,				   int                     height,				   cairo_win32_surface_t **local_out){    cairo_win32_surface_t *local;    cairo_status_t status;    cairo_content_t content = _cairo_content_from_format (surface->format);    local =	(cairo_win32_surface_t *) _cairo_win32_surface_create_similar (surface,								       content,								       width,								       height);    if (local->base.status)	return CAIRO_STATUS_NO_MEMORY;    if (!BitBlt (local->dc,		 0, 0,		 width, height,		 surface->dc,		 x, y,		 SRCCOPY)) {	/* If we fail to BitBlt here, most likely the source is a printer.	 * You can't reliably get bits from a printer DC, so just fill in	 * the surface as white (common case for printing).	 */	RECT r;	r.left = r.top = 0;	r.right = width;	r.bottom = height;	FillRect(local->dc, &r, (HBRUSH)GetStockObject(WHITE_BRUSH));    }    *local_out = local;    return CAIRO_STATUS_SUCCESS; FAIL:    status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_get_subimage");    if (local)	cairo_surface_destroy (&local->base);    return status;}static cairo_status_t_cairo_win32_surface_acquire_source_image (void                    *abstract_surface,					   cairo_image_surface_t  **image_out,					   void                   **image_extra){    cairo_win32_surface_t *surface = abstract_surface;    cairo_win32_surface_t *local = NULL;    cairo_status_t status;    if (surface->image) {	*image_out = (cairo_image_surface_t *)surface->image;	*image_extra = NULL;	return CAIRO_STATUS_SUCCESS;    }    status = _cairo_win32_surface_get_subimage (abstract_surface, 0, 0,						surface->clip_rect.width,						surface->clip_rect.height, &local);    if (status)	return status;    *image_out = (cairo_image_surface_t *)local->image;    *image_extra = local;    return CAIRO_STATUS_SUCCESS;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -