Example #1
0
/*
 * Precalculate the rectangles needed to perform video looping:
 *
 * The nominal pipeline is that the video output buffer is cropped by
 * crop_out, scaled to compose_out, overlaid with the output overlay,
 * cropped on the capture side by crop_cap and scaled again to the video
 * capture buffer using compose_cap.
 *
 * To keep things efficient we calculate the intersection of compose_out
 * and crop_cap (since that's the only part of the video that will
 * actually end up in the capture buffer), determine which part of the
 * video output buffer that is and which part of the video capture buffer
 * so we can scale the video straight from the output buffer to the capture
 * buffer without any intermediate steps.
 *
 * If we need to deal with an output overlay, then there is no choice and
 * that intermediate step still has to be taken. For the output overlay
 * support we calculate the intersection of the framebuffer and the overlay
 * window (which may be partially or wholly outside of the framebuffer
 * itself) and the intersection of that with loop_vid_copy (i.e. the part of
 * the actual looped video that will be overlaid). The result is calculated
 * both in framebuffer coordinates (loop_fb_copy) and compose_out coordinates
 * (loop_vid_overlay). Finally calculate the part of the capture buffer that
 * will receive that overlaid video.
 */
static void vivid_precalc_copy_rects(struct vivid_dev *dev)
{
	/* Framebuffer rectangle */
	struct v4l2_rect r_fb = {
		0, 0, dev->display_width, dev->display_height
	};
	/* Overlay window rectangle in framebuffer coordinates */
	struct v4l2_rect r_overlay = {
		dev->overlay_out_left, dev->overlay_out_top,
		dev->compose_out.width, dev->compose_out.height
	};

	dev->loop_vid_copy = rect_intersect(&dev->crop_cap, &dev->compose_out);

	dev->loop_vid_out = dev->loop_vid_copy;
	rect_scale(&dev->loop_vid_out, &dev->compose_out, &dev->crop_out);
	dev->loop_vid_out.left += dev->crop_out.left;
	dev->loop_vid_out.top += dev->crop_out.top;

	dev->loop_vid_cap = dev->loop_vid_copy;
	rect_scale(&dev->loop_vid_cap, &dev->crop_cap, &dev->compose_cap);

	dprintk(dev, 1,
		"loop_vid_copy: %dx%d@%dx%d loop_vid_out: %dx%d@%dx%d loop_vid_cap: %dx%d@%dx%d\n",
		dev->loop_vid_copy.width, dev->loop_vid_copy.height,
		dev->loop_vid_copy.left, dev->loop_vid_copy.top,
		dev->loop_vid_out.width, dev->loop_vid_out.height,
		dev->loop_vid_out.left, dev->loop_vid_out.top,
		dev->loop_vid_cap.width, dev->loop_vid_cap.height,
		dev->loop_vid_cap.left, dev->loop_vid_cap.top);

	r_overlay = rect_intersect(&r_fb, &r_overlay);

	/* shift r_overlay to the same origin as compose_out */
	r_overlay.left += dev->compose_out.left - dev->overlay_out_left;
	r_overlay.top += dev->compose_out.top - dev->overlay_out_top;

	dev->loop_vid_overlay = rect_intersect(&r_overlay, &dev->loop_vid_copy);
	dev->loop_fb_copy = dev->loop_vid_overlay;

	/* shift dev->loop_fb_copy back again to the fb origin */
	dev->loop_fb_copy.left -= dev->compose_out.left - dev->overlay_out_left;
	dev->loop_fb_copy.top -= dev->compose_out.top - dev->overlay_out_top;

	dev->loop_vid_overlay_cap = dev->loop_vid_overlay;
	rect_scale(&dev->loop_vid_overlay_cap, &dev->crop_cap, &dev->compose_cap);

	dprintk(dev, 1,
		"loop_fb_copy: %dx%d@%dx%d loop_vid_overlay: %dx%d@%dx%d loop_vid_overlay_cap: %dx%d@%dx%d\n",
		dev->loop_fb_copy.width, dev->loop_fb_copy.height,
		dev->loop_fb_copy.left, dev->loop_fb_copy.top,
		dev->loop_vid_overlay.width, dev->loop_vid_overlay.height,
		dev->loop_vid_overlay.left, dev->loop_vid_overlay.top,
		dev->loop_vid_overlay_cap.width, dev->loop_vid_overlay_cap.height,
		dev->loop_vid_overlay_cap.left, dev->loop_vid_overlay_cap.top);
}
Example #2
0
inline void
clip_set(Rect rect)
{
    Rect canvas_rect = rect_make_size(0, 0, CORE->canvas->width, CORE->canvas->height);
    rect_intersect(&rect, &canvas_rect);
    CORE->clip = rect;
}
Example #3
0
void progressive_display_add_rect(struct xrdp_screen * self)
{
  int i, j;
  struct list* update_rects = self->update_rects;
  struct update_rect* urect;
  struct update_rect* fu_rect;
  struct update_rect* ur;
  struct xrdp_rect intersection;
  struct update_rect* tmp;
  struct list* l_tmp = list_create();
  l_tmp->auto_free = 1;

  bool no_inter = true;
  while (!fifo_is_empty(self->candidate_update_rects))
  {
    fu_rect = (struct update_rect*) fifo_pop(self->candidate_update_rects);
    if (update_rects->count > 0)
    {
      no_inter = true;
      for (i = update_rects->count - 1; i >= 0; i--)
      {
        urect = (struct update_rect*) list_get_item(update_rects, i);
        if (!rect_equal(&urect->rect, &fu_rect->rect))
        {
          if (rect_intersect(&urect->rect, &fu_rect->rect, &intersection))
          {
            no_inter = false;
            progressive_display_rect_union(fu_rect, urect, l_tmp);
            list_remove_item(update_rects, i);
            for (j = 0; j < l_tmp->count; j++)
            {
              ur = (struct update_rect*) list_get_item(l_tmp, j);
              tmp = (struct update_rect*) g_malloc(sizeof(struct update_rect), 0);
              g_memcpy(tmp, ur, sizeof(struct update_rect));
              fifo_push(self->candidate_update_rects, tmp);
            }
            list_clear(l_tmp);
            break;
          }
        }
        else
        {
          no_inter = false;
          urect->quality = fu_rect->quality;
          urect->quality_already_send = fu_rect->quality_already_send;
          break;
        }
      }
      if (no_inter)
      {
        list_add_progressive_display_rect(update_rects, fu_rect->rect.left, fu_rect->rect.top, fu_rect->rect.right, fu_rect->rect.bottom, fu_rect->quality, fu_rect->quality_already_send);
      }
    }
    else
    {
      list_add_progressive_display_rect(update_rects, fu_rect->rect.left, fu_rect->rect.top, fu_rect->rect.right, fu_rect->rect.bottom, fu_rect->quality, fu_rect->quality_already_send);
    }
  }
  list_delete(l_tmp);
}
Example #4
0
/* returns int */
int APP_CC
rect_update_bounding_box(struct xrdp_rect* BB, struct xrdp_rect* r, int DELTA)
{
  struct xrdp_rect inter;
  if (rect_equal(BB, r))
  {
    return 0;
  }
  if (rect_contained_by(r, BB->left, BB->top, BB->right, BB->bottom))
  {
    BB->left = r->left;
    BB->top = r->top;
    BB->bottom = r->bottom;
    BB->right = r->right;
    return 0;
  }
  if (rect_contained_by(BB, r->left, r->top, r->right, r->bottom))
  {
    return 0;
  }
  struct xrdp_rect tmp;
  tmp.left = BB->left - DELTA;
  tmp.right = BB->right + DELTA;
  tmp.top = BB->top - DELTA;
  tmp.bottom = BB->bottom + DELTA;

  if (rect_intersect(BB, r, &inter) || rect_intersect(&tmp, r, &inter))
  {
    BB->top = MIN(BB->top, r->top);
    BB->left = MIN(BB->left, r->left);
    BB->right = MAX(BB->right, r->right);
    BB->bottom = MAX(BB->bottom, r->bottom);
    return 0;
  }
  else
  {
    return 1;
  }
  return -1;
}
Example #5
0
/*
	schedule redraw coords.
*/
void redraw_slot_schedule(struct s_redrw_slots * slots, short x0, short y0,
                          short x1, short y1, bool force)
{
	int i = 0;
	struct rect area;

	area.x0 = x0;
	area.y0 = y0;
	area.x1 = x1;
	area.y1 = y1;

    if (force == false) {
        for (i=0; i<slots->areas_used; i++) {
            if (slots->areas[i].x0 <= x0
                && slots->areas[i].x1 >= x1
                && slots->areas[i].y0 <= y0
                && slots->areas[i].y1 >= y1) {
                /* the area is already queued for redraw */
                return;
            } else {
                if (rect_intersect(&slots->areas[i], &area )) {
                    slots->areas[i].x0 = MIN(slots->areas[i].x0, x0);
                    slots->areas[i].y0 = MIN(slots->areas[i].y0, y0);
                    slots->areas[i].x1 = MAX(slots->areas[i].x1, x1);
                    slots->areas[i].y1 = MAX(slots->areas[i].y1, y1);
                    return;
                }
            }
        }
	}

	if (slots->areas_used < slots->size) {
		slots->areas[slots->areas_used].x0 = x0;
		slots->areas[slots->areas_used].x1 = x1;
		slots->areas[slots->areas_used].y0 = y0;
		slots->areas[slots->areas_used].y1 = y1;
		slots->areas_used++;
	} else {
		/*
			we are out of available slots, merge box with last slot
			this is dumb... but also a very rare case.
		*/
		slots->areas[slots->size-1].x0 = MIN(slots->areas[i].x0, x0);
		slots->areas[slots->size-1].y0 = MIN(slots->areas[i].y0, y0);
		slots->areas[slots->size-1].x1 = MAX(slots->areas[i].x1, x1);
		slots->areas[slots->size-1].y1 = MAX(slots->areas[i].y1, y1);
	}
done:
	return;
}
Example #6
0
int entity_intersect_rect(Entity *a,SDL_Rect r)
{
    SDL_Rect aB;
    if (!a)
    {
        slog("ERROR: Missing entity for check");
        return 0;
    }
    aB = rect(
        a->position.x + a->bounds.x,
        a->position.y + a->bounds.y,
        a->bounds.w,
        a->bounds.h);
    return rect_intersect(aB,r);
}
Example #7
0
void
rect_draw(Rect r, u8 color)
{
    rect_tr(&r, CORE->translate_x, CORE->translate_y);
    rect_intersect(&r, &CORE->clip);
    if (r.max_x > r.min_x && r.max_y > r.min_y) {
        u32 canvas_pitch = CORE->canvas->width;
        u8 *row = CORE->canvas->pixels + r.min_x + (r.min_y * canvas_pitch);
        i32 w = r.max_x - r.min_x;
        while (r.max_y != r.min_y) {
            memset(row, color, w);
            row += canvas_pitch;
            r.max_y--;
        }
    }
}
Example #8
0
int entity_intersect(Entity *a, Entity *b)
{
    SDL_Rect aB,bB;
    if ((!a) || (!b))
    {
        slog("ERROR: Missing entity for check");
        return 0;
    }
    aB = rect(
        a->position.x + a->bounds.x,
        a->position.y + a->bounds.y,
        a->bounds.w,
        a->bounds.h);
    bB = rect(
        b->position.x + b->bounds.x,
        b->position.y + b->bounds.y,
        b->bounds.w,
        b->bounds.h);
    return rect_intersect(aB,bB);
}
Example #9
0
int bitmap_set_viewport(struct bitmap * bitmap, struct rect * rect)
{
    struct rect r, x;

    if(!bitmap || !rect)
        return 0;

    x.left = 0;
    x.top = 0;
    x.right = bitmap->info.width;
    x.bottom = bitmap->info.height;

    if(rect_intersect(&r, &x, rect) == 0)
        return 0;

    bitmap->viewport.left = r.left;
    bitmap->viewport.top = r.top;
    bitmap->viewport.right = r.right;
    bitmap->viewport.bottom = r.bottom;

    return 1;
}
Example #10
0
struct surface_t * map_software_rotate(struct surface_t * surface, struct rect_t * rect, enum rotate_type type)
{
	struct surface_t * rotate;
	struct rect_t clipped;
	u32_t w, h;

