mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
Merge branch 'css'
This commit is contained in:
commit
0ef89025ab
@ -131,6 +131,9 @@
|
||||
/* Define if you want: LEDs support */
|
||||
#mesondefine CONFIG_LEDS
|
||||
|
||||
/* Define as 1 to use the libcss library */
|
||||
#mesondefine CONFIG_LIBCSS
|
||||
|
||||
/* Define as 1 to use the libdom library. */
|
||||
#mesondefine CONFIG_LIBDOM
|
||||
|
||||
|
12
configure.ac
12
configure.ac
@ -873,6 +873,18 @@ if test "x$CONFIG_QUICKJS" = xyes; then
|
||||
AC_SUBST(CONFIG_QUICKJS)
|
||||
AC_SUBST(CONFIG_XML)
|
||||
fi
|
||||
|
||||
# ===================================================================
|
||||
# Check for libcss
|
||||
# ===================================================================
|
||||
|
||||
if test "x$CONFIG_XML" = xyes; then
|
||||
LIBCSS_CFLAGS=`$PKG_CONFIG $pkg_config_static --cflags libcss`
|
||||
LIBCSS_LIBS=`$PKG_CONFIG $pkg_config_static --libs libcss`
|
||||
LIBS="$LIBS $LIBCSS_LIBS"
|
||||
CFLAGS="$CFLAGS $LIBCSS_CFLAGS"
|
||||
fi
|
||||
|
||||
# ===================================================================
|
||||
# Check for Guile, optional even if installed.
|
||||
# ===================================================================
|
||||
|
@ -406,6 +406,14 @@ if conf_data.get('CONFIG_ECMASCRIPT_SMJS') or conf_data.get('CONFIG_QUICKJS') or
|
||||
deps += curldeps
|
||||
endif
|
||||
|
||||
conf_data.set('CONFIG_LIBCSS', false)
|
||||
|
||||
if conf_data.get('CONFIG_ECMASCRIPT_SMJS') or conf_data.get('CONFIG_QUICKJS') or conf_data.get('CONFIG_MUJS')
|
||||
cssdeps = dependency('libcss', static: st, version: '>=0.9.1')
|
||||
deps += cssdeps
|
||||
conf_data.set('CONFIG_LIBCSS', true)
|
||||
endif
|
||||
|
||||
if conf_data.get('CONFIG_SCRIPTING_LUA')
|
||||
luadeps = dependency(luapkg, static: st)
|
||||
deps += luadeps
|
||||
|
@ -234,6 +234,9 @@ examine_element(struct html_context *html_context, struct css_selector *base,
|
||||
process_found_selector(selector, CST_PSEUDO, base);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CSS
|
||||
#ifdef CONFIG_LIBCSS
|
||||
#else
|
||||
if (element->attr.class_ && seltype <= CST_CLASS) {
|
||||
const char *class_ = element->attr.class_;
|
||||
|
||||
@ -255,6 +258,8 @@ examine_element(struct html_context *html_context, struct css_selector *base,
|
||||
selector = find_css_selector(selectors, CST_ID, rel, element->attr.id, -1);
|
||||
process_found_selector(selector, CST_ID, base);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef process_found_selector
|
||||
#undef dbginfo
|
||||
|
@ -35,7 +35,11 @@ union option_info css_options_info[] = {
|
||||
INIT_OPT_BOOL("document.css", N_("Enable CSS"),
|
||||
"enable", OPT_ZERO, 1,
|
||||
N_("Enable adding of CSS style info to documents.")),
|
||||
|
||||
#ifdef CONFIG_LIBCSS
|
||||
INIT_OPT_BOOL("document.css", N_("Prefer libcss"),
|
||||
"libcss", OPT_ZERO, 0,
|
||||
N_("Enable experimental code using the libcss library instead of builtin implementation.")),
|
||||
#endif
|
||||
INIT_OPT_BOOL("document.css", N_("Ignore \"display: none\""),
|
||||
"ignore_display_none", OPT_ZERO, 1,
|
||||
N_("When enabled, elements are rendered, even when their "
|
||||
|
831
src/document/css2/css.c
Normal file
831
src/document/css2/css.c
Normal file
@ -0,0 +1,831 @@
|
||||
/*
|
||||
* Copyright 2009 John-Mark Bell <jmb@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/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <libwapcaplet/libwapcaplet.h>
|
||||
#include <dom/dom.h>
|
||||
|
||||
#include "utils/errors.h"
|
||||
#include "utils/corestrings.h"
|
||||
#include "utils/utils.h"
|
||||
#include "utils/http.h"
|
||||
#include "utils/log.h"
|
||||
#include "utils/messages.h"
|
||||
#include "content/content_protected.h"
|
||||
#include "content/content_factory.h"
|
||||
#include "content/fetch.h"
|
||||
#include "content/hlcache.h"
|
||||
#include "desktop/system_colour.h"
|
||||
|
||||
#include "css/css.h"
|
||||
#include "css/hints.h"
|
||||
#include "css/internal.h"
|
||||
|
||||
/* Define to trace import fetches */
|
||||
#undef NSCSS_IMPORT_TRACE
|
||||
|
||||
struct content_css_data;
|
||||
|
||||
/**
|
||||
* Type of callback called when a CSS object has finished
|
||||
*
|
||||
* \param css CSS object that has completed
|
||||
* \param pw Client-specific data
|
||||
*/
|
||||
typedef void (*nscss_done_callback)(struct content_css_data *css, void *pw);
|
||||
|
||||
/**
|
||||
* CSS content data
|
||||
*/
|
||||
struct content_css_data
|
||||
{
|
||||
css_stylesheet *sheet; /**< Stylesheet object */
|
||||
char *charset; /**< Character set of stylesheet */
|
||||
struct nscss_import *imports; /**< Array of imported sheets */
|
||||
uint32_t import_count; /**< Number of sheets imported */
|
||||
uint32_t next_to_register; /**< Index of next import to register */
|
||||
nscss_done_callback done; /**< Completion callback */
|
||||
void *pw; /**< Client data */
|
||||
};
|
||||
|
||||
/**
|
||||
* CSS content data
|
||||
*/
|
||||
typedef struct nscss_content
|
||||
{
|
||||
struct content base; /**< Underlying content object */
|
||||
|
||||
struct content_css_data data; /**< CSS data */
|
||||
} nscss_content;
|
||||
|
||||
/**
|
||||
* Context for import fetches
|
||||
*/
|
||||
typedef struct {
|
||||
struct content_css_data *css; /**< Object containing import */
|
||||
uint32_t index; /**< Index into parent sheet's
|
||||
* imports array */
|
||||
} nscss_import_ctx;
|
||||
|
||||
static bool nscss_convert(struct content *c);
|
||||
static void nscss_destroy(struct content *c);
|
||||
static nserror nscss_clone(const struct content *old, struct content **newc);
|
||||
static bool nscss_matches_quirks(const struct content *c, bool quirks);
|
||||
static content_type nscss_content_type(void);
|
||||
|
||||
static nserror nscss_create_css_data(struct content_css_data *c,
|
||||
const char *url, const char *charset, bool quirks,
|
||||
nscss_done_callback done, void *pw);
|
||||
static css_error nscss_process_css_data(struct content_css_data *c, const char *data,
|
||||
unsigned int size);
|
||||
static css_error nscss_convert_css_data(struct content_css_data *c);
|
||||
static void nscss_destroy_css_data(struct content_css_data *c);
|
||||
|
||||
static void nscss_content_done(struct content_css_data *css, void *pw);
|
||||
static css_error nscss_handle_import(void *pw, css_stylesheet *parent,
|
||||
lwc_string *url);
|
||||
static nserror nscss_import(hlcache_handle *handle,
|
||||
const hlcache_event *event, void *pw);
|
||||
static css_error nscss_import_complete(nscss_import_ctx *ctx);
|
||||
|
||||
static css_error nscss_register_imports(struct content_css_data *c);
|
||||
static css_error nscss_register_import(struct content_css_data *c,
|
||||
const hlcache_handle *import);
|
||||
|
||||
|
||||
static css_stylesheet *blank_import;
|
||||
|
||||
|
||||
/**
|
||||
* Initialise a CSS content
|
||||
*
|
||||
* \param handler content handler
|
||||
* \param imime_type mime-type
|
||||
* \param params Content-Type parameters
|
||||
* \param llcache handle to content
|
||||
* \param fallback_charset The character set to fallback to.
|
||||
* \param quirks allow quirks
|
||||
* \param c Content to initialise
|
||||
* \return NSERROR_OK or error cod eon faliure
|
||||
*/
|
||||
static nserror
|
||||
nscss_create(const content_handler *handler,
|
||||
lwc_string *imime_type,
|
||||
const http_parameter *params,
|
||||
llcache_handle *llcache,
|
||||
const char *fallback_charset,
|
||||
bool quirks,
|
||||
struct content **c)
|
||||
{
|
||||
nscss_content *result;
|
||||
const char *charset = NULL;
|
||||
const char *xnsbase = NULL;
|
||||
lwc_string *charset_value = NULL;
|
||||
nserror error;
|
||||
|
||||
result = calloc(1, sizeof(nscss_content));
|
||||
if (result == NULL)
|
||||
return NSERROR_NOMEM;
|
||||
|
||||
error = content__init(&result->base, handler, imime_type,
|
||||
params, llcache, fallback_charset, quirks);
|
||||
if (error != NSERROR_OK) {
|
||||
free(result);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Find charset specified on HTTP layer, if any */
|
||||
error = http_parameter_list_find_item(params, corestring_lwc_charset,
|
||||
&charset_value);
|
||||
if (error != NSERROR_OK || lwc_string_length(charset_value) == 0) {
|
||||
/* No charset specified, use fallback, if any */
|
||||
/** \todo libcss will take this as gospel, which is wrong */
|
||||
charset = fallback_charset;
|
||||
} else {
|
||||
charset = lwc_string_data(charset_value);
|
||||
}
|
||||
|
||||
/* Compute base URL for stylesheet */
|
||||
xnsbase = llcache_handle_get_header(llcache, "X-NS-Base");
|
||||
if (xnsbase == NULL) {
|
||||
xnsbase = nsurl_access(content_get_url(&result->base));
|
||||
}
|
||||
|
||||
error = nscss_create_css_data(&result->data,
|
||||
xnsbase, charset, result->base.quirks,
|
||||
nscss_content_done, result);
|
||||
if (error != NSERROR_OK) {
|
||||
content_broadcast_error(&result->base, NSERROR_NOMEM, NULL);
|
||||
if (charset_value != NULL)
|
||||
lwc_string_unref(charset_value);
|
||||
free(result);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (charset_value != NULL)
|
||||
lwc_string_unref(charset_value);
|
||||
|
||||
*c = (struct content *) result;
|
||||
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a struct content_css_data, creating a stylesheet object
|
||||
*
|
||||
* \param c Struct to populate
|
||||
* \param url URL of stylesheet
|
||||
* \param charset Stylesheet charset
|
||||
* \param quirks Stylesheet quirks mode
|
||||
* \param done Callback to call when content has completed
|
||||
* \param pw Client data for \a done
|
||||
* \return NSERROR_OK on success, NSERROR_NOMEM on memory exhaustion
|
||||
*/
|
||||
static nserror nscss_create_css_data(struct content_css_data *c,
|
||||
const char *url, const char *charset, bool quirks,
|
||||
nscss_done_callback done, void *pw)
|
||||
{
|
||||
css_error error;
|
||||
css_stylesheet_params params;
|
||||
|
||||
c->pw = pw;
|
||||
c->done = done;
|
||||
c->next_to_register = (uint32_t) -1;
|
||||
c->import_count = 0;
|
||||
c->imports = NULL;
|
||||
if (charset != NULL)
|
||||
c->charset = strdup(charset);
|
||||
else
|
||||
c->charset = NULL;
|
||||
|
||||
params.params_version = CSS_STYLESHEET_PARAMS_VERSION_1;
|
||||
params.level = CSS_LEVEL_DEFAULT;
|
||||
params.charset = charset;
|
||||
params.url = url;
|
||||
params.title = NULL;
|
||||
params.allow_quirks = quirks;
|
||||
params.inline_style = false;
|
||||
params.resolve = nscss_resolve_url;
|
||||
params.resolve_pw = NULL;
|
||||
params.import = nscss_handle_import;
|
||||
params.import_pw = c;
|
||||
params.color = ns_system_colour;
|
||||
params.color_pw = NULL;
|
||||
params.font = NULL;
|
||||
params.font_pw = NULL;
|
||||
|
||||
error = css_stylesheet_create(¶ms, &c->sheet);
|
||||
if (error != CSS_OK) {
|
||||
return NSERROR_NOMEM;
|
||||
}
|
||||
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process CSS source data
|
||||
*
|
||||
* \param c Content structure
|
||||
* \param data Data to process
|
||||
* \param size Number of bytes to process
|
||||
* \return true on success, false on failure
|
||||
*/
|
||||
static bool
|
||||
nscss_process_data(struct content *c, const char *data, unsigned int size)
|
||||
{
|
||||
nscss_content *css = (nscss_content *) c;
|
||||
css_error error;
|
||||
|
||||
error = nscss_process_css_data(&css->data, data, size);
|
||||
if (error != CSS_OK && error != CSS_NEEDDATA) {
|
||||
content_broadcast_error(c, NSERROR_CSS, NULL);
|
||||
}
|
||||
|
||||
return (error == CSS_OK || error == CSS_NEEDDATA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process CSS data
|
||||
*
|
||||
* \param c CSS content object
|
||||
* \param data Data to process
|
||||
* \param size Number of bytes to process
|
||||
* \return CSS_OK on success, appropriate error otherwise
|
||||
*/
|
||||
static css_error nscss_process_css_data(struct content_css_data *c,
|
||||
const char *data, unsigned int size)
|
||||
{
|
||||
return css_stylesheet_append_data(c->sheet,
|
||||
(const uint8_t *) data, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a CSS content ready for use
|
||||
*
|
||||
* \param c Content to convert
|
||||
* \return true on success, false on failure
|
||||
*/
|
||||
bool nscss_convert(struct content *c)
|
||||
{
|
||||
nscss_content *css = (nscss_content *) c;
|
||||
css_error error;
|
||||
|
||||
error = nscss_convert_css_data(&css->data);
|
||||
if (error != CSS_OK) {
|
||||
content_broadcast_error(c, NSERROR_CSS, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert CSS data ready for use
|
||||
*
|
||||
* \param c CSS data to convert
|
||||
* \return CSS error
|
||||
*/
|
||||
static css_error nscss_convert_css_data(struct content_css_data *c)
|
||||
{
|
||||
css_error error;
|
||||
|
||||
error = css_stylesheet_data_done(c->sheet);
|
||||
|
||||
/* Process pending imports */
|
||||
if (error == CSS_IMPORTS_PENDING) {
|
||||
/* We must not have registered any imports yet */
|
||||
assert(c->next_to_register == (uint32_t) -1);
|
||||
|
||||
/* Start registering, until we find one that
|
||||
* hasn't finished fetching */
|
||||
c->next_to_register = 0;
|
||||
error = nscss_register_imports(c);
|
||||
} else if (error == CSS_OK) {
|
||||
/* No imports, and no errors, so complete conversion */
|
||||
c->done(c, c->pw);
|
||||
} else {
|
||||
const char *url;
|
||||
|
||||
if (css_stylesheet_get_url(c->sheet, &url) == CSS_OK) {
|
||||
NSLOG(netsurf, INFO, "Failed converting %p %s (%d)",
|
||||
c, url, error);
|
||||
} else {
|
||||
NSLOG(netsurf, INFO, "Failed converting %p (%d)", c,
|
||||
error);
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up a CSS content
|
||||
*
|
||||
* \param c Content to clean up
|
||||
*/
|
||||
void nscss_destroy(struct content *c)
|
||||
{
|
||||
nscss_content *css = (nscss_content *) c;
|
||||
|
||||
nscss_destroy_css_data(&css->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up CSS data
|
||||
*
|
||||
* \param c CSS data to clean up
|
||||
*/
|
||||
static void nscss_destroy_css_data(struct content_css_data *c)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < c->import_count; i++) {
|
||||
if (c->imports[i].c != NULL) {
|
||||
hlcache_handle_release(c->imports[i].c);
|
||||
}
|
||||
c->imports[i].c = NULL;
|
||||
}
|
||||
|
||||
free(c->imports);
|
||||
|
||||
if (c->sheet != NULL) {
|
||||
css_stylesheet_destroy(c->sheet);
|
||||
c->sheet = NULL;
|
||||
}
|
||||
|
||||
free(c->charset);
|
||||
}
|
||||
|
||||
nserror nscss_clone(const struct content *old, struct content **newc)
|
||||
{
|
||||
const nscss_content *old_css = (const nscss_content *) old;
|
||||
nscss_content *new_css;
|
||||
const uint8_t *data;
|
||||
size_t size;
|
||||
nserror error;
|
||||
|
||||
new_css = calloc(1, sizeof(nscss_content));
|
||||
if (new_css == NULL)
|
||||
return NSERROR_NOMEM;
|
||||
|
||||
/* Clone content */
|
||||
error = content__clone(old, &new_css->base);
|
||||
if (error != NSERROR_OK) {
|
||||
content_destroy(&new_css->base);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Simply replay create/process/convert */
|
||||
error = nscss_create_css_data(&new_css->data,
|
||||
nsurl_access(content_get_url(&new_css->base)),
|
||||
old_css->data.charset,
|
||||
new_css->base.quirks,
|
||||
nscss_content_done, new_css);
|
||||
if (error != NSERROR_OK) {
|
||||
content_destroy(&new_css->base);
|
||||
return error;
|
||||
}
|
||||
|
||||
data = content__get_source_data(&new_css->base, &size);
|
||||
if (size > 0) {
|
||||
if (nscss_process_data(&new_css->base,
|
||||
(char *)data,
|
||||
(unsigned int)size) == false) {
|
||||
content_destroy(&new_css->base);
|
||||
return NSERROR_CLONE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if (old->status == CONTENT_STATUS_READY ||
|
||||
old->status == CONTENT_STATUS_DONE) {
|
||||
if (nscss_convert(&new_css->base) == false) {
|
||||
content_destroy(&new_css->base);
|
||||
return NSERROR_CLONE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
*newc = (struct content *) new_css;
|
||||
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
bool nscss_matches_quirks(const struct content *c, bool quirks)
|
||||
{
|
||||
return c->quirks == quirks;
|
||||
}
|
||||
|
||||
/* exported interface documented in netsurf/css.h */
|
||||
css_stylesheet *nscss_get_stylesheet(struct hlcache_handle *h)
|
||||
{
|
||||
nscss_content *c = (nscss_content *) hlcache_handle_get_content(h);
|
||||
|
||||
assert(c != NULL);
|
||||
|
||||
return c->data.sheet;
|
||||
}
|
||||
|
||||
/* exported interface documented in netsurf/css.h */
|
||||
struct nscss_import *nscss_get_imports(hlcache_handle *h, uint32_t *n)
|
||||
{
|
||||
nscss_content *c = (nscss_content *) hlcache_handle_get_content(h);
|
||||
|
||||
assert(c != NULL);
|
||||
assert(n != NULL);
|
||||
|
||||
*n = c->data.import_count;
|
||||
|
||||
return c->data.imports;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the type of a content
|
||||
*
|
||||
* \return CONTENT_CSS
|
||||
*/
|
||||
content_type nscss_content_type(void)
|
||||
{
|
||||
return CONTENT_CSS;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Object completion *
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Handle notification that a CSS object is done
|
||||
*
|
||||
* \param css CSS object
|
||||
* \param pw Private data
|
||||
*/
|
||||
void nscss_content_done(struct content_css_data *css, void *pw)
|
||||
{
|
||||
struct content *c = pw;
|
||||
uint32_t i;
|
||||
size_t size;
|
||||
css_error error;
|
||||
|
||||
/* Retrieve the size of this sheet */
|
||||
error = css_stylesheet_size(css->sheet, &size);
|
||||
if (error != CSS_OK) {
|
||||
content_broadcast_error(c, NSERROR_CSS, NULL);
|
||||
content_set_error(c);
|
||||
return;
|
||||
}
|
||||
c->size += size;
|
||||
|
||||
/* Add on the size of the imported sheets */
|
||||
for (i = 0; i < css->import_count; i++) {
|
||||
if (css->imports[i].c != NULL) {
|
||||
struct content *import = hlcache_handle_get_content(
|
||||
css->imports[i].c);
|
||||
|
||||
if (import != NULL) {
|
||||
c->size += import->size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, catch the content's users up with reality */
|
||||
content_set_ready(c);
|
||||
content_set_done(c);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Import handling *
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Handle notification of the need for an imported stylesheet
|
||||
*
|
||||
* \param pw CSS object requesting the import
|
||||
* \param parent Stylesheet requesting the import
|
||||
* \param url URL of the imported sheet
|
||||
* \return CSS_OK on success, appropriate error otherwise
|
||||
*/
|
||||
css_error nscss_handle_import(void *pw, css_stylesheet *parent,
|
||||
lwc_string *url)
|
||||
{
|
||||
content_type accept = CONTENT_CSS;
|
||||
struct content_css_data *c = pw;
|
||||
nscss_import_ctx *ctx;
|
||||
hlcache_child_context child;
|
||||
struct nscss_import *imports;
|
||||
const char *referer;
|
||||
css_error error;
|
||||
nserror nerror;
|
||||
|
||||
nsurl *ns_url;
|
||||
nsurl *ns_ref;
|
||||
|
||||
assert(parent == c->sheet);
|
||||
|
||||
error = css_stylesheet_get_url(c->sheet, &referer);
|
||||
if (error != CSS_OK) {
|
||||
return error;
|
||||
}
|
||||
|
||||
ctx = malloc(sizeof(*ctx));
|
||||
if (ctx == NULL)
|
||||
return CSS_NOMEM;
|
||||
|
||||
ctx->css = c;
|
||||
ctx->index = c->import_count;
|
||||
|
||||
/* Increase space in table */
|
||||
imports = realloc(c->imports, (c->import_count + 1) *
|
||||
sizeof(struct nscss_import));
|
||||
if (imports == NULL) {
|
||||
free(ctx);
|
||||
return CSS_NOMEM;
|
||||
}
|
||||
c->imports = imports;
|
||||
|
||||
/** \todo fallback charset */
|
||||
child.charset = NULL;
|
||||
error = css_stylesheet_quirks_allowed(c->sheet, &child.quirks);
|
||||
if (error != CSS_OK) {
|
||||
free(ctx);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Create content */
|
||||
|
||||
/** \todo Why aren't we getting a relative url part, to join? */
|
||||
nerror = nsurl_create(lwc_string_data(url), &ns_url);
|
||||
if (nerror != NSERROR_OK) {
|
||||
free(ctx);
|
||||
return CSS_NOMEM;
|
||||
}
|
||||
|
||||
/** \todo Constructing nsurl for referer here is silly, avoid */
|
||||
nerror = nsurl_create(referer, &ns_ref);
|
||||
if (nerror != NSERROR_OK) {
|
||||
nsurl_unref(ns_url);
|
||||
free(ctx);
|
||||
return CSS_NOMEM;
|
||||
}
|
||||
|
||||
/* Avoid importing ourself */
|
||||
if (nsurl_compare(ns_url, ns_ref, NSURL_COMPLETE)) {
|
||||
c->imports[c->import_count].c = NULL;
|
||||
/* No longer require context as we're not fetching anything */
|
||||
free(ctx);
|
||||
ctx = NULL;
|
||||
} else {
|
||||
nerror = hlcache_handle_retrieve(ns_url,
|
||||
0, ns_ref, NULL, nscss_import, ctx,
|
||||
&child, accept,
|
||||
&c->imports[c->import_count].c);
|
||||
if (nerror != NSERROR_OK) {
|
||||
free(ctx);
|
||||
return CSS_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
nsurl_unref(ns_url);
|
||||
nsurl_unref(ns_ref);
|
||||
|
||||
#ifdef NSCSS_IMPORT_TRACE
|
||||
NSLOG(netsurf, INFO, "Import %d '%s' -> (handle: %p ctx: %p)",
|
||||
c->import_count, lwc_string_data(url),
|
||||
c->imports[c->import_count].c, ctx);
|
||||
#endif
|
||||
|
||||
c->import_count++;
|
||||
|
||||
return CSS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for imported stylesheet events
|
||||
*
|
||||
* \param handle Handle for stylesheet
|
||||
* \param event Event object
|
||||
* \param pw Callback context
|
||||
* \return NSERROR_OK on success, appropriate error otherwise
|
||||
*/
|
||||
nserror nscss_import(hlcache_handle *handle,
|
||||
const hlcache_event *event, void *pw)
|
||||
{
|
||||
nscss_import_ctx *ctx = pw;
|
||||
css_error error = CSS_OK;
|
||||
|
||||
#ifdef NSCSS_IMPORT_TRACE
|
||||
NSLOG(netsurf, INFO, "Event %d for %p (%p)", event->type, handle, ctx);
|
||||
#endif
|
||||
|
||||
assert(ctx->css->imports[ctx->index].c == handle);
|
||||
|
||||
switch (event->type) {
|
||||
case CONTENT_MSG_DONE:
|
||||
error = nscss_import_complete(ctx);
|
||||
break;
|
||||
|
||||
case CONTENT_MSG_ERROR:
|
||||
hlcache_handle_release(handle);
|
||||
ctx->css->imports[ctx->index].c = NULL;
|
||||
|
||||
error = nscss_import_complete(ctx);
|
||||
/* Already released handle */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Preserve out-of-memory. Anything else is OK */
|
||||
return error == CSS_NOMEM ? NSERROR_NOMEM : NSERROR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an imported stylesheet completing
|
||||
*
|
||||
* \param ctx Import context
|
||||
* \return CSS_OK on success, appropriate error otherwise
|
||||
*/
|
||||
css_error nscss_import_complete(nscss_import_ctx *ctx)
|
||||
{
|
||||
css_error error = CSS_OK;
|
||||
|
||||
/* If this import is the next to be registered, do so */
|
||||
if (ctx->css->next_to_register == ctx->index)
|
||||
error = nscss_register_imports(ctx->css);
|
||||
|
||||
#ifdef NSCSS_IMPORT_TRACE
|
||||
NSLOG(netsurf, INFO, "Destroying import context %p for %d", ctx,
|
||||
ctx->index);
|
||||
#endif
|
||||
|
||||
/* No longer need import context */
|
||||
free(ctx);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Import registration *
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Register imports with a stylesheet
|
||||
*
|
||||
* \param c CSS object containing the imports
|
||||
* \return CSS_OK on success, appropriate error otherwise
|
||||
*/
|
||||
css_error nscss_register_imports(struct content_css_data *c)
|
||||
{
|
||||
uint32_t index;
|
||||
css_error error;
|
||||
|
||||
assert(c->next_to_register != (uint32_t) -1);
|
||||
assert(c->next_to_register < c->import_count);
|
||||
|
||||
/* Register imported sheets */
|
||||
for (index = c->next_to_register; index < c->import_count; index++) {
|
||||
/* Stop registering if we encounter one whose fetch hasn't
|
||||
* completed yet. We'll resume at this point when it has
|
||||
* completed.
|
||||
*/
|
||||
if (c->imports[index].c != NULL &&
|
||||
content_get_status(c->imports[index].c) !=
|
||||
CONTENT_STATUS_DONE) {
|
||||
break;
|
||||
}
|
||||
|
||||
error = nscss_register_import(c, c->imports[index].c);
|
||||
if (error != CSS_OK)
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Record identity of the next import to register */
|
||||
c->next_to_register = (uint32_t) index;
|
||||
|
||||
if (c->next_to_register == c->import_count) {
|
||||
/* No more imports: notify parent that we're DONE */
|
||||
c->done(c, c->pw);
|
||||
}
|
||||
|
||||
return CSS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register an import with a stylesheet
|
||||
*
|
||||
* \param c CSS object that requested the import
|
||||
* \param import Cache handle of import, or NULL for blank
|
||||
* \return CSS_OK on success, appropriate error otherwise
|
||||
*/
|
||||
css_error nscss_register_import(struct content_css_data *c,
|
||||
const hlcache_handle *import)
|
||||
{
|
||||
css_stylesheet *sheet;
|
||||
css_error error;
|
||||
|
||||
if (import != NULL) {
|
||||
nscss_content *s =
|
||||
(nscss_content *) hlcache_handle_get_content(import);
|
||||
sheet = s->data.sheet;
|
||||
} else {
|
||||
/* Create a blank sheet if needed. */
|
||||
if (blank_import == NULL) {
|
||||
css_stylesheet_params params;
|
||||
|
||||
params.params_version = CSS_STYLESHEET_PARAMS_VERSION_1;
|
||||
params.level = CSS_LEVEL_DEFAULT;
|
||||
params.charset = NULL;
|
||||
params.url = "";
|
||||
params.title = NULL;
|
||||
params.allow_quirks = false;
|
||||
params.inline_style = false;
|
||||
params.resolve = nscss_resolve_url;
|
||||
params.resolve_pw = NULL;
|
||||
params.import = NULL;
|
||||
params.import_pw = NULL;
|
||||
params.color = ns_system_colour;
|
||||
params.color_pw = NULL;
|
||||
params.font = NULL;
|
||||
params.font_pw = NULL;
|
||||
|
||||
error = css_stylesheet_create(¶ms, &blank_import);
|
||||
if (error != CSS_OK) {
|
||||
return error;
|
||||
}
|
||||
|
||||
error = css_stylesheet_data_done(blank_import);
|
||||
if (error != CSS_OK) {
|
||||
css_stylesheet_destroy(blank_import);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
sheet = blank_import;
|
||||
}
|
||||
|
||||
error = css_stylesheet_register_import(c->sheet, sheet);
|
||||
if (error != CSS_OK) {
|
||||
return error;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up after the CSS content handler
|
||||
*/
|
||||
static void nscss_fini(void)
|
||||
{
|
||||
if (blank_import != NULL) {
|
||||
css_stylesheet_destroy(blank_import);
|
||||
blank_import = NULL;
|
||||
}
|
||||
css_hint_fini();
|
||||
}
|
||||
|
||||
static const content_handler css_content_handler = {
|
||||
.fini = nscss_fini,
|
||||
.create = nscss_create,
|
||||
.process_data = nscss_process_data,
|
||||
.data_complete = nscss_convert,
|
||||
.destroy = nscss_destroy,
|
||||
.clone = nscss_clone,
|
||||
.matches_quirks = nscss_matches_quirks,
|
||||
.type = nscss_content_type,
|
||||
.no_share = false,
|
||||
};
|
||||
|
||||
/* exported interface documented in netsurf/css.h */
|
||||
nserror nscss_init(void)
|
||||
{
|
||||
nserror error;
|
||||
|
||||
error = content_factory_register_handler("text/css",
|
||||
&css_content_handler);
|
||||
if (error != NSERROR_OK)
|
||||
goto error;
|
||||
|
||||
error = css_hint_init();
|
||||
if (error != NSERROR_OK)
|
||||
goto error;
|
||||
|
||||
return NSERROR_OK;
|
||||
|
||||
error:
|
||||
nscss_fini();
|
||||
|
||||
return error;
|
||||
}
|
1615
src/document/css2/css.cpp
Normal file
1615
src/document/css2/css.cpp
Normal file
File diff suppressed because it is too large
Load Diff
23
src/document/css2/css.h
Normal file
23
src/document/css2/css.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef EL__DOCUMENT_CSS2_CSS_H
|
||||
#define EL__DOCUMENT_CSS2_CSS_H
|
||||
|
||||
#include <libcss/libcss.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct html_context;
|
||||
struct html_element;
|
||||
struct uri;
|
||||
|
||||
css_error resolve_url(void *pw, const char *base, lwc_string *rel, lwc_string **abs);
|
||||
void select_css(struct html_context *html_context, struct html_element *element);
|
||||
void parse_css(struct html_context *html_context, char *name);
|
||||
void import_css2(struct html_context *html_context, struct uri *uri);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
1833
src/document/css2/dump.c
Normal file
1833
src/document/css2/dump.c
Normal file
File diff suppressed because it is too large
Load Diff
30
src/document/css2/dump.h
Normal file
30
src/document/css2/dump.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2009 John-Mark Bell <jmb@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/>.
|
||||
*/
|
||||
|
||||
#ifndef NETSURF_CSS_DUMP_H_
|
||||
#define NETSURF_CSS_DUMP_H_
|
||||
|
||||
/**
|
||||
* Dump a computed style \a style to the give file handle \a stream.
|
||||
*
|
||||
* \param stream Stream to write to
|
||||
* \param style Computed style to dump
|
||||
*/
|
||||
void nscss_dump_computed_style(FILE *stream, const css_computed_style *style);
|
||||
|
||||
#endif
|
1691
src/document/css2/hints.c
Normal file
1691
src/document/css2/hints.c
Normal file
File diff suppressed because it is too large
Load Diff
55
src/document/css2/hints.h
Normal file
55
src/document/css2/hints.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2009 John-Mark Bell <jmb@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/>.
|
||||
*/
|
||||
|
||||
#ifndef NETSURF_CSS_HINTS_H_
|
||||
#define NETSURF_CSS_HINTS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libcss/libcss.h>
|
||||
|
||||
nserror css_hint_init(void);
|
||||
void css_hint_fini(void);
|
||||
|
||||
/**
|
||||
* Callback to retrieve presentational hints for a node
|
||||
*
|
||||
* \param[in] pw HTML document
|
||||
* \param[in] node DOM node
|
||||
* \param[out] nhints number of hints retrieved
|
||||
* \param[out] hints retrieved hints
|
||||
* \return CSS_OK on success,
|
||||
* CSS_PROPERTY_NOT_SET if there is no hint for the requested property,
|
||||
* CSS_NOMEM on memory exhaustion.
|
||||
*/
|
||||
css_error node_presentational_hint(
|
||||
void *pw,
|
||||
void *node,
|
||||
uint32_t *nhints,
|
||||
css_hint **hints);
|
||||
|
||||
/**
|
||||
* Parser for colours specified in attribute values.
|
||||
*
|
||||
* \param data Data to parse (NUL-terminated)
|
||||
* \param result Pointer to location to receive resulting css_color
|
||||
* \return true on success, false on invalid input
|
||||
*/
|
||||
bool nscss_parse_colour(const char *data, css_color *result);
|
||||
|
||||
#endif
|
63
src/document/css2/internal.c
Normal file
63
src/document/css2/internal.c
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2009 John-Mark Bell <jmb@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/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <libcss/libcss.h>
|
||||
|
||||
#include "utils/nsurl.h"
|
||||
|
||||
#include "css/internal.h"
|
||||
|
||||
/* exported interface documented in content/handlers/css/internal.h */
|
||||
css_error nscss_resolve_url(void *pw, const char *base,
|
||||
lwc_string *rel, lwc_string **abs)
|
||||
{
|
||||
lwc_error lerror;
|
||||
nserror error;
|
||||
nsurl *nsbase;
|
||||
nsurl *nsabs;
|
||||
|
||||
/* Create nsurl from base */
|
||||
/* TODO: avoid this */
|
||||
error = nsurl_create(base, &nsbase);
|
||||
if (error != NSERROR_OK) {
|
||||
return error == NSERROR_NOMEM ? CSS_NOMEM : CSS_INVALID;
|
||||
}
|
||||
|
||||
/* Resolve URI */
|
||||
error = nsurl_join(nsbase, lwc_string_data(rel), &nsabs);
|
||||
if (error != NSERROR_OK) {
|
||||
nsurl_unref(nsbase);
|
||||
return error == NSERROR_NOMEM ? CSS_NOMEM : CSS_INVALID;
|
||||
}
|
||||
|
||||
nsurl_unref(nsbase);
|
||||
|
||||
/* Intern it */
|
||||
lerror = lwc_intern_string(nsurl_access(nsabs),
|
||||
nsurl_length(nsabs), abs);
|
||||
if (lerror != lwc_error_ok) {
|
||||
*abs = NULL;
|
||||
nsurl_unref(nsabs);
|
||||
return lerror == lwc_error_oom ? CSS_NOMEM : CSS_INVALID;
|
||||
}
|
||||
|
||||
nsurl_unref(nsabs);
|
||||
|
||||
return CSS_OK;
|
||||
}
|
35
src/document/css2/internal.h
Normal file
35
src/document/css2/internal.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2009 John-Mark Bell <jmb@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/>.
|
||||
*/
|
||||
|
||||
#ifndef NETSURF_CSS_INTERNAL_H_
|
||||
#define NETSURF_CSS_INTERNAL_H_
|
||||
|
||||
/**
|
||||
* URL resolution callback for libcss
|
||||
*
|
||||
* \param pw Resolution context
|
||||
* \param base Base URI
|
||||
* \param rel Relative URL
|
||||
* \param abs Pointer to location to receive resolved URL
|
||||
* \return CSS_OK on success,
|
||||
* CSS_NOMEM on memory exhaustion,
|
||||
* CSS_INVALID if resolution failed.
|
||||
*/
|
||||
css_error nscss_resolve_url(void *pw, const char *base, lwc_string *rel, lwc_string **abs);
|
||||
|
||||
#endif
|
1
src/document/css2/meson.build
Normal file
1
src/document/css2/meson.build
Normal file
@ -0,0 +1 @@
|
||||
srcs += files('css.cpp')
|
1892
src/document/css2/select.c
Normal file
1892
src/document/css2/select.c
Normal file
File diff suppressed because it is too large
Load Diff
59
src/document/css2/select.h
Normal file
59
src/document/css2/select.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2009 John-Mark Bell <jmb@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/>.
|
||||
*/
|
||||
|
||||
#ifndef NETSURF_CSS_SELECT_H_
|
||||
#define NETSURF_CSS_SELECT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <dom/dom.h>
|
||||
|
||||
#include <libcss/libcss.h>
|
||||
|
||||
struct content;
|
||||
struct nsurl;
|
||||
|
||||
/**
|
||||
* Selection context
|
||||
*/
|
||||
typedef struct nscss_select_ctx
|
||||
{
|
||||
css_select_ctx *ctx;
|
||||
bool quirks;
|
||||
struct nsurl *base_url;
|
||||
lwc_string *universal;
|
||||
const css_computed_style *root_style;
|
||||
const css_computed_style *parent_style;
|
||||
} nscss_select_ctx;
|
||||
|
||||
css_stylesheet *nscss_create_inline_style(const uint8_t *data, size_t len,
|
||||
const char *charset, const char *url, bool allow_quirks);
|
||||
|
||||
css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node *n,
|
||||
const css_media *media, const css_stylesheet *inline_style);
|
||||
|
||||
css_computed_style *nscss_get_blank_style(nscss_select_ctx *ctx,
|
||||
const css_computed_style *parent);
|
||||
|
||||
|
||||
css_error named_ancestor_node(void *pw, void *node,
|
||||
const css_qname *qname, void **ancestor);
|
||||
|
||||
css_error node_is_visited(void *pw, void *node, bool *match);
|
||||
|
||||
#endif
|
259
src/document/css2/utils.c
Normal file
259
src/document/css2/utils.c
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright 2004 James Bursa <james@netsurf-browser.org>
|
||||
* Copyright 2009 John-Mark Bell <jmb@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/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "utils/nsoption.h"
|
||||
#include "utils/log.h"
|
||||
|
||||
#include "css/utils.h"
|
||||
|
||||
/** Screen DPI in fixed point units: defaults to 90, which RISC OS uses */
|
||||
css_fixed nscss_screen_dpi = F_90;
|
||||
|
||||
/** Medium screen density for device viewing distance. */
|
||||
css_fixed nscss_baseline_pixel_density = F_96;
|
||||
|
||||
/**
|
||||
* Map viewport-relative length units to either vh or vw.
|
||||
*
|
||||
* Non-viewport-relative units are unchanged.
|
||||
*
|
||||
* \param[in] ctx Length conversion context.
|
||||
* \param[in] unit Unit to map.
|
||||
* \return the mapped unit.
|
||||
*/
|
||||
static inline css_unit css_utils__fudge_viewport_units(
|
||||
const nscss_len_ctx *ctx,
|
||||
css_unit unit)
|
||||
{
|
||||
switch (unit) {
|
||||
case CSS_UNIT_VI:
|
||||
assert(ctx->root_style != NULL);
|
||||
if (css_computed_writing_mode(ctx->root_style) ==
|
||||
CSS_WRITING_MODE_HORIZONTAL_TB) {
|
||||
unit = CSS_UNIT_VW;
|
||||
} else {
|
||||
unit = CSS_UNIT_VH;
|
||||
}
|
||||
break;
|
||||
case CSS_UNIT_VB:
|
||||
assert(ctx->root_style != NULL);
|
||||
if (css_computed_writing_mode(ctx->root_style) ==
|
||||
CSS_WRITING_MODE_HORIZONTAL_TB) {
|
||||
unit = CSS_UNIT_VH;
|
||||
} else {
|
||||
unit = CSS_UNIT_VW;
|
||||
}
|
||||
break;
|
||||
case CSS_UNIT_VMIN:
|
||||
if (ctx->vh < ctx->vw) {
|
||||
unit = CSS_UNIT_VH;
|
||||
} else {
|
||||
unit = CSS_UNIT_VW;
|
||||
}
|
||||
break;
|
||||
case CSS_UNIT_VMAX:
|
||||
if (ctx->vh > ctx->vw) {
|
||||
unit = CSS_UNIT_VH;
|
||||
} else {
|
||||
unit = CSS_UNIT_VW;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return unit;
|
||||
}
|
||||
|
||||
/* exported interface documented in content/handlers/css/utils.h */
|
||||
css_fixed nscss_len2pt(
|
||||
const nscss_len_ctx *ctx,
|
||||
css_fixed length,
|
||||
css_unit unit)
|
||||
{
|
||||
/* Length must not be relative */
|
||||
assert(unit != CSS_UNIT_EM &&
|
||||
unit != CSS_UNIT_EX &&
|
||||
unit != CSS_UNIT_CAP &&
|
||||
unit != CSS_UNIT_CH &&
|
||||
unit != CSS_UNIT_IC &&
|
||||
unit != CSS_UNIT_REM &&
|
||||
unit != CSS_UNIT_RLH);
|
||||
|
||||
unit = css_utils__fudge_viewport_units(ctx, unit);
|
||||
|
||||
switch (unit) {
|
||||
/* We assume the screen and any other output has the same dpi */
|
||||
/* 1in = DPIpx => 1px = (72/DPI)pt */
|
||||
case CSS_UNIT_PX: return FDIV(FMUL(length, F_72), F_96);
|
||||
/* 1in = 72pt */
|
||||
case CSS_UNIT_IN: return FMUL(length, F_72);
|
||||
/* 1in = 2.54cm => 1cm = (72/2.54)pt */
|
||||
case CSS_UNIT_CM: return FMUL(length,
|
||||
FDIV(F_72, FLTTOFIX(2.54)));
|
||||
/* 1in = 25.4mm => 1mm = (72/25.4)pt */
|
||||
case CSS_UNIT_MM: return FMUL(length,
|
||||
FDIV(F_72, FLTTOFIX(25.4)));
|
||||
/* 1in = 101.6q => 1mm = (72/101.6)pt */
|
||||
case CSS_UNIT_Q: return FMUL(length,
|
||||
FDIV(F_72, FLTTOFIX(101.6)));
|
||||
case CSS_UNIT_PT: return length;
|
||||
/* 1pc = 12pt */
|
||||
case CSS_UNIT_PC: return FMUL(length, INTTOFIX(12));
|
||||
case CSS_UNIT_VH: return FDIV(FMUL(FDIV(FMUL(length, ctx->vh), F_100), F_72), F_96);
|
||||
case CSS_UNIT_VW: return FDIV(FMUL(FDIV(FMUL(length,ctx->vw), F_100), F_72), F_96);
|
||||
default: break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* exported interface documented in content/handlers/css/utils.h */
|
||||
css_fixed nscss_len2px(
|
||||
const nscss_len_ctx *ctx,
|
||||
css_fixed length,
|
||||
css_unit unit,
|
||||
const css_computed_style *style)
|
||||
{
|
||||
/* We assume the screen and any other output has the same dpi */
|
||||
css_fixed px_per_unit;
|
||||
|
||||
unit = css_utils__fudge_viewport_units(ctx, unit);
|
||||
|
||||
switch (unit) {
|
||||
case CSS_UNIT_EM:
|
||||
case CSS_UNIT_EX:
|
||||
case CSS_UNIT_CAP:
|
||||
case CSS_UNIT_CH:
|
||||
case CSS_UNIT_IC:
|
||||
{
|
||||
css_fixed font_size = 0;
|
||||
css_unit font_unit = CSS_UNIT_PT;
|
||||
|
||||
assert(style != NULL);
|
||||
|
||||
css_computed_font_size(style, &font_size, &font_unit);
|
||||
|
||||
/* Convert to points */
|
||||
font_size = nscss_len2pt(ctx, font_size, font_unit);
|
||||
|
||||
/* Clamp to configured minimum */
|
||||
if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
|
||||
font_size = FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10);
|
||||
}
|
||||
|
||||
/* Convert to pixels (manually, to maximise precision)
|
||||
* 1in = 72pt => 1pt = (DPI/72)px */
|
||||
px_per_unit = FDIV(FMUL(font_size, F_96), F_72);
|
||||
|
||||
/* Scale non-em units to em. We have fixed ratios. */
|
||||
switch (unit) {
|
||||
case CSS_UNIT_EX:
|
||||
px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.6));
|
||||
break;
|
||||
case CSS_UNIT_CAP:
|
||||
px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.9));
|
||||
break;
|
||||
case CSS_UNIT_CH:
|
||||
px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.4));
|
||||
break;
|
||||
case CSS_UNIT_IC:
|
||||
px_per_unit = FMUL(px_per_unit, FLTTOFIX(1.1));
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CSS_UNIT_PX:
|
||||
px_per_unit = F_1;
|
||||
break;
|
||||
/* 1in = 96 CSS pixels */
|
||||
case CSS_UNIT_IN:
|
||||
px_per_unit = F_96;
|
||||
break;
|
||||
/* 1in = 2.54cm => 1cm = (DPI/2.54)px */
|
||||
case CSS_UNIT_CM:
|
||||
px_per_unit = FDIV(F_96, FLTTOFIX(2.54));
|
||||
break;
|
||||
/* 1in = 25.4mm => 1mm = (DPI/25.4)px */
|
||||
case CSS_UNIT_MM:
|
||||
px_per_unit = FDIV(F_96, FLTTOFIX(25.4));
|
||||
break;
|
||||
/* 1in = 101.6q => 1q = (DPI/101.6)px */
|
||||
case CSS_UNIT_Q:
|
||||
px_per_unit = FDIV(F_96, FLTTOFIX(101.6));
|
||||
break;
|
||||
/* 1in = 72pt => 1pt = (DPI/72)px */
|
||||
case CSS_UNIT_PT:
|
||||
px_per_unit = FDIV(F_96, F_72);
|
||||
break;
|
||||
/* 1pc = 12pt => 1in = 6pc => 1pc = (DPI/6)px */
|
||||
case CSS_UNIT_PC:
|
||||
px_per_unit = FDIV(F_96, INTTOFIX(6));
|
||||
break;
|
||||
case CSS_UNIT_REM:
|
||||
{
|
||||
css_fixed font_size = 0;
|
||||
css_unit font_unit = CSS_UNIT_PT;
|
||||
|
||||
assert(ctx->root_style != NULL);
|
||||
|
||||
css_computed_font_size(ctx->root_style,
|
||||
&font_size, &font_unit);
|
||||
|
||||
/* Convert to points */
|
||||
font_size = nscss_len2pt(ctx, font_size, font_unit);
|
||||
|
||||
/* Clamp to configured minimum */
|
||||
if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
|
||||
font_size = FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10);
|
||||
}
|
||||
|
||||
/* Convert to pixels (manually, to maximise precision)
|
||||
* 1in = 72pt => 1pt = (DPI/72)px */
|
||||
px_per_unit = FDIV(FMUL(font_size, F_96), F_72);
|
||||
break;
|
||||
}
|
||||
/* 1rlh = <user_font_size>pt => 1rlh = (DPI/user_font_size)px */
|
||||
case CSS_UNIT_RLH:
|
||||
px_per_unit = FDIV(F_96, FDIV(
|
||||
INTTOFIX(nsoption_int(font_size)),
|
||||
INTTOFIX(10)));
|
||||
break;
|
||||
case CSS_UNIT_VH:
|
||||
px_per_unit = FDIV(ctx->vh, F_100);
|
||||
break;
|
||||
case CSS_UNIT_VW:
|
||||
px_per_unit = FDIV(ctx->vw, F_100);
|
||||
break;
|
||||
default:
|
||||
px_per_unit = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
px_per_unit = nscss_pixels_css_to_physical(px_per_unit);
|
||||
|
||||
/* Ensure we round px_per_unit to the nearest whole number of pixels:
|
||||
* the use of FIXTOINT() below will truncate. */
|
||||
px_per_unit += F_0_5;
|
||||
|
||||
/* Calculate total number of pixels */
|
||||
return FMUL(length, TRUNCATEFIX(px_per_unit));
|
||||
}
|
176
src/document/css2/utils.h
Normal file
176
src/document/css2/utils.h
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright 2009 John-Mark Bell <jmb@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/>.
|
||||
*/
|
||||
|
||||
#ifndef NETSURF_CSS_UTILS_H_
|
||||
#define NETSURF_CSS_UTILS_H_
|
||||
|
||||
#include <libcss/libcss.h>
|
||||
|
||||
#include "netsurf/css.h"
|
||||
|
||||
/** DPI of the screen, in fixed point units */
|
||||
extern css_fixed nscss_screen_dpi;
|
||||
|
||||
/** Medium screen density for device viewing distance. */
|
||||
extern css_fixed nscss_baseline_pixel_density;
|
||||
|
||||
/**
|
||||
* Length conversion context data.
|
||||
*/
|
||||
typedef struct nscss_len_ctx {
|
||||
/**
|
||||
* Viewport width in px.
|
||||
* Only used if unit is vh, vw, vi, vb, vmin, or vmax.
|
||||
*/
|
||||
int vw;
|
||||
/**
|
||||
* Viewport height in px.
|
||||
* Only used if unit is vh, vw, vi, vb, vmin, or vmax.
|
||||
*/
|
||||
int vh;
|
||||
/**
|
||||
* Computed style for the document root element.
|
||||
* May be NULL if unit is not rem, or rlh.
|
||||
*/
|
||||
const css_computed_style *root_style;
|
||||
} nscss_len_ctx;
|
||||
|
||||
/**
|
||||
* Convert an absolute CSS length to points.
|
||||
*
|
||||
* \param[in] ctx Length conversion context.
|
||||
* \param[in] length Absolute CSS length.
|
||||
* \param[in] unit Unit of the length.
|
||||
* \return length in points
|
||||
*/
|
||||
css_fixed nscss_len2pt(
|
||||
const nscss_len_ctx *ctx,
|
||||
css_fixed length,
|
||||
css_unit unit);
|
||||
|
||||
/**
|
||||
* Convert a CSS length to pixels.
|
||||
*
|
||||
* \param[in] ctx Length conversion context.
|
||||
* \param[in] length Length to convert.
|
||||
* \param[in] unit Corresponding unit.
|
||||
* \param[in] style Computed style applying to length.
|
||||
* May be NULL if unit is not em, ex, cap, ch, or ic.
|
||||
* \return length in pixels
|
||||
*/
|
||||
css_fixed nscss_len2px(
|
||||
const nscss_len_ctx *ctx,
|
||||
css_fixed length,
|
||||
css_unit unit,
|
||||
const css_computed_style *style);
|
||||
|
||||
/**
|
||||
* Convert css pixels to physical pixels.
|
||||
*
|
||||
* \param[in] css_pixels Length in css pixels.
|
||||
* \return length in physical pixels
|
||||
*/
|
||||
static inline css_fixed nscss_pixels_css_to_physical(
|
||||
css_fixed css_pixels)
|
||||
{
|
||||
return FDIV(FMUL(css_pixels, nscss_screen_dpi),
|
||||
nscss_baseline_pixel_density);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert physical pixels to css pixels.
|
||||
*
|
||||
* \param[in] physical_pixels Length in physical pixels.
|
||||
* \return length in css pixels
|
||||
*/
|
||||
static inline css_fixed nscss_pixels_physical_to_css(
|
||||
css_fixed physical_pixels)
|
||||
{
|
||||
return FDIV(FMUL(physical_pixels, nscss_baseline_pixel_density),
|
||||
nscss_screen_dpi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary helper wrappers for for libcss computed style getter, while
|
||||
* we don't support flexbox related property values.
|
||||
*/
|
||||
|
||||
static inline uint8_t ns_computed_display(
|
||||
const css_computed_style *style, bool root)
|
||||
{
|
||||
uint8_t value = css_computed_display(style, root);
|
||||
|
||||
if (value == CSS_DISPLAY_FLEX) {
|
||||
return CSS_DISPLAY_BLOCK;
|
||||
|
||||
} else if (value == CSS_DISPLAY_INLINE_FLEX) {
|
||||
return CSS_DISPLAY_INLINE_BLOCK;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
static inline uint8_t ns_computed_display_static(
|
||||
const css_computed_style *style)
|
||||
{
|
||||
uint8_t value = css_computed_display_static(style);
|
||||
|
||||
if (value == CSS_DISPLAY_FLEX) {
|
||||
return CSS_DISPLAY_BLOCK;
|
||||
|
||||
} else if (value == CSS_DISPLAY_INLINE_FLEX) {
|
||||
return CSS_DISPLAY_INLINE_BLOCK;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
static inline uint8_t ns_computed_min_height(
|
||||
const css_computed_style *style,
|
||||
css_fixed *length, css_unit *unit)
|
||||
{
|
||||
uint8_t value = css_computed_min_height(style, length, unit);
|
||||
|
||||
if (value == CSS_MIN_HEIGHT_AUTO) {
|
||||
value = CSS_MIN_HEIGHT_SET;
|
||||
*length = 0;
|
||||
*unit = CSS_UNIT_PX;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
static inline uint8_t ns_computed_min_width(
|
||||
const css_computed_style *style,
|
||||
css_fixed *length, css_unit *unit)
|
||||
{
|
||||
uint8_t value = css_computed_min_width(style, length, unit);
|
||||
|
||||
if (value == CSS_MIN_WIDTH_AUTO) {
|
||||
value = CSS_MIN_WIDTH_SET;
|
||||
*length = 0;
|
||||
*unit = CSS_UNIT_PX;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,4 +1,3 @@
|
||||
|
||||
#ifndef EL__DOCUMENT_HTML_INTERNAL_H
|
||||
#define EL__DOCUMENT_HTML_INTERNAL_H
|
||||
|
||||
@ -6,10 +5,17 @@
|
||||
#include "document/html/parser.h"
|
||||
#include "util/lists.h"
|
||||
|
||||
#ifdef CONFIG_LIBCSS
|
||||
#undef restrict
|
||||
#define restrict __restrict
|
||||
#include <libcss/libcss.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct document;
|
||||
struct document_options;
|
||||
struct uri;
|
||||
|
||||
@ -40,14 +46,38 @@ enum html_whitespace_state {
|
||||
HTML_SPACE_ADD,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_LIBCSS
|
||||
typedef struct nscss_select_ctx
|
||||
{
|
||||
css_select_ctx *ctx;
|
||||
bool quirks;
|
||||
struct nsurl *base_url;
|
||||
lwc_string *universal;
|
||||
const css_computed_style *root_style;
|
||||
const css_computed_style *parent_style;
|
||||
} nscss_select_ctx;
|
||||
|
||||
struct el_sheet {
|
||||
LIST_HEAD(struct el_sheet);
|
||||
css_stylesheet *sheet;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
struct html_context {
|
||||
#ifdef CONFIG_CSS
|
||||
#ifdef CONFIG_LIBCSS
|
||||
struct document *document;
|
||||
LIST_OF(struct el_sheet) sheets;
|
||||
css_select_ctx *select_ctx;
|
||||
/* The default stylesheet is initially merged into it. When parsing CSS
|
||||
* from <style>-tags and external stylesheets if enabled is merged
|
||||
* added to it. */
|
||||
#endif
|
||||
struct css_stylesheet css_styles;
|
||||
#endif
|
||||
|
||||
/* These are global per-document base values, alterable by the <base>
|
||||
* element. */
|
||||
struct uri *base_href;
|
||||
@ -139,7 +169,7 @@ struct html_context {
|
||||
|
||||
#define html_top ((struct html_element *) html_context->stack.next)
|
||||
#define html_bottom ((struct html_element *) html_context->stack.prev)
|
||||
#define elformat (html_top->attr)
|
||||
#define elformat (html_top->attr)
|
||||
#define par_elformat (html_top->parattr)
|
||||
|
||||
#define html_is_preformatted() (elformat.style.attr & AT_PREFORMATTED)
|
||||
@ -153,10 +183,14 @@ void html_focusable(struct html_context *html_context, char *a);
|
||||
void html_skip(struct html_context *html_context, char *a);
|
||||
char *get_target(struct document_options *options, char *a);
|
||||
|
||||
void
|
||||
import_css_stylesheet(struct css_stylesheet *css, struct uri *base_uri,
|
||||
void import_css_stylesheet(struct css_stylesheet *css, struct uri *base_uri,
|
||||
const char *unterminated_url, int len);
|
||||
|
||||
#ifdef CONFIG_LIBCSS
|
||||
void import_css2_stylesheet(struct html_context *, struct uri *base_uri,
|
||||
const char *unterminated_url, int len);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -49,6 +49,11 @@
|
||||
/* Unsafe macros */
|
||||
#include "document/html/internal.h"
|
||||
|
||||
#ifdef CONFIG_LIBCSS
|
||||
#include <libcss/libcss.h>
|
||||
#include "document/css2/css.h"
|
||||
#endif
|
||||
|
||||
/* TODO: This needs rewrite. Yes, no kidding. */
|
||||
|
||||
static int
|
||||
@ -201,6 +206,48 @@ add_fragment_identifier(struct html_context *html_context,
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CSS
|
||||
|
||||
#ifdef CONFIG_LIBCSS
|
||||
void
|
||||
import_css2_stylesheet(struct html_context *html_context, struct uri *base_uri, const char *unterminated_url, int len)
|
||||
{
|
||||
char *url;
|
||||
char *import_url;
|
||||
struct uri *uri;
|
||||
|
||||
assert(html_context);
|
||||
assert(base_uri);
|
||||
|
||||
if (!html_context->options->css_enable
|
||||
|| !html_context->options->css_import)
|
||||
return;
|
||||
|
||||
/* unterminated_url might not end with '\0', but join_urls
|
||||
* requires that, so make a copy. */
|
||||
url = memacpy(unterminated_url, len);
|
||||
if (!url) return;
|
||||
|
||||
/* HTML <head> urls should already be fine but we can.t detect them. */
|
||||
import_url = join_urls(base_uri, url);
|
||||
mem_free(url);
|
||||
|
||||
if (!import_url) return;
|
||||
|
||||
uri = get_uri(import_url, URI_BASE);
|
||||
mem_free(import_url);
|
||||
|
||||
if (!uri) return;
|
||||
|
||||
/* Request the imported stylesheet as part of the document ... */
|
||||
html_context->special_f(html_context, SP_STYLESHEET, uri);
|
||||
|
||||
/* ... and then attempt to import from the cache. */
|
||||
import_css2(html_context, uri);
|
||||
|
||||
done_uri(uri);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
import_css_stylesheet(struct css_stylesheet *css, struct uri *base_uri,
|
||||
const char *unterminated_url, int len)
|
||||
@ -758,7 +805,7 @@ done_html_parser_state(struct html_context *html_context,
|
||||
* The title of the document. This is in the document charset,
|
||||
* and entities have not been decoded. */
|
||||
struct html_context *
|
||||
init_html_parser(struct uri *uri, struct document_options *options,
|
||||
init_html_parser(struct uri *uri, struct document *document,
|
||||
char *start, char *end,
|
||||
struct string *head, struct string *title,
|
||||
void (*put_chars)(struct html_context *, const char *, int),
|
||||
@ -767,6 +814,7 @@ init_html_parser(struct uri *uri, struct document_options *options,
|
||||
{
|
||||
struct html_context *html_context;
|
||||
struct html_element *e;
|
||||
struct document_options *options = &document->options;
|
||||
|
||||
assert(uri && options);
|
||||
if_assert_failed return NULL;
|
||||
@ -775,6 +823,9 @@ init_html_parser(struct uri *uri, struct document_options *options,
|
||||
if (!html_context) return NULL;
|
||||
|
||||
#ifdef CONFIG_CSS
|
||||
#ifdef CONFIG_LIBCSS
|
||||
html_context->document = document;
|
||||
#endif
|
||||
html_context->css_styles.import = import_css_stylesheet;
|
||||
init_css_selector_set(&html_context->css_styles.selectors);
|
||||
#endif
|
||||
@ -832,7 +883,7 @@ init_html_parser(struct uri *uri, struct document_options *options,
|
||||
|
||||
html_top->invisible = 0;
|
||||
html_top->name = NULL;
|
||||
html_top->namelen = 0;
|
||||
html_top->namelen = 0;
|
||||
html_top->options = NULL;
|
||||
html_top->linebreak = 1;
|
||||
html_top->type = ELEMENT_DONT_KILL;
|
||||
@ -841,11 +892,27 @@ init_html_parser(struct uri *uri, struct document_options *options,
|
||||
html_context->table_level = 0;
|
||||
|
||||
#ifdef CONFIG_CSS
|
||||
html_context->css_styles.import_data = html_context;
|
||||
#ifdef CONFIG_LIBCSS
|
||||
if (options->libcss_enable) {
|
||||
if (options->css_enable) {
|
||||
css_error code;
|
||||
|
||||
if (options->css_enable)
|
||||
mirror_css_stylesheet(&default_stylesheet,
|
||||
&html_context->css_styles);
|
||||
init_list(html_context->sheets);
|
||||
/* prepare a selection context containing the stylesheet */
|
||||
code = css_select_ctx_create(&html_context->select_ctx);
|
||||
if (code != CSS_OK) {
|
||||
//fprintf(stderr, "css_select_ctx_create code=%d\n", code);
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
do {
|
||||
html_context->css_styles.import_data = html_context;
|
||||
|
||||
if (options->css_enable)
|
||||
mirror_css_stylesheet(&default_stylesheet,
|
||||
&html_context->css_styles);
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
return html_context;
|
||||
@ -855,10 +922,23 @@ void
|
||||
done_html_parser(struct html_context *html_context)
|
||||
{
|
||||
#ifdef CONFIG_CSS
|
||||
if (html_context->options->css_enable)
|
||||
done_css_stylesheet(&html_context->css_styles);
|
||||
#ifdef CONFIG_LIBCSS
|
||||
if (html_context->options->libcss_enable) {
|
||||
if (html_context->options->css_enable) {
|
||||
struct el_sheet *el;
|
||||
css_error code = css_select_ctx_destroy(html_context->select_ctx);
|
||||
foreach (el, html_context->sheets) {
|
||||
code = css_stylesheet_destroy(el->sheet);
|
||||
}
|
||||
free_list(html_context->sheets);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
do {
|
||||
if (html_context->options->css_enable)
|
||||
done_css_stylesheet(&html_context->css_styles);
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
mem_free(html_context->base_target);
|
||||
done_uri(html_context->base_href);
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct document;
|
||||
struct document_options;
|
||||
struct el_form_control;
|
||||
struct frameset_desc;
|
||||
@ -178,7 +179,7 @@ struct html_element {
|
||||
/* Interface for the renderer */
|
||||
|
||||
struct html_context *
|
||||
init_html_parser(struct uri *uri, struct document_options *options,
|
||||
init_html_parser(struct uri *uri, struct document *document,
|
||||
char *start, char *end,
|
||||
struct string *head, struct string *title,
|
||||
void (*put_chars)(struct html_context *, const char *, int),
|
||||
|
@ -186,11 +186,16 @@ void
|
||||
html_apply_canvas_bgcolor(struct html_context *html_context)
|
||||
{
|
||||
#ifdef CONFIG_CSS
|
||||
#ifdef CONFIG_LIBCSS
|
||||
if (!html_context->options->libcss_enable)
|
||||
#endif
|
||||
/* If there are any CSS twaks regarding bgcolor, make sure we will get
|
||||
* it _and_ prefer it over bgcolor attribute. */
|
||||
do {
|
||||
if (html_context->options->css_enable)
|
||||
css_apply(html_context, html_top, &html_context->css_styles,
|
||||
&html_context->stack);
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
if (par_elformat.color.background != elformat.style.color.background) {
|
||||
|
@ -923,15 +923,29 @@ html_link(struct html_context *html_context, char *a,
|
||||
if (!link.href) goto free_and_return;
|
||||
|
||||
#ifdef CONFIG_CSS
|
||||
if (link.type == LT_STYLESHEET
|
||||
&& supports_html_media_attr(link.media)) {
|
||||
int len = strlen(link.href);
|
||||
#ifdef CONFIG_LIBCSS
|
||||
if (html_context->options->libcss_enable) {
|
||||
if (link.type == LT_STYLESHEET
|
||||
&& supports_html_media_attr(link.media)) {
|
||||
int len = strlen(link.href);
|
||||
|
||||
import_css_stylesheet(&html_context->css_styles,
|
||||
html_context->base_href, link.href, len);
|
||||
}
|
||||
import_css2_stylesheet(html_context, html_context->base_href, link.href, len);
|
||||
}
|
||||
|
||||
if (!link_display) goto free_and_return;
|
||||
if (!link_display) goto free_and_return;
|
||||
} else
|
||||
#endif
|
||||
do {
|
||||
if (link.type == LT_STYLESHEET
|
||||
&& supports_html_media_attr(link.media)) {
|
||||
int len = strlen(link.href);
|
||||
|
||||
import_css_stylesheet(&html_context->css_styles,
|
||||
html_context->base_href, link.href, len);
|
||||
}
|
||||
|
||||
if (!link_display) goto free_and_return;
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
/* Ignore few annoying links.. */
|
||||
|
@ -16,6 +16,9 @@
|
||||
#include "document/css/apply.h"
|
||||
#include "document/css/css.h"
|
||||
#include "document/css/parser.h"
|
||||
#ifdef CONFIG_LIBCSS
|
||||
#include "document/css2/css.h"
|
||||
#endif
|
||||
#include "document/html/parser/forms.h"
|
||||
#include "document/html/parser/general.h"
|
||||
#include "document/html/parser/link.h"
|
||||
@ -896,17 +899,31 @@ start_element(struct element_info *ei,
|
||||
|
||||
/* If this is a style tag, parse it. */
|
||||
#ifdef CONFIG_CSS
|
||||
if (ei->open == html_style && html_context->options->css_enable) {
|
||||
char *media
|
||||
= get_attr_val(attr, "media", html_context->doc_cp);
|
||||
int support = supports_html_media_attr(media);
|
||||
mem_free_if(media);
|
||||
#ifdef CONFIG_LIBCSS
|
||||
if (html_context->options->libcss_enable) {
|
||||
if (ei->open == html_style && html_context->options->css_enable) {
|
||||
char *media = get_attr_val(attr, "media", html_context->doc_cp);
|
||||
int support = supports_html_media_attr(media);
|
||||
mem_free_if(media);
|
||||
|
||||
if (support)
|
||||
css_parse_stylesheet(&html_context->css_styles,
|
||||
html_context->base_href,
|
||||
html, eof);
|
||||
}
|
||||
if (support) {
|
||||
parse_css(html_context, name);
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
do {
|
||||
if (ei->open == html_style && html_context->options->css_enable) {
|
||||
char *media = get_attr_val(attr, "media", html_context->doc_cp);
|
||||
int support = supports_html_media_attr(media);
|
||||
mem_free_if(media);
|
||||
|
||||
if (support)
|
||||
css_parse_stylesheet(&html_context->css_styles,
|
||||
html_context->base_href,
|
||||
html, eof);
|
||||
}
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
/* If this element is inline, non-nestable, and not <li>, and the next
|
||||
@ -977,31 +994,40 @@ start_element(struct element_info *ei,
|
||||
|
||||
/* Apply CSS styles. */
|
||||
#ifdef CONFIG_CSS
|
||||
if (html_top->options && html_context->options->css_enable) {
|
||||
/* XXX: We should apply CSS otherwise as well, but that'll need
|
||||
* some deeper changes in order to have options filled etc.
|
||||
* Probably just applying CSS from more places, since we
|
||||
* usually have type != ET_NESTABLE when we either (1)
|
||||
* rescan on your own from somewhere else (2) html_stack_dup()
|
||||
* in our own way. --pasky */
|
||||
mem_free_set(&html_top->attr.id,
|
||||
get_attr_val(attr, "id", html_context->doc_cp));
|
||||
mem_free_set(&html_top->attr.class_,
|
||||
get_attr_val(attr, "class", html_context->doc_cp));
|
||||
/* Call it now to gain some of the stuff which might affect
|
||||
* formatting of some elements. */
|
||||
/* FIXME: The caching of the CSS selector is broken, since t can
|
||||
* lead to wrong styles being applied to following elements, so
|
||||
* disabled for now. */
|
||||
selector = get_css_selector_for_element(html_context, html_top,
|
||||
#ifdef CONFIG_LIBCSS
|
||||
if (html_context->options->libcss_enable) {
|
||||
if (html_context->options->css_enable) {
|
||||
select_css(html_context, html_top);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
do {
|
||||
if (html_top->options && html_context->options->css_enable) {
|
||||
/* XXX: We should apply CSS otherwise as well, but that'll need
|
||||
* some deeper changes in order to have options filled etc.
|
||||
* Probably just applying CSS from more places, since we
|
||||
* usually have type != ET_NESTABLE when we either (1)
|
||||
* rescan on your own from somewhere else (2) html_stack_dup()
|
||||
* in our own way. --pasky */
|
||||
mem_free_set(&html_top->attr.id,
|
||||
get_attr_val(attr, "id", html_context->doc_cp));
|
||||
mem_free_set(&html_top->attr.class_,
|
||||
get_attr_val(attr, "class", html_context->doc_cp));
|
||||
/* Call it now to gain some of the stuff which might affect
|
||||
* formatting of some elements. */
|
||||
/* FIXME: The caching of the CSS selector is broken, since t can
|
||||
* lead to wrong styles being applied to following elements, so
|
||||
* disabled for now. */
|
||||
selector = get_css_selector_for_element(html_context, html_top,
|
||||
&html_context->css_styles,
|
||||
&html_context->stack);
|
||||
|
||||
if (selector) {
|
||||
apply_css_selector_style(html_context, html_top, selector);
|
||||
done_css_selector(selector);
|
||||
if (selector) {
|
||||
apply_css_selector_style(html_context, html_top, selector);
|
||||
done_css_selector(selector);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
/* 1. Put any linebreaks that the element calls for, and 2. register
|
||||
@ -1019,17 +1045,26 @@ start_element(struct element_info *ei,
|
||||
|
||||
/* Apply CSS styles again. */
|
||||
#ifdef CONFIG_CSS
|
||||
if (selector && html_top->options) {
|
||||
/* Call it now to override default colors of the elements. */
|
||||
selector = get_css_selector_for_element(html_context, html_top,
|
||||
#ifdef CONFIG_LIBCSS
|
||||
if (html_context->options->libcss_enable) {
|
||||
if (html_context->options->css_enable) {
|
||||
select_css(html_context, html_top);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
do {
|
||||
if (selector && html_top->options) {
|
||||
/* Call it now to override default colors of the elements. */
|
||||
selector = get_css_selector_for_element(html_context, html_top,
|
||||
&html_context->css_styles,
|
||||
&html_context->stack);
|
||||
|
||||
if (selector) {
|
||||
apply_css_selector_style(html_context, html_top, selector);
|
||||
done_css_selector(selector);
|
||||
if (selector) {
|
||||
apply_css_selector_style(html_context, html_top, selector);
|
||||
done_css_selector(selector);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
/* If this element was not <br>, clear the was_br flag. */
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
#ifndef EL__DOCUMENT_HTML_PARSER_PARSE_H
|
||||
#define EL__DOCUMENT_HTML_PARSER_PARSE_H
|
||||
|
||||
|
@ -2597,7 +2597,7 @@ render_html_document(struct cache_entry *cached, struct document *document,
|
||||
start = buffer->source;
|
||||
end = buffer->source + buffer->length;
|
||||
|
||||
html_context = init_html_parser(cached->uri, &document->options,
|
||||
html_context = init_html_parser(cached->uri, document,
|
||||
start, end, &head, &title,
|
||||
put_chars_conv, line_break,
|
||||
html_special);
|
||||
|
@ -1,6 +1,9 @@
|
||||
if conf_data.get('CONFIG_CSS')
|
||||
subdir('css')
|
||||
endif
|
||||
if conf_data.get('CONFIG_LIBCSS')
|
||||
subdir('css2')
|
||||
endif
|
||||
if conf_data.get('CONFIG_DOM')
|
||||
subdir('dom')
|
||||
endif
|
||||
|
@ -75,6 +75,9 @@ init_document_options(struct session *ses, struct document_options *doo)
|
||||
|
||||
/* Boolean options. */
|
||||
#ifdef CONFIG_CSS
|
||||
#ifdef CONFIG_LIBCSS
|
||||
doo->libcss_enable = get_opt_bool("document.css.libcss", ses);
|
||||
#endif
|
||||
doo->css_enable = get_opt_bool("document.css.enable", ses);
|
||||
doo->css_ignore_display_none = get_opt_bool("document.css.ignore_display_none", ses);
|
||||
doo->css_import = get_opt_bool("document.css.import", ses);
|
||||
|
@ -76,6 +76,9 @@ struct document_options {
|
||||
|
||||
/* XXX: Keep boolean options grouped to save padding */
|
||||
#ifdef CONFIG_CSS
|
||||
#ifdef CONFIG_LIBCSS
|
||||
unsigned int libcss_enable:1;
|
||||
#endif
|
||||
/** @name CSS stuff
|
||||
* @{ */
|
||||
unsigned int css_enable:1;
|
||||
|
@ -41,234 +41,6 @@
|
||||
#include <map>
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
static void
|
||||
dump_text(struct source_renderer *renderer, unsigned char *html, int length)
|
||||
{
|
||||
struct html_context *html_context = renderer->html_context;
|
||||
unsigned char *eof = html + length;
|
||||
unsigned char *base_pos = html;
|
||||
|
||||
if (length > 0 && (eof[-1] == '\n')) {
|
||||
length--;
|
||||
eof--;
|
||||
}
|
||||
#ifdef CONFIG_CSS
|
||||
if (html_context->was_style) {
|
||||
/// css_parse_stylesheet(&html_context->css_styles, html_context->base_href, html, eof);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
//fprintf(stderr, "html='%s'\n", html);
|
||||
if (length <= 0) {
|
||||
return;
|
||||
}
|
||||
int noupdate = 0;
|
||||
|
||||
main_loop:
|
||||
while (html < eof) {
|
||||
char *name, *attr, *end;
|
||||
int namelen, endingtag;
|
||||
int dotcounter = 0;
|
||||
|
||||
if (!noupdate) {
|
||||
html_context->part = renderer->part;
|
||||
html_context->eoff = eof;
|
||||
base_pos = html;
|
||||
} else {
|
||||
noupdate = 0;
|
||||
}
|
||||
|
||||
if (isspace((unsigned char)*html) && !html_is_preformatted()) {
|
||||
char *h = html;
|
||||
|
||||
while (h < eof && isspace((unsigned char)*h))
|
||||
h++;
|
||||
if (h + 1 < eof && h[0] == '<' && h[1] == '/') {
|
||||
if (!parse_element(h, eof, &name, &namelen, &attr, &end)) {
|
||||
put_chrs(html_context, base_pos, html - base_pos);
|
||||
base_pos = html = h;
|
||||
html_context->putsp = HTML_SPACE_ADD;
|
||||
goto element;
|
||||
}
|
||||
}
|
||||
html++;
|
||||
if (!(html_context->position + (html - base_pos - 1)))
|
||||
goto skip_w; /* ??? */
|
||||
if (*(html - 1) == ' ') { /* Do not replace with isspace((unsigned char)) ! --Zas */
|
||||
/* BIG performance win; not sure if it doesn't cause any bug */
|
||||
if (html < eof && !isspace((unsigned char)*html)) {
|
||||
noupdate = 1;
|
||||
continue;
|
||||
}
|
||||
put_chrs(html_context, base_pos, html - base_pos);
|
||||
} else {
|
||||
put_chrs(html_context, base_pos, html - base_pos - 1);
|
||||
put_chrs(html_context, " ", 1);
|
||||
}
|
||||
|
||||
skip_w:
|
||||
while (html < eof && isspace((unsigned char)*html))
|
||||
html++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (html_is_preformatted()) {
|
||||
html_context->putsp = HTML_SPACE_NORMAL;
|
||||
if (*html == ASCII_TAB) {
|
||||
put_chrs(html_context, base_pos, html - base_pos);
|
||||
put_chrs(html_context, " ",
|
||||
8 - (html_context->position % 8));
|
||||
html++;
|
||||
continue;
|
||||
|
||||
} else if (*html == ASCII_CR || *html == ASCII_LF) {
|
||||
put_chrs(html_context, base_pos, html - base_pos);
|
||||
if (html - base_pos == 0 && html_context->line_breax > 0)
|
||||
html_context->line_breax--;
|
||||
next_break:
|
||||
if (*html == ASCII_CR && html < eof - 1
|
||||
&& html[1] == ASCII_LF)
|
||||
html++;
|
||||
ln_break(html_context, 1);
|
||||
html++;
|
||||
if (*html == ASCII_CR || *html == ASCII_LF) {
|
||||
html_context->line_breax = 0;
|
||||
goto next_break;
|
||||
}
|
||||
continue;
|
||||
|
||||
} else if (html + 5 < eof && *html == '&') {
|
||||
/* Really nasty hack to make handling in
|
||||
* <pre>-tags lynx-compatible. It works around
|
||||
* the entity handling done in the renderer,
|
||||
* since checking #13 value there would require
|
||||
* something along the lines of NBSP_CHAR or
|
||||
* checking for '\n's in AT_PREFORMATTED text. */
|
||||
/* See bug 52 and 387 for more info. */
|
||||
int length = html - base_pos;
|
||||
int newlines;
|
||||
|
||||
html = (char *) count_newline_entities(html, eof, &newlines);
|
||||
if (newlines) {
|
||||
put_chrs(html_context, base_pos, length);
|
||||
ln_break(html_context, newlines);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ((unsigned char)*html < ' ') {
|
||||
if (html - base_pos)
|
||||
put_chrs(html_context, base_pos, html - base_pos);
|
||||
|
||||
dotcounter++;
|
||||
base_pos = ++html;
|
||||
if (*html >= ' ' || isspace((unsigned char)*html) || html >= eof) {
|
||||
char *dots = (char *)fmem_alloc(dotcounter);
|
||||
|
||||
if (dots) {
|
||||
memset(dots, '.', dotcounter);
|
||||
put_chrs(html_context, dots, dotcounter);
|
||||
fmem_free(dots);
|
||||
}
|
||||
goto main_loop;
|
||||
}
|
||||
}
|
||||
|
||||
if (html + 2 <= eof && html[0] == '<' && (html[1] == '!' || html[1] == '?')
|
||||
&& !(html_context->was_xmp || html_context->was_style)) {
|
||||
put_chrs(html_context, base_pos, html - base_pos);
|
||||
html = skip_comment(html, eof);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*html != '<' || parse_element(html, eof, &name, &namelen, &attr, &end)) {
|
||||
html++;
|
||||
noupdate = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
element:
|
||||
endingtag = *name == '/'; name += endingtag; namelen -= endingtag;
|
||||
if (!endingtag && html_context->putsp == HTML_SPACE_ADD && !html_top->invisible)
|
||||
put_chrs(html_context, " ", 1);
|
||||
put_chrs(html_context, base_pos, html - base_pos);
|
||||
if (!html_is_preformatted() && !endingtag && html_context->putsp == HTML_SPACE_NORMAL) {
|
||||
char *ee = end;
|
||||
char *nm;
|
||||
|
||||
/// while (!parse_element(ee, eof, &nm, NULL, NULL, &ee))
|
||||
/// if (*nm == '/')
|
||||
/// goto ng;
|
||||
if (ee < eof && isspace((unsigned char)*ee)) {
|
||||
put_chrs(html_context, " ", 1);
|
||||
}
|
||||
}
|
||||
//ng:
|
||||
// html = process_element(name, namelen, endingtag, end, html, eof, attr, html_context);
|
||||
}
|
||||
|
||||
if (noupdate) put_chrs(html_context, base_pos, html - base_pos);
|
||||
//ln_break(html_context, 1);
|
||||
/* Restore the part in case the html_context was trashed in the last
|
||||
* iteration so that when destroying the stack in the caller we still
|
||||
* get the right part pointer. */
|
||||
html_context->part = renderer->part;
|
||||
html_context->putsp = HTML_SPACE_SUPPRESS;
|
||||
html_context->position = 0;
|
||||
html_context->was_br = 0;
|
||||
}
|
||||
|
||||
#define HTML_MAX_DOM_STRUCTURE_DEPTH 1024
|
||||
|
||||
bool
|
||||
dump_dom_structure(struct source_renderer *renderer, void *nod, int depth)
|
||||
{
|
||||
xmlpp::Node *node = nod;
|
||||
|
||||
if (depth >= HTML_MAX_DOM_STRUCTURE_DEPTH) {
|
||||
return false;
|
||||
}
|
||||
|
||||
xmlpp::ustring tag_name = node->get_name();
|
||||
struct element_info2 *ei = get_tag_value(tag_name.c_str(), tag_name.size());
|
||||
|
||||
if (!ei) return true;
|
||||
|
||||
start_element_2(ei, renderer, node);
|
||||
|
||||
/* Get the node's first child */
|
||||
auto children = node->get_children();
|
||||
auto it = children.begin();
|
||||
auto end = children.end();
|
||||
|
||||
for (;it != end; ++it) {
|
||||
xmlpp::Element *el = dynamic_cast<xmlpp::Element *>(*it);
|
||||
|
||||
if (el) {
|
||||
dump_dom_structure(renderer, el, depth + 1);
|
||||
} else {
|
||||
xmlpp::TextNode *text = dynamic_cast<xmlpp::TextNode *>(*it);
|
||||
|
||||
if (text) {
|
||||
if (renderer->html_context->skip_select || renderer->html_context->skip_textarea) continue;
|
||||
xmlpp::ustring v = text->get_content();
|
||||
dump_text(renderer, v.c_str(), v.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
end_element_2(ei, renderer, node);
|
||||
/*
|
||||
if (ei && ei->close) {
|
||||
ei->close(renderer, node, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
dump_element(std::map<int, xmlpp::Element *> *mapa, struct string *buf, xmlpp::Element *element)
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,5 +13,5 @@
|
||||
</style>
|
||||
<style>) I, love, garbage { dont: you? } </style>
|
||||
<a href="foo" style="color:">no value</a>
|
||||
<div style="{background:#fff}">white bg</div>
|
||||
<div style="background:#fff">white bg</div>
|
||||
<p>should become red when we start supporting escaping of string delimiters</p>
|
||||
|
Loading…
Reference in New Issue
Block a user