mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-11-23 06:51:26 +03:00
Merge branch 'vince/plotctx'
This commit is contained in:
commit
1666944c7e
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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().
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
1319
render/html_redraw.c
1319
render/html_redraw.c
File diff suppressed because it is too large
Load Diff
928
render/html_redraw_border.c
Normal file
928
render/html_redraw_border.c
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user