Dillo v3.1.1-14-g8f67d6e0
Loading...
Searching...
No Matches
styleengine.cc
Go to the documentation of this file.
1/*
2 * File: styleengine.cc
3 *
4 * Copyright 2008-2009 Johannes Hofmann <Johannes.Hofmann@gmx.de>
5 * Copyright 2024 Rodrigo Arias Mallo <rodarima@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 */
12
13#include "../dlib/dlib.h"
14#include "msg.h"
15#include "prefs.h"
16#include "misc.h"
17#include "html_common.hh"
18#include "styleengine.hh"
19#include "web.hh"
20#include "capi.h"
21
22using namespace lout::misc;
23using namespace dw::core::style;
24
33class StyleImageDeletionReceiver:
35{
36 int clientKey;
37
38public:
39 StyleImageDeletionReceiver (int clientKey);
40 ~StyleImageDeletionReceiver ();
41
43};
44
45StyleImageDeletionReceiver::StyleImageDeletionReceiver (int clientKey)
46{
47 this->clientKey = clientKey;
48}
49
50StyleImageDeletionReceiver::~StyleImageDeletionReceiver ()
51{
52}
53
54void StyleImageDeletionReceiver::deleted (lout::signal::ObservedObject *object)
55{
56 a_Capi_stop_client (clientKey, 0);
57 delete this;
58}
59
60// ----------------------------------------------------------------------
61
63 const DilloUrl *pageUrl, const DilloUrl *baseUrl,
64 float zoom) {
65 StyleAttrs style_attrs;
66 FontAttrs font_attrs;
67
68 doctree = new Doctree ();
69 stack = new lout::misc::SimpleVector <Node> (1);
70 cssContext = new CssContext ();
72 this->layout = layout;
73 this->pageUrl = pageUrl ? a_Url_dup(pageUrl) : NULL;
74 this->baseUrl = baseUrl ? a_Url_dup(baseUrl) : NULL;
75 importDepth = 0;
76 dpmm = layout->dpiX () / 25.4; /* assume dpiX == dpiY */
77 this->zoom = zoom;
78
79 stackPush ();
80 Node *n = stack->getLastRef ();
81
82 /* Create a dummy font, attribute, and tag for the bottom of the stack. */
83 font_attrs.name = prefs.font_sans_serif;
84 font_attrs.size = roundInt(14 * prefs.font_factor * zoom);
85 if (font_attrs.size < prefs.font_min_size)
86 font_attrs.size = prefs.font_min_size;
87 if (font_attrs.size > prefs.font_max_size)
88 font_attrs.size = prefs.font_max_size;
89 font_attrs.weight = 400;
90 font_attrs.style = FONT_STYLE_NORMAL;
91 font_attrs.letterSpacing = 0;
93
94 style_attrs.initValues ();
95 style_attrs.font = Font::create (layout, &font_attrs);
96 style_attrs.color = Color::create (layout, 0);
98
99 n->style = Style::create (&style_attrs);
100}
101
103 while (doctree->top ())
105
106 stackPop (); // dummy node on the bottom of the stack
107 assert (stack->size () == 0);
108
111
112 delete stack;
113 delete doctree;
114 delete cssContext;
115}
116
118 static const Node emptyNode = {
119 NULL, NULL, NULL, NULL, NULL, NULL, false, false, NULL
120 };
121
122 stack->setSize (stack->size () + 1, emptyNode);
123}
124
126 Node *n = stack->getRef (stack->size () - 1);
127
128 delete n->styleAttrProperties;
130 delete n->nonCssProperties;
131 if (n->style)
132 n->style->unref ();
133 if (n->wordStyle)
134 n->wordStyle->unref ();
135 if (n->backgroundStyle)
136 n->backgroundStyle->unref ();
137 stack->setSize (stack->size () - 1);
138}
139
144 style (bw); // ensure that style of current node is computed
145
146 stackPush ();
147 Node *n = stack->getLastRef ();
148 DoctreeNode *dn = doctree->push ();
149
150 dn->element = element;
151 n->doctreeNode = dn;
152 if (stack->size () > 1)
153 n->displayNone = stack->getRef (stack->size () - 2)->displayNone;
154}
155
156void StyleEngine::startElement (const char *tagname, BrowserWindow *bw) {
157 startElement (a_Html_tag_index (tagname), bw);
158}
159
160void StyleEngine::setId (const char *id) {
161 DoctreeNode *dn = doctree->top ();
162 assert (dn->id == NULL);
163 dn->id = dStrdup (id);
164}
165
169static lout::misc::SimpleVector<char *> *splitStr (const char *str, char sep) {
170 const char *p1 = NULL;
173
174 for (;; str++) {
175 if (*str != '\0' && *str != sep) {
176 if (!p1)
177 p1 = str;
178 } else if (p1) {
179 list->increase ();
180 list->set (list->size () - 1, dStrndup (p1, str - p1));
181 p1 = NULL;
182 }
183
184 if (*str == '\0')
185 break;
186 }
187
188 return list;
189}
190
191void StyleEngine::setClass (const char *klass) {
192 DoctreeNode *dn = doctree->top ();
193 assert (dn->klass == NULL);
194 dn->klass = splitStr (klass, ' ');
195}
196
197void StyleEngine::setStyle (const char *styleAttr) {
198 Node *n = stack->getRef (stack->size () - 1);
199 assert (n->styleAttrProperties == NULL);
200 // parse style information from style="" attribute, if it exists
201 if (styleAttr && prefs.parse_embedded_css) {
202 n->styleAttrProperties = new CssPropertyList (true);
204
205 CssParser::parseDeclarationBlock (baseUrl, styleAttr, strlen (styleAttr),
208 }
209}
210
217 Node *pn = stack->getRef (stack->size () - 2);
218
219 if (pn->nonCssProperties) {
220 Node *n = stack->getRef (stack->size () - 1);
221 CssPropertyList *origNonCssProperties = n->nonCssProperties;
222
224
225 if (origNonCssProperties) // original nonCssProperties have precedence
226 origNonCssProperties->apply (n->nonCssProperties);
227
228 delete origNonCssProperties;
229 }
230}
231
233 Node *n = stack->getRef (stack->size () - 1);
234
235 delete n->nonCssProperties;
236 n->nonCssProperties = NULL;
237}
238
246 stack->getRef (stack->size () - 1)->inheritBackgroundColor = true;
247}
248
250 for (int i = 1; i < stack->size (); i++) {
251 Node *n = stack->getRef (i);
252
253 if (n->style && n->style->backgroundColor)
254 return n->style->backgroundColor;
255 }
256
257 return NULL;
258}
259
263 dw::core::style::Length *bgPositionX,
264 dw::core::style::Length *bgPositionY) {
265 for (int i = 1; i < stack->size (); i++) {
266 Node *n = stack->getRef (i);
267
268 if (n->style && n->style->backgroundImage) {
269 *bgRepeat = n->style->backgroundRepeat;
270 *bgAttachment = n->style->backgroundAttachment;
271 *bgPositionX = n->style->backgroundPositionX;
272 *bgPositionY = n->style->backgroundPositionY;
273 return n->style->backgroundImage;
274 }
275 }
276
277 return NULL;
278}
279
284 DoctreeNode *dn = doctree->top ();
285 dn->pseudo = "link";
286}
287
292 DoctreeNode *dn = doctree->top ();
293 dn->pseudo = "visited";
294}
295
299void StyleEngine::endElement (int element) {
300 assert (element == doctree->top ()->element);
301
302 stackPop ();
303 doctree->pop ();
304}
305
307 /* workaround for styling of inline elements */
308 if (stack->getRef (stack->size () - 2)->inheritBackgroundColor) {
309 attrs->backgroundColor =
310 stack->getRef (stack->size () - 2)->style->backgroundColor;
311 attrs->backgroundImage =
312 stack->getRef (stack->size () - 2)->style->backgroundImage;
313 attrs->backgroundRepeat =
314 stack->getRef (stack->size () - 2)->style->backgroundRepeat;
315 attrs->backgroundAttachment =
316 stack->getRef (stack->size () - 2)->style->backgroundAttachment;
317 attrs->backgroundPositionX =
318 stack->getRef (stack->size () - 2)->style->backgroundPositionX;
319 attrs->backgroundPositionY =
320 stack->getRef (stack->size () - 2)->style->backgroundPositionY;
321
322 attrs->valign = stack->getRef (stack->size () - 2)->style->valign;
323 }
324 attrs->borderColor.top = (Color *) -1;
325 attrs->borderColor.bottom = (Color *) -1;
326 attrs->borderColor.left = (Color *) -1;
327 attrs->borderColor.right = (Color *) -1;
328 /* initial value of border-width is 'medium' */
329 attrs->borderWidth.top = 2;
330 attrs->borderWidth.bottom = 2;
331 attrs->borderWidth.left = 2;
332 attrs->borderWidth.right = 2;
333}
334
336 /* if border-color is not specified, use color as computed value */
337 if (attrs->borderColor.top == (Color *) -1)
338 attrs->borderColor.top = attrs->color;
339 if (attrs->borderColor.bottom == (Color *) -1)
340 attrs->borderColor.bottom = attrs->color;
341 if (attrs->borderColor.left == (Color *) -1)
342 attrs->borderColor.left = attrs->color;
343 if (attrs->borderColor.right == (Color *) -1)
344 attrs->borderColor.right = attrs->color;
345 /* computed value of border-width is 0 if border-style
346 is 'none' or 'hidden' */
347 if (attrs->borderStyle.top == BORDER_NONE ||
348 attrs->borderStyle.top == BORDER_HIDDEN)
349 attrs->borderWidth.top = 0;
350 if (attrs->borderStyle.bottom == BORDER_NONE ||
352 attrs->borderWidth.bottom = 0;
353 if (attrs->borderStyle.left == BORDER_NONE ||
355 attrs->borderWidth.left = 0;
356 if (attrs->borderStyle.right == BORDER_NONE ||
358 attrs->borderWidth.right = 0;
359}
360
365 BrowserWindow *bw) {
366 FontAttrs fontAttrs = *attrs->font;
367 Font *parentFont = stack->get (i - 1).style->font;
368 char *c, *fontName;
369 int lineHeight;
370 DilloUrl *imgUrl = NULL;
371
372 /* Determine font first so it can be used to resolve relative lengths. */
373 for (int j = 0; j < props->size (); j++) {
374 CssProperty *p = props->getRef (j);
375
376 switch (p->name) {
378 // Check font names in comma separated list.
379 // Note, that p->value.strVal is modified, so that in future calls
380 // the matching font name can be used directly.
381 fontName = NULL;
382 while (p->value.strVal) {
383 if ((c = strchr(p->value.strVal, ',')))
384 *c = '\0';
386
387 if (dStrAsciiCasecmp (p->value.strVal, "serif") == 0)
388 fontName = prefs.font_serif;
389 else if (dStrAsciiCasecmp (p->value.strVal, "sans-serif") == 0)
390 fontName = prefs.font_sans_serif;
391 else if (dStrAsciiCasecmp (p->value.strVal, "cursive") == 0)
392 fontName = prefs.font_cursive;
393 else if (dStrAsciiCasecmp (p->value.strVal, "fantasy") == 0)
394 fontName = prefs.font_fantasy;
395 else if (dStrAsciiCasecmp (p->value.strVal, "monospace") == 0)
396 fontName = prefs.font_monospace;
397 else if (Font::exists(layout, p->value.strVal))
398 fontName = p->value.strVal;
399
400 if (fontName) { // font found
401 fontAttrs.name = fontName;
402 break;
403 } else if (c) { // try next from list
404 memmove(p->value.strVal, c + 1, strlen(c + 1) + 1);
405 } else { // no font found
406 break;
407 }
408 }
409
410 break;
412 if (p->type == CSS_TYPE_ENUM) {
413 switch (p->value.intVal) {
415 fontAttrs.size = roundInt(8.1 * prefs.font_factor * zoom);
416 break;
418 fontAttrs.size = roundInt(9.7 * prefs.font_factor * zoom);
419 break;
421 fontAttrs.size = roundInt(11.7 * prefs.font_factor * zoom);
422 break;
424 fontAttrs.size = roundInt(14.0 * prefs.font_factor * zoom);
425 break;
427 fontAttrs.size = roundInt(16.8 * prefs.font_factor * zoom);
428 break;
430 fontAttrs.size = roundInt(20.2 * prefs.font_factor * zoom);
431 break;
433 fontAttrs.size = roundInt(24.2 * prefs.font_factor * zoom);
434 break;
436 fontAttrs.size = roundInt(fontAttrs.size * 0.83 * zoom);
437 break;
439 fontAttrs.size = roundInt(fontAttrs.size * 1.2 * zoom);
440 break;
441 default:
442 assert(false); // invalid font-size enum
443 }
444 } else {
445 computeValue (&fontAttrs.size, p->value.intVal, parentFont,
446 parentFont->size);
447 }
448
449 if (fontAttrs.size < prefs.font_min_size)
450 fontAttrs.size = prefs.font_min_size;
451 if (fontAttrs.size > prefs.font_max_size)
452 fontAttrs.size = prefs.font_max_size;
453
454 break;
456 fontAttrs.style = (FontStyle) p->value.intVal;
457 break;
459
460 if (p->type == CSS_TYPE_ENUM) {
461 switch (p->value.intVal) {
463 fontAttrs.weight = 700;
464 break;
466 fontAttrs.weight += 300;
467 break;
469 fontAttrs.weight = 100;
470 break;
472 fontAttrs.weight -= 300;
473 break;
475 fontAttrs.weight = 400;
476 break;
477 default:
478 assert(false); // invalid font weight value
479 break;
480 }
481 } else {
482 fontAttrs.weight = p->value.intVal;
483 }
484
485 if (fontAttrs.weight < 100)
486 fontAttrs.weight = 100;
487 if (fontAttrs.weight > 900)
488 fontAttrs.weight = 900;
489
490 break;
492 if (p->type == CSS_TYPE_ENUM) {
494 fontAttrs.letterSpacing = 0;
495 }
496 } else {
497 computeValue (&fontAttrs.letterSpacing, p->value.intVal,
498 parentFont, parentFont->size);
499 }
500
501 /* Limit letterSpacing to reasonable values to avoid overflows e.g,
502 * when measuring word width.
503 */
504 if (fontAttrs.letterSpacing > 1000)
505 fontAttrs.letterSpacing = 1000;
506 else if (fontAttrs.letterSpacing < -1000)
507 fontAttrs.letterSpacing = -1000;
508 break;
510 fontAttrs.fontVariant = (FontVariant) p->value.intVal;
511 break;
512 default:
513 break;
514 }
515 }
516
517 attrs->font = Font::create (layout, &fontAttrs);
518
519 for (int j = 0; j < props->size (); j++) {
520 CssProperty *p = props->getRef (j);
521
522 switch (p->name) {
523 /* \todo missing cases */
525 attrs->backgroundAttachment =
527 break;
529 if (prefs.allow_white_bg || p->value.intVal != 0xffffff)
531 else
532 attrs->backgroundColor =
534 break;
536 // p->value.strVal should be absolute, so baseUrl is not needed
537 imgUrl = a_Url_new (p->value.strVal, NULL);
538 break;
541 attrs->font);
543 attrs->font);
544 break;
547 break;
550 break;
552 attrs->borderColor.top = (p->type == CSS_TYPE_ENUM) ? NULL :
554 break;
556 attrs->borderColor.bottom = (p->type == CSS_TYPE_ENUM) ? NULL :
558 break;
560 attrs->borderColor.left = (p->type == CSS_TYPE_ENUM) ? NULL :
562 break;
564 attrs->borderColor.right = (p->type == CSS_TYPE_ENUM) ? NULL :
566 break;
569 break;
572 break;
575 break;
577 attrs->borderStyle.top = (BorderStyle) p->value.intVal;
578 break;
580 computeBorderWidth (&attrs->borderWidth.bottom, p, attrs->font);
581 break;
583 computeBorderWidth (&attrs->borderWidth.left, p, attrs->font);
584 break;
586 computeBorderWidth (&attrs->borderWidth.right, p, attrs->font);
587 break;
589 computeBorderWidth (&attrs->borderWidth.top, p, attrs->font);
590 break;
592 computeValue (&attrs->hBorderSpacing, p->value.intVal,attrs->font);
593 computeValue (&attrs->vBorderSpacing, p->value.intVal,attrs->font);
594 break;
596 computeLength (&attrs->bottom, p->value.intVal, attrs->font);
597 break;
599 attrs->clear = (ClearType) p->value.intVal;
600 break;
602 attrs->color = Color::create (layout, p->value.intVal);
603 break;
605 attrs->cursor = (Cursor) p->value.intVal;
606 break;
608 attrs->display = (DisplayType) p->value.intVal;
609 if (attrs->display == DISPLAY_NONE)
610 stack->getRef (i)->displayNone = true;
611 break;
613 attrs->vloat = (FloatType) p->value.intVal;
614 break;
616 computeLength (&attrs->left, p->value.intVal, attrs->font);
617 break;
619 if (p->type == CSS_TYPE_ENUM) { //only valid enum value is "normal"
621 } else if (p->type == CSS_TYPE_LENGTH_PERCENTAGE_NUMBER) {
623 attrs->lineHeight =
625 } else if (computeValue (&lineHeight, p->value.intVal,
626 attrs->font, attrs->font->size)) {
627 attrs->lineHeight = createAbsLength(lineHeight);
628 }
629 }
630 break;
633 break;
636 break;
638 computeValue (&attrs->margin.bottom, p->value.intVal, attrs->font);
639 if (attrs->margin.bottom < 0) // \todo fix negative margins in dw/*
640 attrs->margin.bottom = 0;
641 break;
643 computeValue (&attrs->margin.left, p->value.intVal, attrs->font);
644 if (attrs->margin.left < 0) // \todo fix negative margins in dw/*
645 attrs->margin.left = 0;
646 break;
648 computeValue (&attrs->margin.right, p->value.intVal, attrs->font);
649 if (attrs->margin.right < 0) // \todo fix negative margins in dw/*
650 attrs->margin.right = 0;
651 break;
653 computeValue (&attrs->margin.top, p->value.intVal, attrs->font);
654 if (attrs->margin.top < 0) // \todo fix negative margins in dw/*
655 attrs->margin.top = 0;
656 break;
658 attrs->overflow = (Overflow) p->value.intVal;
659 break;
661 computeValue (&attrs->padding.top, p->value.intVal, attrs->font);
662 break;
664 computeValue (&attrs->padding.bottom, p->value.intVal,attrs->font);
665 break;
667 computeValue (&attrs->padding.left, p->value.intVal, attrs->font);
668 break;
670 computeValue (&attrs->padding.right, p->value.intVal, attrs->font);
671 break;
673 attrs->position = (Position) p->value.intVal;
674 break;
676 computeLength (&attrs->right, p->value.intVal, attrs->font);
677 break;
679 attrs->textAlign = (TextAlignType) p->value.intVal;
680 break;
682 attrs->textDecoration |= p->value.intVal;
683 break;
685 computeLength (&attrs->textIndent, p->value.intVal, attrs->font);
686 break;
689 break;
690 case CSS_PROPERTY_TOP:
691 computeLength (&attrs->top, p->value.intVal, attrs->font);
692 break;
694 attrs->valign = (VAlignType) p->value.intVal;
695 break;
697 attrs->whiteSpace = (WhiteSpace) p->value.intVal;
698 break;
700 computeLength (&attrs->width, p->value.intVal, attrs->font);
701 break;
703 computeLength (&attrs->height, p->value.intVal, attrs->font);
704 break;
706 if (p->type == CSS_TYPE_ENUM) {
708 attrs->wordSpacing = 0;
709 }
710 } else {
711 computeValue(&attrs->wordSpacing, p->value.intVal, attrs->font);
712 }
713
714 /* Limit to reasonable values to avoid overflows */
715 if (attrs->wordSpacing > 1000)
716 attrs->wordSpacing = 1000;
717 else if (attrs->wordSpacing < -1000)
718 attrs->wordSpacing = -1000;
719 break;
721 computeLength (&attrs->minWidth, p->value.intVal, attrs->font);
722 break;
724 computeLength (&attrs->maxWidth, p->value.intVal, attrs->font);
725 break;
727 computeLength (&attrs->minHeight, p->value.intVal, attrs->font);
728 break;
730 computeLength (&attrs->maxHeight, p->value.intVal, attrs->font);
731 break;
733 if (p->type == CSS_LENGTH_TYPE_AUTO)
735 else
736 attrs->zIndex = p->value.intVal;
737 break;
738 case PROPERTY_X_LINK:
739 attrs->x_link = p->value.intVal;
740 break;
741 case PROPERTY_X_LANG:
742 attrs->x_lang[0] = D_ASCII_TOLOWER(p->value.strVal[0]);
743 if (attrs->x_lang[0])
744 attrs->x_lang[1] = D_ASCII_TOLOWER(p->value.strVal[1]);
745 else
746 attrs->x_lang[1] = 0;
747 break;
748 case PROPERTY_X_IMG:
749 attrs->x_img = p->value.intVal;
750 break;
753 break;
754 default:
755 break;
756 }
757 }
758
759 if (imgUrl && prefs.load_background_images &&
760 !stack->getRef (i)->displayNone &&
762 {
766 (void*)attrs->backgroundImage
768 0xffffff);
769
770 // we use the pageUrl as requester to prevent cross
771 // domain requests as specified in domainrc
772 DilloWeb *web = a_Web_new(bw, imgUrl, pageUrl);
773 web->Image = image;
775 web->flags |= WEB_Image;
776
777 int clientKey;
778 if ((clientKey = a_Capi_open_url(web, NULL, NULL)) != 0) {
779 a_Bw_add_client(bw, clientKey, 0);
780 a_Bw_add_url(bw, imgUrl);
782 (new StyleImageDeletionReceiver (clientKey));
783 }
784 }
785 a_Url_free (imgUrl);
786}
787
791bool StyleEngine::computeValue (int *dest, CssLength value, Font *font) {
792 switch (CSS_LENGTH_TYPE (value)) {
794 *dest = (int) (CSS_LENGTH_VALUE (value) * zoom);
795 return true;
797 *dest = roundInt (CSS_LENGTH_VALUE (value) * dpmm * zoom);
798 return true;
800 /* Doesn't need zoom as it is already applied to font->size */
801 *dest = roundInt (CSS_LENGTH_VALUE (value) * font->size);
802 return true;
804 /* Doesn't need zoom as it is already applied to font->xHeight */
805 *dest = roundInt (CSS_LENGTH_VALUE(value) * font->xHeight);
806 return true;
808 // length values other than 0 without unit are only allowed
809 // in special cases (line-height) and have to be handled
810 // separately.
811 assert ((int) CSS_LENGTH_VALUE (value) == 0);
812 *dest = 0;
813 return true;
814 default:
815 break;
816 }
817
818 return false;
819}
820
821bool StyleEngine::computeValue (int *dest, CssLength value, Font *font,
822 int percentageBase) {
824 *dest = roundInt (CSS_LENGTH_VALUE (value) * percentageBase);
825 return true;
826 } else
827 return computeValue (dest, value, font);
828}
829
831 CssLength value, Font *font) {
832 int v;
833
835 *dest = createPerLength (CSS_LENGTH_VALUE (value));
836 return true;
837 } else if (CSS_LENGTH_TYPE (value) == CSS_LENGTH_TYPE_AUTO) {
839 return true;
840 } else if (computeValue (&v, value, font)) {
841 *dest = createAbsLength (v);
842 return true;
843 }
844
845 return false;
846}
847
849 dw::core::style::Font *font) {
850 if (p->type == CSS_TYPE_ENUM) {
851 switch (p->value.intVal) {
853 *dest = 1;
854 break;
856 *dest = 2;
857 break;
859 *dest = 3;
860 break;
861 default:
862 assert(false);
863 }
864 } else {
865 computeValue (dest, p->value.intVal, font);
866 }
867}
868
875 if (!stack->getRef (stack->size () - 1)->backgroundStyle) {
876 StyleAttrs attrs = *style (bw);
877
878 for (int i = stack->size () - 1; i >= 0 && ! attrs.backgroundColor; i--)
879 attrs.backgroundColor = stack->getRef (i)->style->backgroundColor;
880
881 assert (attrs.backgroundColor);
882 stack->getRef (stack->size () - 1)->backgroundStyle =
883 Style::create (&attrs);
884 }
885 return stack->getRef (stack->size () - 1)->backgroundStyle;
886}
887
894 CssPropertyList props, *styleAttrProperties, *styleAttrPropertiesImportant;
895 CssPropertyList *nonCssProperties;
896 // get previous style from the stack
897 StyleAttrs attrs = *stack->getRef (i - 1)->style;
898
899 // Ensure that StyleEngine::style0() has not been called before for
900 // this element.
901 // Style computation is expensive so limit it as much as possible.
902 // If this assertion is hit, you need to rearrange the code that is
903 // doing styleEngine calls to call setNonCssHint() before calling
904 // style() or wordStyle() for each new element.
905 assert (stack->getRef (i)->style == NULL);
906
907 // reset values that are not inherited according to CSS
908 attrs.resetValues ();
909 preprocessAttrs (&attrs);
910
911 styleAttrProperties = stack->getRef (i)->styleAttrProperties;
912 styleAttrPropertiesImportant = stack->getRef(i)->styleAttrPropertiesImportant;
913 nonCssProperties = stack->getRef (i)->nonCssProperties;
914
915 // merge style information
916 cssContext->apply (&props, doctree, stack->getRef(i)->doctreeNode,
917 styleAttrProperties, styleAttrPropertiesImportant,
918 nonCssProperties);
919
920 // apply style
921 apply (i, &attrs, &props, bw);
922
923 postprocessAttrs (&attrs);
924
925 stack->getRef (i)->style = Style::create (&attrs);
926
927 return stack->getRef (i)->style;
928}
929
931 StyleAttrs attrs = *style (bw);
932 attrs.resetValues ();
933
934 if (stack->getRef (stack->size() - 1)->inheritBackgroundColor) {
941 }
942
943 attrs.valign = style (bw)->valign;
944
945 stack->getRef(stack->size() - 1)->wordStyle = Style::create(&attrs);
946 return stack->getRef (stack->size () - 1)->wordStyle;
947}
948
957 for (int i = 1; i < stack->size (); i++) {
958 Node *n = stack->getRef (i);
959 if (n->style) {
960 n->style->unref ();
961 n->style = NULL;
962 }
963 if (n->wordStyle) {
964 n->wordStyle->unref ();
965 n->wordStyle = NULL;
966 }
967 if (n->backgroundStyle) {
968 n->backgroundStyle->unref ();
969 n->backgroundStyle = NULL;
970 }
971
972 style0 (i, bw);
973 }
974}
975
976void StyleEngine::parse (DilloHtml *html, DilloUrl *url, const char *buf,
977 int buflen, CssOrigin origin) {
978 if (importDepth > 10) { // avoid looping with recursive @import directives
979 MSG_WARN("Maximum depth of CSS @import reached--ignoring stylesheet.\n");
980 return;
981 }
982
983 importDepth++;
984 CssParser::parse (html, url, cssContext, buf, buflen, origin);
985 importDepth--;
986}
987
995 const char *cssBuf =
996 "body {margin: 5px}"
997 "big {font-size: 1.17em}"
998 "blockquote, dd {margin-left: 40px; margin-right: 40px}"
999 "center {text-align: center}"
1000 "dt {font-weight: bolder}"
1001 ":link {color: blue; text-decoration: underline; cursor: pointer}"
1002 ":visited {color: #800080; text-decoration: underline; cursor: pointer}"
1003 "h1, h2, h3, h4, h5, h6, b, strong {font-weight: bolder}"
1004 "address, article, aside, center, div, figure, figcaption, footer,"
1005 " h1, h2, h3, h4, h5, h6, header, main, nav, ol, p, pre, section, ul"
1006 " {display: block}"
1007 "i, em, cite, address, var {font-style: italic}"
1008 ":link img, :visited img {border: 1px solid}"
1009 "frameset, ul, ol, dir {margin-left: 40px}"
1010 /* WORKAROUND: It should be margin: 1em 0
1011 * but as we don't collapse these margins yet, it
1012 * look better like this.
1013 */
1014 "p {margin: 0.5em 0}"
1015 "figure {margin: 1em 40px}"
1016 "h1 {font-size: 2em; margin-top: .67em; margin-bottom: 0}"
1017 "h2 {font-size: 1.5em; margin-top: .75em; margin-bottom: 0}"
1018 "h3 {font-size: 1.17em; margin-top: .83em; margin-bottom: 0}"
1019 "h4 {margin-top: 1.12em; margin-bottom: 0}"
1020 "h5 {font-size: 0.83em; margin-top: 1.5em; margin-bottom: 0}"
1021 "h6 {font-size: 0.75em; margin-top: 1.67em; margin-bottom: 0}"
1022 "hr {width: 100%; border: 1px inset}"
1023 "li {margin-top: 0.1em; display: list-item}"
1024 "pre {white-space: pre}"
1025 "ol {list-style-type: decimal}"
1026 "ul {list-style-type: disc}"
1027 "ul ul {list-style-type: circle}"
1028 "ul ul ul {list-style-type: square}"
1029 "ul ul ul ul {list-style-type: disc}"
1030 "ins, u {text-decoration: underline}"
1031 "small, sub, sup {font-size: 0.83em}"
1032 "sub {vertical-align: sub}"
1033 "sup {vertical-align: super}"
1034 "s, strike, del {text-decoration: line-through}"
1035 /* HTML5 spec notes that mark styling "is just a suggestion and can be
1036 * changed based on implementation feedback"
1037 */
1038 "mark {background: yellow; color: black;}"
1039 "table {border-spacing: 2px}"
1040 "td, th {padding: 2px}"
1041 "thead, tbody, tfoot {vertical-align: middle}"
1042 "th {font-weight: bolder; text-align: center}"
1043 "code, tt, pre, samp, kbd {font-family: monospace}"
1044 /* WORKAROUND: Reset font properties in tables as some
1045 * pages rely on it (e.g. gmail).
1046 * http://developer.mozilla.org/en-US/Fixing_Table_Inheritance_in_Quirks_Mode
1047 * has a detailed description of the issue.
1048 */
1049 "table, caption {font-size: medium; font-weight: normal}";
1050
1051 CssContext context;
1052 CssParser::parse (NULL, NULL, &context, cssBuf, strlen (cssBuf),
1054}
1055
1057 Dstr *style;
1058 char *filename = dStrconcat(dGethomedir(), "/.dillo/style.css", NULL);
1059
1060 if ((style = a_Misc_file2dstr(filename))) {
1061 CssParser::parse (NULL,NULL,cssContext,style->str, style->len,CSS_ORIGIN_USER);
1062 dStr_free (style, 1);
1063 }
1064 dFree (filename);
1065}
void a_Bw_add_url(BrowserWindow *bw, const DilloUrl *Url)
Add an URL to the browser window's list.
Definition bw.c:209
void a_Bw_add_client(BrowserWindow *bw, int Key, int Root)
Add a reference to a cache-client.
Definition bw.c:128
int a_Capi_open_url(DilloWeb *web, CA_Callback_t Call, void *CbData)
Most used function for requesting a URL.
Definition capi.c:392
void a_Capi_stop_client(int Key, int force)
Remove a client from the cache client queue.
Definition capi.c:621
A set of CssStyleSheets.
Definition css.hh:515
void apply(CssPropertyList *props, Doctree *docTree, DoctreeNode *node, CssPropertyList *tagStyle, CssPropertyList *tagStyleImportant, CssPropertyList *nonCssHints)
Apply a CSS context to a property list.
Definition css.cc:503
static void parseDeclarationBlock(const DilloUrl *baseUrl, const char *buf, int buflen, CssPropertyList *props, CssPropertyList *propsImortant)
static void parse(DilloHtml *html, const DilloUrl *baseUrl, CssContext *context, const char *buf, int buflen, CssOrigin origin)
A list of CssProperty objects.
Definition css.hh:328
void apply(CssPropertyList *props)
Merge properties into argument property list.
Definition css.cc:87
This class holds a CSS property and value pair.
Definition css.hh:302
short type
Definition css.hh:306
short name
Definition css.hh:305
CssPropertyValue value
Definition css.hh:307
const char * pseudo
Definition doctree.hh:14
const char * id
Definition doctree.hh:15
lout::misc::SimpleVector< char * > * klass
Definition doctree.hh:13
int element
Definition doctree.hh:12
HTML document tree interface.
Definition doctree.hh:48
DoctreeNode * push()
Definition doctree.hh:65
void pop()
Definition doctree.hh:75
DoctreeNode * top()
Definition doctree.hh:80
void parse(DilloHtml *html, DilloUrl *url, const char *buf, int buflen, CssOrigin origin)
void setPseudoVisited()
set the CSS pseudo class :visited.
void restyle(BrowserWindow *bw)
Recompute all style information from scratch This is used to take into account CSS styles for the HTM...
void apply(int i, dw::core::style::StyleAttrs *attrs, CssPropertyList *props, BrowserWindow *bw)
Make changes to StyleAttrs attrs according to CssPropertyList props.
void startElement(int tag, BrowserWindow *bw)
tell the styleEngine that a new html element has started.
void setId(const char *id)
dw::core::style::Style * style(BrowserWindow *bw)
lout::misc::SimpleVector< Node > * stack
void buildUserStyle()
void preprocessAttrs(dw::core::style::StyleAttrs *attrs)
void stackPop()
dw::core::style::Style * wordStyle0(BrowserWindow *bw)
dw::core::style::Style * style0(int i, BrowserWindow *bw)
Create a new style object based on the previously opened / closed HTML elements and the nonCssPropert...
dw::core::style::Color * backgroundColor()
DilloUrl * pageUrl
void endElement(int tag)
tell the styleEngine that a html element has ended.
void setPseudoLink()
set the CSS pseudo class :link.
void stackPush()
bool computeValue(int *dest, CssLength value, dw::core::style::Font *font)
Resolve relative lengths to absolute values.
void computeBorderWidth(int *dest, CssProperty *p, dw::core::style::Font *font)
void setStyle(const char *style)
void setClass(const char *klass)
bool computeLength(dw::core::style::Length *dest, CssLength value, dw::core::style::Font *font)
DilloUrl * baseUrl
dw::core::Layout * layout
void clearNonCssHints()
StyleEngine(dw::core::Layout *layout, const DilloUrl *pageUrl, const DilloUrl *baseUrl, float zoom)
dw::core::style::Style * backgroundStyle(BrowserWindow *bw)
Similar to StyleEngine::style(), but with backgroundColor set.
Doctree * doctree
CssContext * cssContext
void inheritBackgroundColor()
Use of the background color of the parent style as default.
void postprocessAttrs(dw::core::style::StyleAttrs *attrs)
static void init()
Create the user agent style.
void inheritNonCssHints()
Instruct StyleEngine to use the nonCssHints from parent element This is only used for tables where no...
dw::core::style::StyleImage * backgroundImage(dw::core::style::BackgroundRepeat *bgRepeat, dw::core::style::BackgroundAttachment *bgAttachment, dw::core::style::Length *bgPositionX, dw::core::style::Length *bgPositionY)
The central class for managing and drawing a widget tree.
Definition layout.hh:17
static Color * create(Layout *layout, int color)
Definition style.cc:528
FontVariant fontVariant
Definition style.hh:687
static bool exists(Layout *layout, const char *name)
Definition style.cc:448
static Font * create(Layout *layout, FontAttrs *attrs)
Definition style.cc:443
ListStyleType listStyleType
Definition style.hh:567
ListStylePosition listStylePosition
Definition style.hh:566
TextTransform textTransform
Definition style.hh:545
StyleImage * backgroundImage
Definition style.hh:536
BackgroundRepeat backgroundRepeat
Definition style.hh:537
struct dw::core::style::StyleAttrs::@20 borderColor
BackgroundAttachment backgroundAttachment
Definition style.hh:538
BorderCollapse borderCollapse
Definition style.hh:560
TextAlignType textAlign
Definition style.hh:542
struct dw::core::style::StyleAttrs::@21 borderStyle
void resetValues()
Reset those style attributes to their standard values, which are not inherited, according to CSS.
Definition style.cc:103
ImgRenderer * getMainImgRenderer()
Definition style.hh:884
static StyleImage * create()
Definition style.hh:871
static Style * create(StyleAttrs *attrs)
Definition style.hh:628
static Tooltip * create(dw::core::Layout *layout, const char *text)
Definition style.cc:535
Simple (simpler than container::untyped::Vector and container::typed::Vector) template based vector.
Definition misc.hh:94
void increase()
Increase the vector size by one.
Definition misc.hh:160
void set(int i, T t)
Store an object in the vector.
Definition misc.hh:246
int size() const
Return the number of elements put into this vector.
Definition misc.hh:141
T * getRef(int i) const
Return the reference of one element.
Definition misc.hh:190
virtual void deleted(ObservedObject *object)=0
An observed object has a signal emitter, which tells the receivers, when the object is deleted.
Definition signal.hh:275
void connectDeletion(DeletionReceiver *receiver)
Definition signal.hh:302
@ CSS_WORD_SPACING_NORMAL
Definition css.hh:295
@ CSS_FONT_WEIGHT_BOLDER
Definition css.hh:272
@ CSS_FONT_WEIGHT_LIGHT
Definition css.hh:273
@ CSS_FONT_WEIGHT_LIGHTER
Definition css.hh:274
@ CSS_FONT_WEIGHT_NORMAL
Definition css.hh:275
@ CSS_FONT_WEIGHT_BOLD
Definition css.hh:271
@ CSS_FONT_SIZE_MEDIUM
Definition css.hh:281
@ CSS_FONT_SIZE_XX_SMALL
Definition css.hh:285
@ CSS_FONT_SIZE_SMALLER
Definition css.hh:283
@ CSS_FONT_SIZE_XX_LARGE
Definition css.hh:284
@ CSS_FONT_SIZE_LARGER
Definition css.hh:280
@ CSS_FONT_SIZE_X_SMALL
Definition css.hh:287
@ CSS_FONT_SIZE_X_LARGE
Definition css.hh:286
@ CSS_FONT_SIZE_LARGE
Definition css.hh:279
@ CSS_FONT_SIZE_SMALL
Definition css.hh:282
@ CSS_LETTER_SPACING_NORMAL
Definition css.hh:291
@ CSS_BORDER_WIDTH_THIN
Definition css.hh:265
@ CSS_BORDER_WIDTH_MEDIUM
Definition css.hh:266
@ CSS_BORDER_WIDTH_THICK
Definition css.hh:267
@ CSS_PROPERTY_MIN_WIDTH
Definition css.hh:218
@ CSS_PROPERTY_PADDING_TOP
Definition css.hh:226
@ CSS_PROPERTY_LIST_STYLE_TYPE
Definition css.hh:208
@ CSS_PROPERTY_BOTTOM
Definition css.hh:182
@ CSS_PROPERTY_MARGIN_BOTTOM
Definition css.hh:209
@ CSS_PROPERTY_LETTER_SPACING
Definition css.hh:204
@ CSS_PROPERTY_BORDER_RIGHT_STYLE
Definition css.hh:176
@ CSS_PROPERTY_BORDER_BOTTOM_COLOR
Definition css.hh:168
@ CSS_PROPERTY_MARGIN_RIGHT
Definition css.hh:211
@ CSS_PROPERTY_RIGHT
Definition css.hh:229
@ CSS_PROPERTY_BORDER_TOP_COLOR
Definition css.hh:179
@ CSS_PROPERTY_LEFT
Definition css.hh:203
@ CSS_PROPERTY_BORDER_LEFT_COLOR
Definition css.hh:172
@ CSS_PROPERTY_LIST_STYLE_POSITION
Definition css.hh:207
@ PROPERTY_X_LANG
Definition css.hh:247
@ CSS_PROPERTY_BORDER_RIGHT_WIDTH
Definition css.hh:177
@ CSS_PROPERTY_BACKGROUND_REPEAT
Definition css.hh:167
@ CSS_PROPERTY_FONT_VARIANT
Definition css.hh:200
@ CSS_PROPERTY_BORDER_LEFT_WIDTH
Definition css.hh:174
@ CSS_PROPERTY_PADDING_BOTTOM
Definition css.hh:223
@ CSS_PROPERTY_Z_INDEX
Definition css.hh:242
@ CSS_PROPERTY_BACKGROUND_ATTACHMENT
Definition css.hh:163
@ PROPERTY_X_LINK
Definition css.hh:246
@ CSS_PROPERTY_MIN_HEIGHT
Definition css.hh:217
@ CSS_PROPERTY_OVERFLOW
Definition css.hh:222
@ PROPERTY_X_TOOLTIP
Definition css.hh:249
@ CSS_PROPERTY_POSITION
Definition css.hh:227
@ CSS_PROPERTY_TOP
Definition css.hh:235
@ CSS_PROPERTY_MAX_WIDTH
Definition css.hh:216
@ CSS_PROPERTY_FLOAT
Definition css.hh:194
@ CSS_PROPERTY_MAX_HEIGHT
Definition css.hh:215
@ CSS_PROPERTY_MARGIN_LEFT
Definition css.hh:210
@ CSS_PROPERTY_HEIGHT
Definition css.hh:202
@ CSS_PROPERTY_WIDTH
Definition css.hh:240
@ CSS_PROPERTY_BORDER_COLLAPSE
Definition css.hh:171
@ CSS_PROPERTY_BORDER_RIGHT_COLOR
Definition css.hh:175
@ PROPERTY_X_IMG
Definition css.hh:248
@ CSS_PROPERTY_BORDER_TOP_WIDTH
Definition css.hh:181
@ CSS_PROPERTY_MARGIN_TOP
Definition css.hh:212
@ CSS_PROPERTY_PADDING_RIGHT
Definition css.hh:225
@ CSS_PROPERTY_TEXT_TRANSFORM
Definition css.hh:234
@ CSS_PROPERTY_PADDING_LEFT
Definition css.hh:224
@ CSS_PROPERTY_VERTICAL_ALIGN
Definition css.hh:237
@ CSS_PROPERTY_BORDER_SPACING
Definition css.hh:178
@ CSS_PROPERTY_BORDER_LEFT_STYLE
Definition css.hh:173
@ CSS_PROPERTY_TEXT_ALIGN
Definition css.hh:230
@ CSS_PROPERTY_BACKGROUND_IMAGE
Definition css.hh:165
@ CSS_PROPERTY_BORDER_TOP_STYLE
Definition css.hh:180
@ CSS_PROPERTY_FONT_STYLE
Definition css.hh:199
@ CSS_PROPERTY_TEXT_INDENT
Definition css.hh:232
@ CSS_PROPERTY_DISPLAY
Definition css.hh:192
@ CSS_PROPERTY_BACKGROUND_COLOR
Definition css.hh:164
@ CSS_PROPERTY_WHITE_SPACE
Definition css.hh:239
@ CSS_PROPERTY_COLOR
Definition css.hh:186
@ CSS_PROPERTY_LINE_HEIGHT
Definition css.hh:205
@ CSS_PROPERTY_WORD_SPACING
Definition css.hh:241
@ CSS_PROPERTY_FONT_SIZE
Definition css.hh:196
@ CSS_PROPERTY_BORDER_BOTTOM_STYLE
Definition css.hh:169
@ CSS_PROPERTY_CURSOR
Definition css.hh:190
@ CSS_PROPERTY_TEXT_DECORATION
Definition css.hh:231
@ CSS_PROPERTY_BORDER_BOTTOM_WIDTH
Definition css.hh:170
@ CSS_PROPERTY_BACKGROUND_POSITION
Definition css.hh:166
@ CSS_PROPERTY_CLEAR
Definition css.hh:184
@ CSS_PROPERTY_FONT_FAMILY
Definition css.hh:195
@ CSS_PROPERTY_FONT_WEIGHT
Definition css.hh:201
@ CSS_TYPE_ENUM
Value is i, if represented by enum_symbols[i].
Definition css.hh:39
@ CSS_TYPE_LENGTH_PERCENTAGE_NUMBER
Definition css.hh:52
int CssLength
Lengths are represented as int in the following way:
Definition css.hh:91
CssLengthType CSS_LENGTH_TYPE(CssLength l)
Definition css.hh:138
@ CSS_LENGTH_TYPE_NONE
Definition css.hh:94
@ CSS_LENGTH_TYPE_EM
Definition css.hh:98
@ CSS_LENGTH_TYPE_MM
"cm", "in", "pt" and "pc" are converted into millimeters.
Definition css.hh:96
@ CSS_LENGTH_TYPE_PX
Definition css.hh:95
@ CSS_LENGTH_TYPE_EX
Definition css.hh:99
@ CSS_LENGTH_TYPE_PERCENTAGE
Definition css.hh:100
@ CSS_LENGTH_TYPE_AUTO
This can be used as a simple value.
Definition css.hh:103
float CSS_LENGTH_VALUE(CssLength l)
Definition css.hh:142
CssOrigin
Definition css.hh:30
@ CSS_ORIGIN_USER
Definition css.hh:32
@ CSS_ORIGIN_USER_AGENT
Definition css.hh:31
char * dStrconcat(const char *s1,...)
Concatenate a NULL-terminated list of strings.
Definition dlib.c:100
void dFree(void *mem)
Definition dlib.c:66
int dStrAsciiCasecmp(const char *s1, const char *s2)
Definition dlib.c:201
char * dStrstrip(char *s)
Remove leading and trailing whitespace.
Definition dlib.c:120
char * dStrdup(const char *s)
Definition dlib.c:75
void dStr_free(Dstr *ds, int all)
Free a dillo string.
Definition dlib.c:335
char * dStrndup(const char *s, size_t sz)
Definition dlib.c:86
char * dGethomedir()
Return the home directory in a static string (don't free)
Definition dlib.c:904
#define D_ASCII_TOLOWER(c)
Definition dlib.h:37
static Layout * layout
static Image * image
int a_Html_tag_index(const char *tag)
Get 'tag' index.
Definition html.cc:3606
#define MSG_WARN(...)
Definition msg.h:26
Dstr * a_Misc_file2dstr(const char *filename)
Load a local file into a dStr.
Definition misc.c:464
Anything related to Dillo Widget styles is defined here.
Definition style.cc:33
Length createPerLength(double v)
Returns a percentage, v is relative to 1, not to 100.
Definition style.hh:434
int Length
Type for representing all lengths within dw::core::style.
Definition style.hh:428
Length createAbsLength(int n)
Returns a length of n pixels.
Definition style.hh:431
@ FONT_VARIANT_NORMAL
Definition style.hh:332
@ Z_INDEX_AUTO
'z-index' is stored as int; use this for the value 'auto'.
Definition style.hh:387
@ LENGTH_AUTO
Represents "auto" lengths.
Definition style.hh:494
Miscellaneous stuff, which does not fit anywhere else.
Definition misc.cc:31
int roundInt(double d)
Definition misc.hh:61
DilloPrefs prefs
Global Data.
Definition prefs.c:33
void a_Image_ref(DilloImage *Image)
Add a reference to an Image struct Do nothing if the argument is NULL.
Definition image.cc:96
DilloImage * a_Image_new(void *layout, void *img_rndr, int32_t bg_color)
Create and initialize a new image structure.
Definition image.cc:33
Contains the specific data for a single window.
Definition bw.h:27
char * font_sans_serif
Definition prefs.h:105
char * font_monospace
Definition prefs.h:108
bool_t parse_embedded_css
Definition prefs.h:99
char * font_fantasy
Definition prefs.h:107
int32_t font_min_size
Definition prefs.h:78
char * font_serif
Definition prefs.h:104
int32_t bg_color
Definition prefs.h:54
int32_t white_bg_replacement
Definition prefs.h:53
bool_t load_background_images
Definition prefs.h:97
bool_t allow_white_bg
Definition prefs.h:52
double font_factor
Definition prefs.h:75
char * font_cursive
Definition prefs.h:106
int32_t font_max_size
Definition prefs.h:77
Definition url.h:88
Definition dlib.h:102
dw::core::style::Style * wordStyle
DoctreeNode * doctreeNode
dw::core::style::Style * style
dw::core::style::Style * backgroundStyle
CssPropertyList * styleAttrProperties
CssPropertyList * styleAttrPropertiesImportant
CssPropertyList * nonCssProperties
int flags
Additional info.
Definition web.hh:29
DilloImage * Image
For image urls [reference].
Definition web.hh:31
static lout::misc::SimpleVector< char * > * splitStr(const char *str, char sep)
split a string at sep chars and return a SimpleVector of strings
CssBackgroundPosition * posVal
Definition css.hh:261
char * strVal
Definition css.hh:260
int32_t intVal
Definition css.hh:259
void a_Url_free(DilloUrl *url)
Free a DilloUrl.
Definition url.c:207
DilloUrl * a_Url_new(const char *url_str, const char *base_url)
Transform (and resolve) an URL string into the respective DilloURL.
Definition url.c:370
DilloUrl * a_Url_dup(const DilloUrl *ori)
Duplicate a Url structure.
Definition url.c:476
#define URL_SpamSafe
Definition url.h:40
#define URL_FLAGS(u)
Definition url.h:79
DilloWeb * a_Web_new(BrowserWindow *bw, const DilloUrl *url, const DilloUrl *requester)
Allocate and set safe values for a DilloWeb structure.
Definition web.cc:121
#define WEB_Image
Definition web.hh:17