void miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box) { box->y1 = MAXSHORT; box->y2 = MINSHORT; box->x1 = MAXSHORT; box->x2 = MINSHORT; for (; ntrap; ntrap--, traps++) { INT16 x1, y1, x2, y2; if (!xTrapezoidValid(traps)) continue; y1 = xFixedToInt (traps->top); if (y1 < box->y1) box->y1 = y1; y2 = xFixedToInt (xFixedCeil (traps->bottom)); if (y2 > box->y2) box->y2 = y2; x1 = xFixedToInt (min (miLineFixedX (&traps->left, traps->top, FALSE), miLineFixedX (&traps->left, traps->bottom, FALSE))); if (x1 < box->x1) box->x1 = x1; x2 = xFixedToInt (xFixedCeil (max (miLineFixedX (&traps->right, traps->top, TRUE), miLineFixedX (&traps->right, traps->bottom, TRUE)))); if (x2 > box->x2) box->x2 = x2; } }
static void pixman_trapezoid_bounds (int ntrap, const pixman_trapezoid_t *traps, pixman_box16_t *box) { box->y1 = MAXSHORT; box->y2 = MINSHORT; box->x1 = MAXSHORT; box->x2 = MINSHORT; for (; ntrap; ntrap--, traps++) { int16_t x1, y1, x2, y2; if (!xTrapezoidValid(traps)) continue; y1 = xFixedToInt (traps->top); if (y1 < box->y1) box->y1 = y1; y2 = xFixedToInt (xFixedCeil (traps->bottom)); if (y2 > box->y2) box->y2 = y2; x1 = xFixedToInt (MIN (pixman_line_fixed_x (&traps->left, traps->top, 0), pixman_line_fixed_x (&traps->left, traps->bottom, 0))); if (x1 < box->x1) box->x1 = x1; x2 = xFixedToInt (xFixedCeil (MAX (pixman_line_fixed_x (&traps->right, traps->top, 1), pixman_line_fixed_x (&traps->right, traps->bottom, 1)))); if (x2 > box->x2) box->x2 = x2; } }
void fbRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid *trap, int x_off, int y_off) { FbBits *buf; int bpp; int width; int stride; int height; int pxoff, pyoff; xFixed x_off_fixed; xFixed y_off_fixed; RenderEdge l, r; xFixed t, b; if (!xTrapezoidValid (trap)) return; fbGetDrawable (pPicture->pDrawable, buf, stride, bpp, pxoff, pyoff); width = pPicture->pDrawable->width; height = pPicture->pDrawable->height; x_off += pxoff; y_off += pyoff; x_off_fixed = IntToxFixed(x_off); y_off_fixed = IntToxFixed(y_off); t = trap->top + y_off_fixed; if (t < 0) t = 0; t = RenderSampleCeilY (t, bpp); b = trap->bottom + y_off_fixed; if (xFixedToInt (b) >= height) b = IntToxFixed (height) - 1; b = RenderSampleFloorY (b, bpp); if (b >= t) { /* initialize edge walkers */ RenderLineFixedEdgeInit (&l, bpp, t, &trap->left, x_off, y_off); RenderLineFixedEdgeInit (&r, bpp, t, &trap->right, x_off, y_off); fbRasterizeEdges (buf, bpp, width, stride, &l, &r, t, b); } }
void pixman_add_trapezoids (pixman_image_t *dst, int x_off, int y_off, const pixman_trapezoid_t *traps, int ntraps) { for (; ntraps; ntraps--, traps++) { if (!xTrapezoidValid (traps)) continue; fbRasterizeTrapezoid (dst, traps, x_off, y_off); } }
/* XXX: There are failure cases in this function. Don't we need to * propagate the errors out? */ void pixman_composite_trapezoids (pixman_operator_t op, pixman_image_t *src, pixman_image_t *dst, int xSrc, int ySrc, const pixman_trapezoid_t *traps, int ntraps) { pixman_image_t *image = NULL; pixman_box16_t traps_bounds, dst_bounds, bounds; pixman_region16_t *traps_region, *dst_region; int16_t xDst, yDst; int16_t xRel, yRel; pixman_format_t *format; if (ntraps == 0) return; /* * Check for solid alpha add */ if (op == PIXMAN_OPERATOR_ADD && miIsSolidAlpha (src)) { for (; ntraps; ntraps--, traps++) fbRasterizeTrapezoid (dst, traps, 0, 0); return; } xDst = traps[0].left.p1.x >> 16; yDst = traps[0].left.p1.y >> 16; pixman_trapezoid_bounds (ntraps, traps, &traps_bounds); traps_region = pixman_region_create_simple (&traps_bounds); /* XXX: If the image has a clip region set, we should really be * fetching it here instead, but it looks like we don't yet expose * a pixman_image_get_clip_region function. */ dst_bounds.x1 = 0; dst_bounds.y1 = 0; dst_bounds.x2 = pixman_image_get_width (dst); dst_bounds.y2 = pixman_image_get_height (dst); dst_region = pixman_region_create_simple (&dst_bounds); pixman_region_intersect (traps_region, traps_region, dst_region); bounds = *(pixman_region_extents (traps_region)); pixman_region_destroy (traps_region); pixman_region_destroy (dst_region); if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) return; format = pixman_format_create (PIXMAN_FORMAT_NAME_A8); if (!format) return; image = FbCreateAlphaPicture (dst, format, bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); if (!image) { pixman_format_destroy (format); return; } for (; ntraps; ntraps--, traps++) { if (!xTrapezoidValid(traps)) continue; fbRasterizeTrapezoid (image, traps, -bounds.x1, -bounds.y1); } xRel = bounds.x1 + xSrc - xDst; yRel = bounds.y1 + ySrc - yDst; pixman_composite (op, src, image, dst, xRel, yRel, 0, 0, bounds.x1, bounds.y1, bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); pixman_image_destroy (image); pixman_format_destroy (format); }