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

📄 pixman-compose.c

📁 嵌入式图形库
💻 C
字号:
/* * * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. *             2005 Lars Knoll & Zack Rusin, Trolltech * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Keith Packard not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission.  Keith Packard makes no * representations about the suitability of this software for any purpose.  It * is provided "as is" without express or implied warranty. * * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdlib.h>#include <string.h>#include <math.h>#include <assert.h>#include <limits.h>#include "pixman-private.h"#ifdef PIXMAN_FB_ACCESSORS#define PIXMAN_COMPOSITE_RECT_GENERAL pixman_composite_rect_general_accessors#define PIXMAN_COMPOSE_FUNCTIONS pixman_composeFunctions_accessors#define FETCH_PROC_FOR_PICTURE pixman_fetchProcForPicture_accessors#define FETCH_PIXEL_PROC_FOR_PICTURE pixman_fetchPixelProcForPicture_accessors#define STORE_PROC_FOR_PICTURE pixman_storeProcForPicture_accessors#define FB_FETCH_TRANSFORMED fbFetchTransformed_accessors#define FB_FETCH_EXTERNAL_ALPHA fbFetchExternalAlpha_accessors#define FB_STORE_EXTERNAL_ALPHA fbStoreExternalAlpha_accessors#else#define PIXMAN_COMPOSITE_RECT_GENERAL pixman_composite_rect_general_no_accessors#define PIXMAN_COMPOSE_FUNCTIONS pixman_composeFunctions#define FETCH_PROC_FOR_PICTURE pixman_fetchProcForPicture#define FETCH_PIXEL_PROC_FOR_PICTURE pixman_fetchPixelProcForPicture#define STORE_PROC_FOR_PICTURE pixman_storeProcForPicture#define FB_FETCH_TRANSFORMED fbFetchTransformed#define FB_FETCH_EXTERNAL_ALPHA fbFetchExternalAlpha#define FB_STORE_EXTERNAL_ALPHA fbStoreExternalAlpha#endifstatic unsigned intSourcePictureClassify (source_image_t *pict,		       int	       x,		       int	       y,		       int	       width,		       int	       height){    if (pict->common.type == SOLID)    {	pict->class = SOURCE_IMAGE_CLASS_HORIZONTAL;    }    else if (pict->common.type == LINEAR)    {	linear_gradient_t *linear = (linear_gradient_t *)pict;	pixman_vector_t   v;	pixman_fixed_32_32_t l;	pixman_fixed_48_16_t dx, dy, a, b, off;	pixman_fixed_48_16_t factors[4];	int	     i;	dx = linear->p2.x - linear->p1.x;	dy = linear->p2.y - linear->p1.y;	l = dx * dx + dy * dy;	if (l)	{	    a = (dx << 32) / l;	    b = (dy << 32) / l;	}	else	{	    a = b = 0;	}	off = (-a * linear->p1.x	       -b * linear->p1.y) >> 16;	for (i = 0; i < 3; i++)	{	    v.vector[0] = pixman_int_to_fixed ((i % 2) * (width  - 1) + x);	    v.vector[1] = pixman_int_to_fixed ((i / 2) * (height - 1) + y);	    v.vector[2] = pixman_fixed_1;	    if (pict->common.transform)	    {		if (!pixman_transform_point_3d (pict->common.transform, &v))		    return SOURCE_IMAGE_CLASS_UNKNOWN;	    }	    factors[i] = ((a * v.vector[0] + b * v.vector[1]) >> 16) + off;	}	if (factors[2] == factors[0])	    pict->class = SOURCE_IMAGE_CLASS_HORIZONTAL;	else if (factors[1] == factors[0])	    pict->class = SOURCE_IMAGE_CLASS_VERTICAL;    }    return pict->class;}static void fbFetchSolid(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits){    uint32_t color;    uint32_t *end;    fetchPixelProc fetch = FETCH_PIXEL_PROC_FOR_PICTURE(pict);    color = fetch(pict, 0, 0);    end = buffer + width;    while (buffer < end)	*(buffer++) = color;}static void fbFetch(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits){    fetchProc fetch = FETCH_PROC_FOR_PICTURE(pict);    fetch(pict, x, y, width, buffer);}#ifdef PIXMAN_FB_ACCESSORS	/* The accessor version can't be parameterized from outside */static const#endifFbComposeFunctions PIXMAN_COMPOSE_FUNCTIONS = {    pixman_fbCombineFuncU,    pixman_fbCombineFuncC,    pixman_fbCombineMaskU};static voidfbStore(bits_image_t * pict, int x, int y, int width, uint32_t *buffer){    uint32_t *bits;    int32_t stride;    storeProc store = STORE_PROC_FOR_PICTURE(pict);    const pixman_indexed_t * indexed = pict->indexed;    bits = pict->bits;    stride = pict->rowstride;    bits += y*stride;    store((pixman_image_t *)pict, bits, buffer, x, width, indexed);}typedef void (*scanStoreProc)(pixman_image_t *, int, int, int, uint32_t *);typedef void (*scanFetchProc)(pixman_image_t *, int, int, int, uint32_t *,			      uint32_t *, uint32_t);#ifndef PIXMAN_FB_ACCESSORSstatic#endifvoidPIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data,			       uint32_t *scanline_buffer){    uint32_t *src_buffer = scanline_buffer;    uint32_t *dest_buffer = src_buffer + data->width;    int i;    scanStoreProc store;    scanFetchProc fetchSrc = NULL, fetchMask = NULL, fetchDest = NULL;    unsigned int srcClass = SOURCE_IMAGE_CLASS_UNKNOWN;    unsigned int maskClass = SOURCE_IMAGE_CLASS_UNKNOWN;    uint32_t *bits;    int32_t stride;    int xoff, yoff;    if (data->op == PIXMAN_OP_CLEAR)        fetchSrc = NULL;    else if (IS_SOURCE_IMAGE (data->src))    {	fetchSrc = (scanFetchProc)pixmanFetchSourcePict;	srcClass = SourcePictureClassify ((source_image_t *)data->src,					  data->xSrc, data->ySrc,					  data->width, data->height);    }    else    {	bits_image_t *bits = (bits_image_t *)data->src;	if (bits->common.alpha_map)	{	    fetchSrc = (scanFetchProc)FB_FETCH_EXTERNAL_ALPHA;	}	else if ((bits->common.repeat == PIXMAN_REPEAT_NORMAL || bits->common.repeat == PIXMAN_REPEAT_PAD) &&		 bits->width == 1 &&		 bits->height == 1)	{	    fetchSrc = (scanFetchProc)fbFetchSolid;	    srcClass = SOURCE_IMAGE_CLASS_HORIZONTAL;	}	else if (!bits->common.transform && bits->common.filter != PIXMAN_FILTER_CONVOLUTION                && bits->common.repeat != PIXMAN_REPEAT_PAD)	{	    fetchSrc = (scanFetchProc)fbFetch;	}	else	{	    fetchSrc = (scanFetchProc)FB_FETCH_TRANSFORMED;	}    }    if (!data->mask || data->op == PIXMAN_OP_CLEAR)    {	fetchMask = NULL;    }    else    {	if (IS_SOURCE_IMAGE (data->mask))	{	    fetchMask = (scanFetchProc)pixmanFetchSourcePict;	    maskClass = SourcePictureClassify ((source_image_t *)data->mask,					       data->xMask, data->yMask,					       data->width, data->height);	}	else	{	    bits_image_t *bits = (bits_image_t *)data->mask;	    if (bits->common.alpha_map)	    {		fetchMask = (scanFetchProc)FB_FETCH_EXTERNAL_ALPHA;	    }	    else if ((bits->common.repeat == PIXMAN_REPEAT_NORMAL || bits->common.repeat == PIXMAN_REPEAT_PAD) &&		     bits->width == 1 && bits->height == 1)	    {		fetchMask = (scanFetchProc)fbFetchSolid;		maskClass = SOURCE_IMAGE_CLASS_HORIZONTAL;	    }	    else if (!bits->common.transform && bits->common.filter != PIXMAN_FILTER_CONVOLUTION                    && bits->common.repeat != PIXMAN_REPEAT_PAD)		fetchMask = (scanFetchProc)fbFetch;	    else		fetchMask = (scanFetchProc)FB_FETCH_TRANSFORMED;	}    }    if (data->dest->common.alpha_map)    {	fetchDest = (scanFetchProc)FB_FETCH_EXTERNAL_ALPHA;	store = (scanStoreProc)FB_STORE_EXTERNAL_ALPHA;	if (data->op == PIXMAN_OP_CLEAR || data->op == PIXMAN_OP_SRC)	    fetchDest = NULL;    }    else    {	fetchDest = (scanFetchProc)fbFetch;	store = (scanStoreProc)fbStore;	switch (data->op)	{	case PIXMAN_OP_CLEAR:	case PIXMAN_OP_SRC:	    fetchDest = NULL;#ifndef PIXMAN_FB_ACCESSORS	    /* fall-through */	case PIXMAN_OP_ADD:	case PIXMAN_OP_OVER:	    switch (data->dest->bits.format) {	    case PIXMAN_a8r8g8b8:	    case PIXMAN_x8r8g8b8:		store = NULL;		break;	    default:		break;	    }#endif	    break;	}    }    if (!store)    {	bits = data->dest->bits.bits;	stride = data->dest->bits.rowstride;	xoff = yoff = 0;    }    else    {	bits = NULL;	stride = 0;	xoff = yoff = 0;    }    if (fetchSrc		   &&	fetchMask		   &&	data->mask		   &&	data->mask->common.type == BITS &&	data->mask->common.component_alpha &&	PIXMAN_FORMAT_RGB (data->mask->bits.format))    {	uint32_t *mask_buffer = dest_buffer + data->width;	CombineFuncC compose = PIXMAN_COMPOSE_FUNCTIONS.combineC[data->op];	if (!compose)	    return;	for (i = 0; i < data->height; ++i) {	    /* fill first half of scanline with source */	    if (fetchSrc)	    {		if (fetchMask)		{		    /* fetch mask before source so that fetching of		       source can be optimized */		    fetchMask (data->mask, data->xMask, data->yMask + i,			       data->width, mask_buffer, 0, 0);		    if (maskClass == SOURCE_IMAGE_CLASS_HORIZONTAL)			fetchMask = NULL;		}		if (srcClass == SOURCE_IMAGE_CLASS_HORIZONTAL)		{		    fetchSrc (data->src, data->xSrc, data->ySrc + i,			      data->width, src_buffer, 0, 0);		    fetchSrc = NULL;		}		else		{		    fetchSrc (data->src, data->xSrc, data->ySrc + i,			      data->width, src_buffer, mask_buffer,			      0xffffffff);		}	    }	    else if (fetchMask)	    {		fetchMask (data->mask, data->xMask, data->yMask + i,			   data->width, mask_buffer, 0, 0);	    }	    if (store)	    {		/* fill dest into second half of scanline */		if (fetchDest)		    fetchDest (data->dest, data->xDest, data->yDest + i,			       data->width, dest_buffer, 0, 0);		/* blend */		compose (dest_buffer, src_buffer, mask_buffer, data->width);		/* write back */		store (data->dest, data->xDest, data->yDest + i, data->width,		       dest_buffer);	    }	    else	    {		/* blend */		compose (bits + (data->yDest + i+ yoff) * stride +			 data->xDest + xoff,			 src_buffer, mask_buffer, data->width);	    }	}    }    else    {	uint32_t *src_mask_buffer = 0, *mask_buffer = 0;	CombineFuncU compose = PIXMAN_COMPOSE_FUNCTIONS.combineU[data->op];	if (!compose)	    return;	if (fetchMask)	    mask_buffer = dest_buffer + data->width;	for (i = 0; i < data->height; ++i) {	    /* fill first half of scanline with source */	    if (fetchSrc)	    {		if (fetchMask)		{		    /* fetch mask before source so that fetching of		       source can be optimized */		    fetchMask (data->mask, data->xMask, data->yMask + i,			       data->width, mask_buffer, 0, 0);		    if (maskClass == SOURCE_IMAGE_CLASS_HORIZONTAL)			fetchMask = NULL;		}		if (srcClass == SOURCE_IMAGE_CLASS_HORIZONTAL)		{		    fetchSrc (data->src, data->xSrc, data->ySrc + i,			      data->width, src_buffer, 0, 0);		    if (mask_buffer)		    {			PIXMAN_COMPOSE_FUNCTIONS.combineU[PIXMAN_OP_IN] (mask_buffer, src_buffer, data->width);			src_mask_buffer = mask_buffer;		    }		    else			src_mask_buffer = src_buffer;		    fetchSrc = NULL;		}		else		{		    fetchSrc (data->src, data->xSrc, data->ySrc + i,			      data->width, src_buffer, mask_buffer,			      0xff000000);		    if (mask_buffer)			PIXMAN_COMPOSE_FUNCTIONS.combineMaskU (src_buffer,							       mask_buffer,							       data->width);		    src_mask_buffer = src_buffer;		}	    }	    else if (fetchMask)	    {		fetchMask (data->mask, data->xMask, data->yMask + i,			   data->width, mask_buffer, 0, 0);		PIXMAN_COMPOSE_FUNCTIONS.combineU[PIXMAN_OP_IN] (mask_buffer, src_buffer, data->width);		src_mask_buffer = mask_buffer;	    }	    if (store)	    {		/* fill dest into second half of scanline */		if (fetchDest)		    fetchDest (data->dest, data->xDest, data->yDest + i,			       data->width, dest_buffer, 0, 0);		/* blend */		compose (dest_buffer, src_mask_buffer, data->width);		/* write back */		store (data->dest, data->xDest, data->yDest + i, data->width,		       dest_buffer);	    }	    else	    {		/* blend */		compose (bits + (data->yDest + i+ yoff) * stride +			 data->xDest + xoff,			 src_mask_buffer, data->width);	    }	}    }}#ifndef PIXMAN_FB_ACCESSORSvoidpixman_composite_rect_general (const FbComposeData *data,			       uint32_t *scanline_buffer){    if (data->src->common.read_func			||	data->src->common.write_func			||	(data->mask && data->mask->common.read_func)	||	(data->mask && data->mask->common.write_func)	||	data->dest->common.read_func			||	data->dest->common.write_func)    {	pixman_composite_rect_general_accessors (data, scanline_buffer);    }    else    {	pixman_composite_rect_general_no_accessors (data, scanline_buffer);    }}#endif

⌨️ 快捷键说明

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