/*- *----------------------------------------------------------------------- *pixman_coalesce-- *Attempttomergetheboxesinthecurrentbandwiththoseinthe *previousone.Weareguaranteedthatthecurrentbandextendsto *theendoftherectsarray.Usedonlybypixman_op. * *Results: *Thenewindexforthepreviousband. * *SideEffects: *Ifcoalescingtakesplace: *-rectanglesinthepreviousbandwillhavetheiry2fields *altered. *-region->data->numRectswillbedecreased. * *-----------------------------------------------------------------------
*/ staticinlineint
pixman_coalesce (region_type_t * region, /* Region to coalesce */ int prev_start, /* Index of start of previous band */ int cur_start) /* Index of start of current band */
{
box_type_t *prev_box; /* Current box in previous band */
box_type_t *cur_box; /* Current box in current band */ int numRects; /* Number rectangles in both bands */ int y2; /* Bottom of current band */
/* Make sure we have enough space for all rectangles to be added */
RECTALLOC (region, new_rects);
next_rect = PIXREGION_TOP (region);
region->data->numRects += new_rects;
do
{
critical_if_fail (r->x1 < r->x2);
ADDRECT (next_rect, r->x1, y1, r->x2, y2);
r++;
} while (r != r_end);
returnTRUE;
}
#define FIND_BAND(r, r_band_end, r_end, ry1) \ do \
{ \
ry1 = r->y1; \
r_band_end = r + 1; \ while ((r_band_end != r_end) && (r_band_end->y1 == ry1)) { \
r_band_end++; \
} \
} while (0)
static pixman_bool_t
pixman_op (region_type_t * new_reg, /* Place to store result */ const region_type_t * reg1, /* First region in operation */ const region_type_t * reg2, /* 2d region in operation */
overlap_proc_ptr overlap_func, /* Function to call for over-
* lapping bands */ int append_non1, /* Append non-overlapping bands *inregion1?
*/ int append_non2 /* Append non-overlapping bands *inregion2?
*/
)
{
box_type_t *r1; /* Pointer into first region */
box_type_t *r2; /* Pointer into 2d region */
box_type_t *r1_end; /* End of 1st region */
box_type_t *r2_end; /* End of 2d region */ int ybot; /* Bottom of intersection */ int ytop; /* Top of intersection */
region_data_type_t *old_data; /* Old data for new_reg */ int prev_band; /* Index of start of
* previous band in new_reg */ int cur_band; /* Index of start of current
* band in new_reg */
box_type_t * r1_band_end; /* End of current band in r1 */
box_type_t * r2_band_end; /* End of current band in r2 */ int top; /* Top of non-overlapping band */ int bot; /* Bottom of non-overlapping band*/ int r1y1; /* Temps for r1->y1 and r2->y1 */ int r2y1; int new_size; int numRects;
if ((r1 != r1_end) && append_non1)
{ /* Do first non_overlap1Func call, which may be able to coalesce */
FIND_BAND (r1, r1_band_end, r1_end, r1y1);
cur_band = new_reg->data->numRects;
if (!pixman_region_append_non_o (new_reg,
r1, r1_band_end,
MAX (r1y1, ybot), r1->y2))
{ goto bail;
}
COALESCE (new_reg, prev_band, cur_band);
/* Just append the rest of the boxes */
APPEND_REGIONS (new_reg, r1_band_end, r1_end);
} elseif ((r2 != r2_end) && append_non2)
{ /* Do first non_overlap2Func call, which may be able to coalesce */
FIND_BAND (r2, r2_band_end, r2_end, r2y1);
cur_band = new_reg->data->numRects;
if (!pixman_region_append_non_o (new_reg,
r2, r2_band_end,
MAX (r2y1, ybot), r2->y2))
{ goto bail;
}
/*- *----------------------------------------------------------------------- *pixman_region_union_o-- *Handleanoverlappingbandfortheunionoperation.Picksthe *left-mostrectangleeachtimeandmergesitintotheregion. * *Results: *TRUEifsuccessful. * *SideEffects: *regionisoverwritten. *overlapissettoTRUEifanyboxesoverlap. * *-----------------------------------------------------------------------
*/ static pixman_bool_t
pixman_region_union_o (region_type_t *region,
box_type_t * r1,
box_type_t * r1_end,
box_type_t * r2,
box_type_t * r2_end, int y1, int y2)
{
box_type_t *next_rect; int x1; /* left and right side of current union */ int x2;
/* Start off current rectangle */ if (r1->x1 < r2->x1)
{
x1 = r1->x1;
x2 = r1->x2;
r1++;
} else
{
x1 = r2->x1;
x2 = r2->x2;
r2++;
} while (r1 != r1_end && r2 != r2_end)
{ if (r1->x1 < r2->x1)
MERGERECT (r1); else
MERGERECT (r2);
}
/* Finish off whoever (if any) is left */ if (r1 != r1_end)
{ do
{
MERGERECT (r1);
} while (r1 != r1_end);
} elseif (r2 != r2_end)
{ do
{
MERGERECT (r2);
} while (r2 != r2_end);
}
/* Convenience function for performing union of region with a *singlerectangle
*/
PIXMAN_EXPORT pixman_bool_t
PREFIX (_union_rect) (region_type_t *dest, const region_type_t *source, int x, int y, unsignedint width, unsignedint height)
{
region_type_t region;
region.extents.x1 = x;
region.extents.y1 = y;
region.extents.x2 = x + width;
region.extents.y2 = y + height;
if (!GOOD_RECT (®ion.extents))
{ if (BAD_RECT (®ion.extents))
_pixman_log_error (FUNC, "Invalid rectangle passed"); return PREFIX (_copy) (dest, source);
}
region.data = NULL;
return PREFIX (_union) (dest, source, ®ion);
}
PIXMAN_EXPORT pixman_bool_t
PREFIX (_union) (region_type_t * new_reg, const region_type_t *reg1, const region_type_t *reg2)
{ /* Return TRUE if some overlap *betweenreg1,reg2
*/
GOOD (reg1);
GOOD (reg2);
GOOD (new_reg);
/* *Region1isempty
*/ if (PIXREGION_NIL (reg1))
{ if (PIXREGION_NAR (reg1)) return pixman_break (new_reg);
if (new_reg != reg2) return PREFIX (_copy) (new_reg, reg2);
returnTRUE;
}
/* *Region2isempty
*/ if (PIXREGION_NIL (reg2))
{ if (PIXREGION_NAR (reg2)) return pixman_break (new_reg);
if (new_reg != reg1) return PREFIX (_copy) (new_reg, reg1);
returnTRUE;
}
/* *Region1completelysubsumesregion2
*/ if (!reg1->data && SUBSUMES (®1->extents, ®2->extents))
{ if (new_reg != reg1) return PREFIX (_copy) (new_reg, reg1);
returnTRUE;
}
/* *Region2completelysubsumesregion1
*/ if (!reg2->data && SUBSUMES (®2->extents, ®1->extents))
{ if (new_reg != reg2) return PREFIX (_copy) (new_reg, reg2);
returnTRUE;
}
if (!pixman_op (new_reg, reg1, reg2, pixman_region_union_o, TRUE, TRUE)) returnFALSE;
new_reg->extents.x1 = MIN (reg1->extents.x1, reg2->extents.x1);
new_reg->extents.y1 = MIN (reg1->extents.y1, reg2->extents.y1);
new_reg->extents.x2 = MAX (reg1->extents.x2, reg2->extents.x2);
new_reg->extents.y2 = MAX (reg1->extents.y2, reg2->extents.y2);
static pixman_bool_t
validate (region_type_t * badreg)
{ /* Descriptor for regions under construction in Step 2. */ typedefstruct
{
region_type_t reg; int prev_band; int cur_band;
} region_info_t;
region_info_t stack_regions[64];
int numRects; /* Original numRects for badreg */
region_info_t *ri; /* Array of current regions */ int num_ri; /* Number of entries used in ri */ int size_ri; /* Number of entries available in ri */ int i; /* Index into rects */ int j; /* Index into ri */
region_info_t *rit; /* &ri[j] */
region_type_t *reg; /* ri[j].reg */
box_type_t *box; /* Current box in rects */
box_type_t *ri_box; /* Last box in ri[j].reg */
region_type_t *hreg; /* ri[j_half].reg */
pixman_bool_t ret = TRUE;
if (!badreg->data)
{
GOOD (badreg); returnTRUE;
}
numRects = badreg->data->numRects; if (!numRects)
{ if (PIXREGION_NAR (badreg)) returnFALSE;
GOOD (badreg); returnTRUE;
}
/* Step 1: Sort the rects array into ascending (y1, x1) order */
quick_sort_rects (PIXREGION_BOXPTR (badreg), numRects);
/* Step 2: Scatter the sorted array into the minimum number of regions */
/* Set up the first region to be the first rectangle in badreg */ /* Note that step 2 code will never overflow the ri[0].reg rects array */
ri = stack_regions;
size_ri = sizeof (stack_regions) / sizeof (stack_regions[0]);
num_ri = 1;
ri[0].prev_band = 0;
ri[0].cur_band = 0;
ri[0].reg = *badreg;
box = PIXREGION_BOXPTR (&ri[0].reg);
ri[0].reg.extents = *box;
ri[0].reg.data->numRects = 1;
badreg->extents = *pixman_region_empty_box;
badreg->data = pixman_region_empty_data;
/* Now scatter rectangles into the minimum set of valid regions. If the *nextrectangletobeaddedtoaregionwouldforceanexistingrectangle *intheregiontobesplitupinordertomaintainy-xbanding,just *forgetit.Trythenextregion.Ifitdoesn'tfitcleanlyintoany *region,makeanewone.
*/
for (i = numRects; --i > 0;)
{
box++; /* Look for a region to append box to */ for (j = num_ri, rit = ri; --j >= 0; rit++)
{
reg = &rit->reg;
ri_box = PIXREGION_END (reg);
if (box->y1 == ri_box->y1 && box->y2 == ri_box->y2)
{ /* box is in same band as ri_box. Merge or append it */ if (box->x1 <= ri_box->x2)
{ /* Merge it with ri_box */ if (box->x2 > ri_box->x2)
ri_box->x2 = box->x2;
} else
{
RECTALLOC_BAIL (reg, 1, bail);
*PIXREGION_TOP (reg) = *box;
reg->data->numRects++;
}
goto next_rect; /* So sue me */
} elseif (box->y1 >= ri_box->y2)
{ /* Put box into new band */ if (reg->extents.x2 < ri_box->x2)
reg->extents.x2 = ri_box->x2;
if (reg->extents.x1 > box->x1)
reg->extents.x1 = box->x1;
if (ri == stack_regions)
{
rit = malloc (data_size); if (!rit) goto bail;
memcpy (rit, ri, num_ri * sizeof (region_info_t));
} else
{
rit = (region_info_t *) realloc (ri, data_size); if (!rit) goto bail;
}
ri = rit;
rit = &ri[num_ri];
}
num_ri++;
rit->prev_band = 0;
rit->cur_band = 0;
rit->reg.extents = *box;
rit->reg.data = (region_data_type_t *)NULL;
/* MUST force allocation */ if (!pixman_rect_alloc (&rit->reg, (i + num_ri) / num_ri)) goto bail;
next_rect: ;
} /* for i */
/* Make a final pass over each region in order to COALESCE and set *extents.x2andextents.y2
*/ for (j = num_ri, rit = ri; --j >= 0; rit++)
{
reg = &rit->reg;
ri_box = PIXREGION_END (reg);
reg->extents.y2 = ri_box->y2;
if (reg->extents.x2 < ri_box->x2)
reg->extents.x2 = ri_box->x2;
/* Step 3: Union all regions into a single region */ while (num_ri > 1)
{ int half = num_ri / 2; for (j = num_ri & 1; j < (half + (num_ri & 1)); j++)
{
reg = &ri[j].reg;
hreg = &ri[j + half].reg;
if (!pixman_op (reg, reg, hreg, pixman_region_union_o, TRUE, TRUE))
ret = FALSE;
if (hreg->extents.x1 < reg->extents.x1)
reg->extents.x1 = hreg->extents.x1;
if (hreg->extents.y1 < reg->extents.y1)
reg->extents.y1 = hreg->extents.y1;
if (hreg->extents.x2 > reg->extents.x2)
reg->extents.x2 = hreg->extents.x2;
if (hreg->extents.y2 > reg->extents.y2)
reg->extents.y2 = hreg->extents.y2;
FREE_DATA (hreg);
}
num_ri -= half;
if (!ret) goto bail;
}
*badreg = ri[0].reg;
if (ri != stack_regions)
free (ri);
GOOD (badreg); return ret;
bail: for (i = 0; i < num_ri; i++)
FREE_DATA (&ri[i].reg);
/* Add those rectangles in region 1 that aren't in region 2, doyuckysubtractionforoverlaps,and
just throw away rectangles in region 2 that aren't in region 1 */ if (!pixman_op (reg_d, reg_m, reg_s, pixman_region_subtract_o, TRUE, FALSE)) returnFALSE;
/* Add those rectangles in region 1 that aren't in region 2, *doyuckysubtractionforoverlaps,and *justthrowawayrectanglesinregion2thataren'tinregion1
*/
inv_reg.extents = *inv_rect;
inv_reg.data = (region_data_type_t *)NULL; if (!pixman_op (new_reg, &inv_reg, reg1, pixman_region_subtract_o, TRUE, FALSE)) returnFALSE;
/* In time O(log n), locate the first box whose y2 is greater than y. *Return@endifnosuchboxexists.
*/ static box_type_t *
find_box_for_y (box_type_t *begin, box_type_t *end, int y)
{
box_type_t *mid;
if (end == begin) return end;
if (end - begin == 1)
{ if (begin->y2 > y) return begin; else return end;
}
mid = begin + (end - begin) / 2; if (mid->y2 > y)
{ /* If no box is found in [begin, mid], the function *willreturn@mid,whichisthenknowntobethe *correctanswer.
*/ return find_box_for_y (begin, mid, y);
} else
{ return find_box_for_y (mid, end, y);
}
}
if (numRects == 1)
{ /* We know that it must be PIXMAN_REGION_IN or PIXMAN_REGION_PART */ if (SUBSUMES (®ion->extents, prect)) return(PIXMAN_REGION_IN); else return(PIXMAN_REGION_PART);
}
part_out = FALSE;
part_in = FALSE;
/* (x,y) starts at upper left of rect, moving to the right and down */
x = prect->x1;
y = prect->y1;
/* can stop when both part_out and part_in are TRUE, or we reach prect->y2 */ for (pbox = PIXREGION_BOXPTR (region), pbox_end = pbox + numRects;
pbox != pbox_end;
pbox++)
{ /* getting up to speed or skipping remainder of band */ if (pbox->y2 <= y)
{ if ((pbox = find_box_for_y (pbox, pbox_end, y)) == pbox_end) break;
}
if (pbox->y1 > y)
{
part_out = TRUE; /* missed part of rectangle above */ if (part_in || (pbox->y1 >= prect->y2)) break;
y = pbox->y1; /* x guaranteed to be == prect->x1 */
}
if (pbox->x2 <= x) continue; /* not far enough over yet */
if (pbox->x1 > x)
{
part_out = TRUE; /* missed part of rectangle to left */ if (part_in) break;
}
if (pbox->x1 < prect->x2)
{
part_in = TRUE; /* definitely overlap */ if (part_out) break;
}
if (pbox->x2 >= prect->x2)
{
y = pbox->y2; /* finished with this band */ if (y >= prect->y2) break;
x = prect->x1; /* reset x out to left again */
} else
{ /* *Becauseboxesinabandaremaximalwidth,ifthefirstbox *tooverlaptherectangledoesn'tcompletelycoveritinthat *band,therectanglemustbepartiallyout,sincesomeofit *willbeuncoveredinthatband.part_inwillhavebeensettrue *bynow...
*/
part_out = TRUE; break;
}
}
if (part_in)
{ if (y < prect->y2) return PIXMAN_REGION_PART; else return PIXMAN_REGION_IN;
} else
{ return PIXMAN_REGION_OUT;
}
}
/* box is "return" value */
PIXMAN_EXPORT int
PREFIX (_contains_point) (const region_type_t * region, int x, int y,
box_type_t * box)
{
box_type_t *pbox, *pbox_end; int numRects;
GOOD (region);
numRects = PIXREGION_NUMRECTS (region);
if (!numRects || !INBOX (®ion->extents, x, y)) return(FALSE);
if (numRects == 1)
{ if (box)
*box = region->extents;
PIXMAN_EXPORT pixman_bool_t
PREFIX (_init_rects) (region_type_t *region, const box_type_t *boxes, int count)
{
box_type_t *rects; int displacement; int i;
/* if it's 1, then we just want to set the extents, so call
* the existing method. */ if (count == 1)
{
PREFIX (_init_rect) (region,
boxes[0].x1,
boxes[0].y1,
boxes[0].x2 - boxes[0].x1,
boxes[0].y2 - boxes[0].y1); returnTRUE;
}
PREFIX (_init) (region);
/* if it's 0, don't call pixman_rect_alloc -- 0 rectangles is *aspecialcase,andcausingpixman_rect_allocwouldcause *ustoleakmemory(becausethe0-rectcaseshouldbethe *staticpixman_region_empty_datadata).
*/ if (count == 0) returnTRUE;
if (!pixman_rect_alloc (region, count)) returnFALSE;
rects = PIXREGION_RECTS (region);
/* Copy in the rects */
memcpy (rects, boxes, sizeof(box_type_t) * count);
region->data->numRects = count;
/* Eliminate empty and malformed rectangles */
displacement = 0;
for (i = 0; i < count; ++i)
{
box_type_t *box = &rects[i];
/* If the Screen left most bit of the word is set, we're starting in
* a box */ if (READ(pw) & mask0)
{
in_box = TRUE;
rx1 = 0;
} else
{
in_box = FALSE;
}
/* Process all words which are fully in the pixmap */
pw_line_end = pw + (width >> 5); for (base = 0; pw < pw_line_end; base += 32)
{
w = READ(pw++); if (in_box)
{ if (!~w) continue;
} else
{ if (!w) continue;
} for (ib = 0; ib < 32; ib++)
{ /* If the Screen left most bit of the word is set, we're
* starting a box */ if (w & mask0)
{ if (!in_box)
{
rx1 = base + ib; /* start new box */
in_box = TRUE;
}
} else
{ if (in_box)
{ /* end box */
rects = bitmap_addrect (region, rects, &first_rect,
rx1, h, base + ib, h + 1); if (rects == NULL) goto error;
in_box = FALSE;
}
} /* Shift the word VISUALLY left one. */
w = SCREEN_SHIFT_LEFT(w, 1);
}
}
if (width & 31)
{ /* Process final partial word on line */
w = READ(pw++); for (ib = 0; ib < (width & 31); ib++)
{ /* If the Screen left most bit of the word is set, we're
* starting a box */ if (w & mask0)
{ if (!in_box)
{
rx1 = base + ib; /* start new box */
in_box = TRUE;
}
} else
{ if (in_box)
{ /* end box */
rects = bitmap_addrect(region, rects, &first_rect,
rx1, h, base + ib, h + 1); if (rects == NULL) goto error;
in_box = FALSE;
}
} /* Shift the word VISUALLY left one. */
w = SCREEN_SHIFT_LEFT(w, 1);
}
} /* If scanline ended with last bit set, end the box */ if (in_box)
{
rects = bitmap_addrect(region, rects, &first_rect,
rx1, h, base + (width & 31), h + 1); if (rects == NULL) goto error;
} /* if all rectangles on this line have the same x-coords as *thoseonthepreviousline,thenadd1toallthepreviousy2sand *throwawayalltherectanglesfromthisline
*/
same = FALSE; if (irect_prev_start != -1)
{
crects = irect_line_start - irect_prev_start; if (crects != 0 &&
crects == ((rects - first_rect) - irect_line_start))
{
old_rect = first_rect + irect_prev_start;
new_rect = prect_line_start = first_rect + irect_line_start;
same = TRUE; while (old_rect < prect_line_start)
{ if ((old_rect->x1 != new_rect->x1) ||
(old_rect->x2 != new_rect->x2))
{
same = FALSE; break;
}
old_rect++;
new_rect++;
} if (same)
{
old_rect = first_rect + irect_prev_start; while (old_rect < prect_line_start)
{
old_rect->y2 += 1;
old_rect++;
}
rects -= crects;
region->data->numRects -= crects;
}
}
} if(!same)
irect_prev_start = irect_line_start;
} if (!region->data->numRects)
{
region->extents.x1 = region->extents.x2 = 0;
} else
{
region->extents.y1 = PIXREGION_BOXPTR(region)->y1;
region->extents.y2 = PIXREGION_END(region)->y2; if (region->data->numRects == 1)
{
free (region->data);
region->data = NULL;
}
}
error: return;
}
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.73Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.