	if(!surface)
		return NULL;

	if (!surface->pixels)
		return NULL;

	if (surface->info.bits_per_pixel < 8)
		return NULL;

	clipped.x = 0;
	clipped.y = 0;
	clipped.w = surface->w;
	clipped.h = surface->h;

	if(rect)
	{
		if (!rect_intersect(rect, &clipped, &clipped))
			return NULL;
	}
	rect = &clipped;

	switch(type)
	{
	case ROTATE_DEGREE_0:
	case ROTATE_DEGREE_180:
	case ROTATE_MIRROR_H:
	case ROTATE_MIRROR_V:
		w = rect->w;
		h = rect->h;
		break;

	case ROTATE_DEGREE_90:
	case ROTATE_DEGREE_270:
		w = rect->h;
		h = rect->w;
		break;

	default:
		return NULL;
	}

	rotate = surface_alloc(NULL, w, h, surface->info.fmt);
	if(!rotate)
		return NULL;

	switch (surface->info.bytes_per_pixel)
	{
	case 1:
		software_rotate_1byte(rotate, surface, rect, type);
		break;

	case 2:
		software_rotate_2byte(rotate, surface, rect, type);
		break;

	case 3:
		software_rotate_3byte(rotate, surface, rect, type);
		break;

	case 4:
		software_rotate_4byte(rotate, surface, rect, type);
		break;

	default:
		surface_free(rotate);
		return NULL;
	}

