summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2004-06-09 19:55:06 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2004-06-09 19:55:06 +0000
commit78594f3f60a2ce28f1d6ee95676bfa10492320fe (patch)
treee8d5e6e06d24e4b663ffb2bcd3115816879bdb0d
parentec820df42f083e60bdeb20d6fc1d83a9985091a3 (diff)
downloadnetsurf-78594f3f60a2ce28f1d6ee95676bfa10492320fe.tar.gz
netsurf-78594f3f60a2ce28f1d6ee95676bfa10492320fe.tar.bz2
[project @ 2004-06-09 19:55:06 by jmb]
Implement background-image, background-repeat, background-position and background-attachment CSS properties. background-attachment and background-position need more work. Some redraw issues remain. svn path=/import/netsurf/; revision=938
-rw-r--r--css/css.c55
-rw-r--r--css/css.h38
-rw-r--r--css/css_enums3
-rw-r--r--css/parser.y58
-rw-r--r--css/ruleset.c277
-rw-r--r--render/box.c72
-rw-r--r--render/box.h4
-rw-r--r--render/html.c21
-rw-r--r--render/html.h2
-rw-r--r--riscos/htmlredraw.c125
10 files changed, 597 insertions, 58 deletions
diff --git a/css/css.c b/css/css.c
index ebf446dba..c42ad3d21 100644
--- a/css/css.c
+++ b/css/css.c
@@ -103,6 +103,11 @@ static void css_dump_selector(const struct css_selector *r);
* spec. */
const struct css_style css_base_style = {
0xffffff,
+ CSS_BACKGROUND_ATTACHMENT_SCROLL,
+ { CSS_BACKGROUND_IMAGE_NONE, 0 },
+ { { CSS_BACKGROUND_POSITION_PERCENT, { 0.0 } },
+ { CSS_BACKGROUND_POSITION_PERCENT, { 0.0 } } },
+ CSS_BACKGROUND_REPEAT_REPEAT,
{ { 0x000000, { CSS_BORDER_WIDTH_LENGTH,
{ 2, CSS_UNIT_PX } }, CSS_BORDER_STYLE_NONE },
{ 0x000000, { CSS_BORDER_WIDTH_LENGTH,
@@ -143,6 +148,11 @@ const struct css_style css_base_style = {
/** Style with no values set. */
const struct css_style css_empty_style = {
CSS_COLOR_INHERIT,
+ CSS_BACKGROUND_ATTACHMENT_INHERIT,
+ { CSS_BACKGROUND_IMAGE_INHERIT, 0 },
+ { { CSS_BACKGROUND_POSITION_INHERIT, { 0.0 } },
+ { CSS_BACKGROUND_POSITION_INHERIT, { 0.0 } } },
+ CSS_BACKGROUND_REPEAT_INHERIT,
{ { CSS_COLOR_INHERIT, { CSS_BORDER_WIDTH_INHERIT,
{ 0, CSS_UNIT_PX } }, CSS_BORDER_STYLE_INHERIT },
{ CSS_COLOR_INHERIT, { CSS_BORDER_WIDTH_INHERIT,
@@ -184,6 +194,11 @@ const struct css_style css_empty_style = {
* and the 'Initial value' otherwise. */
const struct css_style css_blank_style = {
TRANSPARENT,
+ CSS_BACKGROUND_ATTACHMENT_SCROLL,
+ { CSS_BACKGROUND_IMAGE_NONE, 0 },
+ { { CSS_BACKGROUND_POSITION_PERCENT, { 0.0 } },
+ { CSS_BACKGROUND_POSITION_PERCENT, { 0.0 } } },
+ CSS_BACKGROUND_REPEAT_REPEAT,
{ { 0x000000, { CSS_BORDER_WIDTH_LENGTH,
{ 2, CSS_UNIT_PX } }, CSS_BORDER_STYLE_NONE },
{ 0x000000, { CSS_BORDER_WIDTH_LENGTH,
@@ -332,8 +347,11 @@ void css_destroy(struct content *c)
struct css_selector *r;
for (i = 0; i != HASH_SIZE; i++) {
- for (r = c->data.css.css->rule[i]; r != 0; r = r->next)
+ for (r = c->data.css.css->rule[i]; r != 0; r = r->next) {
+ if (r->style->background_image.uri != NULL)
+ free(r->style->background_image.uri);
free(r->style);
+ }
css_free_selector(c->data.css.css->rule[i]);
}
free(c->data.css.css);
@@ -361,7 +379,8 @@ void css_destroy(struct content *c)
* Used by the parser.
*/
-struct css_node * css_new_node(css_node_type type,
+struct css_node * css_new_node(struct content *stylesheet,
+ css_node_type type,
const char *data, unsigned int data_length)
{
struct css_node *node = malloc(sizeof *node);
@@ -375,6 +394,7 @@ struct css_node * css_new_node(css_node_type type,
node->comb = CSS_COMB_NONE;
node->style = 0;
node->specificity = 0;
+ node->stylesheet = stylesheet;
return node;
}
@@ -976,7 +996,9 @@ void css_dump_style(const struct css_style * const style)
if (style->z != css_empty_style.z) \
fprintf(stderr, s ": %s; ", n[style->z]);
+ DUMP_KEYWORD(background_attachment, "background-attachment", css_background_attachment_name);
DUMP_COLOR(background_color, "background-color");
+ DUMP_KEYWORD(background_repeat, "background-repeat", css_background_repeat_name);
DUMP_KEYWORD(clear, "clear", css_clear_name);
DUMP_COLOR(color, "color");
DUMP_KEYWORD(cursor, "cursor", css_cursor_name);
@@ -1294,9 +1316,14 @@ void css_cascade(struct css_style * const style,
style->text_decoration = apply->text_decoration;
/* if (style->display == CSS_DISPLAY_INLINE && apply->display != CSS_DISPLAY_INLINE)
style->text_decoration = CSS_TEXT_DECORATION_NONE;*/
-
+ if (apply->background_attachment != CSS_BACKGROUND_ATTACHMENT_INHERIT)
+ style->background_attachment = apply->background_attachment;
if (apply->background_color != CSS_COLOR_INHERIT)
style->background_color = apply->background_color;
+ if (apply->background_image.type != CSS_BACKGROUND_IMAGE_INHERIT)
+ style->background_image = apply->background_image;
+ if (apply->background_repeat != CSS_BACKGROUND_REPEAT_INHERIT)
+ style->background_repeat = apply->background_repeat;
if (apply->clear != CSS_CLEAR_INHERIT)
style->clear = apply->clear;
if (apply->color != CSS_COLOR_INHERIT)
@@ -1332,6 +1359,14 @@ void css_cascade(struct css_style * const style,
if (apply->white_space != CSS_WHITE_SPACE_INHERIT)
style->white_space = apply->white_space;
+ /* background-position */
+ if (apply->background_position.horz.pos != CSS_BACKGROUND_POSITION_INHERIT) {
+ style->background_position.horz = apply->background_position.horz;
+ }
+ if (apply->background_position.vert.pos != CSS_BACKGROUND_POSITION_INHERIT) {
+ style->background_position.vert = apply->background_position.vert;
+ }
+
/* font-size */
f = apply->font_size.value.percent / 100;
switch (apply->font_size.size) {
@@ -1402,8 +1437,14 @@ void css_merge(struct css_style * const style,
{
unsigned int i;
+ if (apply->background_attachment != CSS_BACKGROUND_ATTACHMENT_INHERIT)
+ style->background_attachment = apply->background_attachment;
if (apply->background_color != CSS_COLOR_INHERIT)
style->background_color = apply->background_color;
+ if (apply->background_image.type != CSS_BACKGROUND_IMAGE_INHERIT)
+ style->background_image = apply->background_image;
+ if (apply->background_repeat != CSS_BACKGROUND_REPEAT_INHERIT)
+ style->background_repeat = apply->background_repeat;
if (apply->clear != CSS_CLEAR_INHERIT)
style->clear = apply->clear;
if (apply->color != CSS_COLOR_INHERIT)
@@ -1443,6 +1484,14 @@ void css_merge(struct css_style * const style,
if (apply->white_space != CSS_WHITE_SPACE_INHERIT)
style->white_space = apply->white_space;
+ /* background-position */
+ if (apply->background_position.horz.pos != CSS_BACKGROUND_POSITION_INHERIT) {
+ style->background_position.horz = apply->background_position.horz;
+ }
+ if (apply->background_position.vert.pos != CSS_BACKGROUND_POSITION_INHERIT) {
+ style->background_position.vert = apply->background_position.vert;
+ }
+
for (i = 0; i != 4; i++) {
if (apply->border[i].color != CSS_COLOR_INHERIT)
style->border[i].color = apply->border[i].color;
diff --git a/css/css.h b/css/css.h
index 14c53a065..d80df9333 100644
--- a/css/css.h
+++ b/css/css.h
@@ -53,10 +53,44 @@ typedef enum {
CSS_TEXT_DECORATION_UNKNOWN = 0x1000
} css_text_decoration;
+typedef enum {
+ CSS_BACKGROUND_POSITION_LENGTH,
+ CSS_BACKGROUND_POSITION_PERCENT,
+ CSS_BACKGROUND_POSITION_INHERIT
+} css_background_position;
+
/** Representation of a complete CSS 2 style. */
struct css_style {
colour background_color;
+ css_background_attachment background_attachment;
+
+ struct {
+ enum { CSS_BACKGROUND_IMAGE_NONE,
+ CSS_BACKGROUND_IMAGE_INHERIT,
+ CSS_BACKGROUND_IMAGE_URI } type;
+ char *uri;
+ } background_image;
+
+ struct {
+ struct {
+ css_background_position pos;
+ union {
+ float percent;
+ struct css_length length;
+ } value;
+ } horz;
+ struct {
+ css_background_position pos;
+ union {
+ float percent;
+ struct css_length length;
+ } value;
+ } vert;
+ } background_position;
+
+ css_background_repeat background_repeat;
+
struct {
colour color;
struct {
@@ -246,6 +280,7 @@ struct css_node {
css_combinator comb;
struct css_style *style;
unsigned long specificity;
+ struct content *stylesheet;
};
@@ -282,7 +317,8 @@ void css_destroy(struct content *c);
#ifdef CSS_INTERNALS
-struct css_node * css_new_node(css_node_type type,
+struct css_node * css_new_node(struct content *stylesheet,
+ css_node_type type,
const char *data, unsigned int data_length);
void css_free_node(struct css_node *node);
struct css_selector * css_new_selector(css_selector_type type,
diff --git a/css/css_enums b/css/css_enums
index 2cccda18a..9df8c81aa 100644
--- a/css/css_enums
+++ b/css/css_enums
@@ -1,7 +1,6 @@
css_unit em ex px in cm mm pt pc
css_background_attachment inherit fixed scroll
-css_background_position inherit top center bottom left right length percent
-css_background_repeat inherit repeat repeat_x repeat_y no_repeat
+css_background_repeat inherit repeat repeat-x repeat-y no-repeat
css_border_style inherit none hidden dotted dashed solid double groove ridge inset outset
css_clear inherit none both left right
css_cursor inherit auto crosshair default pointer move e-resize ne-resize nw-resize n-resize se-resize sw-resize s-resize w-resize text wait help
diff --git a/css/parser.y b/css/parser.y
index fc7a56289..b0f0aeba3 100644
--- a/css/parser.y
+++ b/css/parser.y
@@ -211,7 +211,8 @@ declaration_list(A) ::= declaration(B) SEMI declaration_list(C).
{ if (B) { B->next = C; A = B; } else { A = C; } }
declaration(A) ::= property(B) COLON value(C).
- { if (C && (A = css_new_node(CSS_NODE_DECLARATION,
+ { if (C && (A = css_new_node(param->stylesheet,
+ CSS_NODE_DECLARATION,
B.text, B.length)))
A->value = C;
else {
@@ -245,58 +246,71 @@ any_list_1(A) ::= any(B) any_list(C).
{ if (B) { B->next = C; A = B; }
else { css_free_node(B); css_free_node(C); A = 0; } }
any(A) ::= IDENT(B).
- { A = css_new_node(CSS_NODE_IDENT, B.text, B.length);
+ { A = css_new_node(param->stylesheet, CSS_NODE_IDENT,
+ B.text, B.length);
if (!A) param->memory_error = true; }
any(A) ::= NUMBER(B).
- { A = css_new_node(CSS_NODE_NUMBER, B.text, B.length);
+ { A = css_new_node(param->stylesheet, CSS_NODE_NUMBER,
+ B.text, B.length);
if (!A) param->memory_error = true; }
any(A) ::= PERCENTAGE(B).
- { A = css_new_node(CSS_NODE_PERCENTAGE, B.text, B.length);
+ { A = css_new_node(param->stylesheet, CSS_NODE_PERCENTAGE,
+ B.text, B.length);
if (!A) param->memory_error = true; }
any(A) ::= DIMENSION(B).
- { A = css_new_node(CSS_NODE_DIMENSION, B.text, B.length);
+ { A = css_new_node(param->stylesheet, CSS_NODE_DIMENSION,
+ B.text, B.length);
if (!A) param->memory_error = true; }
any(A) ::= STRING(B).
- { A = css_new_node(CSS_NODE_STRING, B.text + 1, B.length - 2);
+ { A = css_new_node(param->stylesheet, CSS_NODE_STRING,
+ B.text + 1, B.length - 2);
if (!A) param->memory_error = true; }
any(A) ::= DELIM(B).
- { A = css_new_node(CSS_NODE_DELIM, B.text, B.length);
+ { A = css_new_node(param->stylesheet, CSS_NODE_DELIM,
+ B.text, B.length);
if (!A) param->memory_error = true; }
any(A) ::= URI(B).
- { A = css_new_node(CSS_NODE_URI, B.text, B.length);
+ { A = css_new_node(param->stylesheet, CSS_NODE_URI,
+ B.text, B.length);
if (!A) param->memory_error = true; }
any(A) ::= HASH(B).
- { A = css_new_node(CSS_NODE_HASH, B.text, B.length);
+ { A = css_new_node(param->stylesheet, CSS_NODE_HASH,
+ B.text, B.length);
if (!A) param->memory_error = true; }
any(A) ::= UNICODE_RANGE(B).
- { A = css_new_node(CSS_NODE_UNICODE_RANGE, B.text, B.length);
+ { A = css_new_node(param->stylesheet, CSS_NODE_UNICODE_RANGE,
+ B.text, B.length);
if (!A) param->memory_error = true; }
any(A) ::= INCLUDES.
- { A = css_new_node(CSS_NODE_INCLUDES, 0, 0);
+ { A = css_new_node(param->stylesheet, CSS_NODE_INCLUDES,
+ 0, 0);
if (!A) param->memory_error = true; }
any(A) ::= FUNCTION(B).
- { A = css_new_node(CSS_NODE_FUNCTION, B.text, B.length);
+ { A = css_new_node(param->stylesheet, CSS_NODE_FUNCTION,
+ B.text, B.length);
if (!A) param->memory_error = true; }
any(A) ::= DASHMATCH.
- { A = css_new_node(CSS_NODE_DASHMATCH, 0, 0);
+ { A = css_new_node(param->stylesheet, CSS_NODE_DASHMATCH,
+ 0, 0);
if (!A) param->memory_error = true; }
any(A) ::= COLON.
- { A = css_new_node(CSS_NODE_COLON, 0, 0);
+ { A = css_new_node(param->stylesheet, CSS_NODE_COLON, 0, 0);
if (!A) param->memory_error = true; }
any(A) ::= COMMA.
- { A = css_new_node(CSS_NODE_COMMA, 0, 0);
+ { A = css_new_node(param->stylesheet, CSS_NODE_COMMA, 0, 0);
if (!A) param->memory_error = true; }
any(A) ::= DOT.
- { A = css_new_node(CSS_NODE_DOT, 0, 0);
+ { A = css_new_node(param->stylesheet, CSS_NODE_DOT, 0, 0);
if (!A) param->memory_error = true; }
any(A) ::= PLUS.
- { A = css_new_node(CSS_NODE_PLUS, 0, 0);
+ { A = css_new_node(param->stylesheet, CSS_NODE_PLUS, 0, 0);
if (!A) param->memory_error = true; }
any(A) ::= GT.
- { A = css_new_node(CSS_NODE_GT, 0, 0);
+ { A = css_new_node(param->stylesheet, CSS_NODE_GT, 0, 0);
if (!A) param->memory_error = true; }
any(A) ::= LPAREN any_list(B) RPAREN.
- { if ((A = css_new_node(CSS_NODE_PAREN, 0, 0)))
+ { if ((A = css_new_node(param->stylesheet, CSS_NODE_PAREN,
+ 0, 0)))
A->value = B;
else {
param->memory_error = true;
@@ -304,7 +318,8 @@ any(A) ::= LPAREN any_list(B) RPAREN.
A = 0;
} }
any(A) ::= LBRAC any_list(B) RBRAC.
- { if ((A = css_new_node(CSS_NODE_BRAC, 0, 0)))
+ { if ((A = css_new_node(param->stylesheet, CSS_NODE_BRAC,
+ 0, 0)))
A->value = B;
else {
param->memory_error = true;
@@ -312,7 +327,8 @@ any(A) ::= LBRAC any_list(B) RBRAC.
A = 0;
} }
any(A) ::= ASTERISK(B).
- { A = css_new_node(CSS_NODE_DELIM, B.text, B.length);
+ { A = css_new_node(param->stylesheet, CSS_NODE_DELIM,
+ B.text, B.length);
if (!A) param->memory_error = true; }
diff --git a/css/ruleset.c b/css/ruleset.c
index e2e0d03bd..345b86225 100644
--- a/css/ruleset.c
+++ b/css/ruleset.c
@@ -23,6 +23,7 @@
#include "netsurf/content/content.h"
#include "netsurf/desktop/options.h"
#include "netsurf/utils/log.h"
+#include "netsurf/utils/url.h"
#include "netsurf/utils/utils.h"
@@ -33,7 +34,11 @@ static int parse_length(struct css_length * const length,
const struct css_node * const v, bool non_negative);
static colour parse_colour(const struct css_node * const v);
static void parse_background(struct css_style * const s, const struct css_node * v);
+static void parse_background_attachment(struct css_style * const s, const struct css_node * const v);
static void parse_background_color(struct css_style * const s, const struct css_node * const v);
+static void parse_background_image(struct css_style * const s, const struct css_node * const v);
+static void parse_background_position(struct css_style * const s, const struct css_node * const v);
+static void parse_background_repeat(struct css_style * const s, const struct css_node * const v);
static void parse_border(struct css_style * const s, const struct css_node * v);
static void parse_border_bottom(struct css_style * const s, const struct css_node * v);
static void parse_border_bottom_color(struct css_style * const s, const struct css_node * v);
@@ -102,7 +107,7 @@ static css_text_decoration css_text_decoration_parse(const char * const s,
/** An entry in css_property_table. */
struct css_property_entry {
- const char name[20];
+ const char name[25];
void (*parse) (struct css_style * const s,
const struct css_node * const v);
};
@@ -110,7 +115,11 @@ struct css_property_entry {
/** Table of property parsers. MUST be sorted by property name. */
static const struct css_property_entry css_property_table[] = {
{ "background", parse_background },
+ { "background-attachment", parse_background_attachment },
{ "background-color", parse_background_color },
+ { "background-image", parse_background_image },
+ { "background-position", parse_background_position },
+ { "background-repeat", parse_background_repeat },
{ "border", parse_border },
{ "border-bottom", parse_border_bottom },
{ "border-bottom-color", parse_border_bottom_color },
@@ -481,6 +490,16 @@ void parse_background(struct css_style * const s, const struct css_node * v)
}
}
+void parse_background_attachment(struct css_style * const s, const struct css_node * const v)
+{
+ css_background_attachment z;
+ if (v->type != CSS_NODE_IDENT || v->next != 0)
+ return;
+ z = css_background_attachment_parse(v->data, v->data_length);
+ if (z != CSS_BACKGROUND_ATTACHMENT_UNKNOWN)
+ s->background_attachment = z;
+}
+
void parse_background_color(struct css_style * const s, const struct css_node * const v)
{
colour c = parse_colour(v);
@@ -488,6 +507,262 @@ void parse_background_color(struct css_style * const s, const struct css_node *
s->background_color = c;
}
+void parse_background_image(struct css_style * const s, const struct css_node * const v)
+{
+ bool string = false;
+ const char *u;
+ char *t, *url;
+ s->background_image.uri = 0;
+
+ switch (v->type) {
+ case CSS_NODE_URI:
+ for (u = v->data + 4;
+ *u == ' ' || *u == '\t' || *u == '\r' ||
+ *u == '\n' || *u == '\f';
+ u++)
+ ;
+ if (*u == '\'' || *u == '"') {
+ string = true;
+ u++;
+ }
+ url = strndup(u, v->data_length - (u - v->data));
+ if (!url) {
+ return;
+ }
+ for (t = url + strlen(url) - 2;
+ *t == ' ' || *t == '\t' || *t == '\r' ||
+ *t == '\n' || *t == '\f';
+ t--)
+ ;
+ if (string)
+ *t = 0;
+ else
+ *(t + 1) = 0;
+
+ s->background_image.uri = url_join(url, v->stylesheet->url);
+ free(url);
+ if (!s->background_image.uri) return;
+ s->background_image.type = CSS_BACKGROUND_IMAGE_URI;
+ break;
+ case CSS_NODE_STRING:
+ url = strndup(v->data, v->data_length);
+ if (!url)
+ return;
+
+ s->background_image.uri = url_join(url, v->stylesheet->url);
+ free(url);
+ if (!s->background_image.uri) return;
+ s->background_image.type = CSS_BACKGROUND_IMAGE_URI;
+ break;
+ case CSS_NODE_IDENT:
+ if (v->data_length == 7 && strncasecmp(v->data, "inherit", 7) == 0)
+ s->background_image.type = CSS_BACKGROUND_IMAGE_INHERIT;
+ else if (v->data_length == 4 && strncasecmp(v->data, "none", 4) == 0)
+ s->background_image.type = CSS_BACKGROUND_IMAGE_NONE;
+ break;
+ default:
+ break;
+ }
+}
+
+void parse_background_position(struct css_style * const s, const struct css_node * v)
+{
+ struct css_node *w = v->next;
+
+ if (!w) { /* only one value specified */
+ if (v->type == CSS_NODE_IDENT) {
+ if (v->data_length == 3 && strncasecmp(v->data, "top", 3) == 0) {
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 50.0;
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 0.0;
+ }
+ else if (v->data_length == 4 && strncasecmp(v->data, "left", 4) == 0) {
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 0.0;
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 50.0;
+ }
+ else if (v->data_length == 6 && strncasecmp(v->data, "center", 6) == 0) {
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 50.0;
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 50.0;
+ }
+ else if (v->data_length == 5 && strncasecmp(v->data, "right", 5) == 0) {
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 100.0;
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 50.0;
+ }
+ else if (v->data_length == 6 && strncasecmp(v->data, "bottom", 6) == 0) {
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 50.0;
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 100.0;
+ }
+ }
+ else if (v->type == CSS_NODE_PERCENTAGE) {
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = atof(v->data);
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 50.0;
+ }
+ else if (v->type == CSS_NODE_DIMENSION) {
+
+ if (parse_length(&s->background_position.horz.value.length, v, false) == 0) {
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_LENGTH;
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 50.0;
+ }
+ }
+ }
+
+ /* two values specified */
+ if (v->type == CSS_NODE_IDENT && w->type == CSS_NODE_IDENT) {
+ /* both keywords */
+ if ((v->data_length == 3 && strncasecmp(v->data, "top", 3) == 0 && w->data_length == 4 && strncasecmp(w->data, "left", 4) == 0) ||
+ (v->data_length == 4 && strncasecmp(v->data, "left", 4) == 0 && w->data_length == 3 && strncasecmp(w->data, "top", 3) == 0)) {
+ /* top left / left top */
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 0.0;
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 0.0;
+ }
+ else if ((v->data_length == 3 && strncasecmp(v->data, "top", 3) == 0 && w->data_length == 6 && strncasecmp(w->data, "center", 6) == 0) ||
+ (v->data_length == 6 && strncasecmp(v->data, "center", 6) == 0 && w->data_length == 3 && strncasecmp(w->data, "top", 3) == 0)) {
+ /* top center / center top */
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 50.0;
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 0.0;
+ }
+ else if ((v->data_length == 3 && strncasecmp(v->data, "top", 3) == 0 && w->data_length == 5 && strncasecmp(w->data, "right", 5) == 0) ||
+ (v->data_length == 5 && strncasecmp(v->data, "right", 5) == 0 && w->data_length == 3 && strncasecmp(w->data, "top", 3) == 0)) {
+ /* top right / right top */
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 100.0;
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 0.0;
+ }
+ else if ((v->data_length == 4 && strncasecmp(v->data, "left", 4) == 0 && w->data_length == 6 && strncasecmp(w->data, "center", 6) == 0) ||
+ (v->data_length == 6 && strncasecmp(v->data, "center", 6) == 0 && w->data_length == 4 && strncasecmp(w->data, "left", 4) == 0)) {
+ /* left center / center left */
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 0.0;
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 50.0;
+ }
+ else if (v->data_length == 6 && strncasecmp(v->data, "center", 6) == 0 && w->data_length == 6 && strncasecmp(w->data, "center", 6) == 0) {
+ /* center center */
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 50.0;
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 50.0;
+ }
+ else if ((v->data_length == 5 && strncasecmp(v->data, "right", 5) == 0 && w->data_length == 6 && strncasecmp(w->data, "center", 6) == 0) ||
+ (v->data_length == 6 && strncasecmp(v->data, "center", 6) == 0 && w->data_length == 5 && strncasecmp(w->data, "right", 5) == 0)) {
+ /* right center / center right */
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 100.0;
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 50.0;
+ }
+ else if ((v->data_length == 6 && strncasecmp(v->data, "bottom", 6) == 0 && w->data_length == 4 && strncasecmp(w->data, "left", 4) == 0) ||
+ (v->data_length == 4 && strncasecmp(v->data, "left", 4) == 0 && w->data_length == 6 && strncasecmp(w->data, "bottom", 6) == 0)) {
+ /* bottom left / left bottom */
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 0.0;
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 100.0;
+ }
+ else if ((v->data_length == 6 && strncasecmp(v->data, "bottom", 6) == 0 && w->data_length == 6 && strncasecmp(w->data, "center", 6) == 0) ||
+ (v->data_length == 6 && strncasecmp(v->data, "center", 6) == 0 && w->data_length == 6 && strncasecmp(w->data, "bottom", 6) == 0)) {
+ /* bottom center / center bottom */
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 50.0;
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 100.0;
+ }
+ else if ((v->data_length == 6 && strncasecmp(v->data, "bottom", 6) == 0 && w->data_length == 5 && strncasecmp(w->data, "right", 5) == 0) ||
+ (v->data_length == 5 && strncasecmp(v->data, "right", 5) == 0 && w->data_length == 6 && strncasecmp(w->data, "bottom", 6) == 0)) {
+ /* bottom right / right bottom */
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 100.0;
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 100.0;
+ }
+ }
+ else {
+ switch (v->type) { /* horizontal value */
+ case CSS_NODE_IDENT:
+ if (v->data_length == 7 && strncasecmp(v->data, "inherit", 7) == 0)
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_INHERIT;
+ else if (v->data_length == 4 && strncasecmp(v->data, "left", 4) == 0) {
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 0.0;
+ }
+ else if (v->data_length == 5 && strncasecmp(v->data, "right", 5) == 0) {
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 100.0;
+ }
+ else if (v->data_length == 6 && strncasecmp(v->data, "center", 6) == 0) {
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = 50.0;
+ }
+ break;
+ case CSS_NODE_PERCENTAGE:
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.horz.value.percent = atof(v->data);
+ break;
+ case CSS_NODE_DIMENSION:
+ if (parse_length(&s->background_position.horz.value.length, v, false) == 0)
+ s->background_position.horz.pos = CSS_BACKGROUND_POSITION_LENGTH;
+ break;
+ default:
+ break;
+ }
+ switch (w->type) { /* vertical value */
+ case CSS_NODE_IDENT:
+ if (v->data_length == 7 && strncasecmp(v->data, "inherit", 7) == 0)
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_INHERIT;
+ else if (v->data_length == 3 && strncasecmp(v->data, "top", 3) == 0) {
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 0.0;
+ }
+ else if (v->data_length == 6 && strncasecmp(v->data, "bottom", 6) == 0) {
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 100.0;
+ }
+ else if (v->data_length == 6 && strncasecmp(v->data, "center", 6) == 0) {
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = 50.0;
+ }
+ break;
+ case CSS_NODE_PERCENTAGE:
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_PERCENT;
+ s->background_position.vert.value.percent = atof(v->data);
+ break;
+ case CSS_NODE_DIMENSION:
+ if (parse_length(&s->background_position.vert.value.length, v, false) == 0)
+ s->background_position.vert.pos = CSS_BACKGROUND_POSITION_LENGTH;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void parse_background_repeat(struct css_style * const s, const struct css_node * const v)
+{
+ css_background_repeat z;
+ if (v->type != CSS_NODE_IDENT || v->next != 0)
+ return;
+ z = css_background_repeat_parse(v->data, v->data_length);
+ if (z != CSS_BACKGROUND_REPEAT_UNKNOWN)
+ s->background_repeat = z;
+}
+
void parse_border_width(struct css_style * const s,
const struct css_node * const v)
{
diff --git a/render/box.c b/render/box.c
index fdda43c94..eb0befdfd 100644
--- a/render/box.c
+++ b/render/box.c
@@ -60,12 +60,30 @@ struct box_multi_length {
float value;
};
+static const content_type image_types[] = {
+#ifdef WITH_JPEG
+ CONTENT_JPEG,
+#endif
+#ifdef WITH_GIF
+ CONTENT_GIF,
+#endif
+#ifdef WITH_PNG
+ CONTENT_PNG,
+#endif
+#ifdef WITH_SPRITE
+ CONTENT_SPRITE,
+#endif
+#ifdef WITH_DRAW
+ CONTENT_DRAW,
+#endif
+ CONTENT_UNKNOWN };
static struct box * convert_xml_to_box(xmlNode * n, struct content *content,
struct css_style * parent_style,
struct box * parent, struct box *inline_container,
struct box_status status);
-static struct css_style * box_get_style(struct content ** stylesheet,
+static struct css_style * box_get_style(struct content *c,
+ struct content ** stylesheet,
unsigned int stylesheet_count, struct css_style * parent_style,
xmlNode * n);
static void box_text_transform(char *s, unsigned int len,
@@ -195,6 +213,7 @@ struct box * box_create(struct css_style * style,
box->font = 0;
box->gadget = 0;
box->usemap = 0;
+ box->background = 0;
box->object = 0;
box->object_params = 0;
box->object_state = 0;
@@ -312,7 +331,7 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content,
gui_multitask();
- style = box_get_style(content->data.html.stylesheet_content,
+ style = box_get_style(content, content->data.html.stylesheet_content,
content->data.html.stylesheet_count, parent_style, n);
LOG(("display: %s", css_display_name[style->display]));
if (style->display == CSS_DISPLAY_NONE) {
@@ -551,6 +570,17 @@ end:
if (!href_in)
xmlFree(status.href);
+ /* Now fetch any background image for this box */
+ if (box && box->style &&
+ box->style->background_image.type == CSS_BACKGROUND_IMAGE_URI) {
+ /* start fetch */
+ html_fetch_object(content, box->style->background_image.uri,
+ box,
+ image_types,
+ content->available_width,
+ 1000);
+ }
+
LOG(("node %p, node type %i END", n, n->type));
return inline_container;
}
@@ -565,7 +595,8 @@ end:
* 3. the 'style' attribute
*/
-struct css_style * box_get_style(struct content ** stylesheet,
+struct css_style * box_get_style(struct content *c,
+ struct content ** stylesheet,
unsigned int stylesheet_count, struct css_style * parent_style,
xmlNode * n)
{
@@ -584,6 +615,19 @@ struct css_style * box_get_style(struct content ** stylesheet,
}
css_cascade(style, &style_new);
+ /* This property only applies to the body element, if you believe
+ the spec. Many browsers seem to allow it on other elements too,
+ so let's be generic ;)
+ */
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "background"))) {
+ style->background_image.type = CSS_BACKGROUND_IMAGE_URI;
+ /**\todo This will leak memory. */
+ style->background_image.uri = url_join(s, c->data.html.base_url);
+ if (!style->background_image.uri)
+ style->background_image.type = CSS_BACKGROUND_IMAGE_NONE;
+ xmlFree(s);
+ }
+
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "bgcolor"))) {
unsigned int r, g, b;
if (s[0] == '#' && sscanf(s + 1, "%2x%2x%2x", &r, &g, &b) == 3)
@@ -747,7 +791,6 @@ void box_text_transform(char *s, unsigned int len,
* have been processed in some way by the function). If box is 0, no box will
* be created for that element, and convert_children must be 0.
*/
-
struct box_result box_a(xmlNode *n, struct box_status *status,
struct css_style *style)
{
@@ -765,8 +808,9 @@ struct box_result box_body(xmlNode *n, struct box_status *status,
{
struct box *box;
status->content->data.html.background_colour = style->background_color;
- box = box_create(style, status->href, status->title,
+ box = box_create(style, status->href, status->title,
status->content->data.html.box_pool);
+
return (struct box_result) {box, true, false};
}
@@ -780,24 +824,6 @@ struct box_result box_br(xmlNode *n, struct box_status *status,
return (struct box_result) {box, false, false};
}
-static const content_type image_types[] = {
-#ifdef WITH_JPEG
- CONTENT_JPEG,
-#endif
-#ifdef WITH_GIF
- CONTENT_GIF,
-#endif
-#ifdef WITH_PNG
- CONTENT_PNG,
-#endif
-#ifdef WITH_SPRITE
- CONTENT_SPRITE,
-#endif
-#ifdef WITH_DRAW
- CONTENT_DRAW,
-#endif
- CONTENT_UNKNOWN };
-
struct box_result box_image(xmlNode *n, struct box_status *status,
struct css_style *style)
{
diff --git a/render/box.h b/render/box.h
index b4ecfa631..c1250469a 100644
--- a/render/box.h
+++ b/render/box.h
@@ -77,6 +77,7 @@
#include <stdbool.h>
#include "libxml/HTMLparser.h"
#include "netsurf/utils/config.h"
+#include "netsurf/content/content_type.h"
#include "netsurf/css/css.h"
#include "netsurf/render/font.h"
#include "netsurf/utils/pool.h"
@@ -189,6 +190,9 @@ struct box {
char *usemap; /** (Image)map to use with this object, or 0 if none */
+ /** Background image for this box, or 0 if none */
+ struct content *background;
+
/** Object in this box (usually an image), or 0 if none. */
struct content* object;
/** Parameters for the object, or 0. */
diff --git a/render/html.c b/render/html.c
index 722fcc5ba..12f286579 100644
--- a/render/html.c
+++ b/render/html.c
@@ -38,7 +38,8 @@ static void html_head(struct content *c, xmlNode *head);
static void html_find_stylesheets(struct content *c, xmlNode *head);
static void html_object_callback(content_msg msg, struct content *object,
void *p1, void *p2, union content_msg_data data);
-static void html_object_done(struct box *box, struct content *object);
+static void html_object_done(struct box *box, struct content *object,
+ bool background);
static bool html_object_type_permitted(const content_type type,
const content_type *permitted_types);
@@ -537,6 +538,10 @@ void html_fetch_object(struct content *c, char *url, struct box *box,
c->data.html.object[i].url = url;
c->data.html.object[i].box = box;
c->data.html.object[i].permitted_types = permitted_types;
+ if (box->style->background_image.type == CSS_BACKGROUND_IMAGE_URI)
+ c->data.html.object[i].background = true;
+ else
+ c->data.html.object[i].background = false;
/* start fetch */
c->data.html.object[i].content = fetchcache(url, c->url,
@@ -591,13 +596,13 @@ void html_object_callback(content_msg msg, struct content *object,
case CONTENT_MSG_READY:
if (object->type == CONTENT_HTML) {
- html_object_done(box, object);
+ html_object_done(box, object, c->data.html.object[i].background);
content_reformat(c, c->available_width, 0);
}
break;
case CONTENT_MSG_DONE:
- html_object_done(box, object);
+ html_object_done(box, object, c->data.html.object[i].background);
c->active--;
break;
@@ -696,11 +701,17 @@ void html_object_callback(content_msg msg, struct content *object,
* Update a box whose content has completed rendering.
*/
-void html_object_done(struct box *box, struct content *object)
+void html_object_done(struct box *box, struct content *object,
+ bool background)
{
struct box *b;
- box->object = object;
+ if (background) {
+ box->background = object;
+ }
+ else {
+ box->object = object;
+ }
if (box->width != UNKNOWN_WIDTH &&
object->available_width != box->width)
diff --git a/render/html.h b/render/html.h
index 8446b651e..860af9680 100644
--- a/render/html.h
+++ b/render/html.h
@@ -14,6 +14,7 @@
#ifndef _NETSURF_RENDER_HTML_H_
#define _NETSURF_RENDER_HTML_H_
+#include <stdbool.h>
#include "libxml/HTMLparser.h"
#include "netsurf/content/content_type.h"
#include "netsurf/css/css.h"
@@ -72,6 +73,7 @@ struct content_html_data {
/** Pointer to array of permitted content_type, terminated by
* CONTENT_UNKNOWN, or 0 if any type is acceptable. */
const content_type *permitted_types;
+ bool background; /** Is this object a background image? */
} *object;
struct imagemap **imagemaps; /**< Hashtable of imagemaps */
diff --git a/riscos/htmlredraw.c b/riscos/htmlredraw.c
index 2d85204fb..be16fee17 100644
--- a/riscos/htmlredraw.c
+++ b/riscos/htmlredraw.c
@@ -12,11 +12,15 @@
#include "oslib/colourtrans.h"
#include "oslib/draw.h"
#include "oslib/font.h"
+#include "swis.h"
+#include "netsurf/utils/config.h"
#include "netsurf/css/css.h"
#include "netsurf/content/content.h"
#include "netsurf/render/form.h"
#include "netsurf/render/html.h"
#include "netsurf/riscos/gui.h"
+#include "netsurf/riscos/options.h"
+#include "netsurf/riscos/tinct.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/messages.h"
#include "netsurf/utils/utils.h"
@@ -44,6 +48,8 @@ static void html_redraw_radio(int x, int y, int width, int height,
bool selected);
static void html_redraw_file(int x, int y, int width, int height,
struct box *box, float scale);
+static void html_redraw_background(long x, long y, int width, int height,
+ struct box *box);
bool gui_redraw_debug = false;
@@ -194,7 +200,7 @@ void html_redraw_box(struct content *content, struct box * box,
if (clip_x1 < x1) x1 = clip_x1;
if (clip_y1 < y1) y1 = clip_y1;
/* clip to it */
- html_redraw_clip(x0, y0, x1, y1);
+ html_redraw_clip(x0, y0, x1, y1);
} else {
/* clip box unchanged */
x0 = clip_x0;
@@ -210,6 +216,8 @@ void html_redraw_box(struct content *content, struct box * box,
int py0 = y - padding_height < y0 ? y0 : y - padding_height;
int px1 = x + padding_width < x1 ? x + padding_width : x1;
int py1 = y < y1 ? y : y1;
+ /* clip to it */
+ html_redraw_clip(px0, py0, px1, py1);
colourtrans_set_gcol(box->style->background_color << 8,
colourtrans_USE_ECFS, os_ACTION_OVERWRITE, 0);
os_plot(os_MOVE_TO, px0, py0);
@@ -218,6 +226,9 @@ void html_redraw_box(struct content *content, struct box * box,
current_background_color = box->style->background_color;
}
+ /* plot background image */
+ html_redraw_background(x, y, width, clip_y1-clip_y0, box);
+
if (box->object) {
content_redraw(box->object, x + padding_left, y - padding_top,
width, height, x0, y0, x1, y1, scale);
@@ -365,7 +376,7 @@ void html_redraw_box(struct content *content, struct box * box,
if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
box->type == BOX_TABLE_CELL || box->object)
- html_redraw_clip(clip_x0, clip_y0, clip_x1, clip_y1);
+ html_redraw_clip(clip_x0, clip_y0, clip_x1, clip_y1);
/* } else {
if (content->data.html.text_selection.selected == 1) {
@@ -542,3 +553,113 @@ void html_redraw_file(int x, int y, int width, int height,
/* xwimpspriteop_put_sprite_user_coords(sprite, x + 4, */
/* y - height / 2 - 17, os_ACTION_OVERWRITE); */
}
+
+void html_redraw_background(long xi, long yi, int width, int height,
+ struct box *box)
+{
+ unsigned int tinct_options = 0;
+ long x = 0;
+ long y = 0;
+ float multiplier;
+ bool fixed = false;
+
+ if (box->background == 0) return;
+
+ if (ro_gui_current_redraw_gui) {
+ tinct_options = (ro_gui_current_redraw_gui->option_filter_sprites?tinct_BILINEAR_FILTER:0) |
+ (ro_gui_current_redraw_gui->option_dither_sprites?tinct_DITHER:0);
+ } else {
+ tinct_options = (option_filter_sprites?tinct_BILINEAR_FILTER:0) |
+ (option_dither_sprites?tinct_DITHER:0);
+ }
+
+ /* handle background-attachment */
+ switch (box->style->background_attachment) {
+ case CSS_BACKGROUND_ATTACHMENT_FIXED:
+ fixed = true;
+ break;
+ case CSS_BACKGROUND_ATTACHMENT_SCROLL:
+ break;
+ default:
+ break;
+ }
+
+ /* handle background-repeat */
+ switch (box->style->background_repeat) {
+ case CSS_BACKGROUND_REPEAT_REPEAT:
+ tinct_options |= tinct_FILL_HORIZONTALLY | tinct_FILL_VERTICALLY;
+ break;
+ case CSS_BACKGROUND_REPEAT_REPEAT_X:
+ tinct_options |= tinct_FILL_HORIZONTALLY;
+ break;
+ case CSS_BACKGROUND_REPEAT_REPEAT_Y:
+ tinct_options |= tinct_FILL_VERTICALLY;
+ break;
+ case CSS_BACKGROUND_REPEAT_NO_REPEAT:
+ x = xi;
+ if (fixed)
+ /**\todo fixed background attachments */
+ y = yi/*-height*/;
+ else
+ y = yi-height;
+ break;
+ default:
+ break;
+ }
+
+ /* handle background-position */
+ switch (box->style->background_position.horz.pos) {
+ case CSS_BACKGROUND_POSITION_PERCENT:
+ multiplier =
+ box->style->background_position.horz.value.percent / 100;
+ x += box->x + (box->width * multiplier) -
+ (box->background->width * multiplier);
+ break;
+ case CSS_BACKGROUND_POSITION_LENGTH:
+ x += box->x + len(&box->style->background_position.horz.value.length, box->style);
+ break;
+ default:
+ break;
+ }
+
+ switch (box->style->background_position.vert.pos) {
+ case CSS_BACKGROUND_POSITION_PERCENT:
+ multiplier =
+ box->style->background_position.vert.value.percent / 100;
+ y += box->y + (box->height * multiplier) -
+ (box->background->height * multiplier);
+ break;
+ case CSS_BACKGROUND_POSITION_LENGTH:
+ y += box->y + len(&box->style->background_position.vert.value.length, box->style);
+ break;
+ default:
+ break;
+ }
+
+// LOG(("Body [%ld, %ld], Image: [%ld, %ld], Flags: %x", xi, yi, x, y, tinct_options));
+
+ /* and plot the image */
+ switch (box->background->type) {
+#ifdef WITH_PNG
+ case CONTENT_PNG:
+ _swix(Tinct_PlotAlpha, _INR(2,4) | _IN(7),
+ ((char*) box->background->data.png.sprite_area + box->background->data.png.sprite_area->first), x, y, tinct_options);
+ break;
+#endif
+#ifdef WITH_JPEG
+ case CONTENT_JPEG:
+ _swix(Tinct_Plot, _INR(2,4) | _IN(7),
+ ((char*) box->background->data.jpeg.sprite_area + box->background->data.jpeg.sprite_area->first), x, -y, tinct_options);
+ break;
+#endif
+#ifdef WITH_GIF
+ case CONTENT_GIF:
+ _swix(Tinct_PlotAlpha, _INR(2,4) | _IN(7),
+ (char*) box->background->data.gif.gif->frame_image, x, -y, tinct_options);
+ break;
+#endif
+ /**\todo Add draw/sprite background support? */
+ default:
+ break;
+ }
+}