Merge branch 'vince/plotctx'

This commit is contained in:
Vincent Sanders 2017-02-12 20:01:05 +00:00
commit 1666944c7e
50 changed files with 8016 additions and 5387 deletions

View File

@ -600,12 +600,12 @@ bool content_scaled_redraw(struct hlcache_handle *h,
clip.x1 = width;
clip.y1 = height;
new_ctx.plot->clip(&clip);
new_ctx.plot->clip(&new_ctx, &clip);
/* Plot white background */
plot_ok &= new_ctx.plot->rectangle(clip.x0, clip.y0, clip.x1, clip.y1,
plot_style_fill_white);
plot_ok &= (new_ctx.plot->rectangle(&new_ctx,
plot_style_fill_white,
&clip) == NSERROR_OK);
/* Set up content redraw data */
data.x = 0;
@ -628,7 +628,7 @@ bool content_scaled_redraw(struct hlcache_handle *h,
plot_ok &= c->handler->redraw(c, &data, &clip, &new_ctx);
if (ctx->plot->option_knockout) {
knockout_plot_end();
knockout_plot_end(ctx);
}
return plot_ok;

View File

@ -199,8 +199,12 @@ static bool nsbmp_redraw(struct content *c, struct content_redraw_data *data,
if (data->repeat_y)
flags |= BITMAPF_REPEAT_Y;
return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
bmp->bitmap, data->background_colour, flags);
return (ctx->plot->bitmap(ctx,
bmp->bitmap,
data->x, data->y,
data->width, data->height,
data->background_colour,
flags) == NSERROR_OK);
}

View File

@ -137,9 +137,9 @@ bool image_bitmap_plot(struct bitmap *bitmap,
fill_style.stroke_type = PLOT_OP_TYPE_NONE;
fill_style.fill_type = PLOT_OP_TYPE_SOLID;
return ctx->plot->rectangle(area.x0, area.y0,
area.x1, area.y1,
&fill_style);
return (ctx->plot->rectangle(ctx,
&fill_style,
&area) == NSERROR_OK);
} else if ((fill_style.fill_colour & 0xff000000) == 0) {
/* transparent pixel used as spacer, skip it */
@ -154,6 +154,10 @@ bool image_bitmap_plot(struct bitmap *bitmap,
if (data->repeat_y)
flags |= BITMAPF_REPEAT_Y;
return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
bitmap, data->background_colour, flags);
return (ctx->plot->bitmap(ctx,
bitmap,
data->x, data->y,
data->width, data->height,
data->background_colour,
flags) == NSERROR_OK);
}

View File

@ -16,9 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* Content for image/x-riscos-sprite (librosprite implementation).
*
/**
* \file
* librosprite implementation for content image/x-riscos-sprite
*/
#include <stdbool.h>
@ -185,19 +185,28 @@ static void nssprite_destroy(struct content *c)
* Redraw a CONTENT_SPRITE.
*/
static bool nssprite_redraw(struct content *c, struct content_redraw_data *data,
const struct rect *clip, const struct redraw_context *ctx)
static bool
nssprite_redraw(struct content *c,
struct content_redraw_data *data,
const struct rect *clip,
const struct redraw_context *ctx)
{
nssprite_content *nssprite = (nssprite_content *) c;
bitmap_flags_t flags = BITMAPF_NONE;
if (data->repeat_x)
if (data->repeat_x) {
flags |= BITMAPF_REPEAT_X;
if (data->repeat_y)
}
if (data->repeat_y) {
flags |= BITMAPF_REPEAT_Y;
}
return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
nssprite->bitmap, data->background_colour, flags);
return (ctx->plot->bitmap(ctx,
nssprite->bitmap,
data->x, data->y,
data->width, data->height,
data->background_colour,
flags) == NSERROR_OK);
}

View File