	return rotate;
}
Example #11
0
static void TraverseLayer2D(GF_Node *node, void *rs, Bool is_destroy)
{
	GF_List *oldb, *oldv;
	GF_Node *viewport;
	GF_Node *back;
	Bool prev_layer;
	GF_Matrix2D backup;
	SFVec2f prev_vp;

#ifndef GPAC_DISABLE_3D
	GF_Matrix mx3d;
	GF_List *oldf, *oldn;
	GF_List *node_list_backup;
	GF_Rect prev_clipper;
	Bool had_clip;
#endif
	
	M_Layer2D *l = (M_Layer2D *)node;
	Layer2DStack *st = (Layer2DStack *) gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *) rs;
	
	if (is_destroy) {
		gf_list_del(st->backs);
		gf_list_del(st->views);
		group_2d_destroy(node, (GroupingNode2D*)st);
		gf_free(st);
		return;
	}

	/*layers can only be used in a 2D context*/
#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d && tr_state->camera->is_3D) return;
#endif

	/*layer2D maintains its own stacks*/
	oldb = tr_state->backgrounds;
	oldv = tr_state->viewpoints;
	tr_state->backgrounds = st->backs;
	tr_state->viewpoints = st->views;
	prev_layer = tr_state->is_layer;
	tr_state->is_layer = 1;
