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

📄 cairo-win32-surface.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 3 页
字号:
    return status;}static cairo_int_status_t_cairo_win32_surface_set_clip_region (void              *abstract_surface,				      pixman_region16_t *region){    cairo_win32_surface_t *surface = abstract_surface;    cairo_status_t status;    /* If we are in-memory, then we set the clip on the image surface     * as well as on the underlying GDI surface.     */    if (surface->image) {	unsigned int serial;	serial = _cairo_surface_allocate_clip_serial (surface->image);	_cairo_surface_set_clip_region (surface->image, region, serial);    }    /* The semantics we want is that any clip set by cairo combines     * is intersected with the clip on device context that the     * surface was created for. To implement this, we need to     * save the original clip when first setting a clip on surface.     */    if (region == NULL) {	/* Clear any clip set by cairo, return to the original */	if (SelectClipRgn (surface->dc, surface->saved_clip) == ERROR)	    return _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region (reset)");	return CAIRO_STATUS_SUCCESS;    } else {	pixman_box16_t *boxes = pixman_region_rects (region);	int num_boxes = pixman_region_num_rects (region);	pixman_box16_t *extents = pixman_region_extents (region);	RGNDATA *data;	size_t data_size;	RECT *rects;	int i;	HRGN gdi_region;	/* Create a GDI region for the cairo region */	data_size = sizeof (RGNDATAHEADER) + num_boxes * sizeof (RECT);	data = malloc (data_size);	if (!data)	    return CAIRO_STATUS_NO_MEMORY;	rects = (RECT *)data->Buffer;	data->rdh.dwSize = sizeof (RGNDATAHEADER);	data->rdh.iType = RDH_RECTANGLES;	data->rdh.nCount = num_boxes;	data->rdh.nRgnSize = num_boxes * sizeof (RECT);	data->rdh.rcBound.left = extents->x1;	data->rdh.rcBound.top = extents->y1;	data->rdh.rcBound.right = extents->x2;	data->rdh.rcBound.bottom = extents->y2;	for (i = 0; i < num_boxes; i++) {	    rects[i].left = boxes[i].x1;	    rects[i].top = boxes[i].y1;	    rects[i].right = boxes[i].x2;	    rects[i].bottom = boxes[i].y2;	}	gdi_region = ExtCreateRegion (NULL, data_size, data);	free (data);	if (!gdi_region)	    return CAIRO_STATUS_NO_MEMORY;	/* Combine the new region with the original clip */	if (surface->saved_clip) {	    if (CombineRgn (gdi_region, gdi_region, surface->saved_clip, RGN_AND) == ERROR)		goto FAIL;	}	if (SelectClipRgn (surface->dc, gdi_region) == ERROR)	    goto FAIL;	DeleteObject (gdi_region);	return CAIRO_STATUS_SUCCESS;    FAIL:	status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region");	DeleteObject (gdi_region);	return status;    }}static cairo_int_status_t_cairo_win32_surface_get_extents (void		          *abstract_surface,				  cairo_rectangle_int16_t *rectangle){    cairo_win32_surface_t *surface = abstract_surface;    *rectangle = surface->extents;    return CAIRO_STATUS_SUCCESS;}static cairo_status_t_cairo_win32_surface_flush (void *abstract_surface){    return _cairo_surface_reset_clip (abstract_surface);}#define STACK_GLYPH_SIZE 256static cairo_int_status_t_cairo_win32_surface_show_glyphs (void			*surface,				  cairo_operator_t	 op,				  cairo_pattern_t	*source,				  const cairo_glyph_t	*glyphs,				  int			 num_glyphs,				  cairo_scaled_font_t	*scaled_font){    cairo_win32_surface_t *dst = surface;    WORD glyph_buf_stack[STACK_GLYPH_SIZE];    WORD *glyph_buf = glyph_buf_stack;    int dx_buf_stack[STACK_GLYPH_SIZE];    int *dx_buf = dx_buf_stack;    BOOL win_result = 0;    int i;    double last_y = glyphs[0].y;    cairo_solid_pattern_t *solid_pattern;    COLORREF color;    int output_count = 0;    /* We can only handle win32 fonts */    if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32)	return CAIRO_INT_STATUS_UNSUPPORTED;    /* We can only handle opaque solid color sources */    if (!_cairo_pattern_is_opaque_solid(source))	return CAIRO_INT_STATUS_UNSUPPORTED;    /* We can only handle operator SOURCE or OVER with the destination     * having no alpha */    if ((op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER) ||	(dst->format != CAIRO_FORMAT_RGB24))	return CAIRO_INT_STATUS_UNSUPPORTED;    /* If we have a fallback mask clip set on the dst, we have     * to go through the fallback path */    if (dst->base.clip &&	(dst->base.clip->mode != CAIRO_CLIP_MODE_REGION ||	 dst->base.clip->surface != NULL))	return CAIRO_INT_STATUS_UNSUPPORTED;    solid_pattern = (cairo_solid_pattern_t *)source;    color = RGB(((int)solid_pattern->color.red_short) >> 8,		((int)solid_pattern->color.green_short) >> 8,		((int)solid_pattern->color.blue_short) >> 8);    SaveDC(dst->dc);    cairo_win32_scaled_font_select_font(scaled_font, dst->dc);    SetTextColor(dst->dc, color);    SetTextAlign(dst->dc, TA_BASELINE | TA_LEFT);    SetBkMode(dst->dc, TRANSPARENT);    if (num_glyphs > STACK_GLYPH_SIZE) {	glyph_buf = (WORD *)malloc(num_glyphs * sizeof(WORD));	dx_buf = (int *)malloc(num_glyphs * sizeof(int));    }    for (i = 0; i < num_glyphs; ++i) {	output_count++;	glyph_buf[i] = glyphs[i].index;	if (i == num_glyphs - 1)	    dx_buf[i] = 0;	else	    dx_buf[i] = (glyphs[i+1].x - glyphs[i].x) * WIN32_FONT_LOGICAL_SCALE;	if (i == num_glyphs - 1 || glyphs[i].y != glyphs[i+1].y) {	    const int offset = (i - output_count) + 1;	    win_result = ExtTextOutW(dst->dc,				     glyphs[offset].x * WIN32_FONT_LOGICAL_SCALE,				     last_y * WIN32_FONT_LOGICAL_SCALE,				     ETO_GLYPH_INDEX,				     NULL,				     glyph_buf + offset,				     output_count,				     dx_buf + offset);	    if (!win_result) {		_cairo_win32_print_gdi_error("_cairo_win32_surface_show_glyphs(ExtTextOutW failed)");		goto FAIL;	    }	    output_count = 0;	}	last_y = glyphs[i].y;    }FAIL:    RestoreDC(dst->dc, -1);    if (glyph_buf != glyph_buf_stack) {	free(glyph_buf);	free(dx_buf);    }    return (win_result) ? CAIRO_STATUS_SUCCESS : CAIRO_INT_STATUS_UNSUPPORTED;}#undef STACK_GLYPH_SIZE/** * cairo_win32_surface_create: * @hdc: the DC to create a surface for * * Creates a cairo surface that targets the given DC.  The DC will be * queried for its initial clip extents, and this will be used as the * size of the cairo surface.  Also, if the DC is a raster DC, it will * be queried for its pixel format and the cairo surface format will * be set appropriately. * * Return value: the newly created surface **/cairo_surface_t *cairo_win32_surface_create (HDC hdc){    cairo_win32_surface_t *surface;    RECT rect;    int depth;    cairo_format_t format;    /* Try to figure out the drawing bounds for the Device context     */    if (GetClipBox (hdc, &rect) == ERROR) {	_cairo_win32_print_gdi_error ("cairo_win32_surface_create");	/* XXX: Can we make a more reasonable guess at the error cause here? */	_cairo_error (CAIRO_STATUS_NO_MEMORY);	return &_cairo_surface_nil;    }    if (GetDeviceCaps(hdc, TECHNOLOGY) == DT_RASDISPLAY) {	depth = GetDeviceCaps(hdc, BITSPIXEL);	if (depth == 32)	    format = CAIRO_FORMAT_ARGB32;	else if (depth == 24)	    format = CAIRO_FORMAT_RGB24;	else if (depth == 16)	    format = CAIRO_FORMAT_RGB24;	else if (depth == 8)	    format = CAIRO_FORMAT_A8;	else if (depth == 1)	    format = CAIRO_FORMAT_A1;	else {	    _cairo_win32_print_gdi_error("cairo_win32_surface_create(bad BITSPIXEL)");	    _cairo_error (CAIRO_STATUS_NO_MEMORY);	    return &_cairo_surface_nil;	}    } else {	format = CAIRO_FORMAT_RGB24;    }    surface = malloc (sizeof (cairo_win32_surface_t));    if (surface == NULL) {	_cairo_error (CAIRO_STATUS_NO_MEMORY);	return &_cairo_surface_nil;    }    surface->image = NULL;    surface->format = format;    surface->dc = hdc;    surface->bitmap = NULL;    surface->saved_dc_bitmap = NULL;    surface->clip_rect.x = rect.left;    surface->clip_rect.y = rect.top;    surface->clip_rect.width = rect.right - rect.left;    surface->clip_rect.height = rect.bottom - rect.top;    if (surface->clip_rect.width == 0 ||        surface->clip_rect.height == 0)    {        surface->saved_clip = NULL;    } else {        surface->saved_clip = CreateRectRgn (0, 0, 0, 0);        if (GetClipRgn (hdc, 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;}/** * cairo_win32_surface_create_with_dib: * @format: format of pixels in the surface to create * @width: width of the surface, in pixels * @height: height of the surface, in pixels * * Creates a device-independent-bitmap surface not associated with * any particular existing surface or device context. The created * bitmap will be unititialized. * * Return value: the newly created surface * * Since: 1.2 **/cairo_surface_t *cairo_win32_surface_create_with_dib (cairo_format_t format,                                     int	    width,                                     int	    height){    return _cairo_win32_surface_create_for_dc (NULL, format, width, height);}/** * _cairo_surface_is_win32: * @surface: a #cairo_surface_t * * Checks if a surface is an #cairo_win32_surface_t * * Return value: True if the surface is an win32 surface **/int_cairo_surface_is_win32 (cairo_surface_t *surface){    return surface->backend == &cairo_win32_surface_backend;}/** * cairo_win32_surface_get_dc * @surface: a #cairo_surface_t * * Returns the HDC associated with this surface, or NULL if none. * Also returns NULL if the surface is not a win32 surface. * * Return value: HDC or NULL if no HDC available. * * Since: 1.2 **/HDCcairo_win32_surface_get_dc (cairo_surface_t *surface){    cairo_win32_surface_t *winsurf;    if (surface == NULL)	return NULL;    if (!_cairo_surface_is_win32(surface))	return NULL;    winsurf = (cairo_win32_surface_t *) surface;    return winsurf->dc;}static const cairo_surface_backend_t cairo_win32_surface_backend = {    CAIRO_SURFACE_TYPE_WIN32,    _cairo_win32_surface_create_similar,    _cairo_win32_surface_finish,    _cairo_win32_surface_acquire_source_image,    _cairo_win32_surface_release_source_image,    _cairo_win32_surface_acquire_dest_image,    _cairo_win32_surface_release_dest_image,    NULL, /* clone_similar */    _cairo_win32_surface_composite,    _cairo_win32_surface_fill_rectangles,    NULL, /* composite_trapezoids */    NULL, /* copy_page */    NULL, /* show_page */    _cairo_win32_surface_set_clip_region,    NULL, /* intersect_clip_path */    _cairo_win32_surface_get_extents,    NULL, /* old_show_glyphs */    NULL, /* get_font_options */    _cairo_win32_surface_flush,    NULL, /* mark_dirty_rectangle */    NULL, /* scaled_font_fini */    NULL, /* scaled_glyph_fini */    NULL, /* paint */    NULL, /* mask */    NULL, /* stroke */    NULL, /* fill */    _cairo_win32_surface_show_glyphs,    NULL  /* snapshot */};/* * Without pthread, on win32 we need to initialize all the 'mutex'es * before use. It is guaranteed that DllMain will get called single * threaded before any other function. * Initializing more than finally needed should not matter much. */#ifndef HAVE_PTHREAD_HCRITICAL_SECTION cairo_toy_font_face_hash_table_mutex;CRITICAL_SECTION cairo_scaled_font_map_mutex;CRITICAL_SECTION cairo_ft_unscaled_font_map_mutex;BOOL WINAPIDllMain (HINSTANCE hinstDLL,	 DWORD     fdwReason,	 LPVOID    lpvReserved){  switch (fdwReason)  {  case DLL_PROCESS_ATTACH:    /* every 'mutex' from CAIRO_MUTEX_DECALRE needs to be initialized here */    InitializeCriticalSection (&cairo_toy_font_face_hash_table_mutex);    InitializeCriticalSection (&cairo_scaled_font_map_mutex);    InitializeCriticalSection (&cairo_ft_unscaled_font_map_mutex);    break;  case DLL_PROCESS_DETACH:    DeleteCriticalSection (&cairo_toy_font_face_hash_table_mutex);    DeleteCriticalSection (&cairo_scaled_font_map_mutex);    DeleteCriticalSection (&cairo_ft_unscaled_font_map_mutex);    break;  }  return TRUE;}#endif

⌨️ 快捷键说明

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