summaryrefslogtreecommitdiff
path: root/source/html/css-apply.c
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2016-01-22 12:00:55 +0100
committerTor Andersson <tor.andersson@artifex.com>2016-01-22 12:00:55 +0100
commitf501211e904d2c01e47b03e774ffc6f93faeae25 (patch)
treeaa13c9d28c17e3dbb73459ccf7c6a8ca6c3906e4 /source/html/css-apply.c
parentb31c7d1559125b5a0c596e52d632c70e48c506cf (diff)
downloadmupdf-f501211e904d2c01e47b03e774ffc6f93faeae25.tar.xz
epub: Implement @font-face rules.
Note: font->fallback is not reference counted here. The fallback mechanism is probably going to have to change when we add text shaping.
Diffstat (limited to 'source/html/css-apply.c')
-rw-r--r--source/html/css-apply.c119
1 files changed, 115 insertions, 4 deletions
diff --git a/source/html/css-apply.c b/source/html/css-apply.c
index 45fa7713..db588bf7 100644
--- a/source/html/css-apply.c
+++ b/source/html/css-apply.c
@@ -106,6 +106,18 @@ keyword_in_list(const char *name, const char **list, int n)
return 0;
}
+static int
+is_bold_from_font_weight(const char *weight)
+{
+ return !strcmp(weight, "bold") || !strcmp(weight, "bolder") || atoi(weight) > 400;
+}
+
+static int
+is_italic_from_font_style(const char *style)
+{
+ return !strcmp(style, "italic") || !strcmp(style, "oblique");
+}
+
/*
* Compute specificity
*/
@@ -673,6 +685,93 @@ fz_match_css_at_page(fz_context *ctx, fz_css_match *match, fz_css_rule *css)
sort_properties(match); /* speed up subsequent value_from_raw_property lookups */
}
+void
+fz_add_css_font_face(fz_context *ctx, fz_html_font_set *set, fz_archive *zip, const char *base_uri, fz_css_property *declaration)
+{
+ fz_html_font_face *custom;
+ fz_css_property *prop;
+ fz_font *font = NULL;
+ fz_buffer *buf = NULL;
+ int is_bold, is_italic;
+ char path[2048];
+
+ const char *family = "serif";
+ const char *weight = "normal";
+ const char *style = "normal";
+ const char *src = NULL;
+
+ for (prop = declaration; prop; prop = prop->next)
+ {
+ if (!strcmp(prop->name, "font-family")) family = prop->value->data;
+ if (!strcmp(prop->name, "font-weight")) weight = prop->value->data;
+ if (!strcmp(prop->name, "font-style")) style = prop->value->data;
+ if (!strcmp(prop->name, "src")) src = prop->value->data;
+ }
+
+ if (!src)
+ return;
+
+ is_bold = is_bold_from_font_weight(weight);
+ is_italic = is_italic_from_font_style(style);
+
+ fz_strlcpy(path, base_uri, sizeof path);
+ fz_strlcat(path, "/", sizeof path);
+ fz_strlcat(path, src, sizeof path);
+ fz_urldecode(path);
+ fz_cleanname(path);
+
+ for (custom = set->custom; custom; custom = custom->next)
+ if (!strcmp(custom->src, path) && !strcmp(custom->family, family) &&
+ custom->is_bold == is_bold &&
+ custom->is_italic == is_italic)
+ return; /* already loaded */
+
+ printf("epub: @font-face: family='%s' b=%d i=%d src=%s\n", family, is_bold, is_italic, src);
+
+ fz_var(buf);
+ fz_var(font);
+
+ fz_try(ctx)
+ {
+ if (fz_has_archive_entry(ctx, zip, path))
+ buf = fz_read_archive_entry(ctx, zip, path);
+ else
+ buf = fz_read_file(ctx, src);
+ font = fz_new_font_from_buffer(ctx, src, buf, 0, 0);
+ fz_add_html_font_face(ctx, set, family, is_bold, is_italic, path, font);
+ }
+ fz_always(ctx)
+ {
+ fz_drop_buffer(ctx, buf);
+ fz_drop_font(ctx, font);
+ }
+ fz_catch(ctx)
+ {
+ fz_warn(ctx, "cannot load font-face: %s", src);
+ }
+}
+
+void
+fz_add_css_font_faces(fz_context *ctx, fz_html_font_set *set, fz_archive *zip, const char *base_uri, fz_css_rule *css)
+{
+ fz_css_rule *rule;
+ fz_css_selector *sel;
+
+ for (rule = css; rule; rule = rule->next)
+ {
+ sel = rule->selector;
+ while (sel)
+ {
+ if (sel->name && !strcmp(sel->name, "@font-face"))
+ {
+ fz_add_css_font_face(ctx, set, zip, base_uri, rule->declaration);
+ break;
+ }
+ sel = sel->next;
+ }
+ }
+}
+
static fz_css_value *
value_from_raw_property(fz_css_match *match, const char *name)
{
@@ -1156,11 +1255,23 @@ fz_apply_css_style(fz_context *ctx, fz_html_font_set *set, fz_css_style *style,
style->border_width[3] = border_width_from_property(match, "border-left-width");
{
- const char *font_family = string_from_property(match, "font-family", "serif");
- const char *font_variant = string_from_property(match, "font-variant", "normal");
- const char *font_style = string_from_property(match, "font-style", "normal");
const char *font_weight = string_from_property(match, "font-weight", "normal");
- style->font = fz_load_html_font(ctx, set, font_family, font_variant, font_style, font_weight);
+ const char *font_style = string_from_property(match, "font-style", "normal");
+ int is_bold = is_bold_from_font_weight(font_weight);
+ int is_italic = is_italic_from_font_style(font_style);
+ value = value_from_property(match, "font-family");
+ while (value)
+ {
+ if (strcmp(value->data, ",") != 0)
+ {
+ style->font = fz_load_html_font(ctx, set, value->data, is_bold, is_italic);
+ if (style->font)
+ break;
+ }
+ value = value->next;
+ }
+ if (!style->font)
+ style->font = fz_load_html_font(ctx, set, "serif", 0, 0);
}
}