Beispiel #1
0
static inline bool scrollbar_redraw_scrollbar_rectangle(int x0, int y0,
		int x1, int y1, colour c, bool inset,
		const struct redraw_context *ctx)
{
	const struct plotter_table *plot = ctx->plot;

	static plot_style_t c0 = {
		.stroke_type = PLOT_OP_TYPE_SOLID,
		.stroke_width = 1,
	};

	static plot_style_t c1 = {
		.stroke_type = PLOT_OP_TYPE_SOLID,
		.stroke_width = 1,
	};

	static plot_style_t c2 = {
		.stroke_type = PLOT_OP_TYPE_SOLID,
		.stroke_width = 1,
	};

	if (inset) {
		c0.stroke_colour = darken_colour(c);
		c1.stroke_colour = lighten_colour(c);
	} else {
		c0.stroke_colour = lighten_colour(c);
		c1.stroke_colour = darken_colour(c);
	}
	c2.stroke_colour = blend_colour(c0.stroke_colour, c1.stroke_colour);

	/* Plot the outline */
	if (!plot->line(x0, y0, x1, y0, &c0)) return false;
	if (!plot->line(x1, y0, x1, y1 + 1, &c1)) return false;
	if (!plot->line(x1, y0, x1, y0 + 1, &c2)) return false;
	if (!plot->line(x1, y1, x0, y1, &c1)) return false;
	if (!plot->line(x0, y1, x0, y0, &c0)) return false;
	if (!plot->line(x0, y1, x0, y1 + 1, &c2)) return false;

	return true;
}


/*
 * Exported function.  Documented in scrollbar.h
 */