#ifndef GPAC_DISABLE_3D
	oldf = tr_state->fogs;
	oldn = tr_state->navigations;
	tr_state->fogs = tr_state->navigations = NULL;
#endif

	l2d_CheckBindables(node, tr_state, st->first);

	back = (GF_Node*)gf_list_get(st->backs, 0);

	viewport = (GF_Node*)gf_list_get(st->views, 0);

	if ((tr_state->traversing_mode == TRAVERSE_SORT) || (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS)) {
		/*override group bounds*/
		visual_get_size_info(tr_state, &st->clip.width, &st->clip.height);
		/*setup bounds in local coord system*/
		if (l->size.x>=0) st->clip.width = l->size.x;
		if (l->size.y>=0) st->clip.height = l->size.y;
		st->clip = gf_rect_center(st->clip.width, st->clip.height);
		st->bounds = st->clip;
	}
	
	prev_vp = tr_state->vp_size;
	tr_state->vp_size.x = st->clip.width;
	tr_state->vp_size.y = st->clip.height;

	switch (tr_state->traversing_mode) {
	case TRAVERSE_SORT:
#ifndef GPAC_DISABLE_3D
		if (tr_state->visual->type_3d) {
			tr_state->layer_clipper = compositor_2d_update_clipper(tr_state, st->clip, &had_clip, &prev_clipper, 1);

			visual_3d_matrix_push(tr_state->visual);
			gf_mx_copy(mx3d, tr_state->model_matrix);

			/*setup clipping*/
			visual_3d_set_clipper_2d(tr_state->visual, tr_state->layer_clipper);
			
			/*apply background BEFORE viewport*/
			if (back) {
				tr_state->traversing_mode = TRAVERSE_BINDABLE;
				gf_bbox_from_rect(&tr_state->bbox, &st->clip);
				gf_node_traverse(back, tr_state);
			}

			/*sort all children without transform, and use current transform when flushing contexts*/
			gf_mx_init(tr_state->model_matrix);

			/*apply viewport*/
			if (viewport) {
				tr_state->traversing_mode = TRAVERSE_BINDABLE;
				tr_state->bounds = st->clip;
				gf_node_traverse(viewport, tr_state);
				visual_3d_matrix_add(tr_state->visual, tr_state->model_matrix.m);
			}


			node_list_backup = tr_state->visual->alpha_nodes_to_draw;
			tr_state->visual->alpha_nodes_to_draw = gf_list_new();
			tr_state->traversing_mode = TRAVERSE_SORT;
			/*reset cull flag*/
			tr_state->cull_flag = 0;
			group_2d_traverse(node, (GroupingNode2D *)st, tr_state);

			visual_3d_flush_contexts(tr_state->visual, tr_state);
			tr_state->traversing_mode = TRAVERSE_SORT;

			assert(!gf_list_count(tr_state->visual->alpha_nodes_to_draw));
			gf_list_del(tr_state->visual->alpha_nodes_to_draw);
			tr_state->visual->alpha_nodes_to_draw = node_list_backup;

			
			visual_3d_matrix_pop(tr_state->visual);
			gf_mx_copy(tr_state->model_matrix, mx3d);

			visual_3d_reset_clipper_2d(tr_state->visual);

			tr_state->has_layer_clip = had_clip;
			if (had_clip) {
				tr_state->layer_clipper = prev_clipper;
				visual_3d_set_clipper_2d(tr_state->visual, tr_state->layer_clipper);
			}
		} else 
#endif
		{
			GF_IRect prev_clip;
			GF_Rect rc;

			gf_mx2d_copy(backup, tr_state->transform);

			prev_clip = tr_state->visual->top_clipper;
			rc = st->clip;
			
			/*get clipper in world coordinate*/
			gf_mx2d_apply_rect(&tr_state->transform, &rc);

			if (viewport) {
				tr_state->traversing_mode = TRAVERSE_BINDABLE;
				tr_state->bounds = st->clip;
				gf_node_traverse(viewport, tr_state);
#if VIEWPORT_CLIPS
				/*move viewport box in world coordinate*/
				gf_mx2d_apply_rect(&backup, &tr_state->bounds);
				/*and intersect with layer clipper*/
				rect_intersect(&rc, &tr_state->bounds);
#endif
			}

			tr_state->visual->top_clipper = gf_rect_pixelize(&rc);
			gf_irect_intersect(&tr_state->visual->top_clipper, &prev_clip);
			tr_state->traversing_mode = TRAVERSE_SORT;

			if (tr_state->visual->top_clipper.width && tr_state->visual->top_clipper.height) {
				if (back && Bindable_GetIsBound(back) ) {
					DrawableContext *ctx;

					ctx = b2d_get_context((M_Background2D*) back, st->backs);
					gf_mx2d_init(ctx->transform);
					ctx->bi->clip = tr_state->visual->top_clipper;
					ctx->bi->unclip = rc;

					if (tr_state->immediate_draw) {
						tr_state->ctx = ctx;
						tr_state->traversing_mode = TRAVERSE_DRAW_2D;
						gf_node_traverse(back, tr_state);
						tr_state->traversing_mode = TRAVERSE_SORT;
						tr_state->ctx = NULL;
					} else {
						DrawableContext *back_ctx = visual_2d_get_drawable_context(tr_state->visual);

						gf_node_traverse(back, tr_state);

						back_ctx->flags = ctx->flags;
						back_ctx->flags &= ~CTX_IS_TRANSPARENT;
						back_ctx->flags |= CTX_IS_BACKGROUND;
						back_ctx->aspect = ctx->aspect;
						back_ctx->drawable = ctx->drawable;
						drawable_check_bounds(back_ctx, tr_state->visual);
						back_ctx->bi->clip = ctx->bi->clip;
						back_ctx->bi->unclip = ctx->bi->unclip;
					}
					/*keep track of node drawn*/
					if (!(ctx->drawable->flags & DRAWABLE_REGISTERED_WITH_VISUAL) ) {
						struct _drawable_store *it;
						GF_SAFEALLOC(it, struct _drawable_store);
						it->drawable = ctx->drawable;
						if (tr_state->visual->last_prev_entry) {
							tr_state->visual->last_prev_entry->next = it;
							tr_state->visual->last_prev_entry = it;
						} else {
							tr_state->visual->prev_nodes = tr_state->visual->last_prev_entry = it;
						}
						GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Layer2D] Registering new drawn node %s on visual\n", gf_node_get_class_name(it->drawable->node)));
						ctx->drawable->flags |= DRAWABLE_REGISTERED_WITH_VISUAL;
					}
				}

				group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
			}
			tr_state->visual->top_clipper = prev_clip;
			gf_mx2d_copy(tr_state->transform, backup);
		}
		break;
		
		/*check picking - we must fall in our 2D clipper*/
	case TRAVERSE_PICK:
		if (gf_sc_pick_in_clipper(tr_state, &st->clip)) {
		
#ifndef GPAC_DISABLE_3D
			if (tr_state->visual->type_3d) {
				/*apply viewport*/
				if (viewport) {
					gf_mx_copy(mx3d, tr_state->model_matrix);
					tr_state->traversing_mode = TRAVERSE_BINDABLE;
					tr_state->bounds = st->clip;
					gf_node_traverse(viewport, tr_state);
					tr_state->traversing_mode = TRAVERSE_PICK;
					group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
					gf_mx_copy(tr_state->model_matrix, mx3d);
				} else {
					group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
				}
			} else 
#endif
			{
				if (viewport) {
					gf_mx2d_copy(backup, tr_state->transform);
					tr_state->traversing_mode = TRAVERSE_BINDABLE;
					tr_state->bounds = st->clip;
					gf_node_traverse(viewport, tr_state);
					tr_state->traversing_mode = TRAVERSE_PICK;
					group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
					gf_mx2d_copy(tr_state->transform, backup);
				} else {
					group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
				}
			}	
		}
		break;
	case TRAVERSE_GET_BOUNDS:
		if (tr_state->for_node) {
			group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
		} else {
			tr_state->bounds = st->clip;
#ifndef GPAC_DISABLE_3D
			gf_bbox_from_rect(&tr_state->bbox, &st->clip);
#endif
		}
		break;

	case TRAVERSE_DRAW_2D:
		group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
		break;

