summaryrefslogtreecommitdiff
path: root/render/box_construct.c
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2011-01-04 21:52:43 +0000
committerMichael Drake <tlsa@netsurf-browser.org>2011-01-04 21:52:43 +0000
commit61b7c722be75e7456ff3826c25fc509d8f72459c (patch)
tree9c64c8e2244efd74d7b77224761878bb16ddf1f4 /render/box_construct.c
parentf929155a40fbc9afb42456cb46581592e57ef6dc (diff)
downloadnetsurf-61b7c722be75e7456ff3826c25fc509d8f72459c.tar.gz
netsurf-61b7c722be75e7456ff3826c25fc509d8f72459c.tar.bz2
Implement enough support for the :after pseudo element for the widely-used clearfix CSS layout hack to work.
svn path=/trunk/netsurf/; revision=11206
Diffstat (limited to 'render/box_construct.c')
-rw-r--r--render/box_construct.c116
1 files changed, 103 insertions, 13 deletions
diff --git a/render/box_construct.c b/render/box_construct.c
index b115dc026..8bdd59491 100644
--- a/render/box_construct.c
+++ b/render/box_construct.c
@@ -103,12 +103,15 @@ bool box_construct_element(xmlNode *n, struct content *content,
const css_computed_style *parent_style,
struct box *parent, struct box **inline_container,
char *href, const char *target, char *title);
+void box_construct_after(xmlNode *n, struct content *content,
+ struct box *box, const css_computed_style *style);
bool box_construct_text(xmlNode *n, struct content *content,
const css_computed_style *parent_style,
struct box *parent, struct box **inline_container,
char *href, const char *target, char *title);
static css_computed_style * box_get_style(struct content *c,
- const css_computed_style *parent_style, xmlNode *n);
+ const css_computed_style *parent_style, xmlNode *n,
+ enum css_pseudo_element pseudo_element);
static void box_text_transform(char *s, unsigned int len,
enum css_text_transform_e tt);
#define BOX_SPECIAL_PARAMS xmlNode *n, struct content *content, \
@@ -305,16 +308,17 @@ bool box_construct_element(xmlNode *n, struct content *content,
*/
parent->strip_leading_newline = 0;
- style = box_get_style(content, parent_style, n);
+ style = box_get_style(content, parent_style, n,
+ CSS_PSEUDO_ELEMENT_NONE);
if (!style)
return false;
/* extract title attribute, if present */
if ((title0 = xmlGetProp(n, (const xmlChar *) "title"))) {
char *title1 = squash_whitespace((char *) title0);
-
+
xmlFree(title0);
-
+
if (!title1)
return false;
@@ -581,21 +585,105 @@ bool box_construct_element(xmlNode *n, struct content *content,
}
/* fetch any background image for this box */
- if (css_computed_background_image(style, &bgimage_uri) ==
- CSS_BACKGROUND_IMAGE_IMAGE &&
+ if (css_computed_background_image(style, &bgimage_uri) ==
+ CSS_BACKGROUND_IMAGE_IMAGE &&
bgimage_uri != NULL) {
- if (!html_fetch_object(content,
+ if (!html_fetch_object(content,
lwc_string_data(bgimage_uri),
box, image_types, content->available_width,
1000, true))
return false;
}
+ /* handle the :after pseudo element */
+
+ /* TODO: Replace with true implementation.
+ * Currently we only implement enough of this to support the
+ * 'clearfix' hack, which is in widespread use and the layout
+ * of many sites depend on. As such, only bother if box is a
+ * block for now. */
+ if (box->type == BOX_BLOCK) {
+ box_construct_after(n, content, box, style);
+ }
+
return true;
}
/**
+ * Construct the box required for an :after pseudo element.
+ *
+ * \param n XML node of type XML_ELEMENT_NODE
+ * \param content content of type CONTENT_HTML that is being processed
+ * \param box box which may have an :after s
+ * \param style box's style
+ *
+ * TODO:
+ * This is currently incomplete. It just does enough to support the clearfix
+ * hack. ( http://www.positioniseverything.net/easyclearing.html )
+ *
+ * To determine if an element has a pseudo element, we select for it and test to
+ * see if the returned style's content property is set to normal.
+ *
+ * We don't actually support generated content yet.
+ */
+
+void box_construct_after(xmlNode *n, struct content *content,
+ struct box *box, const css_computed_style *style)
+{
+ struct box *after = 0;
+ css_computed_style *after_style = 0;
+ const css_computed_content_item *c_item;
+
+ after_style = box_get_style(content, style, n,
+ CSS_PSEUDO_ELEMENT_AFTER);
+ if (!after_style)
+ return;
+
+ /* create box for this element */
+ if (css_computed_content(after_style, &c_item) != CSS_CONTENT_NORMAL &&
+ css_computed_display(after_style, n->parent == NULL) ==
+ CSS_DISPLAY_BLOCK) {
+ /* :after exists */
+ after = box_create(after_style, true, NULL, NULL, NULL, NULL,
+ content);
+ if (!after) {
+ css_computed_style_destroy(after_style);
+ return;
+ }
+
+ /* set box type from computed display */
+ if ((css_computed_position(after_style) ==
+ CSS_POSITION_ABSOLUTE ||
+ css_computed_position(after_style) ==
+ CSS_POSITION_FIXED) &&
+ (css_computed_display_static(after_style) ==
+ CSS_DISPLAY_INLINE ||
+ css_computed_display_static(after_style) ==
+ CSS_DISPLAY_INLINE_BLOCK ||
+ css_computed_display_static(after_style) ==
+ CSS_DISPLAY_INLINE_TABLE)) {
+ /* Special case for absolute positioning: make
+ * absolute inlines into inline block so that
+ * the boxes are constructed in an inline
+ * container as if they were not absolutely
+ * positioned. Layout expects and handles
+ * this. */
+ after->type = box_map[CSS_DISPLAY_INLINE_BLOCK];
+ } else {
+ /* Normal mapping */
+ after->type = box_map[css_computed_display(
+ after_style, n->parent == NULL)];
+ }
+
+ box_add_child(box, after);
+ } else {
+ css_computed_style_destroy(after_style);
+ }
+}
+
+
+/**
* Construct the box tree for an XML text node.
*
* \param n XML node of type XML_TEXT_NODE
@@ -823,14 +911,15 @@ bool box_construct_text(xmlNode *n, struct content *content,
/**
* Get the style for an element.
*
- * \param c content of type CONTENT_HTML that is being processed
- * \param parent_style style at this point in xml tree, or NULL for root
- * \param n node in xml tree
+ * \param c content of type CONTENT_HTML that is being processed
+ * \param parent_style style at this point in xml tree, or NULL for root
+ * \param n node in xml tree
+ * \param pseudo_element type of (pseudo) element to select for
* \return the new style, or NULL on memory exhaustion
*/
css_computed_style *box_get_style(struct content *c,
const css_computed_style *parent_style,
- xmlNode *n)
+ xmlNode *n, enum css_pseudo_element pseudo_element)
{
char *s;
css_stylesheet *inline_style = NULL;
@@ -838,7 +927,8 @@ css_computed_style *box_get_style(struct content *c,
css_computed_style *style;
/* Firstly, construct inline stylesheet, if any */
- if ((s = (char *) xmlGetProp(n, (const xmlChar *) "style"))) {
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "style")) &&
+ pseudo_element == CSS_PSEUDO_ELEMENT_NONE) {
inline_style = nscss_create_inline_style(
(uint8_t *) s, strlen(s),
c->data.html.encoding, content__get_url(c),
@@ -852,7 +942,7 @@ css_computed_style *box_get_style(struct content *c,
}
/* Select partial style for element */
- partial = nscss_get_style(c, n, CSS_PSEUDO_ELEMENT_NONE,
+ partial = nscss_get_style(c, n, pseudo_element,
CSS_MEDIA_SCREEN, inline_style,
box_style_alloc, NULL);