bool scrollbar_redraw(struct scrollbar *s, int x, int y, 
		const struct rect *clip, float scale,
		const struct redraw_context *ctx)
{
	const struct plotter_table *plot = ctx->plot;
	int w = SCROLLBAR_WIDTH;
	int bar_pos, bar_c0, bar_c1;
	int v[6]; /* array of triangle vertices */
	int x0, y0, x1, y1;

	colour bg_fill_colour = gui_system_colour_char("Scrollbar");
	colour fg_fill_colour = gui_system_colour_char("ButtonFace");
	colour arrow_fill_colour = gui_system_colour_char("ButtonText");

	plot_style_t bg_fill_style = {
		.fill_type = PLOT_OP_TYPE_SOLID,
		.fill_colour = bg_fill_colour
	};
	plot_style_t fg_fill_style = {
		.fill_type = PLOT_OP_TYPE_SOLID,
		.fill_colour = fg_fill_colour
	};
	plot_style_t arrow_fill_style = {
		.fill_type = PLOT_OP_TYPE_SOLID,
		.fill_colour = arrow_fill_colour
	};

	x0 = x;
	y0 = y;
	x1 = x + (s->horizontal ? s->length : SCROLLBAR_WIDTH) - 1;
	y1 = y + (s->horizontal ? SCROLLBAR_WIDTH : s->length) - 1;
	bar_pos = s->bar_pos;
	bar_c1 = (s->horizontal ? x0 : y0) + SCROLLBAR_WIDTH +
			s->bar_pos + s->bar_len - 1;

	if (scale != 1.0) {
		w *= scale;
		x0 *= scale;
		y0 *= scale;
		x1 *= scale;
		y1 *= scale;
		bar_pos *= scale;
		bar_c1 *= scale;
	}

	bar_c0 = (s->horizontal ? x0 : y0) + w + bar_pos;

	if (x1 < clip->x0 || y1 < clip->y0 || clip->x1 < x0 || clip->y1 < y0)
		/* scrollbar is outside the clipping rectangle, nothing to
		 * render */
		return true;

	
	if (s->horizontal) {
		/* scrollbar is horizontal */
		
		/* scrollbar outline */
		if (!scrollbar_redraw_scrollbar_rectangle(x0, y0, x1, y1,
				bg_fill_colour, true, ctx))
			return false;
		/* left arrow icon border */
		if (!scrollbar_redraw_scrollbar_rectangle(x0 + 1,
		     		y0 + 1,
				x0 + w - 2,
    				y1 - 1,
				fg_fill_colour, false, ctx))
			return false;
		/* left arrow icon background */
		if (!plot->rectangle(x0 + 2,
		     		y0 + 2,
				x0 + w - 2,
    				y1 - 1,
				&fg_fill_style))
			return false;
		/* left arrow */
		v[0] = x0 + w / 4;
		v[1] = y0 + w / 2;
		v[2] = x0 + w * 3 / 4;
		v[3] = y0 + w / 4;
		v[4] = x0 + w * 3 / 4;
		v[5] = y0 + w * 3 / 4;
		if (!plot->polygon(v, 3, &arrow_fill_style))
			return false;
		/* scrollbar well background */
		if (!plot->rectangle(x0 + w - 1,
		     		y0 + 1,
	 			x1 - w + 2,
    				y1,
				&bg_fill_style))
			return false;
		/* scrollbar position indicator bar */
		if (!scrollbar_redraw_scrollbar_rectangle(bar_c0,
				y0 + 1,
				bar_c1,
				y1 - 1,
				fg_fill_colour, false, ctx))
			return false;
		if (!plot->rectangle(bar_c0 + 1,
		     		y0 + 2,
				bar_c1,
    				y1 - 1,
				&fg_fill_style))
			return false;
		/* right arrow icon border */
		if (!scrollbar_redraw_scrollbar_rectangle(x1 - w + 2,
				y0 + 1,
				x1 - 1,
				y1 - 1,
				fg_fill_colour, false, ctx))
			return false;
		/* right arrow icon background */
		if (!plot->rectangle(x1 - w + 3,
		     		y0 + 2,
				x1 - 1,
    				y1 - 1,
				&fg_fill_style))
			return false;
		/* right arrow */
		v[0] = x1 - w / 4 + 1;
		v[1] = y0 + w / 2;
		v[2] = x1 - w * 3 / 4 + 1;
		v[3] = y0 + w / 4;
		v[4] = x1 - w * 3 / 4 + 1;
		v[5] = y0 + w * 3 / 4;
		if (!plot->polygon(v, 3, &arrow_fill_style))
			return false;
	} else {
		/* scrollbar is vertical */
		
		/* outline */
		if (!scrollbar_redraw_scrollbar_rectangle(x0, y0, x1, y1,
				bg_fill_colour, true, ctx))
			return false;
 		/* top arrow background */
		if (!scrollbar_redraw_scrollbar_rectangle(x0 + 1,
				y0 + 1,
				x1 - 1,
				y0 + w - 2,
				fg_fill_colour, false, ctx))
			return false;
		if (!plot->rectangle(x0 + 2,
				y0 + 2,
				x1 - 1,
				y0 + w - 2,
				&fg_fill_style))
			return false;
		/* up arrow */
		v[0] = x0 + w / 2;
		v[1] = y0 + w / 4;
		v[2] = x0 + w / 4;
		v[3] = y0 + w * 3 / 4;
		v[4] = x0 + w * 3 / 4;
		v[5] = y0 + w * 3 / 4;
		if (!plot->polygon(v, 3, &arrow_fill_style))
			return false;
		/* scrollbar well background */
		if (!plot->rectangle(x0 + 1,
				y0 + w - 1,
				x1,
				y1 - w + 2,
				&bg_fill_style))
			return false;
		/* scrollbar position indicator bar */
		if (!scrollbar_redraw_scrollbar_rectangle(x0 + 1,
				bar_c0,
				x1 - 1,
				bar_c1,
				fg_fill_colour, false, ctx))
			return false;
		if (!plot->rectangle(x0 + 2,
				bar_c0 + 1,
				x1 - 1,
				bar_c1,
				&fg_fill_style))
			return false;
		/* bottom arrow background */
		if (!scrollbar_redraw_scrollbar_rectangle(x0 + 1,
				y1 - w + 2,
				x1 - 1,
				y1 - 1,
				fg_fill_colour, false, ctx))
			return false;
		if (!plot->rectangle(x0 + 2,
				y1 - w + 3,
				x1 - 1,
				y1 - 1,
				&fg_fill_style))
			return false;
		/* down arrow */
		v[0] = x0 + w / 2;
		v[1] = y1 - w / 4 + 1;
		v[2] = x0 + w / 4;
		v[3] = y1 - w * 3 / 4 + 1;
		v[4] = x0 + w * 3 / 4;
		v[5] = y1 - w * 3 / 4 + 1;
		if (!plot->polygon(v, 3, &arrow_fill_style))
			return false;
	}

	return true;
}