@ -16,8 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* Content handler for image/svg using librsvg (implementation).
/**
* \file
* implementation of content handler for image/svg using librsvg.
*
* SVG files are rendered to a NetSurf bitmap by creating a Cairo rendering
* surface (content_rsvg_data.cs) over the bitmap's data, creating a Cairo
@ -234,8 +235,12 @@ static bool rsvg_redraw(struct content *c, struct content_redraw_data *data,
if (data->repeat_y)
flags |= BITMAPF_REPEAT_Y;
return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
rsvgcontent->bitmap, data->background_colour, flags);
return (ctx->plot->bitmap(ctx,
rsvgcontent->bitmap,
data->x, data->y,
data->width, data->height,
data->background_colour,
flags) == NSERROR_OK);
}
static void rsvg_destroy(struct content *c)

View File

@ -16,8 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* Content for image/svg (implementation).
/**
* \file
* implementation of content for image/svg using libsvgtiny.
*/
#include <assert.h>
@ -154,18 +155,25 @@ static void svg_reformat(struct content *c, int width, int height)
* Redraw a CONTENT_SVG.
*/
static bool svg_redraw_internal(struct content *c, int x, int y,
int width, int height, const struct rect *clip,
const struct redraw_context *ctx, float scale,
colour background_colour)
static bool
svg_redraw_internal(struct content *c,
int x,
int y,
int width,
int height,
const struct rect *clip,
const struct redraw_context *ctx,
float scale,
colour background_colour)
{
svg_content *svg = (svg_content *) c;
float transform[6];
struct svgtiny_diagram *diagram = svg->diagram;
bool ok;
int px, py;
unsigned int i;
plot_font_style_t fstyle = *plot_style_font;
plot_style_t pstyle;
nserror res;
assert(diagram);
@ -183,14 +191,17 @@ static bool svg_redraw_internal(struct content *c, int x, int y,
for (i = 0; i != diagram->shape_count; i++) {
if (diagram->shape[i].path) {
ok = ctx->plot->path(diagram->shape[i].path,
diagram->shape[i].path_length,
BGR(diagram->shape[i].fill),
diagram->shape[i].stroke_width,
BGR(diagram->shape[i].stroke),
transform);
if (!ok)
pstyle.stroke_colour = BGR(diagram->shape[i].stroke);
pstyle.fill_colour = BGR(diagram->shape[i].fill);
res = ctx->plot->path(ctx,
&pstyle,
diagram->shape[i].path,
diagram->shape[i].path_length,
diagram->shape[i].stroke_width,
transform);
if (res != NSERROR_OK) {
return false;
}
} else if (diagram->shape[i].text) {
px = transform[0] * diagram->shape[i].text_x +
@ -204,12 +215,14 @@ static bool svg_redraw_internal(struct content *c, int x, int y,
fstyle.foreground = 0x000000;
fstyle.size = (8 * FONT_SIZE_SCALE) * scale;
ok = ctx->plot->text(px, py,
diagram->shape[i].text,
strlen(diagram->shape[i].text),
&fstyle);
if (!ok)
res = ctx->plot->text(ctx,
&fstyle,
px, py,
diagram->shape[i].text,
strlen(diagram->shape[i].text));
if (res != NSERROR_OK) {
return false;
}
}
}

View File

@ -170,23 +170,21 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
return false;
}
if (bw->current_content == NULL && bw->children == NULL) {
if ((bw->current_content == NULL) &&
(bw->children == NULL)) {
/* Browser window has no content, render blank fill */
ctx->plot->clip(clip);
return ctx->plot->rectangle(clip->x0, clip->y0,
clip->x1, clip->y1,
plot_style_fill_white);
ctx->plot->clip(ctx, clip);
return (ctx->plot->rectangle(ctx, plot_style_fill_white, clip) == NSERROR_OK);
}
/* Browser window has content OR children (frames) */
if ((bw->window != NULL) &&
(ctx->plot->option_knockout)) {
/* Root browser window: start knockout */
knockout_plot_start(ctx, &new_ctx);
}
new_ctx.plot->clip(clip);
new_ctx.plot->clip(ctx, clip);
/* Handle redraw of any browser window children */
if (bw->children) {
@ -194,11 +192,12 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
int cur_child;
int children = bw->rows * bw->cols;
if (bw->window != NULL)
if (bw->window != NULL) {
/* Root browser window; start with blank fill */
plot_ok &= new_ctx.plot->rectangle(clip->x0, clip->y0,
clip->x1, clip->y1,
plot_style_fill_white);
plot_ok &= (new_ctx.plot->rectangle(ctx,
plot_style_fill_white,
clip) == NSERROR_OK);
}
/* Loop through all children of bw */
for (cur_child = 0; cur_child < children; cur_child++) {
@ -225,7 +224,7 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
/* Skip this frame if it lies outside clip rectangle */
if (content_clip.x0 >= content_clip.x1 ||
content_clip.y0 >= content_clip.y1)
content_clip.y0 >= content_clip.y1)
continue;
/* Redraw frame */
@ -235,10 +234,11 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
}
/* Nothing else to redraw for browser windows with children;
* cleanup and return */
* cleanup and return
*/
if (bw->window != NULL && ctx->plot->option_knockout) {
/* Root browser window: knockout end */
knockout_plot_end();
knockout_plot_end(ctx);
}
return plot_ok;
@ -254,8 +254,9 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
/* Non-HTML may not fill viewport to extents, so plot white
* background fill */
plot_ok &= new_ctx.plot->rectangle(clip->x0, clip->y0,
clip->x1, clip->y1, plot_style_fill_white);
plot_ok &= (new_ctx.plot->rectangle(&new_ctx,
plot_style_fill_white,
clip) == NSERROR_OK);
}
/* Set up content redraw data */
@ -290,7 +291,7 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
&content_clip, &new_ctx);
/* Back to full clip rect */
new_ctx.plot->clip(clip);
new_ctx.plot->clip(&new_ctx, clip);
if (!bw->window) {
/* Render scrollbars */
@ -313,7 +314,7 @@ bool browser_window_redraw(struct browser_window *bw, int x, int y,
if (bw->window != NULL && ctx->plot->option_knockout) {
/* Root browser window: end knockout */
knockout_plot_end();
knockout_plot_end(ctx);
}
return plot_ok;

View File

@ -287,7 +287,7 @@ static plot_font_style_t pfstyle_node_sel = {
* \param x window x offset
* \param y window y offset
* \param clip clip redraw
* \param ctx current redraw context
* \param ctx current redraw context
*/
static bool
browser_window_history__redraw_entry(struct history *history,
@ -296,7 +296,6 @@ browser_window_history__redraw_entry(struct history *history,
int x, int y, bool clip,
const struct redraw_context *ctx)
{
const struct plotter_table *plot = ctx->plot;
size_t char_offset;
int actual_x;
struct history_entry *child;
@ -306,7 +305,7 @@ browser_window_history__redraw_entry(struct history *history,
plot_style_t *pstyle;
plot_font_style_t *pfstyle;
struct rect rect;
nserror res;
/* setup plot styles */
@ -320,31 +319,36 @@ browser_window_history__redraw_entry(struct history *history,
/* setup clip area */
if (clip) {
struct rect rect;
rect.x0 = x0 + xoffset;
rect.y0 = y0 + yoffset;
rect.x1 = x1 + xoffset;
rect.y1 = y1 + yoffset;
if (!plot->clip(&rect)) {
res = ctx->plot->clip(ctx, &rect);
if (res != NSERROR_OK) {
return false;
}
}
/* Only attempt to plot bitmap if it is present */
if (entry->bitmap != NULL) {
plot->bitmap(entry->x + xoffset,
entry->y + yoffset,
WIDTH, HEIGHT,
entry->bitmap,
0xffffff,
0);
res = ctx->plot->bitmap(ctx,
entry->bitmap,
entry->x + xoffset,
entry->y + yoffset,
WIDTH, HEIGHT,
0xffffff,
0);
if (res != NSERROR_OK) {
return false;
}
}
if (!plot->rectangle(entry->x - 1 + xoffset,
entry->y - 1 + yoffset,
entry->x + xoffset + WIDTH,
entry->y + yoffset + HEIGHT,
pstyle)) {
rect.x0 = entry->x - 1 + xoffset;
rect.y0 = entry->y - 1 + yoffset;
rect.x1 = entry->x + xoffset + WIDTH;
rect.y1 = entry->y + yoffset + HEIGHT;
res = ctx->plot->rectangle(ctx, pstyle, &rect);
if (res != NSERROR_OK) {
return false;
}
@ -355,38 +359,45 @@ browser_window_history__redraw_entry(struct history *history,
return false;
}
if (!plot->text(entry->x + xoffset,
entry->y + HEIGHT + 12 + yoffset,
entry->page.title,
char_offset,
pfstyle)) {
res = ctx->plot->text(ctx,
pfstyle,
entry->x + xoffset,
entry->y + HEIGHT + 12 + yoffset,
entry->page.title,
char_offset);
if (res != NSERROR_OK) {
return false;
}
/* for each child node draw a line and recurse redraw into it */
for (child = entry->forward; child; child = child->next) {
if (!plot->line(entry->x + WIDTH + xoffset,
entry->y + HEIGHT / 2 + yoffset,
entry->x + WIDTH + tailsize + xoffset,
entry->y + HEIGHT / 2 + yoffset,
&pstyle_line)) {
rect.x0 = entry->x + WIDTH + xoffset;
rect.y0 = entry->y + HEIGHT / 2 + yoffset;
rect.x1 = entry->x + WIDTH + tailsize + xoffset;
rect.y1 = entry->y + HEIGHT / 2 + yoffset;
res = ctx->plot->line(ctx, &pstyle_line, &rect);
if (res != NSERROR_OK) {
return false;
}
if (!plot->line(entry->x + WIDTH + tailsize + xoffset,
entry->y + HEIGHT / 2 + yoffset,
child->x - tailsize +xoffset,
child->y + HEIGHT / 2 + yoffset,
&pstyle_line)) {
rect.x0 = entry->x + WIDTH + tailsize + xoffset;
rect.y0 = entry->y + HEIGHT / 2 + yoffset;
rect.x1 = child->x - tailsize + xoffset;
rect.y1 = child->y + HEIGHT / 2 + yoffset;
res = ctx->plot->line(ctx, &pstyle_line, &rect);
if (res != NSERROR_OK) {
return false;
}
if (!plot->line(child->x - tailsize + xoffset,
child->y + HEIGHT / 2 + yoffset,
child->x + xoffset, child->y +
HEIGHT / 2 + yoffset,
&pstyle_line)) {
rect.x0 = child->x - tailsize + xoffset;
rect.y0 = child->y + HEIGHT / 2 + yoffset;
rect.x1 = child->x + xoffset;
rect.y1 = child->y + HEIGHT / 2 + yoffset;
res = ctx->plot->line(ctx, &pstyle_line, &rect);
if (res != NSERROR_OK) {
return false;
}
if (!browser_window_history__redraw_entry(history, child,
x0, y0, x1, y1, x, y, clip, ctx)) {
return false;

File diff suppressed because it is too large Load Diff

View File

@ -26,9 +26,21 @@
#include "netsurf/plotters.h"
/**
* Start a knockout plotting session
*
* \param ctx the redraw context with real plotter table
* \param knk_ctx updated to copy of ctx, with plotter table replaced
* \return true on success, false otherwise
*/
bool knockout_plot_start(const struct redraw_context *ctx,
struct redraw_context *knk_ctx);
bool knockout_plot_end(void);
/**
* End a knockout plotting session
*
* \return true on success, false otherwise
*/
bool knockout_plot_end(const struct redraw_context *ctx);
extern const struct plotter_table knockout_plotters;

View File

@ -18,8 +18,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* Scrollbar widget (implementation).
/**
* \file
* implementation of scrollbar widget.
*/
#include <stdbool.h>
@ -36,10 +37,14 @@
#include "desktop/system_colour.h"
#include "desktop/scrollbar.h"
/**
* Scrollbar context
*/
struct scrollbar {
bool horizontal; /* Horizontal scrollbar if true, else vertical
*/
int length; /* Length of the scrollbar widget */
/** Horizontal scrollbar if true, else vertical */
bool horizontal;
/** Length of the scrollbar widget */
int length;
int full_size; /* Length of the full scrollable area */
int visible_size; /* Length visible part of the scrollable area */
@ -121,24 +126,27 @@ void scrollbar_destroy(struct scrollbar *s)
/**
* Draw an outline rectangle common to a several scrollbar elements.
* Draw an outline rectangle common to several scrollbar elements.
*
* \param x0 left border of the outline
* \param y0 top border of the outline
* \param x1 right border of the outline
* \param y1 bottom border of the outline
* \param c base colour of the outline, the other colours are created by
* lightening or darkening this one
* lightening or darkening this one
* \param ctx current redraw context
* \param inset true for inset outline, false for an outset one
* \return
*/
static inline bool scrollbar_redraw_scrollbar_rectangle(int x0, int y0,
int x1, int y1, colour c, bool inset,
const struct redraw_context *ctx)
static inline nserror
scrollbar_rectangle(const struct redraw_context *ctx,
struct rect *area,
colour c,
bool inset)
{
const struct plotter_table *plot = ctx->plot;
struct rect line;
nserror res;
static plot_style_t c0 = {
.stroke_type = PLOT_OP_TYPE_SOLID,
@ -165,29 +173,63 @@ static inline bool scrollbar_redraw_scrollbar_rectangle(int x0, int y0,
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;
line.x0 = area->x0; line.y0 = area->y0;
line.x1 = area->x1; line.y1 = area->y0;
res = ctx->plot->line(ctx, &c0, &line);
if (res != NSERROR_OK) {
return res;
}
line.x0 = area->x1; line.y0 = area->y0;
line.x1 = area->x1; line.y1 = area->y1 + 1;
res = ctx->plot->line(ctx, &c1, &line);
if (res != NSERROR_OK) {
return res;
}
line.x0 = area->x1; line.y0 = area->y0;
line.x1 = area->x1; line.y1 = area->y0 + 1;
res = ctx->plot->line(ctx, &c2, &line);
if (res != NSERROR_OK) {
return res;
}
line.x0 = area->x1; line.y0 = area->y1;
line.x1 = area->x0; line.y1 = area->y1;
res = ctx->plot->line(ctx, &c1, &line);
if (res != NSERROR_OK) {
return res;
}
line.x0 = area->x0; line.y0 = area->y1;
line.x1 = area->x0; line.y1 = area->y0;
res = ctx->plot->line(ctx, &c0, &line);
if (res != NSERROR_OK) {
return res;
}
line.x0 = area->x0; line.y0 = area->y1;
line.x1 = area->x0; line.y1 = area->y1 + 1;
res = ctx->plot->line(ctx, &c2, &line);
return res;
}
/*
* Exported function. Documented in scrollbar.h
*/
bool scrollbar_redraw(struct scrollbar *s, int x, int y,
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;
struct rect area;
struct rect rect;
nserror res;
colour bg_fill_colour = ns_system_colour_char("Scrollbar");
colour fg_fill_colour = ns_system_colour_char("ButtonFace");
@ -206,176 +248,236 @@ bool scrollbar_redraw(struct scrollbar *s, int x, int y,
.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;
area.x0 = x;
area.y0 = y;
area.x1 = x + (s->horizontal ? s->length : SCROLLBAR_WIDTH) - 1;
area.y1 = y + (s->horizontal ? SCROLLBAR_WIDTH : s->length) - 1;
bar_pos = s->bar_pos;
bar_c1 = (s->horizontal ? x0 : y0) + SCROLLBAR_WIDTH +
bar_c1 = (s->horizontal ? area.x0 : area.y0) + SCROLLBAR_WIDTH +
s->bar_pos + s->bar_len - 1;
if (scale != 1.0) {
w *= scale;
x0 *= scale;
y0 *= scale;
x1 *= scale;
y1 *= scale;
area.x0 *= scale;
area.y0 *= scale;
area.x1 *= scale;
area.y1 *= scale;
bar_pos *= scale;
bar_c1 *= scale;
}
bar_c0 = (s->horizontal ? x0 : y0) + w + bar_pos;
bar_c0 = (s->horizontal ? area.x0 : area.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 */
/* if scrollbar is outside the clipping rectangle, nothing to render */
if ((area.x1 < clip->x0) ||
(area.y1 < clip->y0) ||
(clip->x1 < area.x0) ||
(clip->y1 < area.y0)) {
return true;
}
if (s->horizontal) {
/* scrollbar is horizontal */
/* scrollbar outline */
if (!scrollbar_redraw_scrollbar_rectangle(x0, y0, x1, y1,
bg_fill_colour, true, ctx))
res = scrollbar_rectangle(ctx, &area, bg_fill_colour, true);
if (res != NSERROR_OK) {
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))
rect.x0 = area.x0 + 1;
rect.y0 = area.y0 + 1;
rect.x1 = area.x0 + w - 2;
rect.y1 = area.y1 - 1;
res = scrollbar_rectangle(ctx, &rect, fg_fill_colour, false);
if (res != NSERROR_OK) {
return false;
}
/* left arrow icon background */
if (!plot->rectangle(x0 + 2,
y0 + 2,
x0 + w - 2,
y1 - 1,
&fg_fill_style))
rect.x0 = area.x0 + 2;
rect.y0 = area.y0 + 2;
rect.x1 = area.x0 + w - 2;
rect.y1 = area.y1 - 1;
res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
if (res != NSERROR_OK) {
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))
v[0] = area.x0 + w / 4;
v[1] = area.y0 + w / 2;
v[2] = area.x0 + w * 3 / 4;
v[3] = area.y0 + w / 4;
v[4] = area.x0 + w * 3 / 4;
v[5] = area.y0 + w * 3 / 4;
res = ctx->plot->polygon(ctx, &arrow_fill_style, v, 3);
if (res != NSERROR_OK) {
return false;
}
/* scrollbar well background */
if (!plot->rectangle(x0 + w - 1,
y0 + 1,
x1 - w + 2,
y1,
&bg_fill_style))
rect.x0 = area.x0 + w - 1;
rect.y0 = area.y0 + 1;
rect.x1 = area.x1 - w + 2;
rect.y1 = area.y1;
res = ctx->plot->rectangle(ctx, &bg_fill_style, &rect);
if (res != NSERROR_OK) {
return false;
}
/* scrollbar position indicator bar */
if (!scrollbar_redraw_scrollbar_rectangle(bar_c0,
y0 + 1,
bar_c1,
y1 - 1,
fg_fill_colour, false, ctx))
rect.x0 = bar_c0;
rect.y0 = area.y0 + 1;
rect.x1 = bar_c1;
rect.y1 = area.y1 - 1;
res = scrollbar_rectangle(ctx, &rect, fg_fill_colour, false);
if (res != NSERROR_OK) {
return false;
if (!plot->rectangle(bar_c0 + 1,
y0 + 2,
bar_c1,
y1 - 1,
&fg_fill_style))
}
rect.x0 = bar_c0 + 1;
rect.y0 = area.y0 + 2;
rect.x1 = bar_c1;
rect.y1 = area.y1 - 1;
res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
if (res != NSERROR_OK) {
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))
rect.x0 = area.x1 - w + 2;
rect.y0 = area.y0 + 1;
rect.x1 = area.x1 - 1;
rect.y1 = area.y1 - 1;
res = scrollbar_rectangle(ctx, &rect, fg_fill_colour, false);
if (res != NSERROR_OK) {
return false;
}
/* right arrow icon background */
if (!plot->rectangle(x1 - w + 3,
y0 + 2,
x1 - 1,
y1 - 1,
&fg_fill_style))
rect.x0 = area.x1 - w + 3;
rect.y0 = area.y0 + 2;
rect.x1 = area.x1 - 1;
rect.y1 = area.y1 - 1;
res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
if (res != NSERROR_OK) {
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))
v[0] = rect.x1 - w / 4 + 1;
v[1] = rect.y0 + w / 2;
v[2] = rect.x1 - w * 3 / 4 + 1;
v[3] = rect.y0 + w / 4;
v[4] = rect.x1 - w * 3 / 4 + 1;
v[5] = rect.y0 + w * 3 / 4;
res = ctx->plot->polygon(ctx, &arrow_fill_style, v, 3);
if (res != NSERROR_OK) {
return false;
}
} else {
/* scrollbar is vertical */
/* outline */
if (!scrollbar_redraw_scrollbar_rectangle(x0, y0, x1, y1,
bg_fill_colour, true, ctx))
res = scrollbar_rectangle(ctx, &area, bg_fill_colour, true);
if (res != NSERROR_OK) {
return false;
/* top arrow background */
if (!scrollbar_redraw_scrollbar_rectangle(x0 + 1,
y0 + 1,
x1 - 1,
y0 + w - 2,
fg_fill_colour, false, ctx))
}
/* top arrow border */
rect.x0 = area.x0 + 1;
rect.y0 = area.y0 + 1;
rect.x1 = area.x1 - 1;
rect.y1 = area.y0 + w - 2;
res = scrollbar_rectangle(ctx, &rect, fg_fill_colour, false);
if (res != NSERROR_OK) {
return false;
if (!plot->rectangle(x0 + 2,
y0 + 2,
x1 - 1,
y0 + w - 2,
&fg_fill_style))
}
/* top arrow background */
rect.x0 = area.x0 + 2;
rect.y0 = area.y0 + 2;
rect.x1 = area.x1 - 1;
rect.y1 = area.y0 + w - 2;
res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
if (res != NSERROR_OK) {
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))
v[0] = area.x0 + w / 2;
v[1] = area.y0 + w / 4;
v[2] = area.x0 + w / 4;
v[3] = area.y0 + w * 3 / 4;
v[4] = area.x0 + w * 3 / 4;
v[5] = area.y0 + w * 3 / 4;
res = ctx->plot->polygon(ctx, &arrow_fill_style, v, 3);
if (res != NSERROR_OK) {
return false;
}
/* scrollbar well background */
if (!plot->rectangle(x0 + 1,
y0 + w - 1,
x1,
y1 - w + 2,
&bg_fill_style))
rect.x0 = area.x0 + 1;
rect.y0 = area.y0 + w - 1;
rect.x1 = area.x1;
rect.y1 = area.y1 - w + 2;
res = ctx->plot->rectangle(ctx, &bg_fill_style, &rect);
if (res != NSERROR_OK) {
return false;
}
/* scrollbar position indicator bar */
if (!scrollbar_redraw_scrollbar_rectangle(x0 + 1,
bar_c0,
x1 - 1,
bar_c1,
fg_fill_colour, false, ctx))
rect.x0 = area.x0 + 1;
rect.y0 = bar_c0;
rect.x1 = area.x1 - 1;
rect.y1 = bar_c1;
res = scrollbar_rectangle(ctx, &rect, fg_fill_colour, false);
if (res != NSERROR_OK) {
return false;
if (!plot->rectangle(x0 + 2,
bar_c0 + 1,
x1 - 1,
bar_c1,
&fg_fill_style))
}
rect.x0 = area.x0 + 2;
rect.y0 = bar_c0 + 1;
rect.x1 = area.x1 - 1;
rect.y1 = bar_c1;
res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
if (res != NSERROR_OK) {
return false;
/* bottom arrow background */
if (!scrollbar_redraw_scrollbar_rectangle(x0 + 1,
y1 - w + 2,
x1 - 1,
y1 - 1,
fg_fill_colour, false, ctx))
}
/* down arrow icon border */
rect.x0 = area.x0 + 1;
rect.y0 = area.y1 - w + 2;
rect.x1 = area.x1 - 1;
rect.y1 = area.y1 - 1;
res = scrollbar_rectangle(ctx, &rect, fg_fill_colour, false);
if (res != NSERROR_OK) {
return false;
if (!plot->rectangle(x0 + 2,
y1 - w + 3,
x1 - 1,
y1 - 1,
&fg_fill_style))
}
/* down arrow icon background */
rect.x0 = area.x0 + 2;
rect.y0 = area.y1 - w + 3;
rect.x1 = area.x1 - 1;
rect.y1 = area.y1 - 1;
res = ctx->plot->rectangle(ctx, &fg_fill_style, &rect);
if (res != NSERROR_OK) {
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))
v[0] = area.x0 + w / 2;
v[1] = area.y1 - w / 4 + 1;
v[2] = area.x0 + w / 4;
v[3] = area.y1 - w * 3 / 4 + 1;
v[4] = area.x0 + w * 3 / 4;
v[5] = area.y1 - w * 3 / 4 + 1;
res = ctx->plot->polygon(ctx, &arrow_fill_style, v, 3);
if (res != NSERROR_OK) {
return false;
}
}
return true;
@ -568,7 +670,7 @@ bool scrollbar_is_horizontal(struct scrollbar *s)
* \param x the X coordinate of the drag start
* \param y the Y coordinate of the drag start
* \param content_drag whether this should be a reverse drag (used when the
* user drags the content area, rather than the scrollbar)
* user drags the content area, rather than the scrollbar)
* \param pair whether the drag is a '2D' scroll
*/
@ -682,7 +784,7 @@ scrollbar_mouse_status scrollbar_mouse_action(struct scrollbar *s,
if (val < SCROLLBAR_WIDTH) {
/* left/up arrow */
status = h ? SCROLLBAR_MOUSE_LFT : SCROLLBAR_MOUSE_UP;
if (but1)
scrollbar_set(s, s->offset - SCROLLBAR_WIDTH, false);
@ -721,15 +823,15 @@ scrollbar_mouse_status scrollbar_mouse_action(struct scrollbar *s,
}
else {
/* scrollbar position indication bar */
status = h ? SCROLLBAR_MOUSE_HRZ : SCROLLBAR_MOUSE_VRT;
}
if (mouse & (BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2) &&
(val >= SCROLLBAR_WIDTH + s->bar_pos
&& val < SCROLLBAR_WIDTH + s->bar_pos +
s->bar_len))
(val >= SCROLLBAR_WIDTH + s->bar_pos
&& val < SCROLLBAR_WIDTH + s->bar_pos +
s->bar_len))
/* The mouse event is a drag start on the scrollbar position
* indication bar. */
scrollbar_drag_start_internal(s, x, y, false,
@ -857,4 +959,3 @@ void *scrollbar_get_data(struct scrollbar *s)
{
return s->client_data;
}

View File

@ -2095,13 +2095,13 @@ bool textarea_set_caret(struct textarea *ta, int caret)
void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
const struct rect *clip, const struct redraw_context *ctx)
{
const struct plotter_table *plot = ctx->plot;
int line0, line1, line, left, right, line_y;
int text_y_offset, text_y_offset_baseline;
unsigned int b_pos, b_len, b_len_part, b_end;
unsigned int sel_start, sel_end;
char *line_text;
struct rect r, s;
struct rect rect;
bool selected = false;
plot_font_style_t fstyle;
int fsize = ta->fstyle.size;
@ -2162,20 +2162,24 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
r.y1 = y + ta->vis_height * scale;
}
plot->clip(&r);
ctx->plot->clip(ctx, &r);
if (ta->border_col != NS_TRANSPARENT &&
ta->border_width > 0) {
/* Plot border */
plot->rectangle(x, y, x + ta->vis_width, y + ta->vis_height,
&plot_style_fill_bg);
rect.x0 = x;
rect.y0 = y;
rect.x1 = x + ta->vis_width;
rect.y1 = y + ta->vis_height;
ctx->plot->rectangle(ctx, &plot_style_fill_bg, &rect);
}
if (ta->fstyle.background != NS_TRANSPARENT) {
/* Plot background */
plot_style_fill_bg.fill_colour = ta->fstyle.background;
plot->rectangle(x + ta->border_width, y + ta->border_width,
x + ta->vis_width - ta->border_width,
y + ta->vis_height - ta->border_width,
&plot_style_fill_bg);
rect.x0 = x + ta->border_width;
rect.y0 = y + ta->border_width;
rect.x1 = x + ta->vis_width - ta->border_width;
rect.y1 = y + ta->vis_height - ta->border_width;
ctx->plot->rectangle(ctx, &plot_style_fill_bg, &rect);
}
if (scale == 1.0) {
@ -2223,16 +2227,16 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
plot_style_fill_bg.fill_colour = ta->sel_fstyle.background;
for (line = line0; (line <= line1) &&
(y + line * ta->line_height <= r.y1 + ta->scroll_y);
line++) {
for (line = line0;
(line <= line1) && (y + line * ta->line_height <= r.y1 + ta->scroll_y);
line++) {
if (ta->lines[line].b_length == 0) {
b_pos++;
continue;
}
/* reset clip rectangle */
plot->clip(&r);
ctx->plot->clip(ctx, &r);
b_len = ta->lines[line].b_length;
@ -2256,12 +2260,12 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
fstyle = ta->fstyle;
fstyle.size = fsize;
plot->text(x + ta->border_width + ta->pad_left -
ta->scroll_x,
ctx->plot->text(ctx,
&fstyle,
x + ta->border_width + ta->pad_left - ta->scroll_x,
y + line_y + text_y_offset_baseline,
ta->show->data +
ta->lines[line].b_start,
ta->lines[line].b_length, &fstyle);
ta->show->data + ta->lines[line].b_start,
ta->lines[line].b_length);
b_pos += b_len;
@ -2338,24 +2342,24 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
continue;
}
plot->clip(&s);
ctx->plot->clip(ctx, &s);
if (selected) {
/* draw selection fill */
plot->rectangle(s.x0, y + line_y +
text_y_offset,
s.x1, y + line_y + line_height +
text_y_offset,
&plot_style_fill_bg);
rect.x0 = s.x0;
rect.y0 = y + line_y + text_y_offset;
rect.x1 = s.x1;
rect.y1 = y + line_y + line_height + text_y_offset;
ctx->plot->rectangle(ctx, &plot_style_fill_bg, &rect);
}
/* draw text */
plot->text(x + ta->border_width + ta->pad_left -
ta->scroll_x,
ctx->plot->text(ctx,
&fstyle,
x + ta->border_width + ta->pad_left - ta->scroll_x,
y + line_y + text_y_offset_baseline,
ta->show->data +
ta->lines[line].b_start,
ta->lines[line].b_length, &fstyle);
ta->show->data + ta->lines[line].b_start,
ta->lines[line].b_length);
b_pos += b_len_part;
b_len -= b_len_part;
@ -2376,16 +2380,17 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale,
/* No native caret, there is no selection, and caret visible */
int caret_y = y - ta->scroll_y + ta->caret_y;
plot->clip(&r);
ctx->plot->clip(ctx, &r);
/* Render our own caret */
plot->line(x - ta->scroll_x + ta->caret_x, caret_y,
x - ta->scroll_x + ta->caret_x,
caret_y + ta->line_height,
&pstyle_stroke_caret);
rect.x0 = x - ta->scroll_x + ta->caret_x;
rect.y0 = caret_y;
rect.x1 = x - ta->scroll_x + ta->caret_x;
rect.y1 = caret_y + ta->line_height;
ctx->plot->line(ctx, &pstyle_stroke_caret, &rect);
}
plot->clip(clip);
ctx->plot->clip(ctx, clip);
if (ta->bar_x != NULL)
scrollbar_redraw(ta->bar_x,

View File

@ -1798,10 +1798,11 @@ void treeview_redraw(treeview *tree, const int x, const int y,
struct treeview_node_style *style = &plot_style_odd;
struct content_redraw_data data;
struct rect r;
struct rect rect;
uint32_t count = 0;
int render_y = y;
int inset;
int x0, y0, y1;
int x0;
int baseline = (tree_g.line_height * 3 + 2) / 4;
enum treeview_resource_id res = TREE_RES_CONTENT;
plot_style_t *bg_style;
@ -1833,7 +1834,7 @@ void treeview_redraw(treeview *tree, const int x, const int y,
r.y0 = clip->y0 + y;
r.x1 = clip->x1 + x;
r.y1 = clip->y1 + y;
new_ctx.plot->clip(&r);
new_ctx.plot->clip(&new_ctx, &r);
/* Draw the tree */
node = root = tree->root;
@ -1912,24 +1913,30 @@ void treeview_redraw(treeview *tree, const int x, const int y,
}
/* Render background */
y0 = render_y;
y1 = render_y + height;
new_ctx.plot->rectangle(r.x0, y0, r.x1, y1, bg_style);
rect.x0 = r.x0;
rect.y0 = render_y;
rect.x1 = r.x1;
rect.y1 = render_y + height;
new_ctx.plot->rectangle(&new_ctx, bg_style, &rect);
/* Render toggle */
new_ctx.plot->bitmap(inset, render_y + tree_g.line_height / 4,
style->furn[TREE_FURN_EXPAND].size,
style->furn[TREE_FURN_EXPAND].size,
furniture,
bg_style->fill_colour, BITMAPF_NONE);
new_ctx.plot->bitmap(&new_ctx,
furniture,
inset,
render_y + tree_g.line_height / 4,
style->furn[TREE_FURN_EXPAND].size,
style->furn[TREE_FURN_EXPAND].size,
bg_style->fill_colour,
BITMAPF_NONE);
/* Render icon */
if (node->type == TREE_NODE_ENTRY)
if (node->type == TREE_NODE_ENTRY) {
res = TREE_RES_CONTENT;
else if (node->flags & TV_NFLAGS_SPECIAL)
} else if (node->flags & TV_NFLAGS_SPECIAL) {
res = TREE_RES_FOLDER_SPECIAL;
else
} else {
res = TREE_RES_FOLDER;
}
if (treeview_res[res].ready) {
/* Icon resource is available */
@ -1944,9 +1951,11 @@ void treeview_redraw(treeview *tree, const int x, const int y,
/* Render text */
x0 = inset + tree_g.step_width + tree_g.icon_step;
new_ctx.plot->text(x0, render_y + baseline,
node->text.data, node->text.len,
text_style);
new_ctx.plot->text(&new_ctx,
text_style,
x0, render_y + baseline,
node->text.data,
node->text.len);
/* Rendered the node */
render_y += tree_g.line_height;
@ -1970,25 +1979,25 @@ void treeview_redraw(treeview *tree, const int x, const int y,
if (ef->flags & TREE_FLAG_SHOW_NAME) {
int max_width = tree->field_width;
new_ctx.plot->text(x0 + max_width -
ef->value.width -
tree_g.step_width,
render_y + baseline,
ef->value.data,
ef->value.len,
infotext_style);
new_ctx.plot->text(&new_ctx,
infotext_style,
x0 + max_width - ef->value.width - tree_g.step_width,
render_y + baseline,
ef->value.data,
ef->value.len);
new_ctx.plot->text(x0 + max_width,
render_y + baseline,
entry->fields[i].value.data,
entry->fields[i].value.len,
infotext_style);
new_ctx.plot->text(&new_ctx,
infotext_style,
x0 + max_width,
render_y + baseline,
entry->fields[i].value.data,
entry->fields[i].value.len);
} else {
new_ctx.plot->text(x0, render_y + baseline,
entry->fields[i].value.data,
entry->fields[i].value.len,
infotext_style);
new_ctx.plot->text(&new_ctx,
infotext_style,
x0, render_y + baseline,
entry->fields[i].value.data,
entry->fields[i].value.len);
}
/* Rendered the expanded entry field */
@ -2006,21 +2015,22 @@ void treeview_redraw(treeview *tree, const int x, const int y,
if (render_y < r.y1) {
/* Fill the blank area at the bottom */
y0 = render_y;
new_ctx.plot->rectangle(r.x0, y0, r.x1, r.y1,
&plot_style_even.bg);
rect.x0 = r.x0;
rect.y0 = render_y;
rect.x1 = r.x1;
rect.y1 = r.y1;
new_ctx.plot->rectangle(&new_ctx, &plot_style_even.bg, &rect);
}
/* All normal treeview rendering is done; render any overlays */
if (tree->move.target_pos != TV_TARGET_NONE &&
treeview_res[TREE_RES_ARROW].ready) {
if ((tree->move.target_pos != TV_TARGET_NONE) &&
(treeview_res[TREE_RES_ARROW].ready)) {
/* Got a MOVE drag; render move indicator arrow */
data.x = tree->move.target_area.x0 + x;
data.y = tree->move.target_area.y0 + y;
data.background_colour = plot_style_even.bg.fill_colour;
content_redraw(treeview_res[TREE_RES_ARROW].c,
&data, &r, &new_ctx);
content_redraw(treeview_res[TREE_RES_ARROW].c, &data, &r, &new_ctx);
} else if (tree->edit.textarea != NULL) {
/* Edit in progress; render textarea */
@ -2031,8 +2041,9 @@ void treeview_redraw(treeview *tree, const int x, const int y,
}
/* Rendering complete */
if (ctx->plot->option_knockout)
knockout_plot_end();
if (ctx->plot->option_knockout) {
knockout_plot_end(ctx);
}
}
struct treeview_selection_walk_data {

View File

@ -270,8 +270,11 @@ bool amiga_dt_anim_redraw(struct content *c,
if (data->repeat_y)
flags |= BITMAPF_REPEAT_Y;
return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
plugin->bitmap, data->background_colour, flags);
return (ctx->plot->bitmap(ctx, plugin->bitmap,
data->x, data->y,
data->width, data->height,
data->background_colour,
flags) == NSERROR_OK);
}
/**

View File

@ -197,18 +197,25 @@ bool amiga_dt_sound_redraw(struct content *c,
.stroke_colour = 0x000000,
.stroke_width = 1,
};
struct rect rect;
LOG("amiga_dt_sound_redraw");
rect.x0 = data->x;
rect.y0 = data->y;
rect.x1 = data->x + data->width;
rect.y1 = data->y + data->height;
/* this should be some sort of play/stop control */
ctx->plot->rectangle(data->x, data->y, data->x + data->width,
data->y + data->height, &pstyle);
ctx->plot->rectangle(ctx, &pstyle, &rect);
return ctx->plot->text(data->x, data->y+20,
lwc_string_data(content__get_mime_type(c)),
lwc_string_length(content__get_mime_type(c)),
plot_style_font);
return (ctx->plot->text(ctx,
plot_style_font,
data->x,
data->y+20,
lwc_string_data(content__get_mime_type(c)),
lwc_string_length(content__get_mime_type(c))) == NSERROR_OK);
}

View File

@ -16,7 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
/**
* \file
* Content for image/x-amiga-icon (icon.library implementation).
*
*/
@ -273,8 +274,14 @@ bool amiga_icon_redraw(struct content *c,
if (data->repeat_y)
flags |= BITMAPF_REPEAT_Y;
return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
icon_c->bitmap, data->background_colour, flags);
return (ctx->plot->bitmap(ctx,
icon_c->bitmap,
data->x,
data->y,
data->width,
data->height,
data->background_colour,
flags) == NSERROR_OK);
}

View File

@ -51,8 +51,15 @@
#include "amiga/rtg.h"
#include "amiga/utf8.h"
/* set AMI_PLOTTER_DEBUG to 0 for no debugging, 1 for debugging */
//#define AMI_PLOTTER_DEBUG 1
#ifdef AMI_PLOTTER_DEBUG
#define PLOT_LOG(x...) LOG(x)
#else
#define PLOT_LOG(x...) ((void) 0)
#endif
HOOKF(void, ami_bitmap_tile_hook, struct RastPort *, rp, struct BackFillMessage *);
struct bfbitmap {
@ -336,171 +343,6 @@ void ami_plot_clear_bbox(struct RastPort *rp, struct IBox *bbox)
}
static bool ami_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
{
#ifdef AMI_PLOTTER_DEBUG
LOG("[ami_plotter] Entered ami_rectangle()");
#endif
if (style->fill_type != PLOT_OP_TYPE_NONE) {
ami_plot_setapen(glob->rp, style->fill_colour);
RectFill(glob->rp, x0, y0, x1-1, y1-1);
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
glob->rp->PenWidth = style->stroke_width;
glob->rp->PenHeight = style->stroke_width;
switch (style->stroke_type) {
case PLOT_OP_TYPE_SOLID: /**< Solid colour */
default:
glob->rp->LinePtrn = PATT_LINE;
break;
case PLOT_OP_TYPE_DOT: /**< Dotted plot */
glob->rp->LinePtrn = PATT_DOT;
break;
case PLOT_OP_TYPE_DASH: /**< dashed plot */
glob->rp->LinePtrn = PATT_DASH;
break;
}
ami_plot_setapen(glob->rp, style->stroke_colour);
Move(glob->rp, x0,y0);
Draw(glob->rp, x1, y0);
Draw(glob->rp, x1, y1);
Draw(glob->rp, x0, y1);
Draw(glob->rp, x0, y0);
glob->rp->PenWidth = 1;
glob->rp->PenHeight = 1;
glob->rp->LinePtrn = PATT_LINE;
}
return true;
}
static bool ami_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
{
#ifdef AMI_PLOTTER_DEBUG
LOG("[ami_plotter] Entered ami_line()");
#endif
glob->rp->PenWidth = style->stroke_width;
glob->rp->PenHeight = style->stroke_width;
switch (style->stroke_type) {
case PLOT_OP_TYPE_SOLID: /**< Solid colour */
default:
glob->rp->LinePtrn = PATT_LINE;
break;
case PLOT_OP_TYPE_DOT: /**< Doted plot */
glob->rp->LinePtrn = PATT_DOT;
break;
case PLOT_OP_TYPE_DASH: /**< dashed plot */
glob->rp->LinePtrn = PATT_DASH;
break;
}
ami_plot_setapen(glob->rp, style->stroke_colour);
Move(glob->rp,x0,y0);
Draw(glob->rp,x1,y1);
glob->rp->PenWidth = 1;
glob->rp->PenHeight = 1;
glob->rp->LinePtrn = PATT_LINE;
return true;
}
static bool ami_polygon(const int *p, unsigned int n, const plot_style_t *style)
{
#ifdef AMI_PLOTTER_DEBUG
LOG("[ami_plotter] Entered ami_polygon()");
#endif
ami_plot_setapen(glob->rp, style->fill_colour);
if(AreaMove(glob->rp,p[0],p[1]) == -1)
LOG("AreaMove: vector list full");
for(uint32 k = 1; k < n; k++) {
if(AreaDraw(glob->rp,p[k*2],p[(k*2)+1]) == -1)
LOG("AreaDraw: vector list full");
}
if(AreaEnd(glob->rp) == -1)
LOG("AreaEnd: error");
return true;
}
static bool ami_clip(const struct rect *clip)
{
#ifdef AMI_PLOTTER_DEBUG
LOG("[ami_plotter] Entered ami_clip()");
#endif
struct Region *reg = NULL;
if(glob->rp->Layer)
{
reg = NewRegion();
glob->rect.MinX = clip->x0;
glob->rect.MinY = clip->y0;
glob->rect.MaxX = clip->x1-1;
glob->rect.MaxY = clip->y1-1;
OrRectRegion(reg,&glob->rect);
reg = InstallClipRegion(glob->rp->Layer,reg);
if(reg) DisposeRegion(reg);
}
return true;
}
static bool ami_text(int x, int y, const char *text, size_t length,
const plot_font_style_t *fstyle)
{
#ifdef AMI_PLOTTER_DEBUG
LOG("[ami_plotter] Entered ami_text()");
#endif
if(__builtin_expect(ami_nsfont == NULL, 0)) return false;
ami_plot_setapen(glob->rp, fstyle->foreground);
ami_nsfont->text(glob->rp, text, length, fstyle, x, y, nsoption_bool(font_antialiasing));
return true;
}
static bool ami_disc(int x, int y, int radius, const plot_style_t *style)
{
#ifdef AMI_PLOTTER_DEBUG
LOG("[ami_plotter] Entered ami_disc()");
#endif
if (style->fill_type != PLOT_OP_TYPE_NONE) {
ami_plot_setapen(glob->rp, style->fill_colour);
AreaCircle(glob->rp,x,y,radius);
AreaEnd(glob->rp);
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
ami_plot_setapen(glob->rp, style->stroke_colour);
DrawEllipse(glob->rp,x,y,radius,radius);
}
return true;
}
static void ami_arc_gfxlib(int x, int y, int radius, int angle1, int angle2)
{
double angle1_r = (double)(angle1) * (M_PI / 180.0);
@ -526,46 +368,37 @@ static void ami_arc_gfxlib(int x, int y, int radius, int angle1, int angle2)
}
}
static bool ami_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style)
/**
*/
static nserror
ami_bitmap(int x, int y, int width, int height, struct bitmap *bitmap)
{
#ifdef AMI_PLOTTER_DEBUG
LOG("[ami_plotter] Entered ami_arc()");
#endif
if (angle2 < angle1) angle2 += 360;
ami_plot_setapen(glob->rp, style->fill_colour);
ami_arc_gfxlib(x, y, radius, angle1, angle2);
return true;
}
static bool ami_bitmap(int x, int y, int width, int height, struct bitmap *bitmap)
{
#ifdef AMI_PLOTTER_DEBUG
LOG("[ami_plotter] Entered ami_bitmap()");
#endif
PLOT_LOG("[ami_plotter] Entered ami_bitmap()");
struct BitMap *tbm;
if(!width || !height) return true;
if (!width || !height) {
return NSERROR_OK;
}
if(((x + width) < glob->rect.MinX) ||
((y + height) < glob->rect.MinY) ||
(x > glob->rect.MaxX) ||
(y > glob->rect.MaxY))
return true;
if (((x + width) < glob->rect.MinX) ||
((y + height) < glob->rect.MinY) ||
(x > glob->rect.MaxX) ||
(y > glob->rect.MaxY)) {
return NSERROR_OK;
}
tbm = ami_bitmap_get_native(bitmap, width, height, glob->rp->BitMap);
if(!tbm) return true;
if (!tbm) {
return NSERROR_OK;
}
#ifdef AMI_PLOTTER_DEBUG
LOG("[ami_plotter] ami_bitmap() got native bitmap");
#endif
PLOT_LOG("[ami_plotter] ami_bitmap() got native bitmap");
#ifdef __amigaos4__
if(__builtin_expect((GfxBase->LibNode.lib_Version >= 53) && (glob->palette_mapped == false) &&
(nsoption_bool(direct_render) == false), 1)) {
if (__builtin_expect((GfxBase->LibNode.lib_Version >= 53) &&
(glob->palette_mapped == false) &&
(nsoption_bool(direct_render) == false), 1)) {
uint32 comptype = COMPOSITE_Src_Over_Dest;
uint32 compflags = COMPFLAG_IgnoreDestAlpha;
if(amiga_bitmap_get_opaque(bitmap)) {
@ -585,19 +418,18 @@ static bool ami_bitmap(int x, int y, int width, int height, struct bitmap *bitma
COMPTAG_OffsetY,y,
COMPTAG_FriendBitMap, scrn->RastPort.BitMap,
TAG_DONE);
}
else
} else
#endif
{
ULONG tag, tag_data, minterm = 0xc0;
if(glob->palette_mapped == false) {
if (glob->palette_mapped == false) {
tag = BLITA_UseSrcAlpha;
tag_data = !amiga_bitmap_get_opaque(bitmap);
minterm = 0xc0;
} else {
tag = BLITA_MaskPlane;
if((tag_data = (ULONG)ami_bitmap_get_mask(bitmap, width, height, tbm)))
if ((tag_data = (ULONG)ami_bitmap_get_mask(bitmap, width, height, tbm)))
minterm = MINTERM_SRCMASK;
}
#ifdef __amigaos4__
@ -613,7 +445,7 @@ static bool ami_bitmap(int x, int y, int width, int height, struct bitmap *bitma
tag, tag_data,
TAG_DONE);
#else
if(tag_data) {
if (tag_data) {
BltMaskBitMapRastPort(tbm, 0, 0, glob->rp, x, y, width, height, minterm, tag_data);
} else {
BltBitMapRastPort(tbm, 0, 0, glob->rp, x, y, width, height, 0xc0);
@ -621,118 +453,13 @@ static bool ami_bitmap(int x, int y, int width, int height, struct bitmap *bitma
#endif
}
if((ami_bitmap_is_nativebm(bitmap, tbm) == false)) {
if ((ami_bitmap_is_nativebm(bitmap, tbm) == false)) {
ami_rtg_freebitmap(tbm);
}
return true;
return NSERROR_OK;
}
static bool ami_bitmap_tile(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg,
bitmap_flags_t flags)
{
#ifdef AMI_PLOTTER_DEBUG
LOG("[ami_plotter] Entered ami_bitmap_tile()");
#endif
int xf,yf,xm,ym,oy,ox;
struct BitMap *tbm = NULL;
struct Hook *bfh = NULL;
struct bfbitmap bfbm;
bool repeat_x = (flags & BITMAPF_REPEAT_X);
bool repeat_y = (flags & BITMAPF_REPEAT_Y);
if((width == 0) || (height == 0)) return true;
if(!(repeat_x || repeat_y))
return ami_bitmap(x, y, width, height, bitmap);
/* If it is a one pixel transparent image, we are wasting our time */
if((amiga_bitmap_get_opaque(bitmap) == false) &&
(bitmap_get_width(bitmap) == 1) && (bitmap_get_height(bitmap) == 1))
return true;
tbm = ami_bitmap_get_native(bitmap,width,height,glob->rp->BitMap);
if(!tbm) return true;
ox = x;
oy = y;
/* get left most tile position */
for (; ox > 0; ox -= width)
;
/* get top most tile position */
for (; oy > 0; oy -= height)
;
if(ox<0) ox = -ox;
if(oy<0) oy = -oy;
if(repeat_x)
{
xf = glob->rect.MaxX;
xm = glob->rect.MinX;
}
else
{
xf = x + width;
xm = x;
}
if(repeat_y)
{
yf = glob->rect.MaxY;
ym = glob->rect.MinY;
}
else
{
yf = y + height;
ym = y;
}
#ifdef __amigaos4__
if(amiga_bitmap_get_opaque(bitmap))
{
bfh = CreateBackFillHook(BFHA_BitMap,tbm,
BFHA_Width,width,
BFHA_Height,height,
BFHA_OffsetX,ox,
BFHA_OffsetY,oy,
TAG_DONE);
}
else
#endif
{
bfbm.bm = tbm;
bfbm.width = width;
bfbm.height = height;
bfbm.offsetx = ox;
bfbm.offsety = oy;
bfbm.mask = ami_bitmap_get_mask(bitmap, width, height, tbm);
bfh = calloc(1, sizeof(struct Hook));
bfh->h_Entry = (HOOKFUNC)ami_bitmap_tile_hook;
bfh->h_SubEntry = 0;
bfh->h_Data = &bfbm;
}
InstallLayerHook(glob->rp->Layer,bfh);
EraseRect(glob->rp,xm,ym,xf,yf);
InstallLayerHook(glob->rp->Layer,LAYERS_NOBACKFILL);
#ifdef __amigaos4__
if(amiga_bitmap_get_opaque(bitmap)) DeleteBackFillHook(bfh);
else
#endif
free(bfh);
if((ami_bitmap_is_nativebm(bitmap, tbm) == false)) {
/**\todo is this logic logical? */
ami_rtg_freebitmap(tbm);
}
return true;
}
HOOKF(void, ami_bitmap_tile_hook, struct RastPort *, rp, struct BackFillMessage *)
{
@ -757,8 +484,7 @@ HOOKF(void, ami_bitmap_tile_hook, struct RastPort *, rp, struct BackFillMessage
COMPTAG_OffsetY, yf,
COMPTAG_FriendBitMap, scrn->RastPort.BitMap,
TAG_DONE);
}
else
} else
#endif
{
ULONG tag, tag_data, minterm = 0xc0;
@ -805,42 +531,323 @@ static void ami_bezier(struct bez_point *restrict a, struct bez_point *restrict
p->y = pow((1 - t), 3) * a->y + 3 * t * pow((1 -t), 2) * b->y + 3 * (1-t) * pow(t, 2)* c->y + pow (t, 3)* d->y;
}
static bool ami_path(const float *p, unsigned int n, colour fill, float width,
colour c, const float transform[6])
bool ami_plot_screen_is_palettemapped(void)
{
return glob->palette_mapped;
}
/**
* \brief Sets a clip rectangle for subsequent plot operations.
*
* \param ctx The current redraw context.
* \param clip The rectangle to limit all subsequent plot
* operations within.
* \return NSERROR_OK on success else error code.
*/
static nserror
ami_clip(const struct redraw_context *ctx, const struct rect *clip)
{
struct Region *reg = NULL;
PLOT_LOG("[ami_plotter] Entered ami_clip()");
if (glob->rp->Layer) {
reg = NewRegion();
glob->rect.MinX = clip->x0;
glob->rect.MinY = clip->y0;
glob->rect.MaxX = clip->x1-1;
glob->rect.MaxY = clip->y1-1;
OrRectRegion(reg,&glob->rect);
reg = InstallClipRegion(glob->rp->Layer,reg);
if(reg) {
DisposeRegion(reg);
}
}
return NSERROR_OK;
}
/**
* Plots an arc
*
* plot an arc segment around (x,y), anticlockwise from angle1
* to angle2. Angles are measured anticlockwise from
* horizontal, in degrees.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the arc plot.
* \param x The x coordinate of the arc.
* \param y The y coordinate of the arc.
* \param radius The radius of the arc.
* \param angle1 The start angle of the arc.
* \param angle2 The finish angle of the arc.
* \return NSERROR_OK on success else error code.
*/
static nserror
ami_arc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius, int angle1, int angle2)
{
PLOT_LOG("[ami_plotter] Entered ami_arc()");
if (angle2 < angle1) {
angle2 += 360;
}
ami_plot_setapen(glob->rp, style->fill_colour);
ami_arc_gfxlib(x, y, radius, angle1, angle2);
return NSERROR_OK;
}
/**
* Plots a circle
*
* Plot a circle centered on (x,y), which is optionally filled.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the circle plot.
* \param x x coordinate of circle centre.
* \param y y coordinate of circle centre.
* \param radius circle radius.
* \return NSERROR_OK on success else error code.
*/
static nserror
ami_disc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius)
{
PLOT_LOG("[ami_plotter] Entered ami_disc()");
if (style->fill_type != PLOT_OP_TYPE_NONE) {
ami_plot_setapen(glob->rp, style->fill_colour);
AreaCircle(glob->rp,x,y,radius);
AreaEnd(glob->rp);
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
ami_plot_setapen(glob->rp, style->stroke_colour);
DrawEllipse(glob->rp,x,y,radius,radius);
}
return NSERROR_OK;
}
/**
* Plots a line
*
* plot a line from (x0,y0) to (x1,y1). Coordinates are at
* centre of line width/thickness.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the line plot.
* \param line A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
static nserror
ami_line(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *line)
{
PLOT_LOG("[ami_plotter] Entered ami_line()");
glob->rp->PenWidth = style->stroke_width;
glob->rp->PenHeight = style->stroke_width;
switch (style->stroke_type) {
case PLOT_OP_TYPE_SOLID: /**< Solid colour */
default:
glob->rp->LinePtrn = PATT_LINE;
break;
case PLOT_OP_TYPE_DOT: /**< Doted plot */
glob->rp->LinePtrn = PATT_DOT;
break;
case PLOT_OP_TYPE_DASH: /**< dashed plot */
glob->rp->LinePtrn = PATT_DASH;
break;
}
ami_plot_setapen(glob->rp, style->stroke_colour);
Move(glob->rp, line->x0, line->y0);
Draw(glob->rp, line->x1, line->y1);
glob->rp->PenWidth = 1;
glob->rp->PenHeight = 1;
glob->rp->LinePtrn = PATT_LINE;
return NSERROR_OK;
}
/**
* Plots a rectangle.
*
* The rectangle can be filled an outline or both controlled
* by the plot style The line can be solid, dotted or
* dashed. Top left corner at (x0,y0) and rectangle has given
* width and height.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the rectangle plot.
* \param rect A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
static nserror
ami_rectangle(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *rect)
{
PLOT_LOG("[ami_plotter] Entered ami_rectangle()");
if (style->fill_type != PLOT_OP_TYPE_NONE) {
ami_plot_setapen(glob->rp, style->fill_colour);
RectFill(glob->rp, rect->x0, rect->y0, rect->x1- 1 , rect->y1 - 1);
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
glob->rp->PenWidth = style->stroke_width;
glob->rp->PenHeight = style->stroke_width;
switch (style->stroke_type) {
case PLOT_OP_TYPE_SOLID: /**< Solid colour */
default:
glob->rp->LinePtrn = PATT_LINE;
break;
case PLOT_OP_TYPE_DOT: /**< Dotted plot */
glob->rp->LinePtrn = PATT_DOT;
break;
case PLOT_OP_TYPE_DASH: /**< dashed plot */
glob->rp->LinePtrn = PATT_DASH;
break;
}
ami_plot_setapen(glob->rp, style->stroke_colour);
Move(glob->rp, rect->x0, rect->y0);
Draw(glob->rp, rect->x1, rect->y0);
Draw(glob->rp, rect->x1, rect->y1);
Draw(glob->rp, rect->x0, rect->y1);
Draw(glob->rp, rect->x0, rect->y0);
glob->rp->PenWidth = 1;
glob->rp->PenHeight = 1;
glob->rp->LinePtrn = PATT_LINE;
}
return NSERROR_OK;
}
/**
* Plot a polygon
*
* Plots a filled polygon with straight lines between
* points. The lines around the edge of the ploygon are not
* plotted. The polygon is filled with the non-zero winding
* rule.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the polygon plot.
* \param p verticies of polygon
* \param n number of verticies.
* \return NSERROR_OK on success else error code.
*/
static nserror
ami_polygon(const struct redraw_context *ctx,
const plot_style_t *style,
const int *p,
unsigned int n)
{
PLOT_LOG("[ami_plotter] Entered ami_polygon()");
ami_plot_setapen(glob->rp, style->fill_colour);
if (AreaMove(glob->rp,p[0],p[1]) == -1) {
LOG("AreaMove: vector list full");
}
for (uint32 k = 1; k < n; k++) {
if (AreaDraw(glob->rp,p[k*2],p[(k*2)+1]) == -1) {
LOG("AreaDraw: vector list full");
}
}
if (AreaEnd(glob->rp) == -1) {
LOG("AreaEnd: error");
}
return NSERROR_OK;
}
/**
* Plots a path.
*
* Path plot consisting of cubic Bezier curves. Line and fill colour is
* controlled by the plot style.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
* \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
static nserror
ami_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
float width,
const float transform[6])
{
unsigned int i;
struct bez_point start_p = {0, 0}, cur_p = {0, 0}, p_a, p_b, p_c, p_r;
#ifdef AMI_PLOTTER_DEBUG
LOG("[ami_plotter] Entered ami_path()");
#endif
PLOT_LOG("[ami_plotter] Entered ami_path()");
if (n == 0)
return true;
if (n == 0) {
return NSERROR_OK;
}
if (p[0] != PLOTTER_PATH_MOVE) {
LOG("Path does not start with move");
return false;
return NSERROR_INVALID;
}
if (fill != NS_TRANSPARENT) {
ami_plot_setapen(glob->rp, fill);
if (c != NS_TRANSPARENT)
ami_plot_setopen(glob->rp, c);
if (pstyle->fill_colour != NS_TRANSPARENT) {
ami_plot_setapen(glob->rp, pstyle->fill_colour);
if (pstyle->stroke_colour != NS_TRANSPARENT) {
ami_plot_setopen(glob->rp, pstyle->stroke_colour);
}
} else {
if (c != NS_TRANSPARENT) {
ami_plot_setapen(glob->rp, c);
if (pstyle->stroke_colour != NS_TRANSPARENT) {
ami_plot_setapen(glob->rp, pstyle->stroke_colour);
} else {
return true; /* wholly transparent */
return NSERROR_OK; /* wholly transparent */
}
}
/* Construct path */
for (i = 0; i < n; ) {
if (p[i] == PLOTTER_PATH_MOVE) {
if (fill != NS_TRANSPARENT) {
if(AreaMove(glob->rp, p[i+1], p[i+2]) == -1)
if (pstyle->fill_colour != NS_TRANSPARENT) {
if (AreaMove(glob->rp, p[i+1], p[i+2]) == -1) {
LOG("AreaMove: vector list full");
}
} else {
Move(glob->rp, p[i+1], p[i+2]);
}
@ -851,17 +858,19 @@ static bool ami_path(const float *p, unsigned int n, colour fill, float width,
cur_p.y = start_p.y;
i += 3;
} else if (p[i] == PLOTTER_PATH_CLOSE) {
if (fill != NS_TRANSPARENT) {
if(AreaEnd(glob->rp) == -1)
if (pstyle->fill_colour != NS_TRANSPARENT) {
if (AreaEnd(glob->rp) == -1) {
LOG("AreaEnd: error");
}
} else {
Draw(glob->rp, start_p.x, start_p.y);
}
i++;
} else if (p[i] == PLOTTER_PATH_LINE) {
if (fill != NS_TRANSPARENT) {
if(AreaDraw(glob->rp, p[i+1], p[i+2]) == -1)
if (pstyle->fill_colour != NS_TRANSPARENT) {
if (AreaDraw(glob->rp, p[i+1], p[i+2]) == -1) {
LOG("AreaDraw: vector list full");
}
} else {
Draw(glob->rp, p[i+1], p[i+2]);
}
@ -876,11 +885,12 @@ static bool ami_path(const float *p, unsigned int n, colour fill, float width,
p_c.x = p[i+5];
p_c.y = p[i+6];
for(double t = 0.0; t <= 1.0; t += 0.1) {
for (double t = 0.0; t <= 1.0; t += 0.1) {
ami_bezier(&cur_p, &p_a, &p_b, &p_c, t, &p_r);
if (fill != NS_TRANSPARENT) {
if(AreaDraw(glob->rp, p_r.x, p_r.y) == -1)
if (pstyle->fill_colour != NS_TRANSPARENT) {
if (AreaDraw(glob->rp, p_r.x, p_r.y) == -1) {
LOG("AreaDraw: vector list full");
}
} else {
Draw(glob->rp, p_r.x, p_r.y);
}
@ -891,25 +901,187 @@ static bool ami_path(const float *p, unsigned int n, colour fill, float width,
} else {
LOG("bad path command %f", p[i]);
/* End path for safety if using Area commands */
if (fill != NS_TRANSPARENT) {
if (pstyle->fill_colour != NS_TRANSPARENT) {
AreaEnd(glob->rp);
BNDRYOFF(glob->rp);
}
return false;
return NSERROR_INVALID;
}
}
if (fill != NS_TRANSPARENT)
if (pstyle->fill_colour != NS_TRANSPARENT) {
BNDRYOFF(glob->rp);
}
return true;
return NSERROR_OK;
}
bool ami_plot_screen_is_palettemapped(void)
/**
* Plot a bitmap
*
* Tiled plot of a bitmap image. (x,y) gives the top left
* coordinate of an explicitly placed tile. From this tile the
* image can repeat in all four directions -- up, down, left
* and right -- to the extents given by the current clip
* rectangle.
*
* The bitmap_flags say whether to tile in the x and y
* directions. If not tiling in x or y directions, the single
* image is plotted. The width and height give the dimensions
* the image is to be scaled to.
*
* \param ctx The current redraw context.
* \param bitmap The bitmap to plot
* \param x The x coordinate to plot the bitmap
* \param y The y coordiante to plot the bitmap
* \param width The width of area to plot the bitmap into
* \param height The height of area to plot the bitmap into
* \param bg the background colour to alpha blend into
* \param flags the flags controlling the type of plot operation
* \return NSERROR_OK on success else error code.
*/
static nserror
ami_bitmap_tile(const struct redraw_context *ctx,
struct bitmap *bitmap,
int x, int y,
int width,
int height,
colour bg,
bitmap_flags_t flags)
{
return glob->palette_mapped;
int xf,yf,xm,ym,oy,ox;
struct BitMap *tbm = NULL;
struct Hook *bfh = NULL;
struct bfbitmap bfbm;
bool repeat_x = (flags & BITMAPF_REPEAT_X);
bool repeat_y = (flags & BITMAPF_REPEAT_Y);
PLOT_LOG("[ami_plotter] Entered ami_bitmap_tile()");
if ((width == 0) || (height == 0)) {
return NSERROR_OK;
}
if (!(repeat_x || repeat_y)) {
return ami_bitmap(x, y, width, height, bitmap);
}
/* If it is a one pixel transparent image, we are wasting our time */
if ((amiga_bitmap_get_opaque(bitmap) == false) &&
(bitmap_get_width(bitmap) == 1) &&
(bitmap_get_height(bitmap) == 1)) {
return NSERROR_OK;
}
tbm = ami_bitmap_get_native(bitmap,width,height,glob->rp->BitMap);
if (!tbm) {
return NSERROR_OK;
}
ox = x;
oy = y;
/* get left most tile position */
for (; ox > 0; ox -= width)
/* get top most tile position */
for (; oy > 0; oy -= height);
if (ox < 0) {
ox = -ox;
}
if (oy < 0) {
oy = -oy;
}
if (repeat_x) {
xf = glob->rect.MaxX;
xm = glob->rect.MinX;
} else {
xf = x + width;
xm = x;
}
if (repeat_y) {
yf = glob->rect.MaxY;
ym = glob->rect.MinY;
} else {
yf = y + height;
ym = y;
}
#ifdef __amigaos4__
if(amiga_bitmap_get_opaque(bitmap)) {
bfh = CreateBackFillHook(BFHA_BitMap,tbm,
BFHA_Width,width,
BFHA_Height,height,
BFHA_OffsetX,ox,
BFHA_OffsetY,oy,
TAG_DONE);
} else
#endif
{
bfbm.bm = tbm;
bfbm.width = width;
bfbm.height = height;
bfbm.offsetx = ox;
bfbm.offsety = oy;
bfbm.mask = ami_bitmap_get_mask(bitmap, width, height, tbm);
bfh = calloc(1, sizeof(struct Hook));
bfh->h_Entry = (HOOKFUNC)ami_bitmap_tile_hook;
bfh->h_SubEntry = 0;
bfh->h_Data = &bfbm;
}
InstallLayerHook(glob->rp->Layer,bfh);
EraseRect(glob->rp,xm,ym,xf,yf);
InstallLayerHook(glob->rp->Layer,LAYERS_NOBACKFILL);
#ifdef __amigaos4__
if (amiga_bitmap_get_opaque(bitmap)) {
DeleteBackFillHook(bfh);
} else
#endif
free(bfh);
if ((ami_bitmap_is_nativebm(bitmap, tbm) == false)) {
/**\todo is this logic logical? */
ami_rtg_freebitmap(tbm);
}
return NSERROR_OK;
}
struct plotter_table plot;
/**
* Text plotting.
*
* \param ctx The current redraw context.
* \param fstyle plot style for this text
* \param x x coordinate
* \param y y coordinate
* \param text UTF-8 string to plot
* \param length length of string, in bytes
* \return NSERROR_OK on success else error code.
*/
static nserror
ami_text(const struct redraw_context *ctx,
const struct plot_font_style *fstyle,
int x,
int y,
const char *text,
size_t length)
{
PLOT_LOG("[ami_plotter] Entered ami_text()");
if (__builtin_expect(ami_nsfont == NULL, 0)) {
return NSERROR_OK;
}
ami_plot_setapen(glob->rp, fstyle->foreground);
ami_nsfont->text(glob->rp, text, length, fstyle, x, y, nsoption_bool(font_antialiasing));
return NSERROR_OK;
}
const struct plotter_table amiplot = {
.rectangle = ami_rectangle,
.line = ami_line,

View File

@ -152,16 +152,27 @@ bool amiga_plugin_hack_redraw(struct content *c,
.stroke_colour = 0x000000,
.stroke_width = 1,
};
struct rect rect;
nserror res;
LOG("amiga_plugin_hack_redraw");
ctx->plot->rectangle(data->x, data->y, data->x + data->width,
data->y + data->height, &pstyle);
rect.x0 = data->x;
rect.y0 = data->y;
rect.x1 = data->x + data->width;
rect.y1 = data->y + data->height;
return ctx->plot->text(data->x, data->y+20,
lwc_string_data(content__get_mime_type(c)),
lwc_string_length(content__get_mime_type(c)),
plot_style_font);
ctx->plot->rectangle(ctx, &pstyle, &rect);
res = ctx->plot->text(ctx,
plot_style_font,
data->x, data->y+20,
lwc_string_data(content__get_mime_type(c)),
lwc_string_length(content__get_mime_type(c)));
if (res != NSERROR_OK) {
return false;
}
return true;
}
/**

View File

@ -39,6 +39,7 @@
#include "netsurf/content.h"
#include "netsurf/cookie_db.h"
#include "netsurf/url_db.h"
#include "netsurf/plotters.h"
#include "content/backing_store.h"
#include "atari/gemtk/gemtk.h"
@ -1019,7 +1020,12 @@ static void gui_init(int argc, char** argv)
nkc_init();
LOG("Initializing plotters...");
plot_init(nsoption_charp(atari_font_driver));
struct redraw_context ctx = {
.interactive = true,
.background_images = true,
.plot = &atari_plotters
};
plot_init(&ctx, nsoption_charp(atari_font_driver));
aes_event_in.emi_m1leave = MO_LEAVE;
aes_event_in.emi_m1.g_w = 1;

File diff suppressed because it is too large Load Diff

View File

@ -55,6 +55,7 @@
#define ERR_PLOTTER_NOT_AVAILABLE 3 /* invalid plotter driver name passed */
struct plot_style_s;
struct redraw_context;
struct s_vdi_sysinfo {
short vdi_handle; /**< vdi handle */
@ -83,7 +84,15 @@ struct rect;
extern const struct plotter_table atari_plotters;
int plot_init(char *);
/**
* Init screen and font driver objects.
*
* \param fdrvrname font driver name.
* \return value > 1 when the objects could be succesfully created or
* <= 0 to indicate an error.
*/
int plot_init(const struct redraw_context *ctx, char *fdrvrname);
int plot_finalise(void);
/**
@ -93,7 +102,15 @@ const char* plot_err_str(int i) ;
bool plot_lock(void);
bool plot_unlock(void);
bool plot_set_dimensions( int x, int y, int w, int h );
/**
* Set plot origin and canvas size
* \param x the x origin
* \param y the y origin
* \param w the width of the plot area
* \param h the height of the plot area
*/
bool plot_set_dimensions(const struct redraw_context *ctx, int x, int y, int w, int h );
bool plot_get_dimensions(GRECT *dst);
float plot_get_scale(void);
float plot_set_scale(float);
@ -101,13 +118,10 @@ void plot_set_abs_clipping(const GRECT *area);
void plot_get_abs_clipping(struct rect *dst);
void plot_get_abs_clipping_grect(GRECT *dst);
bool plot_get_clip(struct rect * out);
/* Get clipping for current framebuffer as GRECT */
/** Get clipping for current framebuffer as GRECT */
void plot_get_clip_grect(GRECT * out);
bool plot_clip(const struct rect *clip);
VdiHdl plot_get_vdi_handle(void);
long plot_get_flags(void);
bool plot_rectangle( int x0, int y0, int x1, int y1,const struct plot_style_s *style );
bool plot_line( int x0, int y0, int x1, int y1, const struct plot_style_s *style );
bool plot_blit_bitmap(struct bitmap * bmp, int x, int y,
unsigned long bg, unsigned long flags);
bool plot_blit_mfdb(GRECT * loc, MFDB * insrc, short fgcolor, uint32_t flags);

View File

@ -758,8 +758,11 @@ void window_redraw_favicon(ROOTWIN *rootwin, GRECT *clip_ro)
xoff = ((work.g_w-work.g_h)/2);
work.g_w = work.g_h;
}
plot_set_dimensions( work.g_x+xoff, work.g_y, work.g_w,
work.g_h);
plot_set_dimensions(&rootwin_rdrw_ctx,
work.g_x+xoff,
work.g_y,
work.g_w,
work.g_h);
wind_get_grect(rootwin->aes_handle, WF_FIRSTXYWH, &visible);
while (visible.g_h > 0 && visible.g_w > 0) {
@ -776,8 +779,14 @@ void window_redraw_favicon(ROOTWIN *rootwin, GRECT *clip_ro)
vs_clip(plot_vdi_handle, 1, (short*)&pxy);
//dbg_pxy("vdi clip", (short*)&pxy);
atari_plotters.bitmap(0, 0, work.g_w, work.g_h,
rootwin->icon, 0xffffff, 0);
rootwin_rdrw_ctx.plot->bitmap(&rootwin_rdrw_ctx,
rootwin->icon,
0,
0,
work.g_w,
work.g_h,
0xffffff,
0);
} else {
//dbg_grect("redraw vis area outside", &visible);
}
@ -822,7 +831,8 @@ static void window_redraw_content(ROOTWIN *rootwin, GRECT *content_area,
//dbg_grect("browser redraw, content area", content_area);
//dbg_grect("browser redraw, content clip", clip);
plot_set_dimensions(content_area->g_x, content_area->g_y,
plot_set_dimensions(&rootwin_rdrw_ctx,
content_area->g_x, content_area->g_y,
content_area->g_w, content_area->g_h);
oldscale = plot_set_scale(browser_window_get_scale(rootwin->active_gui_window->browser->bw));
@ -849,7 +859,7 @@ static void window_redraw_content(ROOTWIN *rootwin, GRECT *content_area,
redraw_area.x1 = content_area_rel.g_x + content_area_rel.g_w;
redraw_area.y1 = content_area_rel.g_y + content_area_rel.g_h;
plot_clip(&redraw_area);
rootwin_rdrw_ctx.plot->clip(&rootwin_rdrw_ctx, &redraw_area);
//dbg_rect("rdrw area", &redraw_area);

View File

@ -435,7 +435,7 @@ void toolbar_redraw(struct s_toolbar *tb, GRECT *clip)
if (rc_intersect(clip, &area)) {
float old_scale;
plot_set_dimensions(area_ro.g_x, area_ro.g_y, area_ro.g_w, area_ro.g_h);
plot_set_dimensions(&toolbar_rdrw_ctx, area_ro.g_x, area_ro.g_y, area_ro.g_w, area_ro.g_h);
struct rect r = {
.x0 = MAX(0,area.g_x - area_ro.g_x),
.y0 = MAX(0,area.g_y - area_ro.g_y),

View File

@ -223,7 +223,11 @@ void atari_treeview_redraw(struct core_window *cw)
.background_images = true,
.plot = &atari_plotters
};
plot_set_dimensions(work.g_x, work.g_y, work.g_w, work.g_h);
plot_set_dimensions(&ctx,
work.g_x,
work.g_y,
work.g_w,
work.g_h);
if (plot_lock() == false)
return;

File diff suppressed because it is too large Load Diff

View File

@ -98,6 +98,11 @@ fb_redraw_text(fbtk_widget_t *widget, fbtk_callback_info *cbi )
int padding;
int scroll = 0;
bool caret = false;
struct redraw_context ctx = {
.interactive = true,
.background_images = true,
.plot = &fb_plotters
};
fb_text_font_style(widget, &fh, &padding, &font_style);
@ -142,8 +147,11 @@ fb_redraw_text(fbtk_widget_t *widget, fbtk_callback_info *cbi )
}
/* Call the fb text plotting, baseline is 3/4 down the font */
fb_plotters.text(x, y, widget->u.text.text,
widget->u.text.len, &font_style);
ctx.plot->text(&ctx,
&font_style,
x, y,
widget->u.text.text,
widget->u.text.len);
}
if (caret) {
@ -209,6 +217,11 @@ fb_redraw_text_button(fbtk_widget_t *widget, fbtk_callback_info *cbi )
int fh;
int border;
fbtk_widget_t *root = fbtk_get_root_widget(widget);
struct redraw_context ctx = {
.interactive = true,
.background_images = true,
.plot = &fb_plotters
};
fb_text_font_style(widget, &fh, &border, &font_style);
@ -256,11 +269,12 @@ fb_redraw_text_button(fbtk_widget_t *widget, fbtk_callback_info *cbi )
if (widget->u.text.text != NULL) {
/* Call the fb text plotting, baseline is 3/4 down the font */
fb_plotters.text(bbox.x0 + border,
bbox.y0 + ((fh * 3) / 4) + border,
widget->u.text.text,
widget->u.text.len,
&font_style);
ctx.plot->text(&ctx,
&font_style,
bbox.x0 + border,
bbox.y0 + ((fh * 3) / 4) + border,
widget->u.text.text,
widget->u.text.len);
}
nsfb_update(root->u.root.fb, &bbox);

View File

@ -45,89 +45,439 @@
static nsfb_t *nsfb;
static bool
framebuffer_plot_disc(int x, int y, int radius, const plot_style_t *style)
/**
* \brief Sets a clip rectangle for subsequent plot operations.
*
* \param ctx The current redraw context.
* \param clip The rectangle to limit all subsequent plot
* operations within.
* \return NSERROR_OK on success else error code.
*/
static nserror
framebuffer_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
{
nsfb_bbox_t ellipse;
ellipse.x0 = x - radius;
ellipse.y0 = y - radius;
ellipse.x1 = x + radius;
ellipse.y1 = y + radius;
nsfb_bbox_t nsfb_clip;
nsfb_clip.x0 = clip->x0;
nsfb_clip.y0 = clip->y0;
nsfb_clip.x1 = clip->x1;
nsfb_clip.y1 = clip->y1;
if (style->fill_type != PLOT_OP_TYPE_NONE) {
nsfb_plot_ellipse_fill(nsfb, &ellipse, style->fill_colour);
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
nsfb_plot_ellipse(nsfb, &ellipse, style->stroke_colour);
}
return true;
if (!nsfb_plot_set_clip(nsfb, &nsfb_clip)) {
return NSERROR_INVALID;
}
return NSERROR_OK;
}
static bool
framebuffer_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style)
/**
* Plots an arc
*
* plot an arc segment around (x,y), anticlockwise from angle1
* to angle2. Angles are measured anticlockwise from
* horizontal, in degrees.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the arc plot.
* \param x The x coordinate of the arc.
* \param y The y coordinate of the arc.
* \param radius The radius of the arc.
* \param angle1 The start angle of the arc.
* \param angle2 The finish angle of the arc.
* \return NSERROR_OK on success else error code.
*/
static nserror
framebuffer_plot_arc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius, int angle1, int angle2)
{
return nsfb_plot_arc(nsfb, x, y, radius, angle1, angle2, style->fill_colour);
if (!nsfb_plot_arc(nsfb, x, y, radius, angle1, angle2, style->fill_colour)) {
return NSERROR_INVALID;
}
return NSERROR_OK;
}
static bool
framebuffer_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
/**
* Plots a circle
*
* Plot a circle centered on (x,y), which is optionally filled.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the circle plot.
* \param x x coordinate of circle centre.
* \param y y coordinate of circle centre.
* \param radius circle radius.
* \return NSERROR_OK on success else error code.
*/
static nserror
framebuffer_plot_disc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius)
{
return nsfb_plot_polygon(nsfb, p, n, style->fill_colour);
nsfb_bbox_t ellipse;
ellipse.x0 = x - radius;
ellipse.y0 = y - radius;
ellipse.x1 = x + radius;
ellipse.y1 = y + radius;
if (style->fill_type != PLOT_OP_TYPE_NONE) {
nsfb_plot_ellipse_fill(nsfb, &ellipse, style->fill_colour);
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
nsfb_plot_ellipse(nsfb, &ellipse, style->stroke_colour);
}
return NSERROR_OK;
}
/**
* Plots a line
*
* plot a line from (x0,y0) to (x1,y1). Coordinates are at
* centre of line width/thickness.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the line plot.
* \param line A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
static nserror
framebuffer_plot_line(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *line)
{
nsfb_bbox_t rect;
nsfb_plot_pen_t pen;
rect.x0 = line->x0;
rect.y0 = line->y0;
rect.x1 = line->x1;
rect.y1 = line->y1;
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
if (style->stroke_type == PLOT_OP_TYPE_DOT) {
pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
pen.stroke_pattern = 0xAAAAAAAA;
} else if (style->stroke_type == PLOT_OP_TYPE_DASH) {
pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
pen.stroke_pattern = 0xF0F0F0F0;
} else {
pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
}
pen.stroke_colour = style->stroke_colour;
pen.stroke_width = style->stroke_width;
nsfb_plot_line(nsfb, &rect, &pen);
}
return NSERROR_OK;
}
/**
* Plots a rectangle.
*
* The rectangle can be filled an outline or both controlled
* by the plot style The line can be solid, dotted or
* dashed. Top left corner at (x0,y0) and rectangle has given
* width and height.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the rectangle plot.
* \param nsrect A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
static nserror
framebuffer_plot_rectangle(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *nsrect)
{
nsfb_bbox_t rect;
bool dotted = false;
bool dashed = false;
rect.x0 = nsrect->x0;
rect.y0 = nsrect->y0;
rect.x1 = nsrect->x1;
rect.y1 = nsrect->y1;
if (style->fill_type != PLOT_OP_TYPE_NONE) {
nsfb_plot_rectangle_fill(nsfb, &rect, style->fill_colour);
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
if (style->stroke_type == PLOT_OP_TYPE_DOT) {
dotted = true;
}
if (style->stroke_type == PLOT_OP_TYPE_DASH) {
dashed = true;
}
nsfb_plot_rectangle(nsfb, &rect, style->stroke_width, style->stroke_colour, dotted, dashed);
}
return NSERROR_OK;
}
/**
* Plot a polygon
*
* Plots a filled polygon with straight lines between
* points. The lines around the edge of the ploygon are not
* plotted. The polygon is filled with the non-zero winding
* rule.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the polygon plot.
* \param p verticies of polygon
* \param n number of verticies.
* \return NSERROR_OK on success else error code.
*/
static nserror
framebuffer_plot_polygon(const struct redraw_context *ctx,
const plot_style_t *style,
const int *p,
unsigned int n)
{
if (!nsfb_plot_polygon(nsfb, p, n, style->fill_colour)) {
return NSERROR_INVALID;
}
return NSERROR_OK;
}
/**
* Plots a path.
*
* Path plot consisting of cubic Bezier curves. Line and fill colour is
* controlled by the plot style.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
* \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
static nserror
framebuffer_plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
float width,
const float transform[6])
{
LOG("path unimplemented");
return NSERROR_OK;
}
/**
* Plot a bitmap
*
* Tiled plot of a bitmap image. (x,y) gives the top left
* coordinate of an explicitly placed tile. From this tile the
* image can repeat in all four directions -- up, down, left
* and right -- to the extents given by the current clip
* rectangle.
*
* The bitmap_flags say whether to tile in the x and y
* directions. If not tiling in x or y directions, the single
* image is plotted. The width and height give the dimensions
* the image is to be scaled to.
*
* \param ctx The current redraw context.
* \param bitmap The bitmap to plot
* \param x The x coordinate to plot the bitmap
* \param y The y coordiante to plot the bitmap
* \param width The width of area to plot the bitmap into
* \param height The height of area to plot the bitmap into
* \param bg the background colour to alpha blend into
* \param flags the flags controlling the type of plot operation
* \return NSERROR_OK on success else error code.
*/
static nserror
framebuffer_plot_bitmap(const struct redraw_context *ctx,
struct bitmap *bitmap,
int x, int y,
int width,
int height,
colour bg,
bitmap_flags_t flags)
{
nsfb_bbox_t loc;
nsfb_bbox_t clipbox;
bool repeat_x = (flags & BITMAPF_REPEAT_X);
bool repeat_y = (flags & BITMAPF_REPEAT_Y);
int bmwidth;
int bmheight;
int bmstride;
enum nsfb_format_e bmformat;
unsigned char *bmptr;
nsfb_t *bm = (nsfb_t *)bitmap;
/* x and y define coordinate of top left of of the initial explicitly
* placed tile. The width and height are the image scaling and the
* bounding box defines the extent of the repeat (which may go in all
* four directions from the initial tile).
*/
if (!(repeat_x || repeat_y)) {
/* Not repeating at all, so just plot it */
loc.x0 = x;
loc.y0 = y;
loc.x1 = loc.x0 + width;
loc.y1 = loc.y0 + height;
return nsfb_plot_copy(bm, NULL, nsfb, &loc);
}
nsfb_plot_get_clip(nsfb, &clipbox);
nsfb_get_geometry(bm, &bmwidth, &bmheight, &bmformat);
nsfb_get_buffer(bm, &bmptr, &bmstride);
/* Optimise tiled plots of 1x1 bitmaps by replacing with a flat fill
* of the area. Can only be done when image is fully opaque. */
if ((bmwidth == 1) && (bmheight == 1)) {
if ((*(nsfb_colour_t *)bmptr & 0xff000000) != 0) {
if (!nsfb_plot_rectangle_fill(nsfb, &clipbox,
*(nsfb_colour_t *)bmptr)) {
return NSERROR_INVALID;
}
return NSERROR_OK;
}
}
/* Optimise tiled plots of bitmaps scaled to 1x1 by replacing with
* a flat fill of the area. Can only be done when image is fully
* opaque. */
if ((width == 1) && (height == 1)) {
if (framebuffer_bitmap_get_opaque(bm)) {
/** TODO: Currently using top left pixel. Maybe centre
* pixel or average value would be better. */
if (!nsfb_plot_rectangle_fill(nsfb, &clipbox,
*(nsfb_colour_t *)bmptr)) {
return NSERROR_INVALID;
}
return NSERROR_OK;
}
}
/* get left most tile position */
if (repeat_x) {
for (; x > clipbox.x0; x -= width);
}
/* get top most tile position */
if (repeat_y) {
for (; y > clipbox.y0; y -= height);
}
/* set up top left tile location */
loc.x0 = x;
loc.y0 = y;
loc.x1 = loc.x0 + width;
loc.y1 = loc.y0 + height;
/* plot tiling across and down to extents */
nsfb_plot_bitmap_tiles(nsfb, &loc,
repeat_x ? ((clipbox.x1 - x) + width - 1) / width : 1,
repeat_y ? ((clipbox.y1 - y) + height - 1) / height : 1,
(nsfb_colour_t *)bmptr, bmwidth, bmheight,
bmstride * 8 / 32, bmformat == NSFB_FMT_ABGR8888);
return NSERROR_OK;
}
#ifdef FB_USE_FREETYPE
static bool
framebuffer_plot_text(int x, int y, const char *text, size_t length,
const plot_font_style_t *fstyle)
/**
* Text plotting.
*
* \param ctx The current redraw context.
* \param fstyle plot style for this text
* \param x x coordinate
* \param y y coordinate
* \param text UTF-8 string to plot
* \param length length of string, in bytes
* \return NSERROR_OK on success else error code.
*/
static nserror
framebuffer_plot_text(const struct redraw_context *ctx,
const struct plot_font_style *fstyle,
int x,
int y,
const char *text,
size_t length)
{
uint32_t ucs4;
size_t nxtchr = 0;
FT_Glyph glyph;
FT_BitmapGlyph bglyph;
nsfb_bbox_t loc;
uint32_t ucs4;
size_t nxtchr = 0;
FT_Glyph glyph;
FT_BitmapGlyph bglyph;
nsfb_bbox_t loc;
while (nxtchr < length) {
ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
nxtchr = utf8_next(text, length, nxtchr);
while (nxtchr < length) {
ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
nxtchr = utf8_next(text, length, nxtchr);
glyph = fb_getglyph(fstyle, ucs4);
if (glyph == NULL)
continue;
glyph = fb_getglyph(fstyle, ucs4);
if (glyph == NULL)
continue;
if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
bglyph = (FT_BitmapGlyph)glyph;
if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
bglyph = (FT_BitmapGlyph)glyph;
loc.x0 = x + bglyph->left;
loc.y0 = y - bglyph->top;
loc.x1 = loc.x0 + bglyph->bitmap.width;
loc.y1 = loc.y0 + bglyph->bitmap.rows;
loc.x0 = x + bglyph->left;
loc.y0 = y - bglyph->top;
loc.x1 = loc.x0 + bglyph->bitmap.width;
loc.y1 = loc.y0 + bglyph->bitmap.rows;
/* now, draw to our target surface */
if (bglyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
nsfb_plot_glyph1(nsfb,
&loc,
bglyph->bitmap.buffer,
bglyph->bitmap.pitch,
fstyle->foreground);
} else {
nsfb_plot_glyph8(nsfb,
&loc,
bglyph->bitmap.buffer,
bglyph->bitmap.pitch,
fstyle->foreground);
}
}
x += glyph->advance.x >> 16;
/* now, draw to our target surface */
if (bglyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
nsfb_plot_glyph1(nsfb,
&loc,
bglyph->bitmap.buffer,
bglyph->bitmap.pitch,
fstyle->foreground);
} else {
nsfb_plot_glyph8(nsfb,
&loc,
bglyph->bitmap.buffer,
bglyph->bitmap.pitch,
fstyle->foreground);
}
}
x += glyph->advance.x >> 16;
}
return true;
}
return NSERROR_OK;
}
#else
static bool framebuffer_plot_text(int x, int y, const char *text, size_t length,
const plot_font_style_t *fstyle)
/**
* Text plotting.
*
* \param ctx The current redraw context.
* \param fstyle plot style for this text
* \param x x coordinate
* \param y y coordinate
* \param text UTF-8 string to plot
* \param length length of string, in bytes
* \return NSERROR_OK on success else error code.
*/
static nserror
framebuffer_plot_text(const struct redraw_context *ctx,
const struct plot_font_style *fstyle,
int x,
int y,
const char *text,
size_t length)
{
enum fb_font_style style = fb_get_font_style(fstyle);
int size = fb_get_font_size(fstyle);
@ -145,196 +495,30 @@ static bool framebuffer_plot_text(int x, int y, const char *text, size_t length,
y += 1;
while (nxtchr < length) {
ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
nxtchr = utf8_next(text, length, nxtchr);
ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
nxtchr = utf8_next(text, length, nxtchr);
if (!codepoint_displayable(ucs4))
continue;
loc.x0 = x;
loc.y0 = y;
loc.x1 = loc.x0 + w;
loc.y1 = loc.y0 + h;
loc.x0 = x;
loc.y0 = y;
loc.x1 = loc.x0 + w;
loc.y1 = loc.y0 + h;
chrp = fb_get_glyph(ucs4, style, size);
nsfb_plot_glyph1(nsfb, &loc, chrp, p, fstyle->foreground);
chrp = fb_get_glyph(ucs4, style, size);
nsfb_plot_glyph1(nsfb, &loc, chrp, p, fstyle->foreground);
x += w;
x += w;
}
return true;
return NSERROR_OK;
}
#endif
static bool
framebuffer_plot_bitmap(int x, int y,
int width, int height,
struct bitmap *bitmap, colour bg,
bitmap_flags_t flags)
{
nsfb_bbox_t loc;
nsfb_bbox_t clipbox;
bool repeat_x = (flags & BITMAPF_REPEAT_X);
bool repeat_y = (flags & BITMAPF_REPEAT_Y);
int bmwidth;
int bmheight;
int bmstride;
enum nsfb_format_e bmformat;
unsigned char *bmptr;
nsfb_t *bm = (nsfb_t *)bitmap;
/* x and y define coordinate of top left of of the initial explicitly
* placed tile. The width and height are the image scaling and the
* bounding box defines the extent of the repeat (which may go in all
* four directions from the initial tile).
*/
if (!(repeat_x || repeat_y)) {
/* Not repeating at all, so just plot it */
loc.x0 = x;
loc.y0 = y;
loc.x1 = loc.x0 + width;
loc.y1 = loc.y0 + height;
return nsfb_plot_copy(bm, NULL, nsfb, &loc);
}
nsfb_plot_get_clip(nsfb, &clipbox);
nsfb_get_geometry(bm, &bmwidth, &bmheight, &bmformat);
nsfb_get_buffer(bm, &bmptr, &bmstride);
/* Optimise tiled plots of 1x1 bitmaps by replacing with a flat fill
* of the area. Can only be done when image is fully opaque. */
if ((bmwidth == 1) && (bmheight == 1)) {
if ((*(nsfb_colour_t *)bmptr & 0xff000000) != 0) {
return nsfb_plot_rectangle_fill(nsfb, &clipbox,
*(nsfb_colour_t *)bmptr);
}
}
/* Optimise tiled plots of bitmaps scaled to 1x1 by replacing with
* a flat fill of the area. Can only be done when image is fully
* opaque. */
if ((width == 1) && (height == 1)) {
if (framebuffer_bitmap_get_opaque(bm)) {
/** TODO: Currently using top left pixel. Maybe centre
* pixel or average value would be better. */
return nsfb_plot_rectangle_fill(nsfb, &clipbox,
*(nsfb_colour_t *)bmptr);
}
}
/* get left most tile position */
if (repeat_x)
for (; x > clipbox.x0; x -= width);
/* get top most tile position */
if (repeat_y)
for (; y > clipbox.y0; y -= height);
/* set up top left tile location */
loc.x0 = x;
loc.y0 = y;
loc.x1 = loc.x0 + width;
loc.y1 = loc.y0 + height;
/* plot tiling across and down to extents */
nsfb_plot_bitmap_tiles(nsfb, &loc,
repeat_x ? ((clipbox.x1 - x) + width - 1) / width : 1,
repeat_y ? ((clipbox.y1 - y) + height - 1) / height : 1,
(nsfb_colour_t *)bmptr, bmwidth, bmheight,
bmstride * 8 / 32, bmformat == NSFB_FMT_ABGR8888);
return true;
}
static bool
framebuffer_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
{
nsfb_bbox_t rect;
bool dotted = false;
bool dashed = false;
rect.x0 = x0;
rect.y0 = y0;
rect.x1 = x1;
rect.y1 = y1;
if (style->fill_type != PLOT_OP_TYPE_NONE) {
nsfb_plot_rectangle_fill(nsfb, &rect, style->fill_colour);
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
if (style->stroke_type == PLOT_OP_TYPE_DOT)
dotted = true;
if (style->stroke_type == PLOT_OP_TYPE_DASH)
dashed = true;
nsfb_plot_rectangle(nsfb, &rect, style->stroke_width, style->stroke_colour, dotted, dashed);
}
return true;
}
static bool
framebuffer_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
{
nsfb_bbox_t rect;
nsfb_plot_pen_t pen;
rect.x0 = x0;
rect.y0 = y0;
rect.x1 = x1;
rect.y1 = y1;
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
if (style->stroke_type == PLOT_OP_TYPE_DOT) {
pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
pen.stroke_pattern = 0xAAAAAAAA;
} else if (style->stroke_type == PLOT_OP_TYPE_DASH) {
pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
pen.stroke_pattern = 0xF0F0F0F0;
} else {
pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
}
pen.stroke_colour = style->stroke_colour;
pen.stroke_width = style->stroke_width;
nsfb_plot_line(nsfb, &rect, &pen);
}
return true;
}
static bool
framebuffer_plot_path(const float *p,
unsigned int n,
colour fill,
float width,
colour c,
const float transform[6])
{
LOG("path unimplemented");
return true;
}
static bool
framebuffer_plot_clip(const struct rect *clip)
{
nsfb_bbox_t nsfb_clip;
nsfb_clip.x0 = clip->x0;
nsfb_clip.y0 = clip->y0;
nsfb_clip.x1 = clip->x1;
nsfb_clip.y1 = clip->y1;
return nsfb_plot_set_clip(nsfb, &nsfb_clip);
}
/** framebuffer plot operation table */
const struct plotter_table fb_plotters = {
.clip = framebuffer_plot_clip,
.arc = framebuffer_plot_arc,
@ -345,7 +529,7 @@ const struct plotter_table fb_plotters = {
.path = framebuffer_plot_path,
.bitmap = framebuffer_plot_bitmap,
.text = framebuffer_plot_text,
.option_knockout = true,
.option_knockout = true,
};
@ -394,33 +578,33 @@ framebuffer_initialise(const char *fename, int width, int height, int bpp)
/* bpp is a proxy for the framebuffer format */
if (framebuffer_format_from_bpp(bpp, &fbfmt) == false) {
return NULL;
return NULL;
}
fbtype = nsfb_type_from_name(fename);
if (fbtype == NSFB_SURFACE_NONE) {
LOG("The %s surface is not available from libnsfb\n", fename);
return NULL;
LOG("The %s surface is not available from libnsfb\n", fename);
return NULL;
}
nsfb = nsfb_new(fbtype);
if (nsfb == NULL) {
LOG("Unable to create %s fb surface\n", fename);
return NULL;
LOG("Unable to create %s fb surface\n", fename);
return NULL;
}
if (nsfb_set_geometry(nsfb, width, height, fbfmt) == -1) {
LOG("Unable to set surface geometry\n");
nsfb_free(nsfb);
return NULL;
LOG("Unable to set surface geometry\n");
nsfb_free(nsfb);
return NULL;
}
nsfb_cursor_init(nsfb);
if (nsfb_init(nsfb) == -1) {
LOG("Unable to initialise nsfb surface\n");
nsfb_free(nsfb);
return NULL;
LOG("Unable to initialise nsfb surface\n");
nsfb_free(nsfb);
return NULL;
}
return nsfb;
@ -434,12 +618,12 @@ framebuffer_resize(nsfb_t *nsfb, int width, int height, int bpp)
/* bpp is a proxy for the framebuffer format */
if (framebuffer_format_from_bpp(bpp, &fbfmt) == false) {
return false;
return false;
}
if (nsfb_set_geometry(nsfb, width, height, fbfmt) == -1) {
LOG("Unable to change surface geometry\n");
return false;
LOG("Unable to change surface geometry\n");
return false;
}
return true;
@ -449,14 +633,14 @@ framebuffer_resize(nsfb_t *nsfb, int width, int height, int bpp)
void
framebuffer_finalise(void)
{
nsfb_free(nsfb);
nsfb_free(nsfb);
}
bool
framebuffer_set_cursor(struct fbtk_bitmap *bm)
{
return nsfb_cursor_set(nsfb, (nsfb_colour_t *)bm->pixdata, bm->width, bm->height, bm->width, bm->hot_x, bm->hot_y);
}
}
nsfb_t *framebuffer_set_surface(nsfb_t *new_nsfb)
{

View File

@ -222,7 +222,7 @@ nsfont_split(const plot_font_style_t *fstyle,
* \param fstyle plot style for this text
* \return true on success, false on error and error reported
*/
bool nsfont_paint(int x, int y, const char *string, size_t length,
nserror nsfont_paint(int x, int y, const char *string, size_t length,
const plot_font_style_t *fstyle)
{
PangoFontDescription *desc;
@ -230,7 +230,7 @@ bool nsfont_paint(int x, int y, const char *string, size_t length,
PangoLayoutLine *line;
if (length == 0)
return true;
return NSERROR_OK;
layout = pango_cairo_create_layout(current_cr);
@ -247,7 +247,7 @@ bool nsfont_paint(int x, int y, const char *string, size_t length,
g_object_unref(layout);
return true;
return NSERROR_OK;
}

View File

@ -30,7 +30,7 @@ struct plot_font_style;
extern struct gui_layout_table *nsgtk_layout_table;
bool nsfont_paint(int x, int y, const char *string, size_t length, const struct plot_font_style *fstyle);
nserror nsfont_paint(int x, int y, const char *string, size_t length, const struct plot_font_style *fstyle);
/**
* Convert a plot style to a PangoFontDescription.

View File

@ -77,8 +77,17 @@ static inline void nsgtk_set_dashed(void)
cairo_set_dash(current_cr, cdashes, 2, 0);
}
/** Set clipping area for subsequent plot operations. */
static bool nsgtk_plot_clip(const struct rect *clip)
/**
* \brief Sets a clip rectangle for subsequent plot operations.
*
* \param ctx The current redraw context.
* \param clip The rectangle to limit all subsequent plot
* operations within.
* \return NSERROR_OK on success else error code.
*/
static nserror
nsgtk_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
{
cairo_reset_clip(current_cr);
cairo_rectangle(current_cr, clip->x0, clip->y0,
@ -90,11 +99,30 @@ static bool nsgtk_plot_clip(const struct rect *clip)
cliprect.width = clip->x1 - clip->x0;
cliprect.height = clip->y1 - clip->y0;
return true;
return NSERROR_OK;
}
static bool nsgtk_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style)
/**
* Plots an arc
*
* plot an arc segment around (x,y), anticlockwise from angle1
* to angle2. Angles are measured anticlockwise from
* horizontal, in degrees.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the arc plot.
* \param x The x coordinate of the arc.
* \param y The y coordinate of the arc.
* \param radius The radius of the arc.
* \param angle1 The start angle of the arc.
* \param angle2 The finish angle of the arc.
* \return NSERROR_OK on success else error code.
*/
static nserror
nsgtk_plot_arc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius, int angle1, int angle2)
{
nsgtk_set_colour(style->fill_colour);
nsgtk_set_solid();
@ -105,10 +133,26 @@ static bool nsgtk_plot_arc(int x, int y, int radius, int angle1, int angle2, con
(angle2 + 90) * (M_PI / 180));
cairo_stroke(current_cr);
return true;
return NSERROR_OK;
}
static bool nsgtk_plot_disc(int x, int y, int radius, const plot_style_t *style)
/**
* Plots a circle
*
* Plot a circle centered on (x,y), which is optionally filled.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the circle plot.
* \param x x coordinate of circle centre.
* \param y y coordinate of circle centre.
* \param radius circle radius.
* \return NSERROR_OK on success else error code.
*/
static nserror
nsgtk_plot_disc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius)
{
if (style->fill_type != PLOT_OP_TYPE_NONE) {
nsgtk_set_colour(style->fill_colour);
@ -147,11 +191,25 @@ static bool nsgtk_plot_disc(int x, int y, int radius, const plot_style_t *style)
cairo_stroke(current_cr);
}
return true;
return NSERROR_OK;
}
static bool
nsgtk_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
/**
* Plots a line
*
* plot a line from (x0,y0) to (x1,y1). Coordinates are at
* centre of line width/thickness.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the line plot.
* \param line A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
static nserror
nsgtk_plot_line(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *line)
{
nsgtk_set_colour(style->stroke_colour);
@ -180,17 +238,22 @@ nsgtk_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
cairo_set_line_width(current_cr, style->stroke_width);
/* core expects horizontal and vertical lines to be on pixels, not
* between pixels */
cairo_move_to(current_cr, (x0 == x1) ? x0 + 0.5 : x0,
(y0 == y1) ? y0 + 0.5 : y0);
cairo_line_to(current_cr, (x0 == x1) ? x1 + 0.5 : x1,
(y0 == y1) ? y1 + 0.5 : y1);
* between pixels
*/
cairo_move_to(current_cr,
(line->x0 == line->x1) ? line->x0 + 0.5 : line->x0,
(line->y0 == line->y1) ? line->y0 + 0.5 : line->y0);
cairo_line_to(current_cr,
(line->x0 == line->x1) ? line->x1 + 0.5 : line->x1,
(line->y0 == line->y1) ? line->y1 + 0.5 : line->y1);
cairo_stroke(current_cr);
return true;
return NSERROR_OK;
}
/** Plot a caret.
/**
* Plot a caret.
*
* @note It is assumed that the plotters have been set up.
*/
@ -207,14 +270,35 @@ void nsgtk_plot_caret(int x, int y, int h)
cairo_stroke(current_cr);
}
static bool nsgtk_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
/**
* Plots a rectangle.
*
* The rectangle can be filled an outline or both controlled
* by the plot style The line can be solid, dotted or
* dashed. Top left corner at (x0,y0) and rectangle has given
* width and height.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the rectangle plot.
* \param rect A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
static nserror
nsgtk_plot_rectangle(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *rect)
{
if (style->fill_type != PLOT_OP_TYPE_NONE) {
nsgtk_set_colour(style->fill_colour);
nsgtk_set_solid();
cairo_set_line_width(current_cr, 0);
cairo_rectangle(current_cr, x0, y0, x1 - x0, y1 - y0);
cairo_rectangle(current_cr,
rect->x0,
rect->y0,
rect->x1 - rect->x0,
rect->y1 - rect->y0);
cairo_fill(current_cr);
cairo_stroke(current_cr);
}
@ -242,13 +326,36 @@ static bool nsgtk_plot_rectangle(int x0, int y0, int x1, int y1, const plot_styl
else
cairo_set_line_width(current_cr, style->stroke_width);
cairo_rectangle(current_cr, x0 + 0.5, y0 + 0.5, x1 - x0, y1 - y0);
cairo_rectangle(current_cr,
rect->x0 + 0.5,
rect->y0 + 0.5,
rect->x1 - rect->x0,
rect->y1 - rect->y0);
cairo_stroke(current_cr);
}
return true;
return NSERROR_OK;
}
static bool nsgtk_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
/**
* Plot a polygon
*
* Plots a filled polygon with straight lines between
* points. The lines around the edge of the ploygon are not
* plotted. The polygon is filled with the non-zero winding
* rule.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the polygon plot.
* \param p verticies of polygon
* \param n number of verticies.
* \return NSERROR_OK on success else error code.
*/
static nserror
nsgtk_plot_polygon(const struct redraw_context *ctx,
const plot_style_t *style,
const int *p,
unsigned int n)
{
unsigned int i;
@ -263,22 +370,116 @@ static bool nsgtk_plot_polygon(const int *p, unsigned int n, const plot_style_t
cairo_fill(current_cr);
cairo_stroke(current_cr);
return true;
return NSERROR_OK;
}
static bool nsgtk_plot_text(int x, int y, const char *text, size_t length,
const struct plot_font_style *fstyle)
/**
* Plots a path.
*
* Path plot consisting of cubic Bezier curves. Line and fill colour is
* controlled by the plot style.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
* \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
static nserror
nsgtk_plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
float width,
const float transform[6])
{
return nsfont_paint(x, y, text, length, fstyle);
unsigned int i;
cairo_matrix_t old_ctm, n_ctm;
if (n == 0)
return NSERROR_OK;
if (p[0] != PLOTTER_PATH_MOVE) {
LOG("Path does not start with move");
return NSERROR_INVALID;
}
/* Save CTM */
cairo_get_matrix(current_cr, &old_ctm);
/* Set up line style and width */
cairo_set_line_width(current_cr, 1);
nsgtk_set_solid();
/* Load new CTM */
n_ctm.xx = transform[0];
n_ctm.yx = transform[1];
n_ctm.xy = transform[2];
n_ctm.yy = transform[3];
n_ctm.x0 = transform[4];
n_ctm.y0 = transform[5];
cairo_set_matrix(current_cr, &n_ctm);
/* Construct path */
for (i = 0; i < n; ) {
if (p[i] == PLOTTER_PATH_MOVE) {
cairo_move_to(current_cr, p[i+1], p[i+2]);
i += 3;
} else if (p[i] == PLOTTER_PATH_CLOSE) {
cairo_close_path(current_cr);
i++;
} else if (p[i] == PLOTTER_PATH_LINE) {
cairo_line_to(current_cr, p[i+1], p[i+2]);
i += 3;
} else if (p[i] == PLOTTER_PATH_BEZIER) {
cairo_curve_to(current_cr, p[i+1], p[i+2],
p[i+3], p[i+4],
p[i+5], p[i+6]);
i += 7;
} else {
LOG("bad path command %f", p[i]);
/* Reset matrix for safety */
cairo_set_matrix(current_cr, &old_ctm);
return NSERROR_INVALID;
}
}
/* Restore original CTM */
cairo_set_matrix(current_cr, &old_ctm);
/* Now draw path */
if (pstyle->fill_colour != NS_TRANSPARENT) {
nsgtk_set_colour(pstyle->fill_colour);
if (pstyle->stroke_colour != NS_TRANSPARENT) {
/* Fill & Stroke */
cairo_fill_preserve(current_cr);
nsgtk_set_colour(pstyle->stroke_colour);
cairo_stroke(current_cr);
} else {
/* Fill only */
cairo_fill(current_cr);
}
} else if (pstyle->stroke_colour != NS_TRANSPARENT) {
/* Stroke only */
nsgtk_set_colour(pstyle->stroke_colour);
cairo_stroke(current_cr);
}
return NSERROR_OK;
}
static bool nsgtk_plot_pixbuf(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg)
/**
* plot a pixbuf
*/
static nserror
nsgtk_plot_pixbuf(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg)
{
int x0, y0, x1, y1;
int dsrcx, dsrcy, dwidth, dheight;
@ -289,13 +490,13 @@ static bool nsgtk_plot_pixbuf(int x, int y, int width, int height,
/* Bail early if we can */
if (width == 0 || height == 0)
/* Nothing to plot */
return true;
return NSERROR_OK;
if ((x > (cliprect.x + cliprect.width)) ||
((x + width) < cliprect.x) ||
(y > (cliprect.y + cliprect.height)) ||
((y + height) < cliprect.y)) {
/* Image completely outside clip region */
return true;
return NSERROR_OK;
}
/* Get clip rectangle / image rectangle edge differences */
@ -332,7 +533,7 @@ static bool nsgtk_plot_pixbuf(int x, int y, int width, int height,
if (dwidth == 0 || dheight == 0)
/* Nothing to plot */
return true;
return NSERROR_OK;
bmwidth = cairo_image_surface_get_width(bmsurface);
bmheight = cairo_image_surface_get_height(bmsurface);
@ -388,12 +589,42 @@ static bool nsgtk_plot_pixbuf(int x, int y, int width, int height,
}
return true;
return NSERROR_OK;
}
static bool nsgtk_plot_bitmap(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg,
bitmap_flags_t flags)
/**
* Plot a bitmap
*
* Tiled plot of a bitmap image. (x,y) gives the top left
* coordinate of an explicitly placed tile. From this tile the
* image can repeat in all four directions -- up, down, left
* and right -- to the extents given by the current clip
* rectangle.
*
* The bitmap_flags say whether to tile in the x and y
* directions. If not tiling in x or y directions, the single
* image is plotted. The width and height give the dimensions
* the image is to be scaled to.
*
* \param ctx The current redraw context.
* \param bitmap The bitmap to plot
* \param x The x coordinate to plot the bitmap
* \param y The y coordiante to plot the bitmap
* \param width The width of area to plot the bitmap into
* \param height The height of area to plot the bitmap into
* \param bg the background colour to alpha blend into
* \param flags the flags controlling the type of plot operation
* \return NSERROR_OK on success else error code.
*/
static nserror
nsgtk_plot_bitmap(const struct redraw_context *ctx,
struct bitmap *bitmap,
int x, int y,
int width,
int height,
colour bg,
bitmap_flags_t flags)
{
int doneheight = 0, donewidth = 0;
bool repeat_x = (flags & BITMAPF_REPEAT_X);
@ -402,7 +633,7 @@ static bool nsgtk_plot_bitmap(int x, int y, int width, int height,
/* Bail early if we can */
if (width == 0 || height == 0)
/* Nothing to plot */
return true;
return NSERROR_OK;
if (!(repeat_x || repeat_y)) {
/* Not repeating at all, so just pass it on */
@ -435,90 +666,33 @@ static bool nsgtk_plot_bitmap(int x, int y, int width, int height,
break;
}
return true;
return NSERROR_OK;
}
static bool nsgtk_plot_path(const float *p, unsigned int n, colour fill, float width,
colour c, const float transform[6])
/**
* Text plotting.
*
* \param ctx The current redraw context.
* \param fstyle plot style for this text
* \param x x coordinate
* \param y y coordinate
* \param text UTF-8 string to plot
* \param length length of string, in bytes
* \return NSERROR_OK on success else error code.
*/
static nserror
nsgtk_plot_text(const struct redraw_context *ctx,
const struct plot_font_style *fstyle,
int x,
int y,
const char *text,
size_t length)
{
unsigned int i;
cairo_matrix_t old_ctm, n_ctm;
if (n == 0)
return true;
if (p[0] != PLOTTER_PATH_MOVE) {
LOG("Path does not start with move");
return false;
}
/* Save CTM */
cairo_get_matrix(current_cr, &old_ctm);
/* Set up line style and width */
cairo_set_line_width(current_cr, 1);
nsgtk_set_solid();
/* Load new CTM */
n_ctm.xx = transform[0];
n_ctm.yx = transform[1];
n_ctm.xy = transform[2];
n_ctm.yy = transform[3];
n_ctm.x0 = transform[4];
n_ctm.y0 = transform[5];
cairo_set_matrix(current_cr, &n_ctm);
/* Construct path */
for (i = 0; i < n; ) {
if (p[i] == PLOTTER_PATH_MOVE) {
cairo_move_to(current_cr, p[i+1], p[i+2]);
i += 3;
} else if (p[i] == PLOTTER_PATH_CLOSE) {
cairo_close_path(current_cr);
i++;
} else if (p[i] == PLOTTER_PATH_LINE) {
cairo_line_to(current_cr, p[i+1], p[i+2]);
i += 3;
} else if (p[i] == PLOTTER_PATH_BEZIER) {
cairo_curve_to(current_cr, p[i+1], p[i+2],
p[i+3], p[i+4],
p[i+5], p[i+6]);
i += 7;
} else {
LOG("bad path command %f", p[i]);
/* Reset matrix for safety */
cairo_set_matrix(current_cr, &old_ctm);
return false;
}
}
/* Restore original CTM */
cairo_set_matrix(current_cr, &old_ctm);
/* Now draw path */
if (fill != NS_TRANSPARENT) {
nsgtk_set_colour(fill);
if (c != NS_TRANSPARENT) {
/* Fill & Stroke */
cairo_fill_preserve(current_cr);
nsgtk_set_colour(c);
cairo_stroke(current_cr);
} else {
/* Fill only */
cairo_fill(current_cr);
}
} else if (c != NS_TRANSPARENT) {
/* Stroke only */
nsgtk_set_colour(c);
cairo_stroke(current_cr);
}
return true;
return nsfont_paint(x, y, text, length, fstyle);
}
/** GTK plotter table */
const struct plotter_table nsgtk_plotters = {
.clip = nsgtk_plot_clip,
@ -532,6 +706,3 @@ const struct plotter_table nsgtk_plotters = {
.text = nsgtk_plot_text,
.option_knockout = true
};

View File

@ -17,8 +17,10 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* GTK printing (implementation).
/**
* \file
* GTK printing implementation.
* All the functions and structures necessary for printing( signal handlers,
* plotters, printer) are here.
* Most of the plotters have been copied from the gtk_plotters.c file.
@ -71,7 +73,7 @@ static inline void nsgtk_print_set_colour(colour c)
static bool gtk_print_font_paint(int x, int y,
static nserror gtk_print_font_paint(int x, int y,
const char *string, size_t length,
const plot_font_style_t *fstyle)
{
@ -81,7 +83,7 @@ static bool gtk_print_font_paint(int x, int y,
PangoLayoutLine *line;
if (length == 0)
return true;
return NSERROR_OK;
desc = nsfont_style_to_description(fstyle);
size = (gint) ((double) pango_font_description_get_size(desc) *
@ -106,7 +108,7 @@ static bool gtk_print_font_paint(int x, int y,
g_object_unref(layout);
pango_font_description_free(desc);
return true;
return NSERROR_OK;
}
@ -131,10 +133,20 @@ static inline void nsgtk_print_set_dashed(void)
cairo_set_dash(gtk_print_current_cr, cdashes, 1, 0);
}
/** Set clipping area for subsequent plot operations. */
static bool nsgtk_print_plot_clip(const struct rect *clip)
/**
* \brief Sets a clip rectangle for subsequent plot operations.
*
* \param ctx The current redraw context.
* \param clip The rectangle to limit all subsequent plot
* operations within.
* \return NSERROR_OK on success else error code.
*/
static nserror
nsgtk_print_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
{
LOG("Clipping. x0: %i ;\t y0: %i ;\t x1: %i ;\t y1: %i", clip->x0, clip->y0, clip->x1, clip->y1);
LOG("Clipping. x0: %i ;\t y0: %i ;\t x1: %i ;\t y1: %i",
clip->x0, clip->y0, clip->x1, clip->y1);
/* Normalize cllipping area - to prevent overflows.
* See comment in pdf_plot_fill. */
@ -153,10 +165,24 @@ static bool nsgtk_print_plot_clip(const struct rect *clip)
cliprect.width = clip_x1 - clip_x0;
cliprect.height = clip_y1 - clip_y0;
return true;
return NSERROR_OK;
}
static bool nsgtk_print_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style)
/**
* Plots an arc
*
* plot an arc segment around (x,y), anticlockwise from angle1
* to angle2. Angles are measured anticlockwise from
* horizontal, in degrees.
*
* \param ctx The current redraw context.
* \return NSERROR_OK on success else error code.
*/
static nserror
nsgtk_print_plot_arc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius, int angle1, int angle2)
{
nsgtk_print_set_colour(style->fill_colour);
nsgtk_print_set_solid();
@ -167,10 +193,23 @@ static bool nsgtk_print_plot_arc(int x, int y, int radius, int angle1, int angle
(angle2 + 90) * (M_PI / 180));
cairo_stroke(gtk_print_current_cr);
return true;
return NSERROR_OK;
}
static bool nsgtk_print_plot_disc(int x, int y, int radius, const plot_style_t *style)
/**
* Plots a circle
*
* Plot a circle centered on (x,y), which is optionally filled.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the circle plot.
* \return NSERROR_OK on success else error code.
*/
static nserror
nsgtk_print_plot_disc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius)
{
if (style->fill_type != PLOT_OP_TYPE_NONE) {
nsgtk_print_set_colour(style->fill_colour);
@ -208,10 +247,25 @@ static bool nsgtk_print_plot_disc(int x, int y, int radius, const plot_style_t *
cairo_stroke(gtk_print_current_cr);
}
return true;
return NSERROR_OK;
}
static bool nsgtk_print_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
/**
* Plots a line
*
* plot a line from (x0,y0) to (x1,y1). Coordinates are at
* centre of line width/thickness.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the line plot.
* \param line A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
static nserror
nsgtk_print_plot_line(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *line)
{
nsgtk_print_set_colour(style->stroke_colour);
@ -235,16 +289,35 @@ static bool nsgtk_print_plot_line(int x0, int y0, int x1, int y1, const plot_sty
else
cairo_set_line_width(gtk_print_current_cr, style->stroke_width);
cairo_move_to(gtk_print_current_cr, x0 + 0.5, y0 + 0.5);
cairo_line_to(gtk_print_current_cr, x1 + 0.5, y1 + 0.5);
cairo_move_to(gtk_print_current_cr, line->x0 + 0.5, line->y0 + 0.5);
cairo_line_to(gtk_print_current_cr, line->x1 + 0.5, line->y1 + 0.5);
cairo_stroke(gtk_print_current_cr);
return true;
return NSERROR_OK;
}
static bool nsgtk_print_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
/**
* Plots a rectangle.
*
* The rectangle can be filled an outline or both controlled
* by the plot style The line can be solid, dotted or
* dashed. Top left corner at (x0,y0) and rectangle has given
* width and height.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the rectangle plot.
* \param rect A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
static nserror
nsgtk_print_plot_rectangle(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *rect)
{
LOG("x0: %i ;\t y0: %i ;\t x1: %i ;\t y1: %i", x0, y0, x1, y1);
int x0,y0,x1,y1;
LOG("x0: %i ;\t y0: %i ;\t x1: %i ;\t y1: %i",
rect->x0, rect->y0, rect->x1, rect->y1);
if (style->fill_type != PLOT_OP_TYPE_NONE) {
@ -253,13 +326,15 @@ static bool nsgtk_print_plot_rectangle(int x0, int y0, int x1, int y1, const plo
/* Normalize boundaries of the area - to prevent overflows.
* See comment in pdf_plot_fill. */
x0 = min(max(x0, 0), settings->page_width);
y0 = min(max(y0, 0), settings->page_height);
x1 = min(max(x1, 0), settings->page_width);
y1 = min(max(y1, 0), settings->page_height);
x0 = min(max(rect->x0, 0), settings->page_width);
y0 = min(max(rect->y0, 0), settings->page_height);
x1 = min(max(rect->x1, 0), settings->page_width);
y1 = min(max(rect->y1, 0), settings->page_height);
cairo_set_line_width(gtk_print_current_cr, 0);
cairo_rectangle(gtk_print_current_cr, x0, y0, x1 - x0, y1 - y0);
cairo_rectangle(gtk_print_current_cr,
x0, y0,
x1 - x0, y1 - y0);
cairo_fill(gtk_print_current_cr);
cairo_stroke(gtk_print_current_cr);
}
@ -291,10 +366,15 @@ static bool nsgtk_print_plot_rectangle(int x0, int y0, int x1, int y1, const plo
cairo_stroke(gtk_print_current_cr);
}
return true;
return NSERROR_OK;
}
static bool nsgtk_print_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
static nserror
nsgtk_print_plot_polygon(const struct redraw_context *ctx,
const plot_style_t *style,
const int *p,
unsigned int n)
{
unsigned int i;
@ -316,18 +396,37 @@ static bool nsgtk_print_plot_polygon(const int *p, unsigned int n, const plot_st
cairo_fill(gtk_print_current_cr);
cairo_stroke(gtk_print_current_cr);
return true;
return NSERROR_OK;
}
static bool nsgtk_print_plot_path(const float *p, unsigned int n, colour fill,
float width, colour c, const float transform[6])
/**
* Plots a path.
*
* Path plot consisting of cubic Bezier curves. Line and fill colour is
* controlled by the plot style.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
* \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
static nserror
nsgtk_print_plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
float width,
const float transform[6])
{
/* Only the internal SVG renderer uses this plot call currently,
* and the GTK version uses librsvg. Thus, we ignore this complexity,
* and just return true obliviously. */
return true;
return NSERROR_OK;
}
@ -445,9 +544,30 @@ static bool nsgtk_print_plot_pixbuf(int x, int y, int width, int height,
}
static bool nsgtk_print_plot_bitmap(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg,
bitmap_flags_t flags)
/**
* Plot a bitmap
*
* Tiled plot of a bitmap image. (x,y) gives the top left
* coordinate of an explicitly placed tile. From this tile the
* image can repeat in all four directions -- up, down, left
* and right -- to the extents given by the current clip
* rectangle.
*
* The bitmap_flags say whether to tile in the x and y
* directions. If not tiling in x or y directions, the single
* image is plotted. The width and height give the dimensions
* the image is to be scaled to.
*
* \param ctx The current redraw context.
* \return NSERROR_OK on success else error code.
*/
static nserror
nsgtk_print_plot_bitmap(const struct redraw_context *ctx,
struct bitmap *bitmap,
int x, int y,
int width, int height,
colour bg,
bitmap_flags_t flags)
{
int doneheight = 0, donewidth = 0;
bool repeat_x = (flags & BITMAPF_REPEAT_X);
@ -495,12 +615,19 @@ static bool nsgtk_print_plot_bitmap(int x, int y, int width, int height,
return true;
}
static bool nsgtk_print_plot_text(int x, int y, const char *text, size_t length,
const plot_font_style_t *fstyle)
static nserror
nsgtk_print_plot_text(const struct redraw_context *ctx,
const struct plot_font_style *fstyle,
int x,
int y,
const char *text,
size_t length)
{
return gtk_print_font_paint(x, y, text, length, fstyle);
}
/** GTK print plotter table */
static const struct plotter_table nsgtk_print_plotters = {
.clip = nsgtk_print_plot_clip,

View File

@ -1706,7 +1706,7 @@ nsgtk_history_draw_event(GtkWidget *widget, GdkEventExpose *event, gpointer g)
clip.y0 = event->area.y;
clip.x1 = event->area.x + event->area.width;
clip.y1 = event->area.y + event->area.height;
ctx.plot->clip(&clip);
ctx.plot->clip(&ctx, &clip);
browser_window_history_redraw(bw, &ctx);

View File

@ -19,82 +19,250 @@
#include <stdio.h>
#include "utils/utils.h"
#include "utils/errors.h"
#include "netsurf/plotters.h"
static bool
monkey_plot_disc(int x, int y, int radius, const plot_style_t *style)
/**
* \brief Sets a clip rectangle for subsequent plot operations.
*
* \param ctx The current redraw context.
* \param clip The rectangle to limit all subsequent plot
* operations within.
* \return NSERROR_OK on success else error code.
*/
static nserror
monkey_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
{
return true;
}
static bool
monkey_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style)
{
return true;
}
static bool
monkey_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
{
return true;
}
static bool
monkey_plot_text(int x, int y, const char *text, size_t length,
const plot_font_style_t *fstyle)
{
fprintf(stdout, "PLOT TEXT X %d Y %d STR %*s\n", x, y, (int)length, text);
return true;
}
static bool
monkey_plot_bitmap(int x, int y,
int width, int height,
struct bitmap *bitmap, colour bg,
bitmap_flags_t flags)
{
fprintf(stdout, "PLOT BITMAP X %d Y %d WIDTH %d HEIGHT %d\n",
x, y, width, height);
return true;
}
static bool
monkey_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
{
fprintf(stdout, "PLOT RECT X0 %d Y0 %d X1 %d Y1 %d\n",
x0, y0, x1, y1);
return true;
}
static bool
monkey_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
{
fprintf(stdout, "PLOT LINE X0 %d Y0 %d X1 %d Y1 %d\n",
x0, y0, x1, y1);
return true;
}
static bool
monkey_plot_path(const float *p,
unsigned int n,
colour fill,
float width,
colour c,
const float transform[6])
{
return true;
}
static bool
monkey_plot_clip(const struct rect *clip)
{
fprintf(stdout, "PLOT CLIP X0 %d Y0 %d X1 %d Y1 %d\n",
fprintf(stdout,
"PLOT CLIP X0 %d Y0 %d X1 %d Y1 %d\n",
clip->x0, clip->y0, clip->x1, clip->y1);
return true;
return NSERROR_OK;
}
/**
* Plots an arc
*
* plot an arc segment around (x,y), anticlockwise from angle1
* to angle2. Angles are measured anticlockwise from
* horizontal, in degrees.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the arc plot.
* \param x The x coordinate of the arc.
* \param y The y coordinate of the arc.
* \param radius The radius of the arc.
* \param angle1 The start angle of the arc.
* \param angle2 The finish angle of the arc.
* \return NSERROR_OK on success else error code.
*/
static nserror
monkey_plot_arc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius, int angle1, int angle2)
{
fprintf(stdout,
"PLOT ARC X %d Y %d RADIUS %d ANGLE1 %d ANGLE2 %d\n",
x, y, radius, angle1, angle2);
return NSERROR_OK;
}
/**
* Plots a circle
*
* Plot a circle centered on (x,y), which is optionally filled.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the circle plot.
* \param x x coordinate of circle centre.
* \param y y coordinate of circle centre.
* \param radius circle radius.
* \return NSERROR_OK on success else error code.
*/
static nserror
monkey_plot_disc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius)
{
fprintf(stdout,
"PLOT DISC X %d Y %d RADIUS %d\n",
x, y, radius);
return NSERROR_OK;
}
/**
* Plots a line
*
* plot a line from (x0,y0) to (x1,y1). Coordinates are at
* centre of line width/thickness.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the line plot.
* \param line A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
static nserror
monkey_plot_line(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *line)
{
fprintf(stdout,
"PLOT LINE X0 %d Y0 %d X1 %d Y1 %d\n",
line->x0, line->y0, line->x1, line->y1);
return NSERROR_OK;
}
/**
* Plots a rectangle.
*
* The rectangle can be filled an outline or both controlled
* by the plot style The line can be solid, dotted or
* dashed. Top left corner at (x0,y0) and rectangle has given
* width and height.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the rectangle plot.
* \param rect A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
static nserror
monkey_plot_rectangle(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *rect)
{
fprintf(stdout,
"PLOT RECT X0 %d Y0 %d X1 %d Y1 %d\n",
rect->x0, rect->y0, rect->x1, rect->y1);
return NSERROR_OK;
}
/**
* Plot a polygon
*
* Plots a filled polygon with straight lines between
* points. The lines around the edge of the ploygon are not
* plotted. The polygon is filled with the non-zero winding
* rule.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the polygon plot.
* \param p verticies of polygon
* \param n number of verticies.
* \return NSERROR_OK on success else error code.
*/
static nserror
monkey_plot_polygon(const struct redraw_context *ctx,
const plot_style_t *style,
const int *p,
unsigned int n)
{
fprintf(stdout,
"PLOT POLYGON VERTICIES %d\n",
n);
return NSERROR_OK;
}
/**
* Plots a path.
*
* Path plot consisting of cubic Bezier curves. Line and fill colour is
* controlled by the plot style.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
* \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
static nserror
monkey_plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
float width,
const float transform[6])
{
fprintf(stdout,
"PLOT PATH VERTICIES %d WIDTH %f\n",
n, width);
return NSERROR_OK;
}
/**
* Plot a bitmap
*
* Tiled plot of a bitmap image. (x,y) gives the top left
* coordinate of an explicitly placed tile. From this tile the
* image can repeat in all four directions -- up, down, left
* and right -- to the extents given by the current clip
* rectangle.
*
* The bitmap_flags say whether to tile in the x and y
* directions. If not tiling in x or y directions, the single
* image is plotted. The width and height give the dimensions
* the image is to be scaled to.
*
* \param ctx The current redraw context.
* \param bitmap The bitmap to plot
* \param x The x coordinate to plot the bitmap
* \param y The y coordiante to plot the bitmap
* \param width The width of area to plot the bitmap into
* \param height The height of area to plot the bitmap into
* \param bg the background colour to alpha blend into
* \param flags the flags controlling the type of plot operation
* \return NSERROR_OK on success else error code.
*/
static nserror
monkey_plot_bitmap(const struct redraw_context *ctx,
struct bitmap *bitmap,
int x, int y,
int width,
int height,
colour bg,
bitmap_flags_t flags)
{
fprintf(stdout,
"PLOT BITMAP X %d Y %d WIDTH %d HEIGHT %d\n",
x, y, width, height);
return NSERROR_OK;
}
/**
* Text plotting.
*
* \param ctx The current redraw context.
* \param fstyle plot style for this text
* \param x x coordinate
* \param y y coordinate
* \param text UTF-8 string to plot
* \param length length of string, in bytes
* \return NSERROR_OK on success else error code.
*/
static nserror
monkey_plot_text(const struct redraw_context *ctx,
const struct plot_font_style *fstyle,
int x,
int y,
const char *text,
size_t length)
{
fprintf(stdout,
"PLOT TEXT X %d Y %d STR %*s\n",
x, y, (int)length, text);
return NSERROR_OK;
}
/** monkey plotter operations table */
static const struct plotter_table plotters = {
.clip = monkey_plot_clip,
.arc = monkey_plot_arc,

View File

@ -317,7 +317,7 @@ bool artworks_redraw(struct content *c, struct content_redraw_data *data,
int clip_x1 = clip->x1;
int clip_y1 = clip->y1;
if (ctx->plot->flush && !ctx->plot->flush())
if (ctx->plot->flush && (ctx->plot->flush(ctx) != NSERROR_OK))
return false;
/* pick up render addresses again in case they've changed

View File

@ -184,7 +184,7 @@ bool draw_redraw(struct content *c, struct content_redraw_data *data,
const void *src_data;
os_error *error;
if (ctx->plot->flush && !ctx->plot->flush())
if (ctx->plot->flush && (ctx->plot->flush(ctx) != NSERROR_OK))
return false;
if (!c->width || !c->height)

View File

@ -180,7 +180,7 @@ bool sprite_redraw(struct content *c, struct content_redraw_data *data,
{
sprite_content *sprite = (sprite_content *) c;
if (ctx->plot->flush && !ctx->plot->flush())
if (ctx->plot->flush && (ctx->plot->flush(ctx) != NSERROR_OK))
return false;
return image_redraw(sprite->data,

View File

@ -30,9 +30,9 @@
#include "oslib/wimp.h"
#include "oslib/wimpspriteop.h"
#include "netsurf/plotters.h"
#include "utils/log.h"
#include "utils/utils.h"
#include "netsurf/plotters.h"
#include "riscos/gui.h"
#include "riscos/tinct.h"
@ -482,6 +482,11 @@ void ro_gui_progress_bar_redraw_window(wimp_draw *redraw,
osbool more = true;
struct rect clip;
int progress_ymid;
struct redraw_context ctx = {
.interactive = true,
.background_images = true,
.plot = &ro_plotters
};
/* initialise the plotters */
ro_plot_origin_x = 0;
@ -513,16 +518,16 @@ void ro_gui_progress_bar_redraw_window(wimp_draw *redraw,
redraw->box.y0 + pb->visible.y0) >> 1;
if ((clip.x0 < clip.x1) && (clip.y0 < clip.y1)) {
if (progress_icon) {
ro_plotters.clip(&clip);
ctx.plot->clip(&ctx, &clip);
_swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
progress_icon,
redraw->box.x0 - pb->offset,
progress_ymid - progress_height,
tinct_FILL_HORIZONTALLY);
} else {
ro_plotters.rectangle(clip.x0, clip.y0,
clip.x1, clip.y1,
plot_style_fill_red);
ctx.plot->rectangle(&ctx,
plot_style_fill_red,
&clip);
}
}
}

View File

@ -28,9 +28,10 @@
#include "oslib/os.h"
#include "oslib/wimp.h"
#include "oslib/wimpspriteop.h"
#include "netsurf/plotters.h"
#include "utils/log.h"
#include "utils/utils.h"
#include "netsurf/plotters.h"
#include "riscos/gui.h"
#include "riscos/wimp.h"
@ -436,6 +437,12 @@ void ro_gui_status_bar_redraw(wimp_draw *redraw)
os_error *error;
osbool more;
rufl_code code;
struct redraw_context ctx = {
.interactive = true,
.background_images = true,
.plot = &ro_plotters
};
struct rect rect;
sb = (struct status_bar *)ro_gui_wimp_event_get_user_data(redraw->w);
assert(sb);
@ -467,18 +474,22 @@ void ro_gui_status_bar_redraw(wimp_draw *redraw)
rufl_BLEND_FONT);
if (code != rufl_OK) {
if (code == rufl_FONT_MANAGER_ERROR)
LOG("rufl_FONT_MANAGER_ERROR: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess);
LOG("rufl_FONT_MANAGER_ERROR: 0x%x: %s",
rufl_fm_error->errnum, rufl_fm_error->errmess);
else
LOG("rufl_paint: 0x%x", code);
}
}
rect.x0 = (redraw->box.x0 + sb->width - WIDGET_WIDTH - 2) >> 1;
rect.y0 = -redraw->box.y0 >> 1;
rect.x1 = (redraw->box.x0 + sb->width - WIDGET_WIDTH) >> 1;
rect.y1 = -redraw->box.y1 >> 1;
/* separate the widget from the text with a line */
ro_plotters.rectangle((redraw->box.x0 + sb->width - WIDGET_WIDTH - 2) >> 1,
-redraw->box.y0 >> 1,
(redraw->box.x0 + sb->width - WIDGET_WIDTH) >> 1,
-redraw->box.y1 >> 1,
plot_style_fill_black);
ctx.plot->rectangle(&ctx,
plot_style_fill_black,
&rect);
error = xwimp_get_rectangle(redraw, &more);
if (error) {

View File

@ -16,8 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* Target independent plotting (RISC OS screen implementation).
/**
* \file
* RISC OS screen plotter implementation.
*/
#include <stdbool.h>
@ -35,38 +36,6 @@
#include "riscos/font.h"
#include "riscos/oslib_pre7.h"
static bool ro_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style);
static bool ro_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style);
static bool ro_plot_draw_path(const draw_path * const path, int width,
colour c, bool dotted, bool dashed);
static bool ro_plot_polygon(const int *p, unsigned int n, const plot_style_t *style);
static bool ro_plot_path(const float *p, unsigned int n, colour fill, float width,
colour c, const float transform[6]);
static bool ro_plot_clip(const struct rect *clip);
static bool ro_plot_text(int x, int y, const char *text, size_t length,
const plot_font_style_t *fstyle);
static bool ro_plot_disc(int x, int y, int radius, const plot_style_t *style);
static bool ro_plot_arc(int x, int y, int radius, int angle1, int angle2,
const plot_style_t *style);
static bool ro_plot_bitmap(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg,
bitmap_flags_t flags);
struct plotter_table plot;
const struct plotter_table ro_plotters = {
.rectangle = ro_plot_rectangle,
.line = ro_plot_line,
.polygon = ro_plot_polygon,
.clip = ro_plot_clip,
.text = ro_plot_text,
.disc = ro_plot_disc,
.arc = ro_plot_arc,
.bitmap = ro_plot_bitmap,
.path = ro_plot_path,
.option_knockout = true,
};
int ro_plot_origin_x = 0;
int ro_plot_origin_y = 0;
@ -74,108 +43,23 @@ int ro_plot_origin_y = 0;
/** One version of the A9home OS is incapable of drawing patterned lines */
bool ro_plot_patterned_lines = true;
bool ro_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
/**
* plot a path on RISC OS
*/
static nserror
ro_plot_draw_path(const draw_path * const path,
int width,
colour c,
bool dotted,
bool dashed)
{
if (style->fill_type != PLOT_OP_TYPE_NONE) {
os_error *error;
error = xcolourtrans_set_gcol(style->fill_colour << 8,
colourtrans_USE_ECFS_GCOL,
os_ACTION_OVERWRITE, 0, 0);
if (error) {
LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
return false;
}
error = xos_plot(os_MOVE_TO,
ro_plot_origin_x + x0 * 2,
ro_plot_origin_y - y0 * 2 - 1);
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return false;
}
error = xos_plot(os_PLOT_RECTANGLE | os_PLOT_TO,
ro_plot_origin_x + x1 * 2 - 1,
ro_plot_origin_y - y1 * 2);
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return false;
}
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
bool dotted = false;
bool dashed = false;
const int path[] = { draw_MOVE_TO,
(ro_plot_origin_x + x0 * 2) * 256,
(ro_plot_origin_y - y0 * 2 - 1) * 256,
draw_LINE_TO,
(ro_plot_origin_x + (x1) * 2) * 256,
(ro_plot_origin_y - y0 * 2 - 1) * 256,
draw_LINE_TO,
(ro_plot_origin_x + (x1) * 2) * 256,
(ro_plot_origin_y - (y1) * 2 - 1) * 256,
draw_LINE_TO,
(ro_plot_origin_x + x0 * 2) * 256,
(ro_plot_origin_y - (y1) * 2 - 1) * 256,
draw_CLOSE_LINE,
(ro_plot_origin_x + x0 * 2) * 256,
(ro_plot_origin_y - y0 * 2 - 1) * 256,
draw_END_PATH };
if (style->stroke_type == PLOT_OP_TYPE_DOT)
dotted = true;
if (style->stroke_type == PLOT_OP_TYPE_DASH)
dashed = true;
ro_plot_draw_path((const draw_path *)path,
style->stroke_width,
style->stroke_colour,
dotted, dashed);
}
return true;
}
bool ro_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
{
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
const int path[] = { draw_MOVE_TO,
(ro_plot_origin_x + x0 * 2) * 256,
(ro_plot_origin_y - y0 * 2 - 1) * 256,
draw_LINE_TO,
(ro_plot_origin_x + x1 * 2) * 256,
(ro_plot_origin_y - y1 * 2 - 1) * 256,
draw_END_PATH };
bool dotted = false;
bool dashed = false;
if (style->stroke_type == PLOT_OP_TYPE_DOT)
dotted = true;
if (style->stroke_type == PLOT_OP_TYPE_DASH)
dashed = true;
return ro_plot_draw_path((const draw_path *)path,
style->stroke_width,
style->stroke_colour,
dotted, dashed);
}
return true;
}
bool ro_plot_draw_path(const draw_path * const path, int width,
colour c, bool dotted, bool dashed)
{
static const draw_line_style line_style = { draw_JOIN_MITRED,
draw_CAP_BUTT, draw_CAP_BUTT, 0, 0x7fffffff,
0, 0, 0, 0 };
static const draw_line_style line_style = {
draw_JOIN_MITRED,
draw_CAP_BUTT,
draw_CAP_BUTT,
0, 0x7fffffff,
0, 0, 0, 0
};
draw_dash_pattern dash = { 0, 1, { 512 } };
const draw_dash_pattern *dash_pattern = 0;
os_error *error;
@ -195,22 +79,351 @@ bool ro_plot_draw_path(const draw_path * const path, int width,
error = xcolourtrans_set_gcol(c << 8, 0, os_ACTION_OVERWRITE, 0, 0);
if (error) {
LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
return false;
LOG("xcolourtrans_set_gcol: 0x%x: %s",
error->errnum, error->errmess);
return NSERROR_INVALID;
}
error = xdraw_stroke(path, 0, 0, 0, width * 2 * 256,
&line_style, dash_pattern);
if (error) {
LOG("xdraw_stroke: 0x%x: %s", error->errnum, error->errmess);
return false;
return NSERROR_INVALID;
}
return true;
return NSERROR_OK;
}
bool ro_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
/**
* \brief Sets a clip rectangle for subsequent plot operations.
*
* \param ctx The current redraw context.
* \param clip The rectangle to limit all subsequent plot
* operations within.
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
{
os_error *error;
char buf[12];
int clip_x0 = ro_plot_origin_x + clip->x0 * 2;
int clip_y0 = ro_plot_origin_y - clip->y0 * 2 - 1;
int clip_x1 = ro_plot_origin_x + clip->x1 * 2 - 1;
int clip_y1 = ro_plot_origin_y - clip->y1 * 2;
if (clip_x1 < clip_x0 || clip_y0 < clip_y1) {
LOG("bad clip rectangle %i %i %i %i",
clip_x0, clip_y0, clip_x1, clip_y1);
return NSERROR_BAD_SIZE;
}
buf[0] = os_VDU_SET_GRAPHICS_WINDOW;
buf[1] = clip_x0;
buf[2] = clip_x0 >> 8;
buf[3] = clip_y1;
buf[4] = clip_y1 >> 8;
buf[5] = clip_x1;
buf[6] = clip_x1 >> 8;
buf[7] = clip_y0;
buf[8] = clip_y0 >> 8;
error = xos_writen(buf, 9);
if (error) {
LOG("xos_writen: 0x%x: %s", error->errnum, error->errmess);
return NSERROR_INVALID;
}
return NSERROR_OK;
}
/**
* Plots an arc
*
* plot an arc segment around (x,y), anticlockwise from angle1
* to angle2. Angles are measured anticlockwise from
* horizontal, in degrees.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the arc plot.
* \param x The x coordinate of the arc.
* \param y The y coordinate of the arc.
* \param radius The radius of the arc.
* \param angle1 The start angle of the arc.
* \param angle2 The finish angle of the arc.
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_plot_arc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius, int angle1, int angle2)
{
os_error *error;
int sx, sy, ex, ey;
double t;
x = ro_plot_origin_x + x * 2;
y = ro_plot_origin_y - y * 2;
radius <<= 1;
error = xcolourtrans_set_gcol(style->fill_colour << 8, 0,
os_ACTION_OVERWRITE, 0, 0);
if (error) {
LOG("xcolourtrans_set_gcol: 0x%x: %s",
error->errnum, error->errmess);
return NSERROR_INVALID;
}
t = ((double)angle1 * M_PI) / 180.0;
sx = (x + (int)(radius * cos(t)));
sy = (y + (int)(radius * sin(t)));
t = ((double)angle2 * M_PI) / 180.0;
ex = (x + (int)(radius * cos(t)));
ey = (y + (int)(radius * sin(t)));
error = xos_plot(os_MOVE_TO, x, y); /* move to centre */
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return NSERROR_INVALID;
}
error = xos_plot(os_MOVE_TO, sx, sy); /* move to start */
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return NSERROR_INVALID;
}
error = xos_plot(os_PLOT_ARC | os_PLOT_TO, ex, ey); /* arc to end */
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return NSERROR_INVALID;
}
return NSERROR_OK;
}
/**
* Plots a circle
*
* Plot a circle centered on (x,y), which is optionally filled.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the circle plot.
* \param x The x coordinate of the circle.
* \param y The y coordinate of the circle.
* \param radius The radius of the circle.
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_plot_disc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius)
{
os_error *error;
if (style->fill_type != PLOT_OP_TYPE_NONE) {
error = xcolourtrans_set_gcol(style->fill_colour << 8, 0,
os_ACTION_OVERWRITE, 0, 0);
if (error) {
LOG("xcolourtrans_set_gcol: 0x%x: %s",
error->errnum, error->errmess);
return NSERROR_INVALID;
}
error = xos_plot(os_MOVE_TO,
ro_plot_origin_x + x * 2,
ro_plot_origin_y - y * 2);
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return NSERROR_INVALID;
}
error = xos_plot(os_PLOT_CIRCLE | os_PLOT_BY, radius * 2, 0);
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return NSERROR_INVALID;
}
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
error = xcolourtrans_set_gcol(style->stroke_colour << 8, 0,
os_ACTION_OVERWRITE, 0, 0);
if (error) {
LOG("xcolourtrans_set_gcol: 0x%x: %s",
error->errnum, error->errmess);
return NSERROR_INVALID;
}
error = xos_plot(os_MOVE_TO,
ro_plot_origin_x + x * 2,
ro_plot_origin_y - y * 2);
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return NSERROR_INVALID;
}
error = xos_plot(os_PLOT_CIRCLE_OUTLINE | os_PLOT_BY,
radius * 2, 0);
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return NSERROR_INVALID;
}
}
return NSERROR_OK;
}
/**
* Plots a line
*
* plot a line from (x0,y0) to (x1,y1). Coordinates are at
* centre of line width/thickness.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the line plot.
* \param line A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_plot_line(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *line)
{
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
const int path[] = {
draw_MOVE_TO,
(ro_plot_origin_x + line->x0 * 2) * 256,
(ro_plot_origin_y - line->y0 * 2 - 1) * 256,
draw_LINE_TO,
(ro_plot_origin_x + line->x1 * 2) * 256,
(ro_plot_origin_y - line->y1 * 2 - 1) * 256,
draw_END_PATH };
bool dotted = false;
bool dashed = false;
if (style->stroke_type == PLOT_OP_TYPE_DOT)
dotted = true;
if (style->stroke_type == PLOT_OP_TYPE_DASH)
dashed = true;
return ro_plot_draw_path((const draw_path *)path,
style->stroke_width,
style->stroke_colour,
dotted, dashed);
}
return NSERROR_OK;
}
/**
* Plots a rectangle.
*
* The rectangle can be filled an outline or both controlled
* by the plot style The line can be solid, dotted or
* dashed. Top left corner at (x0,y0) and rectangle has given
* width and height.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the rectangle plot.
* \param rect A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_plot_rectangle(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *rect)
{
if (style->fill_type != PLOT_OP_TYPE_NONE) {
os_error *error;
error = xcolourtrans_set_gcol(style->fill_colour << 8,
colourtrans_USE_ECFS_GCOL,
os_ACTION_OVERWRITE, 0, 0);
if (error) {
LOG("xcolourtrans_set_gcol: 0x%x: %s",
error->errnum, error->errmess);
return NSERROR_INVALID;
}
error = xos_plot(os_MOVE_TO,
ro_plot_origin_x + rect->x0 * 2,
ro_plot_origin_y - rect->y0 * 2 - 1);
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return NSERROR_INVALID;
}
error = xos_plot(os_PLOT_RECTANGLE | os_PLOT_TO,
ro_plot_origin_x + rect->x1 * 2 - 1,
ro_plot_origin_y - rect->y1 * 2);
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return NSERROR_INVALID;
}
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
bool dotted = false;
bool dashed = false;
const int path[] = {
draw_MOVE_TO,
(ro_plot_origin_x + rect->x0 * 2) * 256,
(ro_plot_origin_y - rect->y0 * 2 - 1) * 256,
draw_LINE_TO,
(ro_plot_origin_x + (rect->x1) * 2) * 256,
(ro_plot_origin_y - rect->y0 * 2 - 1) * 256,
draw_LINE_TO,
(ro_plot_origin_x + (rect->x1) * 2) * 256,
(ro_plot_origin_y - (rect->y1) * 2 - 1) * 256,
draw_LINE_TO,
(ro_plot_origin_x + rect->x0 * 2) * 256,
(ro_plot_origin_y - (rect->y1) * 2 - 1) * 256,
draw_CLOSE_LINE,
(ro_plot_origin_x + rect->x0 * 2) * 256,
(ro_plot_origin_y - rect->y0 * 2 - 1) * 256,
draw_END_PATH
};
if (style->stroke_type == PLOT_OP_TYPE_DOT)
dotted = true;
if (style->stroke_type == PLOT_OP_TYPE_DASH)
dashed = true;
ro_plot_draw_path((const draw_path *)path,
style->stroke_width,
style->stroke_colour,
dotted,
dashed);
}
return NSERROR_OK;
}
/**
* Plot a polygon
*
* Plots a filled polygon with straight lines between
* points. The lines around the edge of the ploygon are not
* plotted. The polygon is filled with the non-zero winding
* rule.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the polygon plot.
* \param p verticies of polygon
* \param n number of verticies.
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_plot_polygon(const struct redraw_context *ctx,
const plot_style_t *style,
const int *p,
unsigned int n)
{
int path[n * 3 + 2];
unsigned int i;
@ -225,34 +438,60 @@ bool ro_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
path[n * 3] = draw_END_PATH;
path[n * 3 + 1] = 0;
error = xcolourtrans_set_gcol(style->fill_colour << 8, 0, os_ACTION_OVERWRITE, 0, 0);
error = xcolourtrans_set_gcol(style->fill_colour << 8,
0, os_ACTION_OVERWRITE, 0, 0);
if (error) {
LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
return false;
LOG("xcolourtrans_set_gcol: 0x%x: %s",
error->errnum, error->errmess);
return NSERROR_INVALID;
}
error = xdraw_fill((draw_path *) path, 0, 0, 0);
if (error) {
LOG("xdraw_fill: 0x%x: %s", error->errnum, error->errmess);
return false;
return NSERROR_INVALID;
}
return true;
return NSERROR_OK;
}
bool ro_plot_path(const float *p, unsigned int n, colour fill, float width,
colour c, const float transform[6])
/**
* Plots a path.
*
* Path plot consisting of cubic Bezier curves. Line and fill colour is
* controlled by the plot style.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
* \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
float width,
const float transform[6])
{
static const draw_line_style line_style = { draw_JOIN_MITRED,
draw_CAP_BUTT, draw_CAP_BUTT, 0, 0x7fffffff,
0, 0, 0, 0 };
static const draw_line_style line_style = {
draw_JOIN_MITRED,
draw_CAP_BUTT,
draw_CAP_BUTT,
0, 0x7fffffff,
0, 0, 0, 0
};
int *path = 0;
unsigned int i;
os_trfm trfm;
os_error *error;
if (n == 0)
return true;
if (n == 0) {
return NSERROR_OK;
}
if (p[0] != PLOTTER_PATH_MOVE) {
LOG("path doesn't start with a move");
@ -303,214 +542,92 @@ bool ro_plot_path(const float *p, unsigned int n, colour fill, float width,
trfm.entries[2][0] = (ro_plot_origin_x + transform[4] * 2) * 256;
trfm.entries[2][1] = (ro_plot_origin_y - transform[5] * 2) * 256;
if (fill != NS_TRANSPARENT) {
error = xcolourtrans_set_gcol(fill << 8, 0,
if (pstyle->fill_colour != NS_TRANSPARENT) {
error = xcolourtrans_set_gcol(pstyle->fill_colour << 8, 0,
os_ACTION_OVERWRITE, 0, 0);
if (error) {
LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
LOG("xcolourtrans_set_gcol: 0x%x: %s",
error->errnum, error->errmess);
goto error;
}
error = xdraw_fill((draw_path *) path, 0, &trfm, 0);
if (error) {
LOG("xdraw_stroke: 0x%x: %s", error->errnum, error->errmess);
LOG("xdraw_stroke: 0x%x: %s",
error->errnum, error->errmess);
goto error;
}
}
if (c != NS_TRANSPARENT) {
error = xcolourtrans_set_gcol(c << 8, 0,
if (pstyle->stroke_colour != NS_TRANSPARENT) {
error = xcolourtrans_set_gcol(pstyle->stroke_colour << 8, 0,
os_ACTION_OVERWRITE, 0, 0);
if (error) {
LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
LOG("xcolourtrans_set_gcol: 0x%x: %s",
error->errnum, error->errmess);
goto error;
}
error = xdraw_stroke((draw_path *) path, 0, &trfm, 0,
width * 2 * 256, &line_style, 0);
if (error) {
LOG("xdraw_stroke: 0x%x: %s", error->errnum, error->errmess);
LOG("xdraw_stroke: 0x%x: %s",
error->errnum, error->errmess);
goto error;
}
}
free(path);
return true;
return NSERROR_OK;
error:
free(path);
return false;
return NSERROR_INVALID;
}
bool ro_plot_clip(const struct rect *clip)
{
os_error *error;
char buf[12];
int clip_x0 = ro_plot_origin_x + clip->x0 * 2;
int clip_y0 = ro_plot_origin_y - clip->y0 * 2 - 1;
int clip_x1 = ro_plot_origin_x + clip->x1 * 2 - 1;
int clip_y1 = ro_plot_origin_y - clip->y1 * 2;
if (clip_x1 < clip_x0 || clip_y0 < clip_y1) {
LOG("bad clip rectangle %i %i %i %i", clip_x0, clip_y0, clip_x1, clip_y1);
return false;
}
buf[0] = os_VDU_SET_GRAPHICS_WINDOW;
buf[1] = clip_x0;
buf[2] = clip_x0 >> 8;
buf[3] = clip_y1;
buf[4] = clip_y1 >> 8;
buf[5] = clip_x1;
buf[6] = clip_x1 >> 8;
buf[7] = clip_y0;
buf[8] = clip_y0 >> 8;
error = xos_writen(buf, 9);
if (error) {
LOG("xos_writen: 0x%x: %s", error->errnum, error->errmess);
return false;
}
return true;
}
bool ro_plot_text(int x, int y, const char *text, size_t length,
const plot_font_style_t *fstyle)
{
os_error *error;
error = xcolourtrans_set_font_colours(font_CURRENT,
fstyle->background << 8, fstyle->foreground << 8,
14, 0, 0, 0);
if (error) {
LOG("xcolourtrans_set_font_colours: 0x%x: %s", error->errnum, error->errmess);
return false;
}
return nsfont_paint(fstyle, text, length,
ro_plot_origin_x + x * 2,
ro_plot_origin_y - y * 2);
}
bool ro_plot_disc(int x, int y, int radius, const plot_style_t *style)
{
os_error *error;
if (style->fill_type != PLOT_OP_TYPE_NONE) {
error = xcolourtrans_set_gcol(style->fill_colour << 8, 0,
os_ACTION_OVERWRITE, 0, 0);
if (error) {
LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
return false;
}
error = xos_plot(os_MOVE_TO,
ro_plot_origin_x + x * 2,
ro_plot_origin_y - y * 2);
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return false;
}
error = xos_plot(os_PLOT_CIRCLE | os_PLOT_BY, radius * 2, 0);
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return false;
}
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
error = xcolourtrans_set_gcol(style->stroke_colour << 8, 0,
os_ACTION_OVERWRITE, 0, 0);
if (error) {
LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
return false;
}
error = xos_plot(os_MOVE_TO,
ro_plot_origin_x + x * 2,
ro_plot_origin_y - y * 2);
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return false;
}
error = xos_plot(os_PLOT_CIRCLE_OUTLINE | os_PLOT_BY,
radius * 2, 0);
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return false;
}
}
return true;
}
bool ro_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style)
{
os_error *error;
int sx, sy, ex, ey;
double t;
x = ro_plot_origin_x + x * 2;
y = ro_plot_origin_y - y * 2;
radius <<= 1;
error = xcolourtrans_set_gcol(style->fill_colour << 8, 0,
os_ACTION_OVERWRITE, 0, 0);
if (error) {
LOG("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess);
return false;
}
t = ((double)angle1 * M_PI) / 180.0;
sx = (x + (int)(radius * cos(t)));
sy = (y + (int)(radius * sin(t)));
t = ((double)angle2 * M_PI) / 180.0;
ex = (x + (int)(radius * cos(t)));
ey = (y + (int)(radius * sin(t)));
error = xos_plot(os_MOVE_TO, x, y); /* move to centre */
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return false;
}
error = xos_plot(os_MOVE_TO, sx, sy); /* move to start */
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return false;
}
error = xos_plot(os_PLOT_ARC | os_PLOT_TO, ex, ey); /* arc to end */
if (error) {
LOG("xos_plot: 0x%x: %s", error->errnum, error->errmess);
return false;
}
return true;
}
bool ro_plot_bitmap(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg,
bitmap_flags_t flags)
/**
* Plot a bitmap
*
* Tiled plot of a bitmap image. (x,y) gives the top left
* coordinate of an explicitly placed tile. From this tile the
* image can repeat in all four directions -- up, down, left
* and right -- to the extents given by the current clip
* rectangle.
*
* The bitmap_flags say whether to tile in the x and y
* directions. If not tiling in x or y directions, the single
* image is plotted. The width and height give the dimensions
* the image is to be scaled to.
*
* \param ctx The current redraw context.
* \param bitmap The bitmap to plot
* \param x The x coordinate to plot the bitmap
* \param y The y coordiante to plot the bitmap
* \param width The width of area to plot the bitmap into
* \param height The height of area to plot the bitmap into
* \param bg the background colour to alpha blend into
* \param flags the flags controlling the type of plot operation
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_plot_bitmap(const struct redraw_context *ctx,
struct bitmap *bitmap,
int x, int y,
int width,
int height,
colour bg,
bitmap_flags_t flags)
{
const uint8_t *buffer;
buffer = riscos_bitmap_get_buffer(bitmap);
if (!buffer) {
LOG("bitmap_get_buffer failed");
return false;
return NSERROR_INVALID;
}
return image_redraw(bitmap->sprite_area,
if (!image_redraw(bitmap->sprite_area,
ro_plot_origin_x + x * 2,
ro_plot_origin_y - y * 2,
width, height,
@ -520,5 +637,64 @@ bool ro_plot_bitmap(int x, int y, int width, int height,
flags & BITMAPF_REPEAT_X, flags & BITMAPF_REPEAT_Y,
flags & BITMAPF_REPEAT_X || flags & BITMAPF_REPEAT_Y,
riscos_bitmap_get_opaque(bitmap) ? IMAGE_PLOT_TINCT_OPAQUE :
IMAGE_PLOT_TINCT_ALPHA);
IMAGE_PLOT_TINCT_ALPHA)) {
return NSERROR_INVALID;
}
return NSERROR_OK;
}
/**
* Text plotting.
*
* \param ctx The current redraw context.
* \param fstyle plot style for this text
* \param x x coordinate
* \param y y coordinate
* \param text UTF-8 string to plot
* \param length length of string, in bytes
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_plot_text(const struct redraw_context *ctx,
const struct plot_font_style *fstyle,
int x,
int y,
const char *text,
size_t length)
{
os_error *error;
error = xcolourtrans_set_font_colours(font_CURRENT,
fstyle->background << 8, fstyle->foreground << 8,
14, 0, 0, 0);
if (error) {
LOG("xcolourtrans_set_font_colours: 0x%x: %s",
error->errnum, error->errmess);
return NSERROR_INVALID;
}
if (!nsfont_paint(fstyle, text, length,
ro_plot_origin_x + x * 2,
ro_plot_origin_y - y * 2)) {
return NSERROR_INVALID;
}
return NSERROR_OK;
}
/**
* RISC OS plotter operation table
*/
const struct plotter_table ro_plotters = {
.rectangle = ro_plot_rectangle,
.line = ro_plot_line,
.polygon = ro_plot_polygon,
.clip = ro_plot_clip,
.text = ro_plot_text,
.disc = ro_plot_disc,
.arc = ro_plot_arc,
.bitmap = ro_plot_bitmap,
.path = ro_plot_path,
.option_knockout = true,
};

View File

@ -104,39 +104,12 @@ static void print_send_printsave(struct hlcache_handle *h);
static bool print_send_printtypeknown(wimp_message *m);
static bool print_document(struct gui_window *g, const char *filename);
static const char *print_declare_fonts(struct hlcache_handle *h);
static bool print_fonts_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style);
static bool print_fonts_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style);
static bool print_fonts_plot_polygon(const int *p, unsigned int n, const plot_style_t *style);
static bool print_fonts_plot_clip(const struct rect *clip);
static bool print_fonts_plot_text(int x, int y, const char *text, size_t length,
const plot_font_style_t *fstyle);
static bool print_fonts_plot_disc(int x, int y, int radius, const plot_style_t *style);
static bool print_fonts_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style);
static bool print_fonts_plot_bitmap(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg,
bitmap_flags_t flags);
static bool print_fonts_plot_path(const float *p, unsigned int n, colour fill, float width,
colour c, const float transform[6]);
static void print_fonts_callback(void *context,
const char *font_name, unsigned int font_size,
const char *s8, unsigned short *s16, unsigned int n,
int x, int y);
/** Plotter for print_declare_fonts(). All the functions do nothing except for
* print_fonts_plot_text, which records the fonts used. */
static const struct plotter_table print_fonts_plotters = {
.rectangle = print_fonts_plot_rectangle,
.line = print_fonts_plot_line,
.polygon = print_fonts_plot_polygon,
.clip = print_fonts_plot_clip,
.text = print_fonts_plot_text,
.disc = print_fonts_plot_disc,
.arc = print_fonts_plot_arc,
.bitmap = print_fonts_plot_bitmap,
.path = print_fonts_plot_path,
.option_knockout = false,
};
/**
@ -780,6 +753,143 @@ error:
}
static nserror
print_fonts_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
{
return NSERROR_OK;
}
static nserror
print_fonts_plot_arc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius, int angle1, int angle2)
{
return NSERROR_OK;
}
static nserror
print_fonts_plot_disc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius)
{
return NSERROR_OK;
}
static nserror
print_fonts_plot_line(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *line)
{
return NSERROR_OK;
}
static nserror
print_fonts_plot_rectangle(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *rect)
{
return NSERROR_OK;
}
static nserror
print_fonts_plot_polygon(const struct redraw_context *ctx,
const plot_style_t *style,
const int *p,
unsigned int n)
{
return NSERROR_OK;
}
static nserror
print_fonts_plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
float width,
const float transform[6])
{
return NSERROR_OK;
}
static nserror
print_fonts_plot_bitmap(const struct redraw_context *ctx,
struct bitmap *bitmap,
int x, int y,
int width,
int height,
colour bg,
bitmap_flags_t flags)
{
return NSERROR_OK;
}
/**
* text plotting during RO print font listing.
*
* \param ctx The current redraw context.
* \param fstyle plot style for this text
* \param x x coordinate
* \param y y coordinate
* \param text UTF-8 string to plot
* \param length length of string, in bytes
* \return NSERROR_OK on success else error code.
*/
static nserror
print_fonts_plot_text(const struct redraw_context *ctx,
const struct plot_font_style *fstyle,
int x,
int y,
const char *text,
size_t length)
{
const char *font_family;
unsigned int font_size;
rufl_style font_style;
rufl_code code;
nsfont_read_style(fstyle, &font_family, &font_size, &font_style);
code = rufl_paint_callback(font_family, font_style, font_size,
text, length, 0, 0, print_fonts_callback, 0);
if (code != rufl_OK) {
if (code == rufl_FONT_MANAGER_ERROR) {
LOG("rufl_paint_callback: rufl_FONT_MANAGER_ERROR: ""0x%x: %s",
rufl_fm_error->errnum, rufl_fm_error->errmess);
print_fonts_error = rufl_fm_error->errmess;
} else {
LOG("rufl_paint_callback: 0x%x", code);
}
return NSERROR_INVALID;
}
if (print_fonts_error)
return NSERROR_INVALID;
return NSERROR_OK;
}
/**
* Plotter table for print_declare_fonts().
*
* All the functions do nothing except for print_fonts_plot_text,
* which records the fonts used.
*/
static const struct plotter_table print_fonts_plotters = {
.rectangle = print_fonts_plot_rectangle,
.line = print_fonts_plot_line,
.polygon = print_fonts_plot_polygon,
.clip = print_fonts_plot_clip,
.text = print_fonts_plot_text,
.disc = print_fonts_plot_disc,
.arc = print_fonts_plot_arc,
.bitmap = print_fonts_plot_bitmap,
.path = print_fonts_plot_path,
.option_knockout = false,
};
/**
* Declare fonts to the printer driver.
*
@ -850,84 +960,6 @@ end:
}
bool print_fonts_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
{
return true;
}
bool print_fonts_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
{
return true;
}
bool print_fonts_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
{
return true;
}
bool print_fonts_plot_clip(const struct rect *clip)
{
return true;
}
bool print_fonts_plot_disc(int x, int y, int radius, const plot_style_t *style)
{
return true;
}
bool print_fonts_plot_arc(int x, int y, int radius, int angle1, int angle2,
const plot_style_t *style)
{
return true;
}
bool print_fonts_plot_bitmap(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg, bitmap_flags_t flags)
{
return true;
}
bool print_fonts_plot_path(const float *p, unsigned int n, colour fill, float width,
colour c, const float transform[6])
{
return true;
}
/**
* Plotter for text plotting during font listing.
*/
bool print_fonts_plot_text(int x, int y, const char *text, size_t length,
const plot_font_style_t *fstyle)
{
const char *font_family;
unsigned int font_size;
rufl_style font_style;
rufl_code code;
nsfont_read_style(fstyle, &font_family, &font_size, &font_style);
code = rufl_paint_callback(font_family, font_style, font_size,
text, length, 0, 0, print_fonts_callback, 0);
if (code != rufl_OK) {
if (code == rufl_FONT_MANAGER_ERROR) {
LOG("rufl_paint_callback: rufl_FONT_MANAGER_ERROR: ""0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess);
print_fonts_error = rufl_fm_error->errmess;
} else {
LOG("rufl_paint_callback: 0x%x", code);
}
return false;
}
if (print_fonts_error)
return false;
return true;
}
/**
* Callback for print_fonts_plot_text().
*

View File

@ -18,7 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
/**
* \file
* Export a content as a DrawFile (implementation).
*/
@ -39,22 +40,516 @@
#include "riscos/save_draw.h"
#include "riscos/font.h"
static bool ro_save_draw_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style);
static bool ro_save_draw_line(int x0, int y0, int x1, int y1, const plot_style_t *style);
static bool ro_save_draw_polygon(const int *p, unsigned int n, const plot_style_t *style);
static bool ro_save_draw_path(const float *p, unsigned int n, colour fill,
float width, colour c, const float transform[6]);
static bool ro_save_draw_clip(const struct rect *clip);
static bool ro_save_draw_text(int x, int y, const char *text, size_t length,
const plot_font_style_t *fstyle);
static bool ro_save_draw_disc(int x, int y, int radius, const plot_style_t *style);
static bool ro_save_draw_arc(int x, int y, int radius, int angle1, int angle2,
const plot_style_t *style);
static bool ro_save_draw_bitmap(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg, bitmap_flags_t flags);
static bool ro_save_draw_group_start(const char *name);
static bool ro_save_draw_group_end(void);
static bool ro_save_draw_error(pencil_code code);
static struct pencil_diagram *ro_save_draw_diagram;
static int ro_save_draw_width;
static int ro_save_draw_height;
/**
* Report an error from pencil.
*
* \param code error code
* \return false
*/
static nserror ro_save_draw_error(pencil_code code)
{
LOG("code %i", code);
switch (code) {
case pencil_OK:
assert(0);
break;
case pencil_OUT_OF_MEMORY:
ro_warn_user("NoMemory", 0);
break;
case pencil_FONT_MANAGER_ERROR:
ro_warn_user("SaveError", rufl_fm_error->errmess);
break;
case pencil_FONT_NOT_FOUND:
case pencil_IO_ERROR:
case pencil_IO_EOF:
ro_warn_user("SaveError", "generating the DrawFile failed");
break;
}
return NSERROR_INVALID;
}
/**
* \brief Sets a clip rectangle for subsequent plot operations.
*
* \param ctx The current redraw context.
* \param clip The rectangle to limit all subsequent plot
* operations within.
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_save_draw_clip(const struct redraw_context *ctx, const struct rect *clip)
{
return NSERROR_OK;
}
/**
* Plots an arc
*
* plot an arc segment around (x,y), anticlockwise from angle1
* to angle2. Angles are measured anticlockwise from
* horizontal, in degrees.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the arc plot.
* \param x The x coordinate of the arc.
* \param y The y coordinate of the arc.
* \param radius The radius of the arc.
* \param angle1 The start angle of the arc.
* \param angle2 The finish angle of the arc.
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_save_draw_arc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius, int angle1, int angle2)
{
return NSERROR_OK;
}
/**
* Plots a circle
*
* Plot a circle centered on (x,y), which is optionally filled.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the circle plot.
* \param x The x coordinate of the circle.
* \param y The y coordinate of the circle.
* \param radius The radius of the circle.
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_save_draw_disc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius)
{
return NSERROR_OK;
}
/**
* Plots a line
*
* plot a line from (x0,y0) to (x1,y1). Coordinates are at
* centre of line width/thickness.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the line plot.
* \param line A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_save_draw_line(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *line)
{
pencil_code code;
const int path[] = {
draw_MOVE_TO, line->x0 * 2, -line->y0 * 2 - 1,
draw_LINE_TO, line->x1 * 2, -line->y1 * 2 - 1,
draw_END_PATH
};
code = pencil_path(ro_save_draw_diagram,
path,
sizeof path / sizeof path[0],
pencil_TRANSPARENT,
style->stroke_colour << 8,
style->stroke_width,
pencil_JOIN_MITRED,
pencil_CAP_BUTT,
pencil_CAP_BUTT,
0, 0, false,
pencil_SOLID);
if (code != pencil_OK)
return ro_save_draw_error(code);
return NSERROR_OK;
}
/**
* Plots a rectangle.
*
* The rectangle can be filled an outline or both controlled
* by the plot style The line can be solid, dotted or
* dashed. Top left corner at (x0,y0) and rectangle has given
* width and height.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the rectangle plot.
* \param rect A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_save_draw_rectangle(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *rect)
{
pencil_code code;
const int path[] = {
draw_MOVE_TO, rect->x0 * 2, -rect->y0 * 2 - 1,
draw_LINE_TO, rect->x1 * 2, -rect->y0 * 2 - 1,
draw_LINE_TO, rect->x1 * 2, -rect->y1 * 2 - 1,
draw_LINE_TO, rect->x0 * 2, -rect->y1 * 2 - 1,
draw_CLOSE_LINE,
draw_END_PATH
};
if (style->fill_type != PLOT_OP_TYPE_NONE) {
code = pencil_path(ro_save_draw_diagram,
path,
sizeof path / sizeof path[0],
style->fill_colour << 8,
pencil_TRANSPARENT,
0,
pencil_JOIN_MITRED,
pencil_CAP_BUTT,
pencil_CAP_BUTT,
0,
0,
false,
pencil_SOLID);
if (code != pencil_OK)
return ro_save_draw_error(code);
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
code = pencil_path(ro_save_draw_diagram,
path,
sizeof path / sizeof path[0],
pencil_TRANSPARENT,
style->stroke_colour << 8,
style->stroke_width,
pencil_JOIN_MITRED,
pencil_CAP_BUTT,
pencil_CAP_BUTT,
0,
0,
false,
pencil_SOLID);
if (code != pencil_OK)
return ro_save_draw_error(code);
}
return NSERROR_OK;
}
/**
* Plot a polygon
*
* Plots a filled polygon with straight lines between
* points. The lines around the edge of the ploygon are not
* plotted. The polygon is filled with the non-zero winding
* rule.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the polygon plot.
* \param p verticies of polygon
* \param n number of verticies.
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_save_draw_polygon(const struct redraw_context *ctx,
const plot_style_t *style,
const int *p,
unsigned int n)
{
pencil_code code;
int path[n * 3 + 1];
unsigned int i;
for (i = 0; i != n; i++) {
path[i * 3 + 0] = draw_LINE_TO;
path[i * 3 + 1] = p[i * 2 + 0] * 2;
path[i * 3 + 2] = -p[i * 2 + 1] * 2;
}
path[0] = draw_MOVE_TO;
path[n * 3] = draw_END_PATH;
code = pencil_path(ro_save_draw_diagram,
path, n * 3 + 1,
style->fill_colour << 8,
pencil_TRANSPARENT,
0,
pencil_JOIN_MITRED,
pencil_CAP_BUTT,
pencil_CAP_BUTT,
0,
0,
false,
pencil_SOLID);
if (code != pencil_OK)
return ro_save_draw_error(code);
return NSERROR_OK;
}
/**
* Plots a path.
*
* Path plot consisting of cubic Bezier curves. Line and fill colour is
* controlled by the plot style.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
* \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_save_draw_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
float width,
const float transform[6])
{
pencil_code code;
int *path;
unsigned int i;
bool empty_path = true;
if (n == 0)
return NSERROR_OK;
if (p[0] != PLOTTER_PATH_MOVE) {
LOG("path doesn't start with a move");
return NSERROR_INVALID;
}
path = malloc(sizeof *path * (n + 10));
if (!path) {
LOG("out of memory");
return NSERROR_INVALID;
}
for (i = 0; i < n; ) {
if (p[i] == PLOTTER_PATH_MOVE) {
path[i] = draw_MOVE_TO;
path[i + 1] = (transform[0] * p[i + 1] +
transform[2] * -p[i + 2] +
transform[4]) * 2;
path[i + 2] = (transform[1] * p[i + 1] +
transform[3] * -p[i + 2] +
-transform[5]) * 2;
i += 3;
} else if (p[i] == PLOTTER_PATH_CLOSE) {
path[i] = draw_CLOSE_LINE;
i++;
} else if (p[i] == PLOTTER_PATH_LINE) {
path[i] = draw_LINE_TO;
path[i + 1] = (transform[0] * p[i + 1] +
transform[2] * -p[i + 2] +
transform[4]) * 2;
path[i + 2] = (transform[1] * p[i + 1] +
transform[3] * -p[i + 2] +
-transform[5]) * 2;
i += 3;
empty_path = false;
} else if (p[i] == PLOTTER_PATH_BEZIER) {
path[i] = draw_BEZIER_TO;
path[i + 1] = (transform[0] * p[i + 1] +
transform[2] * -p[i + 2] +
transform[4]) * 2;
path[i + 2] = (transform[1] * p[i + 1] +
transform[3] * -p[i + 2] +
-transform[5]) * 2;
path[i + 3] = (transform[0] * p[i + 3] +
transform[2] * -p[i + 4] +
transform[4]) * 2;
path[i + 4] = (transform[1] * p[i + 3] +
transform[3] * -p[i + 4] +
-transform[5]) * 2;
path[i + 5] = (transform[0] * p[i + 5] +
transform[2] * -p[i + 6] +
transform[4]) * 2;
path[i + 6] = (transform[1] * p[i + 5] +
transform[3] * -p[i + 6] +
-transform[5]) * 2;
i += 7;
empty_path = false;
} else {
LOG("bad path command %f", p[i]);
free(path);
return NSERROR_INVALID;
}
}
path[i] = draw_END_PATH;
if (empty_path) {
free(path);
return NSERROR_OK;
}
code = pencil_path(ro_save_draw_diagram,
path, i + 1,
pstyle->fill_colour == NS_TRANSPARENT ?
pencil_TRANSPARENT :
pstyle->fill_colour << 8,
pstyle->stroke_colour == NS_TRANSPARENT ?
pencil_TRANSPARENT :
pstyle->stroke_colour << 8,
width, pencil_JOIN_MITRED,
pencil_CAP_BUTT,
pencil_CAP_BUTT,
0,
0,
false,
pencil_SOLID);
free(path);
if (code != pencil_OK)
return ro_save_draw_error(code);
return NSERROR_OK;
}
/**
* Plot a bitmap
*
* Tiled plot of a bitmap image. (x,y) gives the top left
* coordinate of an explicitly placed tile. From this tile the
* image can repeat in all four directions -- up, down, left
* and right -- to the extents given by the current clip
* rectangle.
*
* The bitmap_flags say whether to tile in the x and y
* directions. If not tiling in x or y directions, the single
* image is plotted. The width and height give the dimensions
* the image is to be scaled to.
*
* \param ctx The current redraw context.
* \param bitmap The bitmap to plot
* \param x The x coordinate to plot the bitmap
* \param y The y coordiante to plot the bitmap
* \param width The width of area to plot the bitmap into
* \param height The height of area to plot the bitmap into
* \param bg the background colour to alpha blend into
* \param flags the flags controlling the type of plot operation
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_save_draw_bitmap(const struct redraw_context *ctx,
struct bitmap *bitmap,
int x, int y,
int width,
int height,
colour bg,
bitmap_flags_t flags)
{
pencil_code code;
const uint8_t *buffer;
buffer = riscos_bitmap_get_buffer(bitmap);
if (!buffer) {
ro_warn_user("NoMemory", 0);
return NSERROR_INVALID;
}
code = pencil_sprite(ro_save_draw_diagram,
x * 2, (-y - height) * 2,
width * 2, height * 2,
((char *) bitmap->sprite_area) +
bitmap->sprite_area->first);
if (code != pencil_OK)
return ro_save_draw_error(code);
return NSERROR_OK;
}
/**
* Text plotting.
*
* \param ctx The current redraw context.
* \param fstyle plot style for this text
* \param x x coordinate
* \param y y coordinate
* \param text UTF-8 string to plot
* \param length length of string, in bytes
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_save_draw_text(const struct redraw_context *ctx,
const struct plot_font_style *fstyle,
int x,
int y,
const char *text,
size_t length)
{
pencil_code code;
const char *font_family;
unsigned int font_size;
rufl_style font_style;
nsfont_read_style(fstyle, &font_family, &font_size, &font_style);
code = pencil_text(ro_save_draw_diagram, x * 2, -y * 2, font_family,
font_style, font_size, text, length,
fstyle->foreground << 8);
if (code != pencil_OK)
return ro_save_draw_error(code);
return NSERROR_OK;
}
/**
* Start of a group of objects.
*
* \param ctx The current redraw context.
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_save_draw_group_start(const struct redraw_context *ctx, const char *name)
{
pencil_code code;
code = pencil_group_start(ro_save_draw_diagram, name);
if (code != pencil_OK)
return ro_save_draw_error(code);
return NSERROR_OK;
}
/**
* End of the most recently started group.
*
* \param ctx The current redraw context.
* \return NSERROR_OK on success else error code.
*/
static nserror
ro_save_draw_group_end(const struct redraw_context *ctx)
{
pencil_code code;
code = pencil_group_end(ro_save_draw_diagram);
if (code != pencil_OK)
return ro_save_draw_error(code);
return NSERROR_OK;
}
static const struct plotter_table ro_save_draw_plotters = {
@ -72,19 +567,8 @@ static const struct plotter_table ro_save_draw_plotters = {
.option_knockout = false,
};
static struct pencil_diagram *ro_save_draw_diagram;
static int ro_save_draw_width;
static int ro_save_draw_height;
/**
* Export a content as a DrawFile.
*
* \param h content to export
* \param path path to save DrawFile as
* \return true on success, false on error and error reported
*/
/* exported interface documented in save_draw.h */
bool save_as_draw(struct hlcache_handle *h, const char *path)
{
pencil_code code;
@ -137,10 +621,11 @@ bool save_as_draw(struct hlcache_handle *h, const char *path)
assert(drawfile_buffer);
error = xosfile_save_stamped(path, osfile_TYPE_DRAW,
(byte *) drawfile_buffer,
(byte *) drawfile_buffer,
(byte *) drawfile_buffer + drawfile_size);
if (error) {
LOG("xosfile_save_stamped failed: 0x%x: %s", error->errnum, error->errmess);
LOG("xosfile_save_stamped failed: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("SaveError", error->errmess);
pencil_free(ro_save_draw_diagram);
return false;
@ -151,322 +636,4 @@ bool save_as_draw(struct hlcache_handle *h, const char *path)
return true;
}
bool ro_save_draw_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
{
pencil_code code;
const int path[] = { draw_MOVE_TO, x0 * 2, -y0 * 2 - 1,
draw_LINE_TO, x1 * 2, -y0 * 2 - 1,
draw_LINE_TO, x1 * 2, -y1 * 2 - 1,
draw_LINE_TO, x0 * 2, -y1 * 2 - 1,
draw_CLOSE_LINE,
draw_END_PATH };
if (style->fill_type != PLOT_OP_TYPE_NONE) {
code = pencil_path(ro_save_draw_diagram,
path,
sizeof path / sizeof path[0],
style->fill_colour << 8,
pencil_TRANSPARENT,
0,
pencil_JOIN_MITRED,
pencil_CAP_BUTT,
pencil_CAP_BUTT,
0,
0,
false,
pencil_SOLID);
if (code != pencil_OK)
return ro_save_draw_error(code);
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
code = pencil_path(ro_save_draw_diagram,
path,
sizeof path / sizeof path[0],
pencil_TRANSPARENT,
style->stroke_colour << 8,
style->stroke_width,
pencil_JOIN_MITRED,
pencil_CAP_BUTT,
pencil_CAP_BUTT,
0,
0,
false,
pencil_SOLID);
if (code != pencil_OK)
return ro_save_draw_error(code);
}
return true;
}
bool ro_save_draw_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
{
pencil_code code;
const int path[] = { draw_MOVE_TO, x0 * 2, -y0 * 2 - 1,
draw_LINE_TO, x1 * 2, -y1 * 2 - 1,
draw_END_PATH };
code = pencil_path(ro_save_draw_diagram,
path,
sizeof path / sizeof path[0],
pencil_TRANSPARENT,
style->stroke_colour << 8,
style->stroke_width,
pencil_JOIN_MITRED,
pencil_CAP_BUTT,
pencil_CAP_BUTT,
0, 0, false,
pencil_SOLID);
if (code != pencil_OK)
return ro_save_draw_error(code);
return true;
}
bool ro_save_draw_polygon(const int *p, unsigned int n, const plot_style_t *style)
{
pencil_code code;
int path[n * 3 + 1];
unsigned int i;
for (i = 0; i != n; i++) {
path[i * 3 + 0] = draw_LINE_TO;
path[i * 3 + 1] = p[i * 2 + 0] * 2;
path[i * 3 + 2] = -p[i * 2 + 1] * 2;
}
path[0] = draw_MOVE_TO;
path[n * 3] = draw_END_PATH;
code = pencil_path(ro_save_draw_diagram,
path, n * 3 + 1,
style->fill_colour << 8,
pencil_TRANSPARENT,
0,
pencil_JOIN_MITRED,
pencil_CAP_BUTT,
pencil_CAP_BUTT,
0,
0,
false,
pencil_SOLID);
if (code != pencil_OK)
return ro_save_draw_error(code);
return true;
}
bool ro_save_draw_path(const float *p, unsigned int n, colour fill,
float width, colour c, const float transform[6])
{
if (n == 0)
return true;
if (p[0] != PLOTTER_PATH_MOVE) {
LOG("path doesn't start with a move");
return false;
}
int *path = malloc(sizeof *path * (n + 10));
if (!path) {
LOG("out of memory");
return false;
}
unsigned int i;
bool empty_path = true;
for (i = 0; i < n; ) {
if (p[i] == PLOTTER_PATH_MOVE) {
path[i] = draw_MOVE_TO;
path[i + 1] = (transform[0] * p[i + 1] +
transform[2] * -p[i + 2] +
transform[4]) * 2;
path[i + 2] = (transform[1] * p[i + 1] +
transform[3] * -p[i + 2] +
-transform[5]) * 2;
i += 3;
} else if (p[i] == PLOTTER_PATH_CLOSE) {
path[i] = draw_CLOSE_LINE;
i++;
} else if (p[i] == PLOTTER_PATH_LINE) {
path[i] = draw_LINE_TO;
path[i + 1] = (transform[0] * p[i + 1] +
transform[2] * -p[i + 2] +
transform[4]) * 2;
path[i + 2] = (transform[1] * p[i + 1] +
transform[3] * -p[i + 2] +
-transform[5]) * 2;
i += 3;
empty_path = false;
} else if (p[i] == PLOTTER_PATH_BEZIER) {
path[i] = draw_BEZIER_TO;
path[i + 1] = (transform[0] * p[i + 1] +
transform[2] * -p[i + 2] +
transform[4]) * 2;
path[i + 2] = (transform[1] * p[i + 1] +
transform[3] * -p[i + 2] +
-transform[5]) * 2;
path[i + 3] = (transform[0] * p[i + 3] +
transform[2] * -p[i + 4] +
transform[4]) * 2;
path[i + 4] = (transform[1] * p[i + 3] +
transform[3] * -p[i + 4] +
-transform[5]) * 2;
path[i + 5] = (transform[0] * p[i + 5] +
transform[2] * -p[i + 6] +
transform[4]) * 2;
path[i + 6] = (transform[1] * p[i + 5] +
transform[3] * -p[i + 6] +
-transform[5]) * 2;
i += 7;
empty_path = false;
} else {
LOG("bad path command %f", p[i]);
free(path);
return false;
}
}
path[i] = draw_END_PATH;
if (empty_path) {
free(path);
return true;
}
pencil_code code = pencil_path(ro_save_draw_diagram, path, i + 1,
fill == NS_TRANSPARENT ? pencil_TRANSPARENT : fill << 8,
c == NS_TRANSPARENT ? pencil_TRANSPARENT : c << 8,
width, pencil_JOIN_MITRED,
pencil_CAP_BUTT, pencil_CAP_BUTT, 0, 0, false,
pencil_SOLID);
free(path);
if (code != pencil_OK)
return ro_save_draw_error(code);
return true;
}
bool ro_save_draw_clip(const struct rect *clip)
{
return true;
}
bool ro_save_draw_text(int x, int y, const char *text, size_t length,
const plot_font_style_t *fstyle)
{
pencil_code code;
const char *font_family;
unsigned int font_size;
rufl_style font_style;
nsfont_read_style(fstyle, &font_family, &font_size, &font_style);
code = pencil_text(ro_save_draw_diagram, x * 2, -y * 2, font_family,
font_style, font_size, text, length,
fstyle->foreground << 8);
if (code != pencil_OK)
return ro_save_draw_error(code);
return true;
}
bool ro_save_draw_disc(int x, int y, int radius, const plot_style_t *style)
{
return true;
}
bool ro_save_draw_arc(int x, int y, int radius, int angle1, int angle2,
const plot_style_t *style)
{
return true;
}
bool ro_save_draw_bitmap(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg, bitmap_flags_t flags)
{
pencil_code code;
const uint8_t *buffer;
buffer = riscos_bitmap_get_buffer(bitmap);
if (!buffer) {
ro_warn_user("NoMemory", 0);
return false;
}
code = pencil_sprite(ro_save_draw_diagram, x * 2, (-y - height) * 2,
width * 2, height * 2,
((char *) bitmap->sprite_area) +
bitmap->sprite_area->first);
if (code != pencil_OK)
return ro_save_draw_error(code);
return true;
}
bool ro_save_draw_group_start(const char *name)
{
pencil_code code;
code = pencil_group_start(ro_save_draw_diagram, name);
if (code != pencil_OK)
return ro_save_draw_error(code);
return true;
}
bool ro_save_draw_group_end(void)
{
pencil_code code;
code = pencil_group_end(ro_save_draw_diagram);
if (code != pencil_OK)
return ro_save_draw_error(code);
return true;
}
/**
* Report an error from pencil.
*
* \param code error code
* \return false
*/
bool ro_save_draw_error(pencil_code code)
{
LOG("code %i", code);
switch (code) {
case pencil_OK:
assert(0);
break;
case pencil_OUT_OF_MEMORY:
ro_warn_user("NoMemory", 0);
break;
case pencil_FONT_MANAGER_ERROR:
ro_warn_user("SaveError", rufl_fm_error->errmess);
break;
case pencil_FONT_NOT_FOUND:
case pencil_IO_ERROR:
case pencil_IO_EOF:
ro_warn_user("SaveError", "generating the DrawFile failed");
break;
}
return false;
}
#endif

View File

@ -24,6 +24,13 @@
#include <stdbool.h>
struct hlcache_handle;
/**
* Export a content as a DrawFile.
*
* \param h content to export
* \param path path to save DrawFile as
* \return true on success, false on error and error reported
*/
bool save_as_draw(struct hlcache_handle *h, const char *path);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,7 @@
struct bitmap;
struct rect;
struct plotter_table;
typedef unsigned long bitmap_flags_t;
#define BITMAPF_NONE 0
@ -44,50 +45,45 @@ enum path_command {
PLOTTER_PATH_BEZIER,
};
/** Set of target specific plotting functions.
*
* The functions are:
* arc - Plots an arc, around (x,y), from anticlockwise from angle1 to
* angle2. Angles are measured anticlockwise from horizontal, in
* degrees.
* disc - Plots a circle, centered on (x,y), which is optionally filled.
* line - Plots a line from (x0,y0) to (x1,y1). Coordinates are at
* centre of line width/thickness.
* path - Plots a path consisting of cubic Bezier curves. Line colour is
* given by c and fill colour is given by fill.
* polygon - Plots a filled polygon with straight lines between points.
* The lines around the edge of the ploygon are not plotted. The
* polygon is filled with the non-zero winding rule.
* rectangle - Plots a rectangle outline. The line can be solid, dotted or
* dashed. Top left corner at (x0,y0) and rectangle has given
* width and height.
* fill - Plots a filled rectangle. Top left corner at (x0,y0), bottom
* right corner at (x1,y1). Note: (x0,y0) is inside filled area,
* but (x1,y1) is below and to the right. See diagram below.
* clip - Sets a clip rectangle for subsequent plots.
* text - Plots text. (x,y) is the coordinate of the left hand side of
* the text's baseline. The text is UTF-8 encoded. The colour, c,
* is the colour of the text. Background colour, bg, may be used
* optionally to attempt to provide anti-aliased text without
* screen reads. Font information is provided in the style.
* bitmap - Tiled plot of a bitmap image. (x,y) gives the top left
* coordinate of an explicitly placed tile. From this tile the
* image can repeat in all four directions -- up, down, left and
* right -- to the extents given by the current clip rectangle.
* The bitmap_flags say whether to tile in the x and y
* directions. If not tiling in x or y directions, the single
* image is plotted. The width and height give the dimensions
* the image is to be scaled to.
* group_start - Start of a group of objects. Used when plotter implements
* export to a vector graphics file format. (Optional.)
* group_end - End of the most recently started group. (Optional.)
* flush - Only used internally by the knockout code. Should be NULL in
* any front end display plotters or export plotters.
*
* Plotter options:
* option_knockout - Optimisation particularly for unaccelerated screen
* redraw. It tries to avoid plotting to the same area
* more than once. See desktop/knockout.c
/**
* Redraw context
*/
struct redraw_context {
/**
* Redraw to show interactive features.
*
* Active features include selections etc.
*
* \note Should be off for printing.
*/
bool interactive;
/**
* Render background images.
*
* \note May want it off for printing.
*/
bool background_images;
/**
* Current plot operation table
*
* \warning must be assigned before use.
*/
const struct plotter_table *plot;
/**
* Private context.
*
* Private context allows callers to pass context through to
* plot operations without using a global.
*/
void *priv;
};
/**
* Plotter operations table.
*
* Coordinates are from top left of canvas and (0,0) is the top left grid
* denomination. If a "fill" is drawn from (0,0) to (4,3), the result is:
@ -101,61 +97,189 @@ enum path_command {
* 2 |#|#|#|#| |
* +-+-+-+-+-+-
* 3 | | | | | |
*
*/
struct plotter_table {
/* clipping operations */
bool (*clip)(const struct rect *clip);
/* shape primatives */
bool (*arc)(int x, int y, int radius, int angle1, int angle2, const plot_style_t *pstyle);
bool (*disc)(int x, int y, int radius, const plot_style_t *pstyle);
bool (*line)(int x0, int y0, int x1, int y1, const plot_style_t *pstyle);
bool (*rectangle)(int x0, int y0, int x1, int y1, const plot_style_t *pstyle);
bool (*polygon)(const int *p, unsigned int n, const plot_style_t *pstyle);
/* complex path (for SVG) */
bool (*path)(const float *p, unsigned int n, colour fill, float width,
colour c, const float transform[6]);
/* Image */
bool (*bitmap)(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg,
bitmap_flags_t flags);
/**
* \brief Sets a clip rectangle for subsequent plot operations.
*
* \param ctx The current redraw context.
* \param clip The rectangle to limit all subsequent plot
* operations within.
* \return NSERROR_OK on success else error code.
*/
nserror (*clip)(const struct redraw_context *ctx, const struct rect *clip);
/**
* Text.
* Plots an arc
*
* \param x x coordinate
* \param y y coordinate
* \param text UTF-8 string to plot
* \param length length of string, in bytes
* \param fstyle plot style for this text
* \return true on success, false on error and error reported
* plot an arc segment around (x,y), anticlockwise from angle1
* to angle2. Angles are measured anticlockwise from
* horizontal, in degrees.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the arc plot.
* \param x The x coordinate of the arc.
* \param y The y coordinate of the arc.
* \param radius The radius of the arc.
* \param angle1 The start angle of the arc.
* \param angle2 The finish angle of the arc.
* \return NSERROR_OK on success else error code.
*/
bool (*text)(int x, int y, const char *text, size_t length,
const plot_font_style_t *fstyle);
nserror (*arc)(const struct redraw_context *ctx, const plot_style_t *pstyle, int x, int y, int radius, int angle1, int angle2);
/* optional callbacks */
bool (*group_start)(const char *name); /**< optional, may be NULL */
bool (*group_end)(void); /**< optional, may be NULL */
bool (*flush)(void); /**< optional, may be NULL */
/**
* Plots a circle
*
* Plot a circle centered on (x,y), which is optionally filled.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the circle plot.
* \param x The x coordinate of the circle.
* \param y The y coordinate of the circle.
* \param radius The radius of the circle.
* \return NSERROR_OK on success else error code.
*/
nserror (*disc)(const struct redraw_context *ctx, const plot_style_t *pstyle, int x, int y, int radius);
/* flags */
bool option_knockout; /**< set if knockout rendering is required */
};
/**
* Plots a line
*
* plot a line from (x0,y0) to (x1,y1). Coordinates are at
* centre of line width/thickness.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the line plot.
* \param line A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
nserror (*line)(const struct redraw_context *ctx, const plot_style_t *pstyle, const struct rect *line);
/**
* Plots a rectangle.
*
* The rectangle can be filled an outline or both controlled
* by the plot style The line can be solid, dotted or
* dashed. Top left corner at (x0,y0) and rectangle has given
* width and height.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the rectangle plot.
* \param rect A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
nserror (*rectangle)(const struct redraw_context *ctx, const plot_style_t *pstyle, const struct rect *rectangle);
/* Redraw context */
struct redraw_context {
/** Redraw to show interactive features, such as active selections
* etc. Should be off for printing. */
bool interactive;
/**
* Plot a polygon
*
* Plots a filled polygon with straight lines between
* points. The lines around the edge of the ploygon are not
* plotted. The polygon is filled with the non-zero winding
* rule.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the polygon plot.
* \param p verticies of polygon
* \param n number of verticies.
* \return NSERROR_OK on success else error code.
*/
nserror (*polygon)(const struct redraw_context *ctx, const plot_style_t *pstyle, const int *p, unsigned int n);
/** Render background images. May want it off for printing. */
bool background_images;
/**
* Plots a path.
*
* Path plot consisting of cubic Bezier curves. Line and fill colour is
* controlled by the plot style.
*
* \param ctx The current redraw context.
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
* \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
nserror (*path)(const struct redraw_context *ctx, const plot_style_t *pstyle, const float *p, unsigned int n, float width, const float transform[6]);
/** Current plotters, must be assigned before use. */
const struct plotter_table *plot;
/**
* Plot a bitmap
*
* Tiled plot of a bitmap image. (x,y) gives the top left
* coordinate of an explicitly placed tile. From this tile the
* image can repeat in all four directions -- up, down, left
* and right -- to the extents given by the current clip
* rectangle.
*
* The bitmap_flags say whether to tile in the x and y
* directions. If not tiling in x or y directions, the single
* image is plotted. The width and height give the dimensions
* the image is to be scaled to.
*
* \param ctx The current redraw context.
* \param bitmap The bitmap to plot
* \param x The x coordinate to plot the bitmap
* \param y The y coordiante to plot the bitmap
* \param width The width of area to plot the bitmap into
* \param height The height of area to plot the bitmap into
* \param bg the background colour to alpha blend into
* \param flags the flags controlling the type of plot operation
* \return NSERROR_OK on success else error code.
*/
nserror (*bitmap)(const struct redraw_context *ctx, struct bitmap *bitmap, int x, int y, int width, int height, colour bg, bitmap_flags_t flags);
/**
* Text plotting.
*
* \param ctx The current redraw context.
* \param fstyle plot style for this text
* \param x x coordinate
* \param y y coordinate
* \param text UTF-8 string to plot
* \param length length of string, in bytes
* \return NSERROR_OK on success else error code.
*/
nserror (*text)(const struct redraw_context *ctx, const plot_font_style_t *fstyle, int x, int y, const char *text, size_t length);
/**
* Start of a group of objects.
*
* optional, may be NULL. Used when plotter implements export
* to a vector graphics file format.
*
* \param ctx The current redraw context.
* \return NSERROR_OK on success else error code.
*/
nserror (*group_start)(const struct redraw_context *ctx, const char *name);
/**
* End of the most recently started group.
*
* optional, may be NULL
*
* \param ctx The current redraw context.
* \return NSERROR_OK on success else error code.
*/
nserror (*group_end)(const struct redraw_context *ctx);
/**
* Only used internally by the knockout code. Must be NULL in
* any front end display plotters or export plotters.
*
* \param ctx The current redraw context.
* \return NSERROR_OK on success else error code.
*/
nserror (*flush)(const struct redraw_context *ctx);
/* flags */
/**
* flag to enable knockout rendering.
*
* Optimisation particularly for unaccelerated screen
* redraw. It tries to avoid plotting to the same area more
* than once. See desktop/knockout.c
*/
bool option_knockout;
};
#endif

View File

@ -3,7 +3,8 @@
S_RENDER := box.c box_construct.c box_normalise.c box_textarea.c \
font.c form.c imagemap.c layout.c search.c table.c textplain.c \
html.c html_css.c html_css_fetcher.c html_script.c \
html_interaction.c html_redraw.c html_forms.c html_object.c
html_interaction.c html_redraw.c html_redraw_border.c \
html_forms.c html_object.c
S_RENDER := $(addprefix render/,$(S_RENDER))

View File

@ -1167,7 +1167,6 @@ bool form_redraw_select_menu(struct form_control *control, int x, int y,
float scale, const struct rect *clip,
const struct redraw_context *ctx)
{
const struct plotter_table *plot = ctx->plot;
struct box *box;
struct form_select_menu *menu = control->data.select.menu;
struct form_option *option;
@ -1181,7 +1180,9 @@ bool form_redraw_select_menu(struct form_control *control, int x, int y,
int scroll;
int x_cp, y_cp;
struct rect r;
struct rect rect;
nserror res;
box = control->box;
x_cp = x;
@ -1220,12 +1221,20 @@ bool form_redraw_select_menu(struct form_control *control, int x, int y,
r.y0 = y0;
r.x1 = x1 + 1;
r.y1 = y1 + 1;
if (!plot->clip(&r))
res = ctx->plot->clip(ctx, &r);
if (res != NSERROR_OK) {
return false;
if (!plot->rectangle(x0, y0, x1, y1 ,plot_style_stroke_darkwbasec))
}
rect.x0 = x0;
rect.y0 = y0;
rect.x1 = x1;
rect.y1 = y1;
res = ctx->plot->rectangle(ctx, plot_style_stroke_darkwbasec, &rect);
if (res != NSERROR_OK) {
return false;
}
x0 = x0 + SELECT_BORDER_WIDTH;
y0 = y0 + SELECT_BORDER_WIDTH;
x1 = x1 - SELECT_BORDER_WIDTH;
@ -1236,11 +1245,16 @@ bool form_redraw_select_menu(struct form_control *control, int x, int y,
r.y0 = y0;
r.x1 = x1 + 1;
r.y1 = y1 + 1;
if (!plot->clip(&r))
res = ctx->plot->clip(ctx, &r);
if (res != NSERROR_OK) {
return false;
if (!plot->rectangle(x0, y0, x1 + 1, y1 + 1,
plot_style_fill_lightwbasec))
}
res = ctx->plot->rectangle(ctx, plot_style_fill_lightwbasec, &r);
if (res != NSERROR_OK) {
return false;
}
option = control->data.select.items;
item_y = line_height_with_spacing;
@ -1256,32 +1270,40 @@ bool form_redraw_select_menu(struct form_control *control, int x, int y,
plot_fstyle_entry.size = menu->f_size;
while (option && item_y - scroll < height) {
if (option->selected) {
y2 = y + item_y - scroll;
y3 = y + item_y + line_height_with_spacing - scroll;
if (!plot->rectangle(x0, (y0 > y2 ? y0 : y2),
scrollbar_x + 1,
(y3 < y1 + 1 ? y3 : y1 + 1),
&plot_style_fill_selected))
rect.x0 = x0;
rect.y0 = y0 > y2 ? y0 : y2;
rect.x1 = scrollbar_x + 1;
rect.y1 = y3 < y1 + 1 ? y3 : y1 + 1;
res = ctx->plot->rectangle(ctx, &plot_style_fill_selected, &rect);
if (res != NSERROR_OK) {
return false;
}
}
y2 = text_pos_offset + item_y;
if (!plot->text(text_x, y2, option->text,
strlen(option->text), &plot_fstyle_entry))
res = ctx->plot->text(ctx,
&plot_fstyle_entry,
text_x, y2,
option->text, strlen(option->text));
if (res != NSERROR_OK) {
return false;
}
item_y += line_height_with_spacing;
option = option->next;
}
if (!scrollbar_redraw(menu->scrollbar,
x_cp + menu->width - SCROLLBAR_WIDTH,
y_cp,
clip, scale, ctx))
return false;
return true;
}

View File

@ -258,6 +258,15 @@ bool html_begin_conversion(html_content *htmlc);
bool html_redraw(struct content *c, struct content_redraw_data *data,
const struct rect *clip, const struct redraw_context *ctx);
/* in render/html_redraw_border.c */
bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
int p_width, int p_height, const struct rect *clip, float scale,
const struct redraw_context *ctx);
bool html_redraw_inline_borders(struct box *box, struct rect b,
const struct rect *clip, float scale, bool first, bool last,
const struct redraw_context *ctx);
/* in render/html_interaction.c */
void html_mouse_track(struct content *c, struct browser_window *bw,
browser_mouse_state mouse, int x, int y);

File diff suppressed because it is too large Load Diff

928
render/html_redraw_border.c Normal file
View File

@ -0,0 +1,928 @@
/*
* Copyright 2017 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \file
*
* Redrawing CONTENT_HTML borders implementation.
*/
#include <stdbool.h>
#include <stdlib.h>
#include "utils/log.h"
#include "netsurf/plotters.h"
#include "netsurf/css.h"
#include "render/box.h"
#include "render/html_internal.h"
static plot_style_t plot_style_bdr = {
.stroke_type = PLOT_OP_TYPE_DASH,
};
static plot_style_t plot_style_fillbdr = {
.fill_type = PLOT_OP_TYPE_SOLID,
};
static plot_style_t plot_style_fillbdr_dark = {
.fill_type = PLOT_OP_TYPE_SOLID,
};
static plot_style_t plot_style_fillbdr_light = {
.fill_type = PLOT_OP_TYPE_SOLID,
};
static plot_style_t plot_style_fillbdr_ddark = {
.fill_type = PLOT_OP_TYPE_SOLID,
};
static plot_style_t plot_style_fillbdr_dlight = {
.fill_type = PLOT_OP_TYPE_SOLID,
};
static inline nserror
plot_clipped_rectangle(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *clip,
struct rect *rect)
{
nserror res;
rect->x0 = (clip->x0 > rect->x0) ? clip->x0 : rect->x0;
rect->y0 = (clip->y0 > rect->y0) ? clip->y0 : rect->y0;
rect->x1 = (clip->x1 < rect->x1) ? clip->x1 : rect->x1;
rect->y1 = (clip->y1 < rect->y1) ? clip->y1 : rect->y1;
if ((rect->x0 < rect->x1) && (rect->y0 < rect->y1)) {
/* valid clip rectangles only */
res = ctx->plot->rectangle(ctx, style, rect);
} else {
res = NSERROR_OK;
}
return res;
}
/**
* 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_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;
}
/**
* Draw borders for a box.
*
* \param box box to draw
* \param x_parent coordinate of left padding edge of parent of box
* \param y_parent coordinate of top padding edge of parent of box
* \param p_width width of padding box
* \param p_height height of padding box
* \param clip cliping area for redrawing border.
* \param scale scale for redraw
* \param ctx current redraw context
* \return true if successful, false otherwise
*/
bool
html_redraw_borders(struct box *box,
int x_parent,
int y_parent,
int p_width,
int p_height,
const struct rect *clip,
float scale,
const struct redraw_context *ctx)
{
unsigned int sides[] = { LEFT, RIGHT, TOP, BOTTOM };
int top = box->border[TOP].width;
int right = box->border[RIGHT].width;
int bottom = box->border[BOTTOM].width;
int left = box->border[LEFT].width;
int x, y;
unsigned int i, side;
int p[8]; /* Box border vertices */
int z[8]; /* Border vertices */
bool square_end_1 = false;
bool square_end_2 = false;
nserror res;
x = x_parent + box->x;
y = y_parent + box->y;
if (scale != 1.0) {
top *= scale;
right *= scale;
bottom *= scale;
left *= scale;
x *= scale;
y *= scale;
}
assert(box->style);
/* Calculate border vertices
*
* A----------------------+
* | \ / |
* | B--------------+ |
* | | | |
* | +--------------C |
* | / \ |
* +----------------------D
*/
p[0] = x - left; p[1] = y - top; /* A */
p[2] = x; p[3] = y; /* B */
p[4] = x + p_width; p[5] = y + p_height; /* C */
p[6] = x + p_width + right; p[7] = y + p_height + bottom; /* D */
for (i = 0; i != 4; i++) {
colour col = 0;
side = sides[i]; /* plot order */
if (box->border[side].width == 0 ||
nscss_color_is_transparent(box->border[side].c)) {
continue;
}
switch (side) {
case LEFT:
square_end_1 = (top == 0);
square_end_2 = (bottom == 0);
z[0] = p[0]; z[1] = p[7];
z[2] = p[2]; z[3] = p[5];
z[4] = p[2]; z[5] = p[3];
z[6] = p[0]; z[7] = p[1];
if (nscss_color_is_transparent(box->border[TOP].c) == false &&
box->border[TOP].style != CSS_BORDER_STYLE_DOUBLE) {
/* make border overhang top corner fully,
* if top border is opaque
*/
z[5] -= top;
square_end_1 = true;
}
if (nscss_color_is_transparent(box->border[BOTTOM].c) == false &&
box->border[BOTTOM].style != CSS_BORDER_STYLE_DOUBLE) {
/* make border overhang bottom corner fully,
* if bottom border is opaque
*/
z[3] += bottom;
square_end_2 = true;
}
col = nscss_color_to_ns(box->border[side].c);
res = html_redraw_border_plot(side,
z,
col,
box->border[side].style,
box->border[side].width * scale,
square_end_1 && square_end_2,
clip,
ctx);
if (res != NSERROR_OK) {
return false;
}
break;
case RIGHT:
square_end_1 = (top == 0);
square_end_2 = (bottom == 0);
z[0] = p[6]; z[1] = p[1];
z[2] = p[4]; z[3] = p[3];
z[4] = p[4]; z[5] = p[5];
z[6] = p[6]; z[7] = p[7];
if (nscss_color_is_transparent(box->border[TOP].c) == false &&
box->border[TOP].style != CSS_BORDER_STYLE_DOUBLE) {
/* make border overhang top corner fully,
* if top border is opaque
*/
z[3] -= top;
square_end_1 = true;
}
if (nscss_color_is_transparent(box->border[BOTTOM].c) == false &&
box->border[BOTTOM].style != CSS_BORDER_STYLE_DOUBLE) {
/* make border overhang bottom corner fully,
* if bottom border is opaque
*/
z[5] += bottom;
square_end_2 = true;
}
col = nscss_color_to_ns(box->border[side].c);
res = html_redraw_border_plot(side,
z,
col,
box->border[side].style,
box->border[side].width * scale,
square_end_1 && square_end_2,
clip,
ctx);
if (res != NSERROR_OK) {
return false;
}
break;
case TOP:
if (clip->y0 > p[3]) {
/* clip rectangle is below border; nothing to
* plot
*/
continue;
}
square_end_1 = (left == 0);
square_end_2 = (right == 0);
z[0] = p[2]; z[1] = p[3];
z[2] = p[0]; z[3] = p[1];
z[4] = p[6]; z[5] = p[1];
z[6] = p[4]; z[7] = p[3];
if (box->border[TOP].style == CSS_BORDER_STYLE_SOLID &&
box->border[TOP].c == box->border[LEFT].c) {
/* don't bother overlapping left corner if
* it's the same colour anyway
*/
z[2] += left;
square_end_1 = true;
}
if (box->border[TOP].style == CSS_BORDER_STYLE_SOLID &&
box->border[TOP].c == box->border[RIGHT].c) {
/* don't bother overlapping right corner if
* it's the same colour anyway
*/
z[4] -= right;
square_end_2 = true;
}
col = nscss_color_to_ns(box->border[side].c);
res = html_redraw_border_plot(side,
z,
col,
box->border[side].style,
box->border[side].width * scale,
square_end_1 && square_end_2,
clip,
ctx);
if (res != NSERROR_OK) {
return false;
}
break;
case BOTTOM:
if (clip->y1 < p[5]) {
/* clip rectangle is above border; nothing to
* plot
*/
continue;
}
square_end_1 = (left == 0);
square_end_2 = (right == 0);
z[0] = p[4]; z[1] = p[5];
z[2] = p[6]; z[3] = p[7];
z[4] = p[0]; z[5] = p[7];
z[6] = p[2]; z[7] = p[5];
if (box->border[BOTTOM].style == CSS_BORDER_STYLE_SOLID &&
box->border[BOTTOM].c == box->border[LEFT].c) {
/* don't bother overlapping left corner if
* it's the same colour anyway
*/
z[4] += left;
square_end_1 = true;
}
if (box->border[BOTTOM].style == CSS_BORDER_STYLE_SOLID &&
box->border[BOTTOM].c == box->border[RIGHT].c) {
/* don't bother overlapping right corner if
* it's the same colour anyway
*/
z[2] -= right;
square_end_2 = true;
}
col = nscss_color_to_ns(box->border[side].c);
res = html_redraw_border_plot(side,
z,
col,
box->border[side].style,
box->border[side].width * scale,
square_end_1 && square_end_2,
clip,
ctx);
if (res != NSERROR_OK) {
return false;
}
break;
default:
assert(side == TOP || side == BOTTOM ||
side == LEFT || side == RIGHT);
break;
}
}
return true;
}
/**
* Draw an inline's borders.
*
* \param box BOX_INLINE which created the border
* \param b coordinates of border edge rectangle
* \param clip cliping area for redrawing border.
* \param scale scale for redraw
* \param first true if this is the first rectangle associated with the inline
* \param last true if this is the last rectangle associated with the inline
* \param ctx current redraw context
* \return true if successful, false otherwise
*/
bool
html_redraw_inline_borders(struct box *box,
struct rect b,
const struct rect *clip,
float scale,
bool first,
bool last,
const struct redraw_context *ctx)
{
int top = box->border[TOP].width;
int right = box->border[RIGHT].width;
int bottom = box->border[BOTTOM].width;
int left = box->border[LEFT].width;
colour col;
int p[8]; /* Box border vertices */
int z[8]; /* Border vertices */
bool square_end_1;
bool square_end_2;
nserror res;
if (scale != 1.0) {
top *= scale;
right *= scale;
bottom *= scale;
left *= scale;
}
/* Calculate border vertices
*
* A----------------------+
* | \ / |
* | B--------------+ |
* | | | |
* | +--------------C |
* | / \ |
* +----------------------D
*/
p[0] = b.x0; p[1] = b.y0; /* A */
p[2] = first ? b.x0 + left : b.x0; p[3] = b.y0 + top; /* B */
p[4] = last ? b.x1 - right : b.x1; p[5] = b.y1 - bottom; /* C */
p[6] = b.x1; p[7] = b.y1; /* D */
assert(box->style);
/* Left */
square_end_1 = (top == 0);
square_end_2 = (bottom == 0);
if (left != 0 &&
first &&
nscss_color_is_transparent(box->border[LEFT].c) == false) {
col = nscss_color_to_ns(box->border[LEFT].c);
z[0] = p[0]; z[1] = p[7];
z[2] = p[2]; z[3] = p[5];
z[4] = p[2]; z[5] = p[3];
z[6] = p[0]; z[7] = p[1];
if (nscss_color_is_transparent(box->border[TOP].c) == false &&
box->border[TOP].style != CSS_BORDER_STYLE_DOUBLE) {
/* make border overhang top corner fully,
* if top border is opaque
*/
z[5] -= top;
square_end_1 = true;
}
if (nscss_color_is_transparent(box->border[BOTTOM].c) == false &&
box->border[BOTTOM].style != CSS_BORDER_STYLE_DOUBLE) {
/* make border overhang bottom corner fully,
* if bottom border is opaque
*/
z[3] += bottom;
square_end_2 = true;
}
res = html_redraw_border_plot(LEFT,
z,
col,
box->border[LEFT].style,
left,
square_end_1 && square_end_2,
clip,
ctx);
if (res != NSERROR_OK) {
return false;
}
}
/* Right */
square_end_1 = (top == 0);
square_end_2 = (bottom == 0);
if (right != 0 &&
last &&
nscss_color_is_transparent(box->border[RIGHT].c) == false) {
col = nscss_color_to_ns(box->border[RIGHT].c);
z[0] = p[6]; z[1] = p[1];
z[2] = p[4]; z[3] = p[3];
z[4] = p[4]; z[5] = p[5];
z[6] = p[6]; z[7] = p[7];
if (nscss_color_is_transparent(box->border[TOP].c) == false &&
box->border[TOP].style != CSS_BORDER_STYLE_DOUBLE) {
/* make border overhang top corner fully,
* if top border is opaque
*/
z[3] -= top;
square_end_1 = true;
}
if (nscss_color_is_transparent(box->border[BOTTOM].c) == false &&
box->border[BOTTOM].style != CSS_BORDER_STYLE_DOUBLE) {
/* make border overhang bottom corner fully,
* if bottom border is opaque
*/
z[5] += bottom;
square_end_2 = true;
}
res = html_redraw_border_plot(RIGHT,
z,
col,
box->border[RIGHT].style,
right,
square_end_1 && square_end_2,
clip,
ctx);
if (res != NSERROR_OK) {
return false;
}
}
/* Top */
square_end_1 = (left == 0);
square_end_2 = (right == 0);
if (top != 0 &&
nscss_color_is_transparent(box->border[TOP].c) == false) {
col = nscss_color_to_ns(box->border[TOP].c);
z[0] = p[2]; z[1] = p[3];
z[2] = p[0]; z[3] = p[1];
z[4] = p[6]; z[5] = p[1];
z[6] = p[4]; z[7] = p[3];
if (first &&
box->border[TOP].style == CSS_BORDER_STYLE_SOLID &&
box->border[TOP].c == box->border[LEFT].c) {
/* don't bother overlapping left corner if
* it's the same colour anyway
*/
z[2] += left;
square_end_1 = true;
}
if (last &&
box->border[TOP].style == CSS_BORDER_STYLE_SOLID &&
box->border[TOP].c == box->border[RIGHT].c) {
/* don't bother overlapping right corner if
* it's the same colour anyway
*/
z[4] -= right;
square_end_2 = true;
}
res = html_redraw_border_plot(TOP,
z,
col,
box->border[TOP].style,
top,
square_end_1 && square_end_2,
clip,
ctx);
if (res != NSERROR_OK) {
return false;
}
}
/* Bottom */
square_end_1 = (left == 0);
square_end_2 = (right == 0);
if (bottom != 0 &&
nscss_color_is_transparent(box->border[BOTTOM].c) == false) {
col = nscss_color_to_ns(box->border[BOTTOM].c);
z[0] = p[4]; z[1] = p[5];
z[2] = p[6]; z[3] = p[7];
z[4] = p[0]; z[5] = p[7];
z[6] = p[2]; z[7] = p[5];
if (first &&
box->border[BOTTOM].style == CSS_BORDER_STYLE_SOLID &&
box->border[BOTTOM].c == box->border[LEFT].c) {
/* don't bother overlapping left corner if
* it's the same colour anyway
*/
z[4] += left;
square_end_1 = true;
}
if (last &&
box->border[BOTTOM].style == CSS_BORDER_STYLE_SOLID &&
box->border[BOTTOM].c == box->border[RIGHT].c) {
/* don't bother overlapping right corner if
* it's the same colour anyway
*/
z[2] -= right;
square_end_2 = true;
}
res = html_redraw_border_plot(BOTTOM,
z,
col,
box->border[BOTTOM].style,
bottom,
square_end_1 && square_end_2,
clip,
ctx);
if (res != NSERROR_OK) {
return false;
}
}
return true;
}

View File

@ -865,7 +865,6 @@ bool textplain_redraw(struct content *c, struct content_redraw_data *data,
{
textplain_content *text = (textplain_content *) c;
struct browser_window *bw = text->bw;
const struct plotter_table *plot = ctx->plot;
char *utf8_data = text->utf8_data;
long lineno;
int x = data->x;
@ -878,6 +877,7 @@ bool textplain_redraw(struct content *c, struct content_redraw_data *data,
struct textplain_line *line = text->physical_line;
size_t length;
plot_style_t *plot_style_highlight;
nserror res;
if (line0 < 0)
line0 = 0;
@ -890,9 +890,10 @@ bool textplain_redraw(struct content *c, struct content_redraw_data *data,
if (line1 < line0)
line1 = line0;
if (!plot->rectangle(clip->x0, clip->y0, clip->x1, clip->y1,
plot_style_fill_white))
res = ctx->plot->rectangle(ctx, plot_style_fill_white, clip);
if (res != NSERROR_OK) {
return false;
}
if (!line)
return true;
@ -979,11 +980,17 @@ bool textplain_redraw(struct content *c, struct content_redraw_data *data,
}
if (highlighted) {
int sy = y + (lineno * scaled_line_height);
if (!plot->rectangle(tx, sy,
ntx, sy + scaled_line_height,
plot_style_highlight))
struct rect rect;
rect.x0 = tx;
rect.y0 = y + (lineno * scaled_line_height);
rect.x1 = ntx;
rect.y1 = rect.y0 + scaled_line_height;
res = ctx->plot->rectangle(ctx,
plot_style_highlight,
&rect);
if (res != NSERROR_OK) {
return false;
}
}
}