#ifndef GPAC_DISABLE_3D
	/*drawing a layer means drawing all sub-elements as a whole (no depth sorting with parents)*/
	case TRAVERSE_DRAW_3D:
		assert(0);
		break;
#endif
	}
	
	/*restore traversing state*/
	tr_state->vp_size = prev_vp;
	tr_state->backgrounds = oldb;
	tr_state->viewpoints = oldv;
	tr_state->is_layer = prev_layer;
#ifndef GPAC_DISABLE_3D
	tr_state->fogs = oldf;
	tr_state->navigations = oldn;
#endif

	/*in case we missed bindables*/
	if (st->first) {
		st->first = 0;
		gf_sc_invalidate(tr_state->visual->compositor, NULL);
	}
}
Example #12
0
/* We take the trouble to do this efficiently in the simple cases. */
int
gs_rectfill(gs_state * pgs, const gs_rect * pr, uint count)
{
    const gs_rect *rlist = pr;
    gx_clip_path *pcpath;
    uint rcount = count;
    int code;
    gx_device * pdev = pgs->device;
    gx_device_color *pdc = gs_currentdevicecolor_inline(pgs);
    const gs_imager_state *pis = (const gs_imager_state *)pgs;
    bool hl_color_available = gx_hld_is_hl_color_available(pis, pdc);
    bool hl_color = (hl_color_available &&
                dev_proc(pdev, dev_spec_op)(pdev, gxdso_supports_hlcolor, 
                                  NULL, 0));
    bool center_of_pixel = (pgs->fill_adjust.x == 0 && pgs->fill_adjust.y == 0);

    /* Processing a fill object operation */
    dev_proc(pgs->device, set_graphics_type_tag)(pgs->device, GS_PATH_TAG);

    code = gx_set_dev_color(pgs);
    if (code != 0)
        return code;
    if ((is_fzero2(pgs->ctm.xy, pgs->ctm.yx) ||
         is_fzero2(pgs->ctm.xx, pgs->ctm.yy)) &&
        gx_effective_clip_path(pgs, &pcpath) >= 0 &&
        clip_list_is_rectangle(gx_cpath_list(pcpath)) &&
        (hl_color ||
         pdc->type == gx_dc_type_pure ||
         pdc->type == gx_dc_type_ht_binary ||
         pdc->type == gx_dc_type_ht_colored) &&
        gs_state_color_load(pgs) >= 0 &&
        (*dev_proc(pdev, get_alpha_bits)) (pdev, go_graphics)
        <= 1 &&
        (!pgs->overprint || !pgs->effective_overprint_mode)
        ) {
        uint i;
        gs_fixed_rect clip_rect;

        gx_cpath_inner_box(pcpath, &clip_rect);
        /* We should never plot anything for an empty clip rectangle */
        if ((clip_rect.p.x >= clip_rect.q.x) &&
            (clip_rect.p.y >= clip_rect.q.y))
            return 0;
        for (i = 0; i < count; ++i) {
            gs_fixed_point p, q;
            gs_fixed_rect draw_rect;

            if (gs_point_transform2fixed(&pgs->ctm, pr[i].p.x, pr[i].p.y, &p) < 0 ||
                gs_point_transform2fixed(&pgs->ctm, pr[i].q.x, pr[i].q.y, &q) < 0
                ) {		/* Switch to the slow algorithm. */
                goto slow;
            }
            draw_rect.p.x = min(p.x, q.x);
            draw_rect.p.y = min(p.y, q.y);
            draw_rect.q.x = max(p.x, q.x);
            draw_rect.q.y = max(p.y, q.y);
            if (hl_color) {
                rect_intersect(draw_rect, clip_rect);
                /* We do pass on 0 extant rectangles to high level
                   devices.  It isn't clear how a client and an output
                   device should interact if one uses a center of
                   pixel algorithm and the other uses any part of
                   pixel.  For now we punt and just pass the high
                   level rectangle on without adjustment. */
                if (draw_rect.p.x <= draw_rect.q.x &&
                    draw_rect.p.y <= draw_rect.q.y) {
                    code = dev_proc(pdev, fill_rectangle_hl_color)(pdev,
                             &draw_rect, pis, pdc, pcpath);
                    if (code < 0)
                        return code;
                }
            } else {
                int x, y, w, h;

                rect_intersect(draw_rect, clip_rect);
                if (center_of_pixel) {
                    draw_rect.p.x = fixed_rounded(draw_rect.p.x);
                    draw_rect.p.y = fixed_rounded(draw_rect.p.y);
                    draw_rect.q.x = fixed_rounded(draw_rect.q.x);
                    draw_rect.q.y = fixed_rounded(draw_rect.q.y);
                } else { /* any part of pixel rule - touched */
                    draw_rect.p.x = fixed_floor(draw_rect.p.x);
                    draw_rect.p.y = fixed_floor(draw_rect.p.y);
                    draw_rect.q.x = fixed_ceiling(draw_rect.q.x);
                    draw_rect.q.y = fixed_ceiling(draw_rect.q.y);
                }
                x = fixed2int(draw_rect.p.x);
                y = fixed2int(draw_rect.p.y);
                w = fixed2int(draw_rect.q.x) - x;
                h = fixed2int(draw_rect.q.y) - y;
                /* clients that use the "any part of pixel" rule also
                   fill 0 areas.  This is true of current graphics
                   library clients but not a general rule.  */
                if (!center_of_pixel) {
                    if (w == 0)
                        w = 1;
                    /* yes Adobe Acrobat 8, seems to back up the y
                       coordinate when the width is 0, sigh. */
                    if (h == 0) {
                        y--;
                        h = 1;
                    }
                }
                if (gx_fill_rectangle(x, y, w, h, pdc, pgs) < 0)
                    goto slow;
            }
        }
        return 0;
      slow:rlist = pr + i;
        rcount = count - i;
    } {
        bool do_save = !gx_path_is_null(pgs->path);

        if (do_save) {
            if ((code = gs_gsave(pgs)) < 0)
                return code;
            gs_newpath(pgs);
        }
        if ((code = gs_rectappend(pgs, rlist, rcount)) < 0 ||
            (code = gs_fill(pgs)) < 0
            )
            DO_NOTHING;
        if (do_save)
            gs_grestore(pgs);
        else if (code < 0)
            gs_newpath(pgs);
    }
    return code;
}
Example #13
0
/* We take the trouble to do this efficiently in the simple cases. */
int
gs_rectfill(gs_state * pgs, const gs_rect * pr, uint count)
{
    const gs_rect *rlist = pr;
    gx_clip_path *pcpath;
    uint rcount = count;
    int code;
    gx_device * pdev = pgs->device;
    gx_device_color *pdc = pgs->dev_color;
    const gs_imager_state *pis = (const gs_imager_state *)pgs;
    bool hl_color_available = gx_hld_is_hl_color_available(pis, pdc);
    gs_fixed_rect empty = {{0, 0}, {0, 0}};
    bool hl_color = (hl_color_available && 
		dev_proc(pdev, fill_rectangle_hl_color)(pdev, 
		    	    &empty, pis, pdc, NULL) == 0);

    gx_set_dev_color(pgs);
    if ((is_fzero2(pgs->ctm.xy, pgs->ctm.yx) ||
	 is_fzero2(pgs->ctm.xx, pgs->ctm.yy)) &&
	gx_effective_clip_path(pgs, &pcpath) >= 0 &&
	clip_list_is_rectangle(gx_cpath_list(pcpath)) &&
	(hl_color ||
	 pdc->type == gx_dc_type_pure ||
	 pdc->type == gx_dc_type_ht_binary ||
	 pdc->type == gx_dc_type_ht_colored
	 /* DeviceN todo: add wts case */) &&
	gs_state_color_load(pgs) >= 0 &&
	(*dev_proc(pdev, get_alpha_bits)) (pdev, go_graphics)
	<= 1 &&
        (!pgs->overprint || !pgs->effective_overprint_mode)
	) {
	uint i;
	gs_fixed_rect clip_rect;

	gx_cpath_inner_box(pcpath, &clip_rect);
	for (i = 0; i < count; ++i) {
	    gs_fixed_point p, q;
	    gs_fixed_rect draw_rect;
	    
	    if (gs_point_transform2fixed(&pgs->ctm, pr[i].p.x, pr[i].p.y, &p) < 0 ||
		gs_point_transform2fixed(&pgs->ctm, pr[i].q.x, pr[i].q.y, &q) < 0
		) {		/* Switch to the slow algorithm. */
		goto slow;
	    }
	    draw_rect.p.x = min(p.x, q.x);
	    draw_rect.p.y = min(p.y, q.y);
	    draw_rect.q.x = max(p.x, q.x);
	    draw_rect.q.y = max(p.y, q.y);
	    if (hl_color) {
		rect_intersect(draw_rect, clip_rect);
		if (draw_rect.p.x < draw_rect.q.x &&
		    draw_rect.p.y < draw_rect.q.y) {
		    code = dev_proc(pdev, fill_rectangle_hl_color)(pdev,
			     &draw_rect, pis, pdc, pcpath);
		    if (code < 0)
			return code;
		}
	    } else {
		int x, y, w, h;

		draw_rect.p.x -= pgs->fill_adjust.x;
		draw_rect.p.y -= pgs->fill_adjust.x;
		draw_rect.q.x += pgs->fill_adjust.x;
		draw_rect.q.y += pgs->fill_adjust.x;
		rect_intersect(draw_rect, clip_rect);
		x = fixed2int_pixround(draw_rect.p.x);
		y = fixed2int_pixround(draw_rect.p.y);
		w = fixed2int_pixround(draw_rect.q.x) - x;
		h = fixed2int_pixround(draw_rect.q.y) - y;
		if (w > 0 && h > 0)
    		    if (gx_fill_rectangle(x, y, w, h, pdc, pgs) < 0)
			goto slow;
	    }
	}
	return 0;
      slow:rlist = pr + i;
	rcount = count - i;
    } {
	bool do_save = !gx_path_is_null(pgs->path);

	if (do_save) {
	    if ((code = gs_gsave(pgs)) < 0)
		return code;
	    gs_newpath(pgs);
	}
	if ((code = gs_rectappend(pgs, rlist, rcount)) < 0 ||
	    (code = gs_fill(pgs)) < 0
	    )
	    DO_NOTHING;
	if (do_save)
	    gs_grestore(pgs);
	else if (code < 0)
	    gs_newpath(pgs);
    }
    return code;
}
Example #14
0
/* returns boolean */
int APP_CC
rect_union(struct xrdp_rect* in1, struct xrdp_rect* in2, struct list* out) {
	struct xrdp_rect tmp;
	if (!rect_intersect(in1, in2, &tmp)) {
		return 0;
	}
	if (rect_equal(in1, in2)) {
		return 0; 
	} 
	if (in1->left <= in2->left &&
		in1->top <= in2->top &&
		in1->right >= in2->right &&
		in1->bottom >= in2->bottom) {
		list_add_rect(out, in1->left, in1->top, in1->right, in1->bottom);
	} else if (in1->left <= in2->left &&
		in1->right >= in2->right &&
		in1->bottom < in2->bottom &&
		in1->top <= in2->top) { /* partially covered(whole top) */
		list_add_rect(out, in1->left, in1->top, in1->right, in1->bottom);
		list_add_rect(out, in2->left, in1->bottom, in2->right, in2->bottom);
	} else if (in1->top <= in2->top &&
			   in1->bottom >= in2->bottom &&
			   in1->right < in2->right &&
			   in1->left <= in2->left) { /* partially covered(left) */
		list_add_rect(out, in1->left, in1->top, in1->right, in1->bottom);
		list_add_rect(out, in1->right, in2->top, in2->right, in2->bottom);
	} else if (in1->left <= in2->left &&
			   in1->right >= in2->right &&
			   in1->top > in2->top &&
			   in1->bottom >= in2->bottom) { /* partially covered(bottom) */
		list_add_rect(out, in1->left, in1->top, in1->right, in1->bottom);
		list_add_rect(out, in2->left, in2->top, in2->right, in1->top);
	} else if (in1->top <= in2->top &&
			   in1->bottom >= in2->bottom &&
			   in1->left > in2->left &&
			   in1->right >= in2->right) { /* partially covered(right) */
		list_add_rect(out, in1->left, in1->top, in1->right, in1->bottom);
		list_add_rect(out, in2->left, in2->top, in1->left, in2->bottom);
	} else if (in1->left <= in2->left &&
			   in1->top <= in2->top &&
			   in1->right < in2->right &&
			   in1->bottom < in2->bottom) { /* partially covered(top left) */
		list_add_rect(out, in1->left, in1->top, in1->right, in1->bottom);
		list_add_rect(out, in1->right, in2->top, in2->right, in1->bottom);
		list_add_rect(out, in2->left, in1->bottom, in2->right, in2->bottom);
	} else if (in1->left <= in2->left &&
			   in1->bottom >= in2->bottom &&
			   in1->right < in2->right &&
			   in1->top > in2->top) { /* partially covered(bottom left) */
		list_add_rect(out, in1->left, in1->top, in1->right, in1->bottom);
		list_add_rect(out, in2->left, in2->top, in2->right, in1->top);
		list_add_rect(out, in1->right, in1->top, in2->right, in2->bottom);
	} else if (in1->left > in2->left &&
			   in1->right >= in2->right &&
			   in1->top <= in2->top &&
			   in1->bottom < in2->bottom) { /* partially covered(top right) */
		list_add_rect(out, in1->left, in1->top, in1->right, in1->bottom);
		list_add_rect(out, in2->left, in2->top, in1->left, in2->bottom);
		list_add_rect(out, in2->left, in1->bottom, in2->right, in2->bottom);
	} else if (in1->left > in2->left &&
			   in1->right >= in2->right &&
			   in1->top > in2->top &&
			   in1->bottom >= in2->bottom) { /* partially covered(bottom right) */
		list_add_rect(out, in1->left, in1->top, in1->right, in1->bottom);
		list_add_rect(out, in2->left, in2->top, in2->right, in1->top);
		list_add_rect(out, in2->left, in1->top, in1->left, in2->bottom);
	} else if (in1->left > in2->left &&
			   in1->top <= in2->top &&
			   in1->right < in2->right &&
			   in1->bottom >= in2->bottom) { /* 2 rects, one on each end */
		list_add_rect(out, in1->left, in1->top, in1->right, in1->bottom);
		list_add_rect(out, in2->left, in2->top, in1->left, in2->bottom);
		list_add_rect(out, in1->right, in2->top, in2->right, in2->bottom);
	} else if (in1->left <= in2->left &&
			   in1->top > in2->top &&
			   in1->right >= in2->right &&
			   in1->bottom < in2->bottom) { /* 2 rects, one on each end */
		list_add_rect(out, in2->left, in2->top, in2->right, in2->bottom);
		list_add_rect(out, in1->left, in1->top, in2->left, in1->bottom);
		list_add_rect(out, in2->right, in1->top, in1->right, in1->bottom);
	 } else if (in1->left > in2->left &&
			 in1->right < in2->right &&
			 in1->top <= in2->top &&
			 in1->bottom < in2->bottom) { /* partially covered(top) */
		 list_add_rect(out, in2->left, in2->top, in2->right, in2->bottom);
		 list_add_rect(out, in1->left, in1->top, in1->right, in2->top);
	} else if (in1->top > in2->top &&
			   in1->bottom < in2->bottom &&
			   in1->left <= in2->left &&
			   in1->right < in2->right) { /* partially covered(left) */
		list_add_rect(out, in2->left, in2->top, in2->right, in2->bottom);
		list_add_rect(out, in1->left, in1->top, in2->left, in1->bottom);
	} else if (in1->left > in2->left &&
			   in1->right < in2->right &&
			   in1->bottom >= in2->bottom &&
			   in1->top > in2->top) { /* partially covered(bottom) */
		list_add_rect(out, in2->left, in2->top, in2->right, in2->bottom);
		list_add_rect(out, in1->left, in2->bottom, in1->right, in1->bottom);
	} else if (in1->top > in2->top &&
			   in1->bottom < in2->bottom &&
			   in1->right >= in2->right &&
			   in1->left > in2->left) { /* partially covered(right) */
		list_add_rect(out, in2->left, in2->top, in2->right, in2->bottom);
		list_add_rect(out, in2->right, in1->top, in1->right, in1->bottom);
	} else if (in1->left > in2->left &&
			   in1->top > in2->top &&
			   in1->right < in2->right &&
			   in1->bottom < in2->bottom) { /* totally contained, 4 rects */
		list_add_rect(out, in2->left, in2->top, in2->right, in2->bottom);
	}
	return 0;
}