/*
 * Exported function.  Documented in scrollbar.h
 */
void scrollbar_set(struct scrollbar *s, int value, bool bar_pos)
{
	int well_length;
	int old_offset = s->offset;
	struct scrollbar_msg_data msg;

	if (value < 0)
		value = 0;

	if (s->full_size == s->visible_size)
		return;

	well_length = s->length - 2 * SCROLLBAR_WIDTH;
	if (bar_pos) {
		if (value > well_length - s->bar_len)
			s->bar_pos = well_length - s->bar_len;
		else
			s->bar_pos = value;

		s->offset = ((well_length - s->bar_len) < 1) ? 0 :
				(((s->full_size - s->visible_size) *
				s->bar_pos) / (well_length - s->bar_len));

	} else {
		if (value > s->full_size - s->visible_size)
			s->offset = s->full_size - s->visible_size;
		else
			s->offset = value;

		s->bar_pos = (s->full_size < 1) ? 0 :
				((well_length * s->offset) / s->full_size);
	}

	if (s->offset == old_offset)
		/* Nothing happened */
		return;

	msg.scrollbar = s;
	msg.msg = SCROLLBAR_MSG_MOVED;
	msg.scroll_offset = s->offset;
	s->client_callback(s->client_data, &msg);

	msg.msg = SCROLLBAR_MSG_REDRAW;
	msg.x0 = s->horizontal ? SCROLLBAR_WIDTH - 1 : 0;
	msg.y0 = s->horizontal ? 0 : SCROLLBAR_WIDTH - 1;
	msg.x1 = (s->horizontal ? s->length - SCROLLBAR_WIDTH + 1 :
			SCROLLBAR_WIDTH);
	msg.y1 = (s->horizontal ? SCROLLBAR_WIDTH :
			s->length - SCROLLBAR_WIDTH + 1);

	s->client_callback(s->client_data, &msg);
}


/*
 * Exported function.  Documented in scrollbar.h
 */
bool scrollbar_scroll(struct scrollbar *s, int change)
{
	int well_length;
	int old_offset = s->offset;
	struct scrollbar_msg_data msg;

	if (change == 0 || s->full_size <= s->visible_size)
		/* zero scroll step, or unscrollable */
		return false;

	/* Convert named change values to appropriate pixel offset value */
	switch (change) {
	case SCROLL_TOP:
		change = -s->full_size;
		break;

	case SCROLL_PAGE_UP:
		change = -s->visible_size;
		break;

	case SCROLL_PAGE_DOWN:
		change = s->visible_size;
		break;

	case SCROLL_BOTTOM:
		change = s->full_size;
		break;

	default:
		/* Change value is already a pixel offset */
		break;
	}

	/* Get new offset */
	if (s->offset + change > s->full_size - s->visible_size)
		s->offset = s->full_size - s->visible_size;
	else if (s->offset + change < 0)
		s->offset = 0;
	else
		s->offset += change;

	if (s->offset == old_offset)
		/* Nothing happened */
		return false;

	/* Update scrollbar */
	well_length = s->length - 2 * SCROLLBAR_WIDTH;
	s->bar_pos = (s->full_size < 1) ? 0 :
			((well_length * s->offset) / s->full_size);

	msg.scrollbar = s;
	msg.msg = SCROLLBAR_MSG_MOVED;
	msg.scroll_offset = s->offset;
	s->client_callback(s->client_data, &msg);

	msg.msg = SCROLLBAR_MSG_REDRAW;
	msg.x0 = s->horizontal ? SCROLLBAR_WIDTH - 1 : 0;
	msg.y0 = s->horizontal ? 0 : SCROLLBAR_WIDTH - 1;
	msg.x1 = (s->horizontal ? s->length - SCROLLBAR_WIDTH + 1 :
			SCROLLBAR_WIDTH);
	msg.y1 = (s->horizontal ? SCROLLBAR_WIDTH :
			s->length - SCROLLBAR_WIDTH + 1);

	s->client_callback(s->client_data, &msg);

	return true;
}


/*
 * Exported function.  Documented in scrollbar.h
 */
int scrollbar_get_offset(struct scrollbar *s)
{
	if (s == NULL)
		return 0;
	return s->offset;
}


