/********************************************************************** * pattern_brush * * Fill a number of rectangles with the pattern brush * FIXME: Should we insist l < r && t < b? Currently we assume this. */ static BOOL pattern_brush(dibdrv_physdev *pdev, int num, RECT *rects) { int i, j; const WINEREGION *clip; POINT origin; if(pdev->brush_and_bits == NULL) { switch(pdev->brush_style) { case BS_DIBPATTERN: if(!create_pattern_brush_bits(pdev)) return FALSE; break; case BS_HATCHED: if(!create_hatch_brush_bits(pdev)) return FALSE; break; default: ERR("Unexpected brush style %d\n", pdev->brush_style); return FALSE; } } GetBrushOrgEx(pdev->dev.hdc, &origin); clip = get_wine_region(pdev->clip); for(i = 0; i < num; i++) { for(j = 0; j < clip->numRects; j++) { RECT rect = rects[i]; /* Optimize unclipped case */ if(clip->rects[j].top <= rect.top && clip->rects[j].bottom >= rect.bottom && clip->rects[j].left <= rect.left && clip->rects[j].right >= rect.right) { pdev->dib.funcs->pattern_rects(&pdev->dib, 1, &rect, &origin, &pdev->brush_dib, pdev->brush_and_bits, pdev->brush_xor_bits); break; } if(clip->rects[j].top >= rect.bottom) break; if(clip->rects[j].bottom <= rect.top) continue; if(clip->rects[j].right > rect.left && clip->rects[j].left < rect.right) { rect.left = max(rect.left, clip->rects[j].left); rect.top = max(rect.top, clip->rects[j].top); rect.right = min(rect.right, clip->rects[j].right); rect.bottom = min(rect.bottom, clip->rects[j].bottom); pdev->dib.funcs->pattern_rects(&pdev->dib, 1, &rect, &origin, &pdev->brush_dib, pdev->brush_and_bits, pdev->brush_xor_bits); } } } release_wine_region(pdev->clip); return TRUE; }
void add_clipped_bounds( dibdrv_physdev *dev, const RECT *rect, HRGN clip ) { const WINEREGION *region; RECT rc; if (!dev->bounds) return; if (clip) { if (!(region = get_wine_region( clip ))) return; if (!rect) rc = region->extents; else intersect_rect( &rc, rect, ®ion->extents ); release_wine_region( clip ); } else rc = *rect; if (is_rect_empty( &rc )) return; offset_rect( &rc, dev->dib.rect.left, dev->dib.rect.top ); add_bounds_rect( dev->bounds, &rc ); }
int get_clipped_rects( const dib_info *dib, const RECT *rc, HRGN clip, struct clipped_rects *clip_rects ) { const WINEREGION *region; RECT rect, *out = clip_rects->buffer; int i; init_clipped_rects( clip_rects ); rect.left = max( 0, -dib->rect.left ); rect.top = max( 0, -dib->rect.top ); rect.right = min( dib->rect.right, dib->width ) - dib->rect.left; rect.bottom = min( dib->rect.bottom, dib->height ) - dib->rect.top; if (is_rect_empty( &rect )) return 0; if (rc && !intersect_rect( &rect, &rect, rc )) return 0; if (!clip) { *out = rect; clip_rects->count = 1; return 1; } if (!(region = get_wine_region( clip ))) return 0; for (i = 0; i < region->numRects; i++) { if (region->rects[i].top >= rect.bottom) break; if (!intersect_rect( out, &rect, ®ion->rects[i] )) continue; out++; if (out == &clip_rects->buffer[sizeof(clip_rects->buffer) / sizeof(RECT)]) { clip_rects->rects = HeapAlloc( GetProcessHeap(), 0, region->numRects * sizeof(RECT) ); if (!clip_rects->rects) return 0; memcpy( clip_rects->rects, clip_rects->buffer, (out - clip_rects->buffer) * sizeof(RECT) ); out = clip_rects->rects + (out - clip_rects->buffer); } } release_wine_region( clip ); clip_rects->count = out - clip_rects->rects; return clip_rects->count; }
/********************************************************************** * solid_brush * * Fill a number of rectangles with the solid brush * FIXME: Should we insist l < r && t < b? Currently we assume this. */ static BOOL solid_brush(dibdrv_physdev *pdev, int num, RECT *rects) { int i, j; const WINEREGION *clip = get_wine_region(pdev->clip); for(i = 0; i < num; i++) { for(j = 0; j < clip->numRects; j++) { RECT rect = rects[i]; /* Optimize unclipped case */ if(clip->rects[j].top <= rect.top && clip->rects[j].bottom >= rect.bottom && clip->rects[j].left <= rect.left && clip->rects[j].right >= rect.right) { pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, pdev->brush_and, pdev->brush_xor); break; } if(clip->rects[j].top >= rect.bottom) break; if(clip->rects[j].bottom <= rect.top) continue; if(clip->rects[j].right > rect.left && clip->rects[j].left < rect.right) { rect.left = max(rect.left, clip->rects[j].left); rect.top = max(rect.top, clip->rects[j].top); rect.right = min(rect.right, clip->rects[j].right); rect.bottom = min(rect.bottom, clip->rects[j].bottom); pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, pdev->brush_and, pdev->brush_xor); } } } release_wine_region(pdev->clip); return TRUE; }
static BOOL dashed_pen_line(dibdrv_physdev *pdev, POINT *start, POINT *end) { const WINEREGION *clip = get_wine_region(pdev->clip); DWORD and, xor; int i, dash_len; RECT rect; const dash_pos start_pos = pdev->dash_pos; if(start->y == end->y) /* hline */ { BOOL l_to_r; INT left, right, cur_x; rect.top = start->y; rect.bottom = start->y + 1; if(start->x <= end->x) { left = start->x; right = end->x - 1; l_to_r = TRUE; } else { left = end->x + 1; right = start->x; l_to_r = FALSE; } for(i = 0; i < clip->numRects; i++) { if(clip->rects[i].top > start->y) break; if(clip->rects[i].bottom <= start->y) continue; if(clip->rects[i].right > left && clip->rects[i].left <= right) { int clipped_left = max(clip->rects[i].left, left); int clipped_right = min(clip->rects[i].right - 1, right); pdev->dash_pos = start_pos; if(l_to_r) { cur_x = clipped_left; if(cur_x != left) skip_dash(pdev, clipped_left - left); while(cur_x <= clipped_right) { get_dash_colors(pdev, &and, &xor); dash_len = pdev->dash_pos.left_in_dash; if(cur_x + dash_len > clipped_right + 1) dash_len = clipped_right - cur_x + 1; rect.left = cur_x; rect.right = cur_x + dash_len; pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, and, xor); cur_x += dash_len; skip_dash(pdev, dash_len); } } else { cur_x = clipped_right; if(cur_x != right) skip_dash(pdev, right - clipped_right); while(cur_x >= clipped_left) { get_dash_colors(pdev, &and, &xor); dash_len = pdev->dash_pos.left_in_dash; if(cur_x - dash_len < clipped_left - 1) dash_len = cur_x - clipped_left + 1; rect.left = cur_x - dash_len + 1; rect.right = cur_x + 1; pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, and, xor); cur_x -= dash_len; skip_dash(pdev, dash_len); } } } } pdev->dash_pos = start_pos; skip_dash(pdev, right - left + 1); } else if(start->x == end->x) /* vline */ { BOOL t_to_b; INT top, bottom, cur_y; rect.left = start->x; rect.right = start->x + 1; if(start->y <= end->y) { top = start->y; bottom = end->y - 1; t_to_b = TRUE; } else { top = end->y + 1; bottom = start->y; t_to_b = FALSE; } for(i = 0; i < clip->numRects; i++) { if(clip->rects[i].top > bottom) break; if(clip->rects[i].bottom <= top) continue; if(clip->rects[i].right > start->x && clip->rects[i].left <= start->x) { int clipped_top = max(clip->rects[i].top, top); int clipped_bottom = min(clip->rects[i].bottom - 1, bottom); pdev->dash_pos = start_pos; if(t_to_b) { cur_y = clipped_top; if(cur_y != top) skip_dash(pdev, clipped_top - top); while(cur_y <= clipped_bottom) { get_dash_colors(pdev, &and, &xor); dash_len = pdev->dash_pos.left_in_dash; if(cur_y + dash_len > clipped_bottom + 1) dash_len = clipped_bottom - cur_y + 1; rect.top = cur_y; rect.bottom = cur_y + dash_len; pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, and, xor); cur_y += dash_len; skip_dash(pdev, dash_len); } } else { cur_y = clipped_bottom; if(cur_y != bottom) skip_dash(pdev, bottom - clipped_bottom); while(cur_y >= clipped_top) { get_dash_colors(pdev, &and, &xor); dash_len = pdev->dash_pos.left_in_dash; if(cur_y - dash_len < clipped_top - 1) dash_len = cur_y - clipped_top + 1; rect.top = cur_y - dash_len + 1; rect.bottom = cur_y + 1; pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, and, xor); cur_y -= dash_len; skip_dash(pdev, dash_len); } } } } pdev->dash_pos = start_pos; skip_dash(pdev, bottom - top + 1); } else { bres_params params; INT dx = end->x - start->x; INT dy = end->y - start->y; INT i; params.dx = abs(dx); params.dy = abs(dy); params.octant = get_octant_mask(dx, dy); /* Octants 3, 5, 6 and 8 take a bias */ params.bias = (params.octant & 0xb4) ? 1 : 0; for(i = 0; i < clip->numRects; i++) { POINT clipped_start, clipped_end; int clip_status; clip_status = clip_line(start, end, clip->rects + i, ¶ms, &clipped_start, &clipped_end); if(clip_status) { int m = abs(clipped_start.x - start->x); int n = abs(clipped_start.y - start->y); int err; BOOL last_pt = FALSE; pdev->dash_pos = start_pos; if(is_xmajor(params.octant)) { err = 2 * params.dy - params.dx + m * 2 * params.dy - n * 2 * params.dx; skip_dash(pdev, m); } else { err = 2 * params.dx - params.dy + n * 2 * params.dx - m * 2 * params.dy; skip_dash(pdev, n); } if(clip_status == 1 && (end->x != clipped_end.x || end->y != clipped_end.y)) last_pt = TRUE; bres_line_with_bias(clipped_start.x, clipped_start.y, clipped_end.x, clipped_end.y, ¶ms, err, last_pt, dashed_pen_line_callback, pdev); if(clip_status == 2) break; /* completely unclipped, so we can finish */ } } pdev->dash_pos = start_pos; if(is_xmajor(params.octant)) skip_dash(pdev, params.dx); else skip_dash(pdev, params.dy); } release_wine_region(pdev->clip); return TRUE; }
static BOOL solid_pen_line(dibdrv_physdev *pdev, POINT *start, POINT *end) { const WINEREGION *clip = get_wine_region(pdev->clip); if(start->y == end->y) { RECT rect; int i; rect.left = start->x; rect.top = start->y; rect.right = end->x; rect.bottom = end->y + 1; order_end_points(&rect.left, &rect.right); for(i = 0; i < clip->numRects; i++) { if(clip->rects[i].top >= rect.bottom) break; if(clip->rects[i].bottom <= rect.top) continue; /* Optimize the unclipped case */ if(clip->rects[i].left <= rect.left && clip->rects[i].right >= rect.right) { pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, pdev->pen_and, pdev->pen_xor); break; } if(clip->rects[i].right > rect.left && clip->rects[i].left < rect.right) { RECT tmp = rect; tmp.left = max(rect.left, clip->rects[i].left); tmp.right = min(rect.right, clip->rects[i].right); pdev->dib.funcs->solid_rects(&pdev->dib, 1, &tmp, pdev->pen_and, pdev->pen_xor); } } } else if(start->x == end->x) { RECT rect; int i; rect.left = start->x; rect.top = start->y; rect.right = end->x + 1; rect.bottom = end->y; order_end_points(&rect.top, &rect.bottom); for(i = 0; i < clip->numRects; i++) { /* Optimize unclipped case */ if(clip->rects[i].top <= rect.top && clip->rects[i].bottom >= rect.bottom && clip->rects[i].left <= rect.left && clip->rects[i].right >= rect.right) { pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, pdev->pen_and, pdev->pen_xor); break; } if(clip->rects[i].top >= rect.bottom) break; if(clip->rects[i].bottom <= rect.top) continue; if(clip->rects[i].right > rect.left && clip->rects[i].left < rect.right) { RECT tmp = rect; tmp.top = max(rect.top, clip->rects[i].top); tmp.bottom = min(rect.bottom, clip->rects[i].bottom); pdev->dib.funcs->solid_rects(&pdev->dib, 1, &tmp, pdev->pen_and, pdev->pen_xor); } } } else { bres_params params; INT dx = end->x - start->x; INT dy = end->y - start->y; INT i; params.dx = abs(dx); params.dy = abs(dy); params.octant = get_octant_mask(dx, dy); /* Octants 3, 5, 6 and 8 take a bias */ params.bias = (params.octant & 0xb4) ? 1 : 0; for(i = 0; i < clip->numRects; i++) { POINT clipped_start, clipped_end; int clip_status; clip_status = clip_line(start, end, clip->rects + i, ¶ms, &clipped_start, &clipped_end); if(clip_status) { int m = abs(clipped_start.x - start->x); int n = abs(clipped_start.y - start->y); int err; BOOL last_pt = FALSE; if(is_xmajor(params.octant)) err = 2 * params.dy - params.dx + m * 2 * params.dy - n * 2 * params.dx; else err = 2 * params.dx - params.dy + n * 2 * params.dx - m * 2 * params.dy; if(clip_status == 1 && (end->x != clipped_end.x || end->y != clipped_end.y)) last_pt = TRUE; bres_line_with_bias(clipped_start.x, clipped_start.y, clipped_end.x, clipped_end.y, ¶ms, err, last_pt, solid_pen_line_callback, pdev); if(clip_status == 2) break; /* completely unclipped, so we can finish */ } } } release_wine_region(pdev->clip); return TRUE; }