/*
 * Exported function.  Documented in scrollbar.h
 */
void scrollbar_set_extents(struct scrollbar *s, int length,
		int visible_size, int full_size)
{
	int well_length;
	int cur_excess = s->full_size - s->visible_size;

	if (length != -1)
		s->length = length;
	if (visible_size != -1)
		s->visible_size = visible_size;
	if (full_size != -1)
		s->full_size = full_size;

	if (s->full_size < s->visible_size)
		s->full_size = s->visible_size;

	/* Update scroll offset (scaled in proportion with change in excess) */
	s->offset = (cur_excess < 1) ? 0 :
			((s->full_size - s->visible_size) * s->offset /
			cur_excess);

	well_length = s->length - 2 * SCROLLBAR_WIDTH;

	if (s->full_size < 1) {
		s->bar_len = well_length;
		s->bar_pos = 0;
	} else {
		s->bar_len = (well_length * s->visible_size) / s->full_size;
		s->bar_pos = (well_length * s->offset) / s->full_size;
	}
}
Beispiel #2
0
/**
 * Draw one border.
 *
 * \param side index of border side (TOP, RIGHT, BOTTOM, LEFT)
 * \param p array of precomputed border vertices
 * \param c colour for border
 * \param style border line style
 * \param thickness border thickness
 * \param rectangular whether border is rectangular
 * \param clip cliping area for redrawing border.
 * \param ctx current redraw context
 * \return NSERROR_OK if successful otherwise appropriate error code
 */
static nserror
html_redraw_border_plot(const int side,
			const int *p,
			colour c,
			enum css_border_style_e style,
			int thickness,
			bool rectangular,
			const struct rect *clip,
			const struct redraw_context *ctx)
{
	int z[8]; /* Vertices of border part */
	unsigned int light = side;
	plot_style_t *plot_style_bdr_in;
	plot_style_t *plot_style_bdr_out;
	nserror res = NSERROR_OK;
	struct rect rect;

	if (c == NS_TRANSPARENT) {
		return res;
	}

	plot_style_bdr.stroke_type = PLOT_OP_TYPE_DASH;
	plot_style_bdr.stroke_colour = c;
	plot_style_bdr.stroke_width = (thickness << PLOT_STYLE_RADIX);
	plot_style_fillbdr.fill_colour = c;
	plot_style_fillbdr_dark.fill_colour = darken_colour(c);
	plot_style_fillbdr_light.fill_colour = lighten_colour(c);
	plot_style_fillbdr_ddark.fill_colour = double_darken_colour(c);
	plot_style_fillbdr_dlight.fill_colour = double_lighten_colour(c);

	switch (style) {
	case CSS_BORDER_STYLE_DOTTED:
		plot_style_bdr.stroke_type = PLOT_OP_TYPE_DOT;
		/* fall through */
	case CSS_BORDER_STYLE_DASHED:
		rect.x0 = (p[0] + p[2]) / 2;
		rect.y0 = (p[1] + p[3]) / 2;
		rect.x1 = (p[4] + p[6]) / 2;
		rect.y1 = (p[5] + p[7]) / 2;
		res = ctx->plot->line(ctx, &plot_style_bdr, &rect);
		break;

	case CSS_BORDER_STYLE_SOLID:
		/* fall through to default */
	default:
		if (rectangular || thickness == 1) {

			if (side == TOP || side == RIGHT) {
				rect.x0 = p[2];
				rect.y0 = p[3];
				if ((side == TOP) &&
				    (p[4] - p[6] != 0)) {
					rect.x1 = p[4];
				} else {
					rect.x1 = p[6];
				}
				rect.y1 = p[7];
			} else {
				rect.x0 = p[6];
				rect.y0 = p[7];
				rect.x1 = p[2];
				if ((side == LEFT) &&
				    (p[1] - p[3] != 0)) {
					rect.y1 = p[1];
				} else {
					rect.y1 = p[3];
				}
			}
			res = plot_clipped_rectangle(ctx,
						     &plot_style_fillbdr,
						     clip,
						     &rect);
		} else {
			res = ctx->plot->polygon(ctx, &plot_style_fillbdr, p, 4);
		}
		break;

	case CSS_BORDER_STYLE_DOUBLE:
		z[0] = p[0];
		z[1] = p[1];
		z[2] = (p[0] * 2 + p[2]) / 3;
		z[3] = (p[1] * 2 + p[3]) / 3;
		z[4] = (p[6] * 2 + p[4]) / 3;
		z[5] = (p[7] * 2 + p[5]) / 3;
		z[6] = p[6];
		z[7] = p[7];
		res = ctx->plot->polygon(ctx, &plot_style_fillbdr, z, 4);
		if (res == NSERROR_OK) {
			z[0] = p[2];
			z[1] = p[3];
			z[2] = (p[2] * 2 + p[0]) / 3;
			z[3] = (p[3] * 2 + p[1]) / 3;
			z[4] = (p[4] * 2 + p[6]) / 3;
			z[5] = (p[5] * 2 + p[7]) / 3;
			z[6] = p[4];
			z[7] = p[5];
			res = ctx->plot->polygon(ctx, &plot_style_fillbdr, z, 4);
		}
		break;

	case CSS_BORDER_STYLE_GROOVE:
		light = 3 - light;
		/* fall through */
	case CSS_BORDER_STYLE_RIDGE:
		/* choose correct colours for each part of the border line */
		if (light <= 1) {
			plot_style_bdr_in = &plot_style_fillbdr_dark;
			plot_style_bdr_out = &plot_style_fillbdr_light;
		} else {
			plot_style_bdr_in = &plot_style_fillbdr_light;
			plot_style_bdr_out = &plot_style_fillbdr_dark;
		}

		/* Render border */
		if ((rectangular || thickness == 2) && thickness != 1) {
			/* Border made up from two parts and can be
			 * plotted with rectangles
			 */

			/* First part */
			if (side == TOP || side == RIGHT) {
				rect.x0 = (p[0] + p[2]) / 2;
				rect.y0 = (p[1] + p[3]) / 2;
				rect.x1 = p[6];
				rect.y1 = p[7];
			} else {
				rect.x0 = p[6];
				rect.y0 = p[7];
				rect.x1 = (p[0] + p[2]) / 2;
				rect.y1 = (p[1] + p[3]) / 2;
			}
			res = plot_clipped_rectangle(ctx,
						     plot_style_bdr_in,
						     clip,
						     &rect);
			if (res != NSERROR_OK) {
				return res;
			}

			/* Second part */
			if (side == TOP || side == RIGHT) {
				rect.x0 = p[2];
				rect.y0 = p[3];
				rect.x1 = (p[6] + p[4]) / 2;
				rect.y1 = (p[7] + p[5]) / 2;
			} else {
				rect.x0 = (p[6] + p[4]) / 2;
				rect.y0 = (p[7] + p[5]) / 2;
				rect.x1 = p[2];
				rect.y1 = p[3];
			}
			res = plot_clipped_rectangle(ctx,
						     plot_style_bdr_out,
						     clip,
						     &rect);
		} else if (thickness == 1) {
			/* Border made up from one part which can be
			 * plotted as a rectangle
			 */

			if (side == TOP || side == RIGHT) {
				rect.x0 = p[2];
				rect.y0 = p[3];
				rect.x1 = p[6];
				rect.y1 = p[7];
				rect.x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
					rect.x1 + p[4] - p[6] : rect.x1;

				res = plot_clipped_rectangle(ctx,
							     plot_style_bdr_in,
							     clip,
							     &rect);
			} else {
				rect.x0 = p[6];
				rect.y0 = p[7];
				rect.x1 = p[2];
				rect.y1 = p[3];
				rect.y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
					rect.y1 + p[1] - p[3] : rect.y1;
				res = plot_clipped_rectangle(ctx,
							     plot_style_bdr_out,
							     clip,
							     &rect);
			}
		} else {
			/* Border made up from two parts and can't be
			 * plotted with rectangles
			 */
			z[0] = p[0];
			z[1] = p[1];
			z[2] = (p[0] + p[2]) / 2;
			z[3] = (p[1] + p[3]) / 2;
			z[4] = (p[6] + p[4]) / 2;
			z[5] = (p[7] + p[5]) / 2;
			z[6] = p[6];
			z[7] = p[7];
			res = ctx->plot->polygon(ctx, plot_style_bdr_in, z, 4);
			if (res == NSERROR_OK) {
				z[0] = p[2];
				z[1] = p[3];
				z[6] = p[4];
				z[7] = p[5];
				res = ctx->plot->polygon(ctx,
							 plot_style_bdr_out,
							 z,
							 4);
			}
		}
		break;

	case CSS_BORDER_STYLE_INSET:
		light = (light + 2) % 4;
		/* fall through */
	case CSS_BORDER_STYLE_OUTSET:
		/* choose correct colours for each part of the border line */
		switch (light) {
		case 0:
			plot_style_bdr_in = &plot_style_fillbdr_light;
			plot_style_bdr_out = &plot_style_fillbdr_dlight;
			break;
		case 1:
			plot_style_bdr_in = &plot_style_fillbdr_ddark;
			plot_style_bdr_out = &plot_style_fillbdr_dark;
			break;
		case 2:
			plot_style_bdr_in = &plot_style_fillbdr_dark;
			plot_style_bdr_out = &plot_style_fillbdr_ddark;
			break;
		case 3:
			plot_style_bdr_in = &plot_style_fillbdr_dlight;
			plot_style_bdr_out = &plot_style_fillbdr_light;
			break;
		default:
			plot_style_bdr_in = &plot_style_fillbdr;
			plot_style_bdr_out = &plot_style_fillbdr;
			break;
		}

		/* Render border */
		if ((rectangular || thickness == 2) && thickness != 1) {
			/* Border made up from two parts and can be
			 * plotted with rectangles
			 */

			/* First part */
			if (side == TOP || side == RIGHT) {
				rect.x0 = (p[0] + p[2]) / 2;
				rect.y0 = (p[1] + p[3]) / 2;
				rect.x1 = p[6];
				rect.y1 = p[7];
			} else {
				rect.x0 = p[6];
				rect.y0 = p[7];
				rect.x1 = (p[0] + p[2]) / 2;
				rect.y1 = (p[1] + p[3]) / 2;
			}
			res = plot_clipped_rectangle(ctx,
						     plot_style_bdr_in,
						     clip,
						     &rect);
			if (res != NSERROR_OK) {
				return res;
			}

			/* Second part */
			if (side == TOP || side == RIGHT) {
				rect.x0 = p[2];
				rect.y0 = p[3];
				rect.x1 = (p[6] + p[4]) / 2;
				rect.y1 = (p[7] + p[5]) / 2;
			} else {
				rect.x0 = (p[6] + p[4]) / 2;
				rect.y0 = (p[7] + p[5]) / 2;
				rect.x1 = p[2];
				rect.y1 = p[3];
			}
			res = plot_clipped_rectangle(ctx,
						     plot_style_bdr_out,
						     clip,
						     &rect);
		} else if (thickness == 1) {
			/* Border made up from one part which can be
			 * plotted as a rectangle
			 */

			if (side == TOP || side == RIGHT) {
				rect.x0 = p[2];
				rect.y0 = p[3];
				rect.x1 = p[6];
				rect.y1 = p[7];
				rect.x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
					rect.x1 + p[4] - p[6] : rect.x1;
				res = plot_clipped_rectangle(ctx,
							     plot_style_bdr_in,
							     clip,
							     &rect);
			} else {
				rect.x0 = p[6];
				rect.y0 = p[7];
				rect.x1 = p[2];
				rect.y1 = p[3];
				rect.y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
					rect.y1 + p[1] - p[3] : rect.y1;
				res = plot_clipped_rectangle(ctx,
							     plot_style_bdr_out,
							     clip,
							     &rect);
			}
		} else {
			/* Border made up from two parts and can't be
			 * plotted with rectangles
			 */

			z[0] = p[0];
			z[1] = p[1];
			z[2] = (p[0] + p[2]) / 2;
			z[3] = (p[1] + p[3]) / 2;
			z[4] = (p[6] + p[4]) / 2;
			z[5] = (p[7] + p[5]) / 2;
			z[6] = p[6];
			z[7] = p[7];
			res = ctx->plot->polygon(ctx, plot_style_bdr_in, z, 4);
			if (res != NSERROR_OK) {
				return res;
			}
			z[0] = p[2];
			z[1] = p[3];
			z[6] = p[4];
			z[7] = p[5];
			res = ctx->plot->polygon(ctx, plot_style_bdr_out, z, 4);
		}
		break;
	}

	return res;
}