summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dillorc4
-rw-r--r--doc/Makefile.am3
-rw-r--r--doc/rounding-errors.doc15
-rw-r--r--dpi/cookies.c10
-rw-r--r--dw/alignedtextblock.cc1
-rw-r--r--dw/findtext.cc2
-rw-r--r--dw/fltkimgbuf.cc35
-rw-r--r--dw/fltkplatform.cc2
-rw-r--r--dw/fltkviewport.cc3
-rw-r--r--dw/image.cc4
-rw-r--r--dw/imgbuf.hh8
-rw-r--r--dw/imgrenderer.hh6
-rw-r--r--dw/layout.cc22
-rw-r--r--dw/listitem.cc1
-rw-r--r--dw/selection.cc1
-rw-r--r--dw/style.cc58
-rw-r--r--dw/style.hh14
-rw-r--r--dw/table.cc4
-rw-r--r--dw/tablecell.cc1
-rw-r--r--dw/textblock.cc6
-rw-r--r--dw/ui.cc1
-rw-r--r--dw/widget.cc4
-rw-r--r--lout/container.cc10
-rw-r--r--lout/container.hh44
-rw-r--r--lout/debug.hh26
-rw-r--r--lout/misc.cc2
-rw-r--r--lout/misc.hh34
-rw-r--r--src/css.cc141
-rw-r--r--src/css.hh51
-rw-r--r--src/cssparser.cc14
-rw-r--r--src/dillo.cc3
-rw-r--r--src/form.cc2
-rw-r--r--src/html.cc280
-rw-r--r--src/html_common.hh9
-rw-r--r--src/misc.c1
-rw-r--r--src/styleengine.cc10
-rw-r--r--src/styleengine.hh3
-rw-r--r--src/url.c10
-rw-r--r--test/dw_image_background.cc2
39 files changed, 565 insertions, 282 deletions
diff --git a/dillorc b/dillorc
index fc0b1019..829d4f6f 100644
--- a/dillorc
+++ b/dillorc
@@ -209,8 +209,8 @@ search_url="Google http://www.google.com/search?ie=UTF-8&oe=UTF-8&q=%s"
#
# See http://zytrax.com/tech/web/browser_ids.htm for a compilation of strings.
#
-# http_user_agent="Mozilla/5.0 (Windows NT 5.1; rv:18.0) Gecko/20100101 Firefox/18.0"
-# http_user_agent="Wget/1.12 (linux-gnu)"
+# http_user_agent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0"
+# http_user_agent="Wget/1.13.4 (linux-gnu)"
#The default is "Dillo/"+current_version_number
#-------------------------------------------------------------------------
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 0721f0ba..8ade3d15 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -16,6 +16,7 @@ EXTRA_DIST = \
fltk-problems.doc \
rounding-errors.doc \
uml-legend.doc \
+ dw-line-breaking.doc \
dw-example-screenshot.png \
dw-viewport-without-scrollbar.png \
dw-viewport-with-scrollbar.png \
@@ -29,6 +30,7 @@ EXTRA_DIST = \
dw-textblock-collapsing-spaces-2-1.png \
dw-textblock-collapsing-spaces-2-2.png \
dw-floats-01.png \
+ not-so-simple-container.png \
Cache.txt \
Cookies.txt \
Dillo.txt \
@@ -40,6 +42,7 @@ EXTRA_DIST = \
NC_design.txt \
Selection.txt \
Dpid.txt \
+ CCCwork.txt \
README \
dillo.1.in
diff --git a/doc/rounding-errors.doc b/doc/rounding-errors.doc
index 133a1fe5..a442033e 100644
--- a/doc/rounding-errors.doc
+++ b/doc/rounding-errors.doc
@@ -19,6 +19,17 @@ avoided by transforming the formula into
Of corse, when all \f$y_i\f$ are calculated in a sequence,
\f$\sum_{j=0}^{j=i} x_j\f$ and \f$\sum_{j=0}^{j=i-1} y_j\f$ can be
-accumulated in the same loop.
+accumulated in the same loop. Regard this as sample:
-*/ \ No newline at end of file
+\code
+int n, x[n], a, b; // Should all be initialized.
+int y[n], cumX = 0, cumY = 0;
+
+for (int i = 0; i < n; i++) {
+ cumX += x[i]
+ y[i] = (cumX * a) / b - cumY;
+ cumY += y[i];
+}
+\endcode
+
+*/
diff --git a/dpi/cookies.c b/dpi/cookies.c
index 32f2d5b9..6c5e958e 100644
--- a/dpi/cookies.c
+++ b/dpi/cookies.c
@@ -1042,14 +1042,14 @@ static uint_t Cookies_internal_dots_required(const char *host)
if (tld_len > 0) {
/* These TLDs were chosen by examining the current publicsuffix list
- * in September 2013 and picking out those where it was simplest for
+ * in February 2014 and picking out those where it was simplest for
* them to describe the situation by beginning with a "*.[tld]" rule
* or every rule was "[something].[tld]".
*/
- const char *const tlds[] = {"au","bd","bn","ck","cy","er","et","fj",
- "fk","gn","gu","il","jm","ke","kh","kp",
- "kw","lb","lr","mm","mt","mz","ni","np",
- "nz","pg","tr","uk","ye","za","zm","zw"};
+ const char *const tlds[] = {"bd","bn","ck","cy","er","et","fj","fk",
+ "gu","il","jm","ke","kh","kw","mm","mz",
+ "ni","np","nz","pg","tr","uk","ye","za",
+ "zm","zw"};
uint_t i, tld_num = sizeof(tlds) / sizeof(tlds[0]);
for (i = 0; i < tld_num; i++) {
diff --git a/dw/alignedtextblock.cc b/dw/alignedtextblock.cc
index 0d910c93..24dab2e8 100644
--- a/dw/alignedtextblock.cc
+++ b/dw/alignedtextblock.cc
@@ -81,6 +81,7 @@ void AlignedTextblock::setRefTextblock (AlignedTextblock *ref)
AlignedTextblock::~AlignedTextblock()
{
list->unref (listPos);
+ DBG_OBJ_DELETE ();
}
void AlignedTextblock::updateValue ()
diff --git a/dw/findtext.cc b/dw/findtext.cc
index e86116f1..e9384917 100644
--- a/dw/findtext.cc
+++ b/dw/findtext.cc
@@ -47,6 +47,8 @@ FindtextState::~FindtextState ()
delete iterator;
if (hlIterator)
delete hlIterator;
+
+ DBG_OBJ_DELETE ();
}
void FindtextState::setWidget (Widget *widget)
diff --git a/dw/fltkimgbuf.cc b/dw/fltkimgbuf.cc
index d9d653ec..26b46969 100644
--- a/dw/fltkimgbuf.cc
+++ b/dw/fltkimgbuf.cc
@@ -52,10 +52,10 @@ uchar *FltkImgbuf::findGammaCorrectionTable (double gamma)
}
_MSG("Creating new table for gamma = %g\n", gamma);
-
+
GammaCorrectionTable *gct = new GammaCorrectionTable();
gct->gamma = gamma;
-
+
for (int i = 0; i < 256; i++)
gct->map[i] = 255 * pow((double)i / 255, gamma);
@@ -78,6 +78,8 @@ void FltkImgbuf::freeall ()
FltkImgbuf::FltkImgbuf (Type type, int width, int height, double gamma)
{
+ DBG_OBJ_CREATE ("dw::fltk::FltkImgbuf");
+
_MSG("FltkImgbuf: new root %p\n", this);
init (type, width, height, gamma, NULL);
}
@@ -85,6 +87,8 @@ FltkImgbuf::FltkImgbuf (Type type, int width, int height, double gamma)
FltkImgbuf::FltkImgbuf (Type type, int width, int height, double gamma,
FltkImgbuf *root)
{
+ DBG_OBJ_CREATE ("dw::fltk::FltkImgbuf");
+
_MSG("FltkImgbuf: new scaled %p, root is %p\n", this, root);
init (type, width, height, gamma, root);
}
@@ -103,7 +107,7 @@ void FltkImgbuf::init (Type type, int width, int height, double gamma,
} else if (width > MAX_WIDTH) {
// Too large dimensions cause dangerous overflow errors, so we
// limit dimensions to harmless values.
- //
+ //
// Example: 65535 * 65536 / 65536 (see scaling below) results in
// the negative value -1.
@@ -122,6 +126,9 @@ void FltkImgbuf::init (Type type, int width, int height, double gamma,
this->height = height;
this->gamma = gamma;
+ DBG_OBJ_SET_NUM ("width", width);
+ DBG_OBJ_SET_NUM ("height", height);
+
// TODO: Maybe this is only for root buffers
switch (type) {
case RGBA: bpp = 4; break;
@@ -133,11 +140,11 @@ void FltkImgbuf::init (Type type, int width, int height, double gamma,
rawdata = new uchar[bpp * width * height];
// Set light-gray as interim background color.
memset(rawdata, 222, width*height*bpp);
-
+
refCount = 1;
deleteOnUnref = true;
copiedRows = new lout::misc::BitSet (height);
-
+
// The list is only used for root buffers.
if (isRoot())
scaledBuffers = new lout::container::typed::List <FltkImgbuf> (true);
@@ -156,8 +163,6 @@ void FltkImgbuf::init (Type type, int width, int height, double gamma,
FltkImgbuf::~FltkImgbuf ()
{
- _MSG("~FltkImgbuf[%s %p] deleted\n", isRoot() ? "root":"scaled", this);
-
if (!isRoot())
root->detachScaledBuf (this);
@@ -166,6 +171,8 @@ FltkImgbuf::~FltkImgbuf ()
if (scaledBuffers)
delete scaledBuffers;
+
+ DBG_OBJ_DELETE ();
}
/**
@@ -301,15 +308,15 @@ inline void FltkImgbuf::scaleBuffer (const core::byte *src, int srcWidth,
int v[bpp];
for(int i = 0; i < bpp; i++)
v[i] = 0;
-
+
for(int xo = xo1; xo < xo2; xo++)
for(int yo = yo1; yo < yo2; yo++) {
const core::byte *ps = src + bpp * (yo * srcWidth + xo);
for(int i = 0; i < bpp; i++)
- v[i] +=
+ v[i] +=
(scaleMode == BEAUTIFUL_GAMMA ? gammaMap2[ps[i]] : ps[i]);
}
-
+
core::byte *pd = dest + bpp * (y * destWidth + x);
for(int i = 0; i < bpp; i++)
pd[i] =
@@ -325,7 +332,7 @@ void FltkImgbuf::copyRow (int row, const core::byte *data)
// Flag the row done and copy its data.
copiedRows->set (row, true);
memcpy(rawdata + row * width * bpp, data, width * bpp);
-
+
// Update all the scaled buffers of this root image.
for (Iterator <FltkImgbuf> it = scaledBuffers->iterator();
it.hasNext(); ) {
@@ -386,6 +393,8 @@ core::Imgbuf* FltkImgbuf::getScaledBuf (int width, int height)
// This size is not yet used, so a new buffer has to be created.
FltkImgbuf *sb = new FltkImgbuf (type, width, height, gamma, this);
scaledBuffers->append (sb);
+ DBG_OBJ_ASSOC_CHILD (sb);
+
return sb;
}
@@ -408,7 +417,7 @@ void FltkImgbuf::getRowArea (int row, dw::core::Rectangle *area)
// scaled buffer
int sr1 = scaledY (row);
int sr2 = scaledY (row + 1);
-
+
area->x = 0;
area->y = sr1;
area->width = width;
@@ -524,7 +533,7 @@ int FltkImgbuf::scaledY(int ySrc)
int FltkImgbuf::backscaledY(int yScaled)
{
assert (root != NULL);
-
+
// Notice that rounding errors because of integers do not play a
// role. This method cannot be the exact inverse of scaledY, since
// scaleY is not bijective, and so not invertible. Instead, both
diff --git a/dw/fltkplatform.cc b/dw/fltkplatform.cc
index 2a160d63..9f51eba2 100644
--- a/dw/fltkplatform.cc
+++ b/dw/fltkplatform.cc
@@ -474,6 +474,8 @@ FltkPlatform::~FltkPlatform ()
Fl::remove_idle (generalStaticIdle, (void*)this);
delete idleQueue;
delete resources;
+
+ DBG_OBJ_DELETE ();
}
void FltkPlatform::setLayout (core::Layout *layout)
diff --git a/dw/fltkviewport.cc b/dw/fltkviewport.cc
index 7e91a83a..707c0bd7 100644
--- a/dw/fltkviewport.cc
+++ b/dw/fltkviewport.cc
@@ -85,6 +85,7 @@ FltkViewport::FltkViewport (int X, int Y, int W, int H, const char *label):
FltkViewport::~FltkViewport ()
{
delete gadgets;
+ DBG_OBJ_DELETE ();
}
void FltkViewport::adjustScrollbarsAndGadgetsAllocation ()
@@ -392,7 +393,7 @@ void FltkViewport::scrollTo (int x, int y)
}
/* multiple calls to scroll can happen before a redraw occurs.
- * scrollDX / scrollDY can therefore be non-zero here.
+ * scrollDX and scrollDY can therefore be non-zero here.
*/
updateCanvasWidgets (x - scrollX, y - scrollY);
scrollDX += x - scrollX;
diff --git a/dw/image.cc b/dw/image.cc
index 3aef42ac..74f96e57 100644
--- a/dw/image.cc
+++ b/dw/image.cc
@@ -164,6 +164,8 @@ Image::~Image()
buffer->unref ();
if (mapKey)
delete mapKey;
+
+ DBG_OBJ_DELETE ();
}
void Image::sizeRequestImpl (core::Requisition *requisition)
@@ -435,6 +437,8 @@ void Image::setBuffer (core::Imgbuf *buffer, bool resize)
buffer->ref ();
}
+ DBG_OBJ_ASSOC_CHILD (this->buffer);
+
if (oldBuf)
oldBuf->unref ();
}
diff --git a/dw/imgbuf.hh b/dw/imgbuf.hh
index 3ccbe3c5..f9870bcf 100644
--- a/dw/imgbuf.hh
+++ b/dw/imgbuf.hh
@@ -5,6 +5,8 @@
# error Do not include this file directly, use "core.hh" instead.
#endif
+#include "../lout/debug.hh"
+
namespace dw {
namespace core {
@@ -161,6 +163,12 @@ class Imgbuf: public lout::object::Object, public lout::signal::ObservedObject
public:
enum Type { RGB, RGBA, GRAY, INDEXED, INDEXED_ALPHA };
+ inline Imgbuf () {
+ DBG_OBJ_CREATE ("dw::core::Imgbuf");
+ DBG_OBJ_BASECLASS (lout::object::Object);
+ DBG_OBJ_BASECLASS (lout::signal::ObservedObject);
+ }
+
/*
* Methods called from the image decoding
*/
diff --git a/dw/imgrenderer.hh b/dw/imgrenderer.hh
index 325a1998..e3b5e95e 100644
--- a/dw/imgrenderer.hh
+++ b/dw/imgrenderer.hh
@@ -18,14 +18,14 @@ class ImgRenderer
public:
virtual ~ImgRenderer () { }
- /**
+ /**
* \brief Called, when an image buffer is attached.
*
* This is typically the case when all meta data (size, depth) has been read.
*/
virtual void setBuffer (core::Imgbuf *buffer, bool resize = false) = 0;
- /**
+ /**
* \brief Called, when data from a row is available and has been copied into
* the image buffer.
*
@@ -40,7 +40,7 @@ public:
* limit the number of draws.
*/
virtual void finish () = 0;
-
+
/**
* \brief Called, when there are problems with the retrieval of image data.
*
diff --git a/dw/layout.cc b/dw/layout.cc
index e7516972..58b30fb3 100644
--- a/dw/layout.cc
+++ b/dw/layout.cc
@@ -88,7 +88,7 @@ void Layout::LayoutImgRenderer::draw (int x, int y, int width, int height)
{
layout->queueDraw (x, y, width, height);
}
-
+
// ----------------------------------------------------------------------
void Layout::Receiver::canvasSizeChanged (int width, int ascent, int descent)
@@ -319,6 +319,8 @@ Layout::~Layout ()
delete view;
delete anchorsTable;
delete textZone;
+
+ DBG_OBJ_DELETE ();
}
void Layout::addWidget (Widget *widget)
@@ -770,10 +772,10 @@ void Layout::setBgImage (style::StyleImage *bgImage,
if (bgImage)
bgImage->ref ();
-
+
if (this->bgImage)
this->bgImage->unref ();
-
+
this->bgImage = bgImage;
this->bgRepeat = bgRepeat;
this->bgAttachment = bgAttachment;
@@ -831,7 +833,7 @@ void Layout::resizeIdle ()
// Reset already here, since in this function, queueResize() may be
// called again.
resizeIdleId = -1;
-
+
if (topLevel) {
Requisition requisition;
Allocation allocation;
@@ -851,21 +853,21 @@ void Layout::resizeIdle ()
allocation.ascent = requisition.ascent;
allocation.descent = requisition.descent;
topLevel->sizeAllocate (&allocation);
-
+
canvasWidth = requisition.width;
canvasAscent = requisition.ascent;
canvasDescent = requisition.descent;
-
+
emitter.emitCanvasSizeChanged (canvasWidth, canvasAscent, canvasDescent);
-
+
// Tell the view about the new world size.
view->setCanvasSize (canvasWidth, canvasAscent, canvasDescent);
// view->queueDrawTotal (false);
-
+
if (usesViewport) {
int currHThickness = currHScrollbarThickness();
int currVThickness = currVScrollbarThickness();
-
+
if (!canvasHeightGreater &&
canvasAscent + canvasDescent
> viewportHeight - currHThickness) {
@@ -873,7 +875,7 @@ void Layout::resizeIdle ()
setSizeHints ();
/* May queue a new resize. */
}
-
+
// Set viewport sizes.
view->setViewportSize (viewportWidth, viewportHeight,
currHThickness, currVThickness);
diff --git a/dw/listitem.cc b/dw/listitem.cc
index 11086a9e..05344d79 100644
--- a/dw/listitem.cc
+++ b/dw/listitem.cc
@@ -37,6 +37,7 @@ ListItem::ListItem (ListItem *ref, bool limitTextWidth):
ListItem::~ListItem()
{
+ DBG_OBJ_DELETE ();
}
void ListItem::initWithWidget (core::Widget *widget,
diff --git a/dw/selection.cc b/dw/selection.cc
index 2201af44..b67f4a6d 100644
--- a/dw/selection.cc
+++ b/dw/selection.cc
@@ -61,6 +61,7 @@ SelectionState::SelectionState ()
SelectionState::~SelectionState ()
{
reset ();
+ DBG_OBJ_DELETE ();
}
void SelectionState::reset ()
diff --git a/dw/style.cc b/dw/style.cc
index 3f39a39e..5edb7047 100644
--- a/dw/style.cc
+++ b/dw/style.cc
@@ -258,8 +258,20 @@ container::typed::HashTable <StyleAttrs, Style> * Style::styleTable =
Style::Style (StyleAttrs *attrs)
{
+ DBG_OBJ_CREATE ("dw::core::style::Style");
+
copyAttrs (attrs);
+ DBG_OBJ_ASSOC_CHILD (font);
+ DBG_OBJ_ASSOC_CHILD (color);
+ DBG_OBJ_ASSOC_CHILD (backgroundColor);
+ DBG_OBJ_ASSOC_CHILD (backgroundImage);
+ DBG_OBJ_ASSOC_CHILD (borderColor.top);
+ DBG_OBJ_ASSOC_CHILD (borderColor.bottom);
+ DBG_OBJ_ASSOC_CHILD (borderColor.left);
+ DBG_OBJ_ASSOC_CHILD (borderColor.right);
+ //DBG_OBJ_ASSOC_CHILD (x_tooltip);
+
refCount = 1;
font->ref ();
@@ -306,6 +318,8 @@ Style::~Style ()
styleTable->remove (this);
totalRef--;
+
+ DBG_OBJ_DELETE ();
}
void Style::copyAttrs (StyleAttrs *attrs)
@@ -384,6 +398,7 @@ int FontAttrs::hashValue()
Font::~Font ()
{
free ((char*)name);
+ DBG_OBJ_DELETE ();
}
void Font::copyAttrs (FontAttrs *attrs)
@@ -427,6 +442,7 @@ int ColorAttrs::hashValue()
Color::~Color ()
{
+ DBG_OBJ_DELETE ();
}
int Color::shadeColor (int color, int d)
@@ -510,6 +526,8 @@ void StyleImage::StyleImgRenderer::setBuffer (core::Imgbuf *buffer, bool resize)
image->imgbufTiled = NULL;
image->imgbufSrc = buffer;
+ DBG_OBJ_ASSOC (image, image->imgbufSrc);
+
if (image->imgbufSrc) {
image->imgbufSrc->ref ();
@@ -534,6 +552,8 @@ void StyleImage::StyleImgRenderer::setBuffer (core::Imgbuf *buffer, bool resize)
image->imgbufSrc->createSimilarBuf
(image->tilesX * image->imgbufSrc->getRootWidth(),
image->tilesY * image->imgbufSrc->getRootHeight());
+
+ DBG_OBJ_ASSOC (image, image->imgbufTiled);
}
}
}
@@ -554,7 +574,7 @@ void StyleImage::StyleImgRenderer::drawRow (int row)
int w = image->imgbufSrc->getRootWidth ();
int h = image->imgbufSrc->getRootHeight ();
-
+
for (int x = 0; x < image->tilesX; x++)
for (int y = 0; y < image->tilesX; y++)
image->imgbufSrc->copyTo (image->imgbufTiled, x * w, y * h,
@@ -574,7 +594,7 @@ void StyleImage::StyleImgRenderer::fatal ()
StyleImage::StyleImage ()
{
- //printf ("new StyleImage %p\n", this);
+ DBG_OBJ_CREATE ("dw::core::style::StyleImage");
refCount = 0;
imgbufSrc = NULL;
@@ -587,8 +607,6 @@ StyleImage::StyleImage ()
StyleImage::~StyleImage ()
{
- //printf ("delete StyleImage %p\n", this);
-
if (imgbufSrc)
imgbufSrc->unref ();
if (imgbufTiled)
@@ -596,6 +614,8 @@ StyleImage::~StyleImage ()
delete imgRendererDist;
delete styleImgRenderer;
+
+ DBG_OBJ_DELETE ();
}
void StyleImage::ExternalImgRenderer::setBuffer (core::Imgbuf *buffer,
@@ -610,20 +630,20 @@ void StyleImage::ExternalImgRenderer::drawRow (int row)
StyleImage *backgroundImage;
if (readyToDraw () && (backgroundImage = getBackgroundImage ())) {
// All single rows are drawn.
-
+
Imgbuf *imgbuf = backgroundImage->getImgbufSrc();
int imgWidth = imgbuf->getRootWidth ();
int imgHeight = imgbuf->getRootHeight ();
-
+
int x, y, width, height;
getBgArea (&x, &y, &width, &height);
-
+
int xRef, yRef, widthRef, heightRef;
getRefArea (&xRef, &yRef, &widthRef, &heightRef);
-
+
bool repeatX, repeatY, doDraw;
int origX, origY, tileX1, tileX2, tileY1, tileY2;
-
+
calcBackgroundRelatedValues (backgroundImage,
getBackgroundRepeat (),
getBackgroundAttachment (),
@@ -643,7 +663,7 @@ void StyleImage::ExternalImgRenderer::drawRow (int row)
for (int tileY = tileY1; tileY <= tileY2; tileY++) {
int x1 = misc::max (origX + tileX1 * imgWidth, x);
int x2 = misc::min (origX + (tileX2 + 1) * imgWidth, x + width);
-
+
int yt = origY + tileY * imgHeight + row;
if (yt >= y && yt < y + height)
draw (x1, yt, x2 - x1, 1);
@@ -1204,7 +1224,7 @@ void drawBackground (View *view, Layout *layout, Rectangle *area,
Color::SHADING_INVERSE : Color::SHADING_NORMAL,
true, intersection.x, intersection.y,
intersection.width, intersection.height);
-
+
if (bgImage)
drawBackgroundImage (view, style->backgroundImage,
style->backgroundRepeat,
@@ -1214,7 +1234,7 @@ void drawBackground (View *view, Layout *layout, Rectangle *area,
intersection.x, intersection.y,
intersection.width, intersection.height,
xRef, yRef, widthRef, heightRef);
-
+
}
}
}
@@ -1233,7 +1253,7 @@ void drawBackgroundImage (View *view, StyleImage *backgroundImage,
bool repeatX, repeatY, doDraw;
int origX, origY, tileX1, tileX2, tileY1, tileY2;
-
+
calcBackgroundRelatedValues (backgroundImage, backgroundRepeat,
backgroundAttachment, backgroundPositionX,
backgroundPositionY, x, y, width, height,
@@ -1266,8 +1286,8 @@ void drawBackgroundImage (View *view, StyleImage *backgroundImage,
int yt = origY + tileY * imgHeightS;
int y1 = misc::max (yt, y);
int y2 = misc::min (yt + imgHeightT, y + height);
-
- view->drawImage (imgbufT, xt, yt, x1 - xt, y1 - yt,
+
+ view->drawImage (imgbufT, xt, yt, x1 - xt, y1 - yt,
x2 - x1, y2 - y1);
}
}
@@ -1293,7 +1313,7 @@ void calcBackgroundRelatedValues (StyleImage *backgroundImage,
backgroundRepeat == BACKGROUND_REPEAT_X;
*repeatY = backgroundRepeat == BACKGROUND_REPEAT ||
backgroundRepeat == BACKGROUND_REPEAT_Y;
-
+
*origX = xRef +
(isPerLength (backgroundPositionX) ?
multiplyWithPerLength (widthRef - imgWidth, backgroundPositionX) :
@@ -1302,7 +1322,7 @@ void calcBackgroundRelatedValues (StyleImage *backgroundImage,
(isPerLength (backgroundPositionY) ?
multiplyWithPerLength (heightRef - imgHeight, backgroundPositionY) :
absLengthVal (backgroundPositionY));
-
+
*tileX1 = xDraw < *origX ?
- (*origX - xDraw + imgWidth - 1) / imgWidth :
(xDraw - *origX) / imgWidth;
@@ -1315,7 +1335,7 @@ void calcBackgroundRelatedValues (StyleImage *backgroundImage,
*tileY2 = *origY < yDraw + heightDraw ?
(yDraw + heightDraw - *origY - 1) / imgHeight :
- (*origY - (yDraw + heightDraw) + imgHeight - 1) / imgHeight;
-
+
*doDraw = true;
if (!*repeatX) {
// Only center tile (tileX = 0) is drawn, ...
@@ -1326,7 +1346,7 @@ void calcBackgroundRelatedValues (StyleImage *backgroundImage,
// ... but is not visible.
*doDraw = false;
}
-
+
if (!*repeatY) {
// Analogue.
if (*tileY1 <= 0 && *tileY2 >= 0)
diff --git a/dw/style.hh b/dw/style.hh
index 3fe3b7c9..2cc258bf 100644
--- a/dw/style.hh
+++ b/dw/style.hh
@@ -8,6 +8,7 @@
#endif
#include "../lout/signal.hh"
+#include "../lout/debug.hh"
namespace dw {
namespace core {
@@ -466,7 +467,7 @@ inline int multiplyWithRelLength(int x, Length l) {
return x * relLengthVal(l);
}
-
+
enum {
/** \brief Represents "auto" lengths. */
LENGTH_AUTO = 0
@@ -685,7 +686,10 @@ private:
static Font *create0 (Layout *layout, FontAttrs *attrs, bool tryEverything);
protected:
- inline Font () { refCount = 0; }
+ inline Font () {
+ DBG_OBJ_CREATE ("dw::core::style::Font");
+ refCount = 0;
+ }
virtual ~Font ();
void copyAttrs (FontAttrs *attrs);
@@ -737,7 +741,9 @@ private:
protected:
inline Color (int color): ColorAttrs (color) {
- refCount = 0; }
+ DBG_OBJ_CREATE ("dw::core::style::Color");
+ refCount = 0;
+ }
virtual ~Color ();
public:
@@ -832,7 +838,7 @@ public:
{
public:
void getPaddingArea (int *x, int *y, int *width, int *height);
-
+
StyleImage *getBackgroundImage ();
BackgroundRepeat getBackgroundRepeat ();
BackgroundAttachment getBackgroundAttachment ();
diff --git a/dw/table.cc b/dw/table.cc
index eef1b6ce..565dfc9e 100644
--- a/dw/table.cc
+++ b/dw/table.cc
@@ -98,6 +98,8 @@ Table::~Table()
delete baseline;
delete rowStyle;
delete colPercents;
+
+ DBG_OBJ_DELETE ();
}
void Table::sizeRequestImpl (core::Requisition *requisition)
@@ -1070,7 +1072,7 @@ void Table::apportion_percentages2(int totalWidth, int forceTotalWidth)
for (int col = 0; col < numCols; col++) {
if (core::style::isPerLength (colPercents->get(col))) {
// This could cause rounding errors:
- //
+ //
// int d =
// core::dw::multiplyWithPerLength (extraWidth,
// colPercents->get(col))
diff --git a/dw/tablecell.cc b/dw/tablecell.cc
index edad1524..67d6cf2d 100644
--- a/dw/tablecell.cc
+++ b/dw/tablecell.cc
@@ -42,6 +42,7 @@ TableCell::TableCell (TableCell *ref, bool limitTextWidth):
TableCell::~TableCell()
{
+ DBG_OBJ_DELETE ();
}
bool TableCell::wordWrap(int wordIndex, bool wrapAll)
diff --git a/dw/textblock.cc b/dw/textblock.cc
index 27bc584e..91f9a82e 100644
--- a/dw/textblock.cc
+++ b/dw/textblock.cc
@@ -322,7 +322,7 @@ Textblock::~Textblock ()
parent class destructor. (???) */
words = NULL;
- //DBG_OBJ_SET_NUM(this, "num_lines", lines->size ());
+ DBG_OBJ_DELETE ();
}
/**
@@ -2125,6 +2125,7 @@ void Textblock::addText0 (const char *text, size_t len, short flags,
Word *word = addWord (size->width, size->ascent, size->descent,
flags, style);
+ DBG_OBJ_ASSOC_CHILD (style);
word->content.type = core::Content::TEXT;
word->content.text = layout->textZone->strndup(text, len);
@@ -2438,6 +2439,7 @@ void Textblock::addParbreak (int space, core::style::Style *style)
}
word = addWord (0, 0, 0, 0, style);
+ DBG_OBJ_ASSOC_CHILD (style);
word->content.type = core::Content::BREAK;
word->badnessAndPenalty.setPenalty (PENALTY_FORCE_BREAK);
word->content.breakSpace = space;
@@ -2466,6 +2468,8 @@ void Textblock::addLinebreak (core::style::Style *style)
// ... otherwise, it has no size (and does not enlarge the line).
word = addWord (0, 0, 0, 0, style);
+ DBG_OBJ_ASSOC_CHILD (style);
+
word->content.type = core::Content::BREAK;
word->badnessAndPenalty.setPenalty (PENALTY_FORCE_BREAK);
word->content.breakSpace = 0;
diff --git a/dw/ui.cc b/dw/ui.cc
index 17cf2288..d571599c 100644
--- a/dw/ui.cc
+++ b/dw/ui.cc
@@ -44,6 +44,7 @@ Embed::Embed(Resource *resource)
Embed::~Embed()
{
delete resource;
+ DBG_OBJ_DELETE ();
}
void Embed::sizeRequestImpl (Requisition *requisition)
diff --git a/dw/widget.cc b/dw/widget.cc
index 21b55f47..8147e3d7 100644
--- a/dw/widget.cc
+++ b/dw/widget.cc
@@ -108,6 +108,8 @@ Widget::~Widget ()
parent->removeChild (this);
else
layout->removeWidget ();
+
+ DBG_OBJ_DELETE ();
}
@@ -461,6 +463,8 @@ void Widget::setStyle (style::Style *style)
this->style = style;
+ DBG_OBJ_ASSOC_CHILD (style);
+
if (style && style->backgroundImage) {
// Create instance of WidgetImgRenderer when needed. Until this
// widget is deleted, "widgetImgRenderer" will be kept, since it
diff --git a/lout/container.cc b/lout/container.cc
index 602553d3..dcac4726 100644
--- a/lout/container.cc
+++ b/lout/container.cc
@@ -428,7 +428,7 @@ void HashSet::clearNode(HashSet::Node *node)
}
}
-HashSet::Node *HashSet::findNode(Object *object)
+HashSet::Node *HashSet::findNode(Object *object) const
{
int h = calcHashValue(object);
for (Node *node = table[h]; node; node = node->next) {
@@ -462,7 +462,7 @@ void HashSet::put(Object *object)
insertNode (object);
}
-bool HashSet::contains(Object *object)
+bool HashSet::contains(Object *object) const
{
int h = calcHashValue(object);
for (Node *n = table[h]; n; n = n->next) {
@@ -578,7 +578,7 @@ HashTable::~HashTable()
PRINTF ("- deleting value: %s\n", value->toString());
delete value;
}
- }
+ }
}
}
}
@@ -612,7 +612,7 @@ void HashTable::intoStringBuffer(misc::StringBuffer *sb)
node->object->intoStringBuffer(sb);
sb->append(" => ");
-
+
Object *value = ((KeyValuePair*)node)->value;
if (value)
value->intoStringBuffer(sb);
@@ -632,7 +632,7 @@ void HashTable::put(Object *key, Object *value)
node->value = value;
}
-Object *HashTable::get(Object *key)
+Object *HashTable::get(Object *key) const
{
Node *node = findNode(key);
if (node)
diff --git a/lout/container.hh b/lout/container.hh
index 9180b9e0..03800efd 100644
--- a/lout/container.hh
+++ b/lout/container.hh
@@ -114,7 +114,7 @@ private:
private:
Vector *vector;
int index;
-
+
public:
VectorIterator(Vector *vector) { this->vector = vector; index = -1; }
bool hasNext();
@@ -143,7 +143,7 @@ public:
{ insert (newElement, bsearch (newElement, false, comparator)); }
void remove(int pos);
- inline object::Object *get(int pos)
+ inline object::Object *get(int pos) const
{ return (pos >= 0 && pos < numElements) ? array[pos] : NULL; }
inline int size() { return numElements; }
void clear();
@@ -203,10 +203,10 @@ public:
{ return remove0(element, true, false); }
inline bool detachRef(object::Object *element)
{ return remove0(element, false, true); }
- inline int size() { return numElements; }
- inline bool isEmpty() { return numElements == 0; }
- inline object::Object *getFirst() { return first->object; }
- inline object::Object *getLast() { return last->object; }
+ inline int size() const { return numElements; }
+ inline bool isEmpty() const { return numElements == 0; }
+ inline object::Object *getFirst() const { return first->object; }
+ inline object::Object *getLast() const { return last->object; }
};
@@ -228,7 +228,7 @@ protected:
int tableSize;
bool ownerOfObjects;
- inline int calcHashValue(object::Object *object)
+ inline int calcHashValue(object::Object *object) const
{
return abs(object->hashValue()) % tableSize;
}
@@ -236,7 +236,7 @@ protected:
virtual Node *createNode();
virtual void clearNode(Node *node);
- Node *findNode(object::Object *object);
+ Node *findNode(object::Object *object) const;
Node *insertNode(object::Object *object);
AbstractIterator* createIterator();
@@ -262,7 +262,7 @@ public:
~HashSet();
void put (object::Object *object);
- bool contains (object::Object *key);
+ bool contains (object::Object *key) const;
bool remove (object::Object *key);
//Object *getReference (object::Object *object);
};
@@ -291,7 +291,7 @@ public:
void intoStringBuffer(misc::StringBuffer *sb);
void put (object::Object *key, object::Object *value);
- object::Object *get (object::Object *key);
+ object::Object *get (object::Object *key) const;
};
/**
@@ -335,9 +335,9 @@ public:
void push (object::Object *object);
void pushUnder (object::Object *object);
- inline object::Object *getTop () { return top ? top->object : NULL; }
+ inline object::Object *getTop () const { return top ? top->object : NULL; }
void pop ();
- inline int size() { return numElements; }
+ inline int size() const { return numElements; }
};
} // namespace untyped
@@ -418,9 +418,9 @@ public:
&object::standardComparator)
{ ((untyped::Vector*)this->base)->insertSorted(newElement, comparator); }
inline void remove(int pos) { ((untyped::Vector*)this->base)->remove(pos); }
- inline T *get(int pos)
+ inline T *get(int pos) const
{ return (T*)((untyped::Vector*)this->base)->get(pos); }
- inline int size() { return ((untyped::Vector*)this->base)->size(); }
+ inline int size() const { return ((untyped::Vector*)this->base)->size(); }
inline void clear() { ((untyped::Vector*)this->base)->clear(); }
inline void sort(object::Comparator *comparator =
&object::standardComparator)
@@ -457,12 +457,12 @@ public:
inline bool detachRef(T *element) {
return ((untyped::List*)this->base)->detachRef(element); }
- inline int size() { return ((untyped::List*)this->base)->size(); }
- inline bool isEmpty()
+ inline int size() const { return ((untyped::List*)this->base)->size(); }
+ inline bool isEmpty() const
{ return ((untyped::List*)this->base)->isEmpty(); }
- inline T *getFirst()
+ inline T *getFirst() const
{ return (T*)((untyped::List*)this->base)->getFirst(); }
- inline T *getLast()
+ inline T *getLast() const
{ return (T*)((untyped::List*)this->base)->getLast(); }
};
@@ -480,7 +480,7 @@ public:
inline void put(T *object)
{ return ((untyped::HashSet*)this->base)->put(object); }
- inline bool contains(T *object)
+ inline bool contains(T *object) const
{ return ((untyped::HashSet*)this->base)->contains(object); }
inline bool remove(T *object)
{ return ((untyped::HashSet*)this->base)->remove(object); }
@@ -500,7 +500,7 @@ public:
inline void put(K *key, V *value)
{ return ((untyped::HashTable*)this->base)->put(key, value); }
- inline V *get(K *key)
+ inline V *get(K *key) const
{ return (V*)((untyped::HashTable*)this->base)->get(key); }
};
@@ -517,10 +517,10 @@ public:
((untyped::Stack*)this->base)->push (object); }
inline void pushUnder (T *object)
{ ((untyped::Stack*)this->base)->pushUnder (object); }
- inline T *getTop ()
+ inline T *getTop () const
{ return (T*)((untyped::Stack*)this->base)->getTop (); }
inline void pop () { ((untyped::Stack*)this->base)->pop (); }
- inline int size() { return ((untyped::Stack*)this->base)->size(); }
+ inline int size() const { return ((untyped::Stack*)this->base)->size(); }
};
} // namespace untyped
diff --git a/lout/debug.hh b/lout/debug.hh
index 999a4a8b..a2393470 100644
--- a/lout/debug.hh
+++ b/lout/debug.hh
@@ -115,6 +115,13 @@
fflush (stdout); \
} D_STMT_END
+#define DBG_OBJ_DELETE() \
+ D_STMT_START { \
+ printf (RTFL_PREFIX_FMT "obj-delete:%p\n", \
+ RTFL_PREFIX_ARGS, this); \
+ fflush (stdout); \
+ } D_STMT_END
+
#define DBG_OBJ_BASECLASS(klass) \
D_STMT_START { \
printf (RTFL_PREFIX_FMT "obj-ident:%p:%p\n", \
@@ -124,9 +131,11 @@
#define DBG_OBJ_ASSOC(parent, child) \
D_STMT_START { \
- printf (RTFL_PREFIX_FMT "obj-assoc:%p:%p\n", \
- RTFL_PREFIX_ARGS, parent, child); \
- fflush (stdout); \
+ if (child) { \
+ printf (RTFL_PREFIX_FMT "obj-assoc:%p:%p\n", \
+ RTFL_PREFIX_ARGS, parent, child); \
+ fflush (stdout); \
+ } \
} D_STMT_END
#define DBG_OBJ_ASSOC_PARENT(parent) \
@@ -138,9 +147,11 @@
#define DBG_OBJ_ASSOC_CHILD(child) \
D_STMT_START { \
- printf (RTFL_PREFIX_FMT "obj-assoc:%p:%p\n", \
- RTFL_PREFIX_ARGS, this, child); \
- fflush (stdout); \
+ if (child) { \
+ printf (RTFL_PREFIX_FMT "obj-assoc:%p:%p\n", \
+ RTFL_PREFIX_ARGS, this, child); \
+ fflush (stdout); \
+ } \
} D_STMT_END
#define DBG_OBJ_SET_NUM(var, val) \
@@ -254,6 +265,7 @@
#define DBG_OBJ_MSG_END() D_STMT_NOP
#define DBG_OBJ_MSG_END_O(obj) D_STMT_NOP
#define DBG_OBJ_CREATE(klass) D_STMT_NOP
+#define DBG_OBJ_DELETE() D_STMT_NOP
#define DBG_OBJ_BASECLASS(klass) D_STMT_NOP
#define DBG_OBJ_ASSOC_PARENT(parent) D_STMT_NOP
#define DBG_OBJ_ASSOC_CHILD(child) D_STMT_NOP
@@ -271,7 +283,7 @@
#define DBG_OBJ_ARRATTRSET_SYM(var, ind, attr, val) D_STMT_NOP
#define DBG_OBJ_ARRATTRSET_STR(var, ind, attr, val) D_STMT_NOP
#define DBG_OBJ_ARRATTRSET_PTR(var, ind, attr, val) D_STMT_NOP
-#define DBG_OBJ_COLOR(klass, color)
+#define DBG_OBJ_COLOR(klass, color) D_STMT_NOP
#endif /* DBG_RTFL */
diff --git a/lout/misc.cc b/lout/misc.cc
index d4db609e..8d630efc 100644
--- a/lout/misc.cc
+++ b/lout/misc.cc
@@ -151,7 +151,7 @@ void BitSet::intoStringBuffer(misc::StringBuffer *sb)
sb->append("]");
}
-bool BitSet::get(int i)
+bool BitSet::get(int i) const
{
if (8 * i >= numBytes)
return false;
diff --git a/lout/misc.hh b/lout/misc.hh
index 2ed5e1b0..2bb28b12 100644
--- a/lout/misc.hh
+++ b/lout/misc.hh
@@ -92,7 +92,7 @@ private:
}
public:
- inline SimpleVector (int initAlloc)
+ inline SimpleVector (int initAlloc = 1)
{
this->num = 0;
this->numAlloc = initAlloc;
@@ -116,9 +116,9 @@ public:
/**
* \brief Return the number of elements put into this vector.
*/
- inline int size() { return this->num; }
+ inline int size() const { return this->num; }
- inline T* getArray() { return array; }
+ inline T* getArray() const { return array; }
inline T* detachArray() {
T* arr = array;
@@ -163,7 +163,7 @@ public:
*
* \sa misc::SimpleVector::get
*/
- inline T* getRef (int i) {
+ inline T* getRef (int i) const {
assert (i >= 0 && this->num - i > 0);
return array + i;
}
@@ -174,7 +174,7 @@ public:
* The element is copied, so for complex elements, you should rather used
* misc::SimpleVector::getRef.
*/
- inline T get (int i) {
+ inline T get (int i) const {
assert (i >= 0 && this->num - i > 0);
return this->array[i];
}
@@ -182,7 +182,7 @@ public:
/**
* \brief Return the reference of the first element (convenience method).
*/
- inline T* getFirstRef () {
+ inline T* getFirstRef () const {
assert (this->num > 0);
return this->array;
}
@@ -190,7 +190,7 @@ public:
/**
* \brief Return the first element, explicitly.
*/
- inline T getFirst () {
+ inline T getFirst () const {
assert (this->num > 0);
return this->array[0];
}
@@ -198,7 +198,7 @@ public:
/**
* \brief Return the reference of the last element (convenience method).
*/
- inline T* getLastRef () {
+ inline T* getLastRef () const {
assert (this->num > 0);
return this->array + this->num - 1;
}
@@ -206,7 +206,7 @@ public:
/**
* \brief Return the last element, explicitly.
*/
- inline T getLast () {
+ inline T getLast () const {
assert (this->num > 0);
return this->array[this->num - 1];
}
@@ -352,7 +352,7 @@ public:
free (this->arrayExtra2);
}
- inline int size() { return this->numMain + this->numExtra; }
+ inline int size() const { return this->numMain + this->numExtra; }
inline void increase() { setSize(size() + 1); }
@@ -419,7 +419,7 @@ public:
*
* \sa misc::SimpleVector::get
*/
- inline T* getRef (int i)
+ inline T* getRef (int i) const
{
if (this->startExtra == -1)
return this->arrayMain + i;
@@ -439,7 +439,7 @@ public:
* The element is copied, so for complex elements, you should rather used
* misc::SimpleVector::getRef.
*/
- inline T get (int i)
+ inline T get (int i) const
{
return *(this->getRef(i));
}
@@ -447,7 +447,7 @@ public:
/**
* \brief Return the reference of the first element (convenience method).
*/
- inline T* getFirstRef () {
+ inline T* getFirstRef () const {
assert (size () > 0);
return this->getRef(0);
}
@@ -455,14 +455,14 @@ public:
/**
* \brief Return the first element, explicitly.
*/
- inline T getFirst () {
+ inline T getFirst () const {
return *(this->getFirstRef());
}
/**
* \brief Return the reference of the last element (convenience method).
*/
- inline T* getLastRef () {
+ inline T* getLastRef () const {
assert (size () > 0);
return this->getRef(size () - 1);
}
@@ -470,7 +470,7 @@ public:
/**
* \brief Return the last element, explicitly.
*/
- inline T getLast () {
+ inline T getLast () const {
return *(this->getLastRef());
}
@@ -541,7 +541,7 @@ public:
BitSet(int initBits);
~BitSet();
void intoStringBuffer(misc::StringBuffer *sb);
- bool get(int i);
+ bool get(int i) const;
void set(int i, bool val);
void clear();
};
diff --git a/src/css.cc b/src/css.cc
index d4dc72ad..4938a1cf 100644
--- a/src/css.cc
+++ b/src/css.cc
@@ -1,7 +1,7 @@
/*
* File: css.cc
*
- * Copyright 2008-2009 Johannes Hofmann <Johannes.Hofmann@gmx.de>
+ * Copyright 2008-2014 Johannes Hofmann <Johannes.Hofmann@gmx.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -108,33 +108,31 @@ CssSelector::CssSelector () {
struct CombinatorAndSelector *cs;
refCount = 0;
- selectorList = new lout::misc::SimpleVector
- <struct CombinatorAndSelector> (1);
- selectorList->increase ();
- cs = selectorList->getRef (selectorList->size () - 1);
+ matchCacheOffset = -1;
+ selectorList.increase ();
+ cs = selectorList.getRef (selectorList.size () - 1);
- cs->notMatchingBefore = -1;
cs->combinator = COMB_NONE;
cs->selector = new CssSimpleSelector ();
}
CssSelector::~CssSelector () {
- for (int i = selectorList->size () - 1; i >= 0; i--)
- delete selectorList->getRef (i)->selector;
- delete selectorList;
+ for (int i = selectorList.size () - 1; i >= 0; i--)
+ delete selectorList.getRef (i)->selector;
}
/**
* \brief Return whether selector matches at a given node in the document tree.
*/
bool CssSelector::match (Doctree *docTree, const DoctreeNode *node,
- int i, Combinator comb) {
+ int i, Combinator comb, MatchCache *matchCache) {
+ int *matchCacheEntry;
assert (node);
if (i < 0)
return true;
- struct CombinatorAndSelector *cs = selectorList->getRef (i);
+ struct CombinatorAndSelector *cs = selectorList.getRef (i);
CssSimpleSelector *sel = cs->selector;
switch (comb) {
@@ -148,14 +146,16 @@ bool CssSelector::match (Doctree *docTree, const DoctreeNode *node,
break;
case COMB_DESCENDANT:
node = docTree->parent (node);
+ matchCacheEntry = matchCache->getRef(matchCacheOffset + i);
for (const DoctreeNode *n = node;
- n && n->num > cs->notMatchingBefore; n = docTree->parent (n))
- if (sel->match (n) && match (docTree, n, i - 1, cs->combinator))
+ n && n->num > *matchCacheEntry; n = docTree->parent (n))
+ if (sel->match (n) &&
+ match (docTree, n, i - 1, cs->combinator, matchCache))
return true;
if (node) // remember that it didn't match to avoid future tests
- cs->notMatchingBefore = node->num;
+ *matchCacheEntry = node->num;
return false;
break;
@@ -167,23 +167,23 @@ bool CssSelector::match (Doctree *docTree, const DoctreeNode *node,
return false;
// tail recursion should be optimized by the compiler
- return match (docTree, node, i - 1, cs->combinator);
+ return match (docTree, node, i - 1, cs->combinator, matchCache);
}
void CssSelector::addSimpleSelector (Combinator c) {
struct CombinatorAndSelector *cs;
- selectorList->increase ();
- cs = selectorList->getRef (selectorList->size () - 1);
+ assert (matchCacheOffset == -1);
+ selectorList.increase ();
+ cs = selectorList.getRef (selectorList.size () - 1);
cs->combinator = c;
- cs->notMatchingBefore = -1;
cs->selector = new CssSimpleSelector ();
}
bool CssSelector::checksPseudoClass () {
- for (int i = 0; i < selectorList->size (); i++)
- if (selectorList->getRef (i)->selector->getPseudoClass ())
+ for (int i = 0; i < selectorList.size (); i++)
+ if (selectorList.getRef (i)->selector->getPseudoClass ())
return true;
return false;
}
@@ -197,18 +197,18 @@ bool CssSelector::checksPseudoClass () {
int CssSelector::specificity () {
int spec = 0;
- for (int i = 0; i < selectorList->size (); i++)
- spec += selectorList->getRef (i)->selector->specificity ();
+ for (int i = 0; i < selectorList.size (); i++)
+ spec += selectorList.getRef (i)->selector->specificity ();
return spec;
}
void CssSelector::print () {
- for (int i = 0; i < selectorList->size (); i++) {
- selectorList->getRef (i)->selector->print ();
+ for (int i = 0; i < selectorList.size (); i++) {
+ selectorList.getRef (i)->selector->print ();
- if (i < selectorList->size () - 1) {
- switch (selectorList->getRef (i + 1)->combinator) {
+ if (i < selectorList.size () - 1) {
+ switch (selectorList.getRef (i + 1)->combinator) {
case COMB_CHILD:
fprintf (stderr, "> ");
break;
@@ -230,17 +230,13 @@ void CssSelector::print () {
CssSimpleSelector::CssSimpleSelector () {
element = ELEMENT_ANY;
- klass = NULL;
id = NULL;
pseudo = NULL;
}
CssSimpleSelector::~CssSimpleSelector () {
- if (klass) {
- for (int i = 0; i < klass->size (); i++)
- dFree (klass->get (i));
- delete klass;
- }
+ for (int i = 0; i < klass.size (); i++)
+ dFree (klass.get (i));
dFree (id);
dFree (pseudo);
}
@@ -248,10 +244,8 @@ CssSimpleSelector::~CssSimpleSelector () {
void CssSimpleSelector::setSelect (SelectType t, const char *v) {
switch (t) {
case SELECT_CLASS:
- if (klass == NULL)
- klass = new lout::misc::SimpleVector <char *> (1);
- klass->increase ();
- klass->set (klass->size () - 1, dStrdup (v));
+ klass.increase ();
+ klass.set (klass.size () - 1, dStrdup (v));
break;
case SELECT_PSEUDO_CLASS:
if (pseudo == NULL)
@@ -279,20 +273,18 @@ bool CssSimpleSelector::match (const DoctreeNode *n) {
return false;
if (id != NULL && (n->id == NULL || dStrAsciiCasecmp (id, n->id) != 0))
return false;
- if (klass != NULL) {
- for (int i = 0; i < klass->size (); i++) {
- bool found = false;
- if (n->klass != NULL) {
- for (int j = 0; j < n->klass->size (); j++) {
- if (dStrAsciiCasecmp (klass->get(i), n->klass->get(j)) == 0) {
- found = true;
- break;
- }
+ for (int i = 0; i < klass.size (); i++) {
+ bool found = false;
+ if (n->klass != NULL) {
+ for (int j = 0; j < n->klass->size (); j++) {
+ if (dStrAsciiCasecmp (klass.get(i), n->klass->get(j)) == 0) {
+ found = true;
+ break;
}
}
- if (! found)
- return false;
}
+ if (! found)
+ return false;
}
return true;
@@ -308,8 +300,7 @@ int CssSimpleSelector::specificity () {
if (id)
spec += 1 << 20;
- if (klass)
- spec += klass->size() << 10;
+ spec += klass.size() << 10;
if (pseudo)
spec += 1 << 10;
if (element != ELEMENT_ANY)
@@ -321,11 +312,9 @@ int CssSimpleSelector::specificity () {
void CssSimpleSelector::print () {
fprintf (stderr, "Element %d, pseudo %s, id %s ",
element, pseudo, id);
- if (klass != NULL) {
- fprintf (stderr, "class ");
- for (int i = 0; i < klass->size (); i++)
- fprintf (stderr, ".%s", klass->get (i));
- }
+ fprintf (stderr, "class ");
+ for (int i = 0; i < klass.size (); i++)
+ fprintf (stderr, ".%s", klass.get (i));
}
CssRule::CssRule (CssSelector *selector, CssPropertyList *props, int pos) {
@@ -344,9 +333,9 @@ CssRule::~CssRule () {
props->unref ();
}
-void CssRule::apply (CssPropertyList *props,
- Doctree *docTree, const DoctreeNode *node) {
- if (selector->match (docTree, node))
+void CssRule::apply (CssPropertyList *props, Doctree *docTree,
+ const DoctreeNode *node, MatchCache *matchCache) const {
+ if (selector->match (docTree, node, matchCache))
this->props->apply (props);
}
@@ -410,6 +399,8 @@ void CssStyleSheet::addRule (CssRule *rule) {
}
if (ruleList) {
+ rule->selector->setMatchCacheOffset (matchCacheOffset);
+ matchCacheOffset += rule->selector->size ();
ruleList->insert (rule);
} else {
assert (top->getElement () == CssSimpleSelector::ELEMENT_NONE);
@@ -423,10 +414,10 @@ void CssStyleSheet::addRule (CssRule *rule) {
* The properties are set as defined by the rules in the stylesheet that
* match at the given node in the document tree.
*/
-void CssStyleSheet::apply (CssPropertyList *props,
- Doctree *docTree, const DoctreeNode *node) {
+void CssStyleSheet::apply (CssPropertyList *props, Doctree *docTree,
+ const DoctreeNode *node, MatchCache *matchCache) const {
static const int maxLists = 32;
- RuleList *ruleList[maxLists];
+ const RuleList *ruleList[maxLists];
int numLists = 0, index[maxLists] = {0};
if (node->id) {
@@ -470,7 +461,7 @@ void CssStyleSheet::apply (CssPropertyList *props,
int minSpecIndex = -1;
for (int i = 0; i < numLists; i++) {
- RuleList *rl = ruleList[i];
+ const RuleList *rl = ruleList[i];
if (rl && rl->size () > index[i] &&
(rl->get(index[i])->specificity () < minSpec ||
@@ -484,8 +475,8 @@ void CssStyleSheet::apply (CssPropertyList *props,
}
if (minSpecIndex >= 0) {
- ruleList[minSpecIndex]->get (index[minSpecIndex])->apply
- (props, docTree, node);
+ CssRule *rule = ruleList[minSpecIndex]->get (index[minSpecIndex]);
+ rule->apply(props, docTree, node, matchCache);
index[minSpecIndex]++;
} else {
break;
@@ -493,8 +484,11 @@ void CssStyleSheet::apply (CssPropertyList *props,
}
}
+CssStyleSheet CssContext::userAgentSheet;
+
CssContext::CssContext () {
pos = 0;
+ matchCache[CSS_PRIMARY_USER_AGENT].setSize (userAgentSheet.matchCacheOffset, -1);
}
/**
@@ -511,23 +505,28 @@ void CssContext::apply (CssPropertyList *props, Doctree *docTree,
CssPropertyList *tagStyle, CssPropertyList *tagStyleImportant,
CssPropertyList *nonCssHints) {
- sheet[CSS_PRIMARY_USER_AGENT].apply (props, docTree, node);
- sheet[CSS_PRIMARY_USER].apply (props, docTree, node);
+ userAgentSheet.apply (props, docTree, node,
+ &matchCache[CSS_PRIMARY_USER_AGENT]);
+ sheet[CSS_PRIMARY_USER].apply (props, docTree, node,
+ &matchCache[CSS_PRIMARY_USER]);
if (nonCssHints)
nonCssHints->apply (props);
- sheet[CSS_PRIMARY_AUTHOR].apply (props, docTree, node);
+ sheet[CSS_PRIMARY_AUTHOR].apply (props, docTree, node,
+ &matchCache[CSS_PRIMARY_AUTHOR]);
if (tagStyle)
tagStyle->apply (props);
- sheet[CSS_PRIMARY_AUTHOR_IMPORTANT].apply (props, docTree, node);
+ sheet[CSS_PRIMARY_AUTHOR_IMPORTANT].apply (props, docTree, node,
+ &matchCache[CSS_PRIMARY_AUTHOR_IMPORTANT]);
if (tagStyleImportant)
tagStyleImportant->apply (props);
- sheet[CSS_PRIMARY_USER_IMPORTANT].apply (props, docTree, node);
+ sheet[CSS_PRIMARY_USER_IMPORTANT].apply (props, docTree, node,
+ &matchCache[CSS_PRIMARY_USER_IMPORTANT]);
}
void CssContext::addRule (CssSelector *sel, CssPropertyList *props,
@@ -541,8 +540,12 @@ void CssContext::addRule (CssSelector *sel, CssPropertyList *props,
!rule->isSafe ()) {
MSG_WARN ("Ignoring unsafe author style that might reveal browsing history\n");
delete rule;
- } else {
+ } else if (order == CSS_PRIMARY_USER_AGENT) {
+ userAgentSheet.addRule (rule);
+ matchCache[CSS_PRIMARY_USER_AGENT].setSize (userAgentSheet.matchCacheOffset, -1);
+ } else {
sheet[order].addRule (rule);
+ matchCache[order].setSize (sheet[order].matchCacheOffset, -1);
}
}
}
diff --git a/src/css.hh b/src/css.hh
index a7143c27..4dd94ffe 100644
--- a/src/css.hh
+++ b/src/css.hh
@@ -293,6 +293,7 @@ class CssProperty {
switch (type) {
case CSS_TYPE_STRING:
case CSS_TYPE_SYMBOL:
+ case CSS_TYPE_URI:
dFree (value.strVal);
break;
case CSS_TYPE_BACKGROUND_POSITION:
@@ -335,7 +336,7 @@ class CssSimpleSelector {
private:
int element;
char *pseudo, *id;
- lout::misc::SimpleVector <char *> *klass;
+ lout::misc::SimpleVector <char *> klass;
public:
enum {
@@ -354,7 +355,7 @@ class CssSimpleSelector {
~CssSimpleSelector ();
inline void setElement (int e) { element = e; };
void setSelect (SelectType t, const char *v);
- inline lout::misc::SimpleVector <char *> *getClass () { return klass; };
+ inline lout::misc::SimpleVector <char *> *getClass () { return &klass; };
inline const char *getPseudoClass () { return pseudo; };
inline const char *getId () { return id; };
inline int getElement () { return element; };
@@ -363,6 +364,11 @@ class CssSimpleSelector {
void print ();
};
+class MatchCache : public lout::misc::SimpleVector <int> {
+ public:
+ MatchCache() : lout::misc::SimpleVector <int> (0) {};
+};
+
/**
* \brief CSS selector class.
*
@@ -379,26 +385,31 @@ class CssSelector {
private:
struct CombinatorAndSelector {
- int notMatchingBefore; // used for optimizing CSS selector matching
Combinator combinator;
CssSimpleSelector *selector;
};
- int refCount;
- lout::misc::SimpleVector <struct CombinatorAndSelector> *selectorList;
+ int refCount, matchCacheOffset;
+ lout::misc::SimpleVector <struct CombinatorAndSelector> selectorList;
- bool match (Doctree *dt, const DoctreeNode *node, int i, Combinator comb);
+ bool match (Doctree *dt, const DoctreeNode *node, int i, Combinator comb,
+ MatchCache *matchCache);
public:
CssSelector ();
~CssSelector ();
void addSimpleSelector (Combinator c);
inline CssSimpleSelector *top () {
- return selectorList->getRef (selectorList->size () - 1)->selector;
+ return selectorList.getRef (selectorList.size () - 1)->selector;
+ };
+ inline int size () { return selectorList.size (); };
+ inline bool match (Doctree *dt, const DoctreeNode *node,
+ MatchCache *matchCache) {
+ return match (dt, node, selectorList.size () - 1, COMB_NONE,
+ matchCache);
};
- inline int size () { return selectorList->size (); };
- inline bool match (Doctree *dt, const DoctreeNode *node) {
- return match (dt, node, selectorList->size () - 1, COMB_NONE);
+ inline void setMatchCacheOffset (int mo) {
+ matchCacheOffset = mo;
};
int specificity ();
bool checksPseudoClass ();
@@ -423,8 +434,8 @@ class CssRule {
CssRule (CssSelector *selector, CssPropertyList *props, int pos);
~CssRule ();
- void apply (CssPropertyList *props,
- Doctree *docTree, const DoctreeNode *node);
+ void apply (CssPropertyList *props, Doctree *docTree,
+ const DoctreeNode *node, MatchCache *matchCache) const;
inline bool isSafe () {
return !selector->checksPseudoClass () || props->isSafe ();
};
@@ -463,19 +474,23 @@ class CssStyleSheet {
<lout::object::ConstString, RuleList > (true, true, 256) {};
};
- static const int ntags = 90 + 10; // \todo don't hardcode
+ static const int ntags = 90 + 14; // \todo don't hardcode
/* 90 is the full number of html4 elements, including those which we have
- * implemented. From html 5, let's add: article, header, footer, mark,
- * nav, section, aside, figure, figcaption, wbr.
+ * implemented. From html5, let's add: article, header, footer, mark,
+ * nav, section, aside, figure, figcaption, wbr, audio, video, source,
+ * embed.
*/
RuleList elementTable[ntags], anyTable;
RuleMap idTable, classTable;
public:
+ int matchCacheOffset;
+
+ CssStyleSheet () { matchCacheOffset = 0; }
void addRule (CssRule *rule);
- void apply (CssPropertyList *props,
- Doctree *docTree, const DoctreeNode *node);
+ void apply (CssPropertyList *props, Doctree *docTree,
+ const DoctreeNode *node, MatchCache *matchCache) const;
};
/**
@@ -483,7 +498,9 @@ class CssStyleSheet {
*/
class CssContext {
private:
+ static CssStyleSheet userAgentSheet;
CssStyleSheet sheet[CSS_PRIMARY_USER_IMPORTANT + 1];
+ MatchCache matchCache[CSS_PRIMARY_USER_IMPORTANT + 1];
int pos;
public:
diff --git a/src/cssparser.cc b/src/cssparser.cc
index 4ff8f4f7..07412a8d 100644
--- a/src/cssparser.cc
+++ b/src/cssparser.cc
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <stdio.h>
+#include "lout/debug.hh"
#include "msg.h"
#include "colors.h"
#include "html_common.hh"
@@ -27,7 +28,6 @@
using namespace dw::core::style;
-#define DEBUG_MSG(A, B, ...) _MSG(B, __VA_ARGS__)
#define MSG_CSS(A, ...) MSG(A, __VA_ARGS__)
#define DEBUG_TOKEN_LEVEL 0
#define DEBUG_PARSE_LEVEL 0
@@ -287,7 +287,7 @@ typedef struct {
CSS_SHORTHAND_BORDER, /* special, used for 'border' */
CSS_SHORTHAND_FONT, /* special, used for 'font' */
} type;
- const CssPropertyName * properties;/* CSS_SHORTHAND_MULTIPLE:
+ const CssPropertyName *properties; /* CSS_SHORTHAND_MULTIPLE:
* must be terminated by -1
* CSS_SHORTHAND_DIRECTIONS:
* must have length 4
@@ -728,7 +728,7 @@ bool CssParser::tokenMatchesProperty(CssPropertyName prop, CssValueType *type)
dStrAsciiCasecmp(tval, "right") == 0 ||
dStrAsciiCasecmp(tval, "top") == 0 ||
dStrAsciiCasecmp(tval, "bottom") == 0))
- return true;
+ return true;
// Fall Through (lenght and percentage)
case CSS_TYPE_LENGTH_PERCENTAGE:
case CSS_TYPE_LENGTH_PERCENTAGE_NUMBER:
@@ -871,7 +871,7 @@ bool CssParser::parseRgbColor(int32_t *c) {
bool CssParser::parseValue(CssPropertyName prop,
CssValueType type,
- CssPropertyValue * val)
+ CssPropertyValue *val)
{
CssLengthType lentype;
bool found, ret = false;
@@ -1199,8 +1199,8 @@ static int Css_shorthand_info_cmp(const void *a, const void *b)
((CssShorthandInfo *) b)->symbol);
}
-void CssParser::parseDeclaration(CssPropertyList * props,
- CssPropertyList * importantProps)
+void CssParser::parseDeclaration(CssPropertyList *props,
+ CssPropertyList *importantProps)
{
CssPropertyInfo pi = {NULL, {CSS_TYPE_UNUSED}, NULL}, *pip;
CssShorthandInfo *sip;
@@ -1715,7 +1715,7 @@ void CssParser::ignoreStatement()
}
}
-void CssParser::parse(DilloHtml *html, DilloUrl *url, CssContext * context,
+void CssParser::parse(DilloHtml *html, DilloUrl *url, CssContext *context,
const char *buf,
int buflen, CssOrigin origin)
{
diff --git a/src/dillo.cc b/src/dillo.cc
index 9930ae74..4d96988f 100644
--- a/src/dillo.cc
+++ b/src/dillo.cc
@@ -52,6 +52,7 @@
#include "cookies.h"
#include "domain.h"
#include "auth.h"
+#include "styleengine.hh"
#include "lout/debug.hh"
#include "dw/fltkcore.hh"
@@ -379,6 +380,7 @@ int main(int argc, char **argv)
DBG_OBJ_COLOR("#c0ff80", "dw::*");
DBG_OBJ_COLOR("#c0c0ff", "dw::fltk::*");
DBG_OBJ_COLOR("#ffa0a0", "dw::core::*");
+ DBG_OBJ_COLOR("#ffe0a0", "dw::core::style::*");
DBG_OBJ_COLOR ("#80ffa0", "dw::Image");
DBG_OBJ_COLOR ("#f0ff80", "dw::Textblock");
@@ -479,6 +481,7 @@ int main(int argc, char **argv)
a_Cookies_init();
a_Auth_init();
a_UIcmd_init();
+ StyleEngine::init();
dw::Textblock::setPenaltyHyphen (prefs.penalty_hyphen);
dw::Textblock::setPenaltyHyphen2 (prefs.penalty_hyphen_2);
diff --git a/src/form.cc b/src/form.cc
index c5bb10af..07c12815 100644
--- a/src/form.cc
+++ b/src/form.cc
@@ -2003,7 +2003,7 @@ static Embed *Html_input_image(DilloHtml *html, const char *tag, int tagsize)
html->styleEngine->setPseudoLink ();
/* create new image and add it to the button */
- a_Html_image_attrs(html, tag, tagsize);
+ a_Html_common_image_attrs(html, tag, tagsize);
if ((Image = a_Html_image_new(html, tag, tagsize))) {
// At this point, we know that Image->ir represents an image
// widget. Notice that the order of the casts matters, because
diff --git a/src/html.cc b/src/html.cc
index 74b90577..3319b35e 100644
--- a/src/html.cc
+++ b/src/html.cc
@@ -1383,7 +1383,7 @@ static void Html_tag_cleanup_at_close(DilloHtml *html, int new_idx)
* by closing them before opening another.
* This is not an HTML SPEC restriction , but it avoids lots of trouble
* inside dillo (concurrent inputs), and makes almost no sense to have.
- */
+ */
static void Html_tag_cleanup_nested_inputs(DilloHtml *html, int new_idx)
{
static int i_BUTTON = a_Html_tag_index("button"),
@@ -1696,9 +1696,9 @@ static void Html_tag_close_head(DilloHtml *html)
/* match for the well formed start of HEAD section */
if (html->Num_TITLE == 0)
BUG_MSG("HEAD section lacks the TITLE element\n");
-
+
html->InFlags &= ~IN_HEAD;
-
+
/* charset is already set, load remote stylesheets now */
for (int i = 0; i < html->cssUrls->size(); i++) {
a_Html_load_stylesheet(html, html->cssUrls->get(i));
@@ -2084,13 +2084,13 @@ static void Html_tag_open_abbr(DilloHtml *html, const char *tag, int tagsize)
/*
* Read image-associated tag attributes and create new image.
*/
-void a_Html_image_attrs(DilloHtml *html, const char *tag, int tagsize)
+void a_Html_common_image_attrs(DilloHtml *html, const char *tag, int tagsize)
{
char *width_ptr, *height_ptr;
const char *attrbuf;
CssLength l_w = CSS_CREATE_LENGTH(0.0, CSS_LENGTH_TYPE_AUTO);
CssLength l_h = CSS_CREATE_LENGTH(0.0, CSS_LENGTH_TYPE_AUTO);
- int space, border, w = 0, h = 0;
+ int w = 0, h = 0;
if (prefs.show_tooltip &&
(attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) {
@@ -2126,7 +2126,8 @@ void a_Html_image_attrs(DilloHtml *html, const char *tag, int tagsize)
dFree(width_ptr);
dFree(height_ptr);
width_ptr = height_ptr = NULL;
- MSG("a_Html_image_attrs: suspicious image size request %d x %d\n", w, h);
+ MSG("a_Html_common_image_attrs: suspicious image size request %d x %d\n",
+ w, h);
} else {
if (CSS_LENGTH_TYPE(l_w) != CSS_LENGTH_TYPE_AUTO)
html->styleEngine->setNonCssHint (CSS_PROPERTY_WIDTH,
@@ -2143,55 +2144,6 @@ void a_Html_image_attrs(DilloHtml *html, const char *tag, int tagsize)
[...]
*/
- /* Spacing to the left and right */
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "hspace"))) {
- space = strtol(attrbuf, NULL, 10);
- if (space > 0) {
- space = CSS_CREATE_LENGTH(space, CSS_LENGTH_TYPE_PX);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_LEFT,
- CSS_TYPE_LENGTH_PERCENTAGE, space);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_RIGHT,
- CSS_TYPE_LENGTH_PERCENTAGE, space);
- }
- }
-
- /* Spacing at the top and bottom */
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "vspace"))) {
- space = strtol(attrbuf, NULL, 10);
- if (space > 0) {
- space = CSS_CREATE_LENGTH(space, CSS_LENGTH_TYPE_PX);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_TOP,
- CSS_TYPE_LENGTH_PERCENTAGE, space);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_BOTTOM,
- CSS_TYPE_LENGTH_PERCENTAGE, space);
- }
- }
-
- /* Border */
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "border"))) {
- border = strtol(attrbuf, NULL, 10);
- if (border >= 0) {
- border = CSS_CREATE_LENGTH(border, CSS_LENGTH_TYPE_PX);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_WIDTH,
- CSS_TYPE_LENGTH_PERCENTAGE, border);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
- CSS_TYPE_LENGTH_PERCENTAGE, border);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_WIDTH,
- CSS_TYPE_LENGTH_PERCENTAGE, border);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_WIDTH,
- CSS_TYPE_LENGTH_PERCENTAGE, border);
-
- html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_STYLE,
- CSS_TYPE_ENUM, BORDER_SOLID);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_STYLE,
- CSS_TYPE_ENUM, BORDER_SOLID);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_STYLE,
- CSS_TYPE_ENUM, BORDER_SOLID);
- html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_STYLE,
- CSS_TYPE_ENUM, BORDER_SOLID);
- }
- }
-
/* x_img is an index to a list of {url,image} pairs.
* We know a_Html_image_new() will use size() as its next index */
html->styleEngine->setNonCssHint (PROPERTY_X_IMG, CSS_TYPE_INTEGER,
@@ -2272,7 +2224,60 @@ static bool Html_load_image(BrowserWindow *bw, DilloUrl *url,
static void Html_tag_open_img(DilloHtml *html, const char *tag, int tagsize)
{
- a_Html_image_attrs(html, tag, tagsize);
+ int space, border;
+ const char *attrbuf;
+
+ a_Html_common_image_attrs(html, tag, tagsize);
+
+ /* Spacing to the left and right */
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "hspace"))) {
+ space = strtol(attrbuf, NULL, 10);
+ if (space > 0) {
+ space = CSS_CREATE_LENGTH(space, CSS_LENGTH_TYPE_PX);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_LEFT,
+ CSS_TYPE_LENGTH_PERCENTAGE, space);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_RIGHT,
+ CSS_TYPE_LENGTH_PERCENTAGE, space);
+ }
+ }
+
+ /* Spacing at the top and bottom */
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "vspace"))) {
+ space = strtol(attrbuf, NULL, 10);
+ if (space > 0) {
+ space = CSS_CREATE_LENGTH(space, CSS_LENGTH_TYPE_PX);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_TOP,
+ CSS_TYPE_LENGTH_PERCENTAGE, space);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_BOTTOM,
+ CSS_TYPE_LENGTH_PERCENTAGE, space);
+ }
+ }
+
+ /* Border */
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "border"))) {
+ border = strtol(attrbuf, NULL, 10);
+ if (border >= 0) {
+ border = CSS_CREATE_LENGTH(border, CSS_LENGTH_TYPE_PX);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_WIDTH,
+ CSS_TYPE_LENGTH_PERCENTAGE, border);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
+ CSS_TYPE_LENGTH_PERCENTAGE, border);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_WIDTH,
+ CSS_TYPE_LENGTH_PERCENTAGE, border);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_WIDTH,
+ CSS_TYPE_LENGTH_PERCENTAGE, border);
+
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_STYLE,
+ CSS_TYPE_ENUM, BORDER_SOLID);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_STYLE,
+ CSS_TYPE_ENUM, BORDER_SOLID);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_STYLE,
+ CSS_TYPE_ENUM, BORDER_SOLID);
+ html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_STYLE,
+ CSS_TYPE_ENUM, BORDER_SOLID);
+ }
+ }
+
}
/*
@@ -2509,10 +2514,156 @@ static void Html_tag_open_object(DilloHtml *html, const char *tag, int tagsize)
html->styleEngine->setNonCssHint(PROPERTY_X_LINK, CSS_TYPE_INTEGER,
Html_set_new_link(html, &url));
+ }
+ a_Url_free(base_url);
+}
+static void Html_tag_content_object(DilloHtml *html, const char *tag,
+ int tagsize)
+{
+ if (a_Html_get_attr(html, tag, tagsize, "data"))
HT2TB(html)->addText("[OBJECT]", html->wordStyle ());
+}
+
+/*
+ * <VIDEO>
+ * Provide a link to the video.
+ */
+static void Html_tag_open_video(DilloHtml *html, const char *tag, int tagsize)
+{
+ DilloUrl *url;
+ const char *attrbuf;
+
+ if (html->InFlags & IN_MEDIA) {
+ MSG("<video> not handled when already inside a media element.\n");
+ return;
}
- a_Url_free(base_url);
+ /* TODO: poster attr */
+
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "src"))) {
+ url = a_Html_url_new(html, attrbuf, NULL, 0);
+ dReturn_if_fail ( url != NULL );
+
+ if (a_Capi_get_flags_with_redirection(url) & CAPI_IsCached) {
+ html->styleEngine->setPseudoVisited ();
+ } else {
+ html->styleEngine->setPseudoLink ();
+ }
+
+ html->styleEngine->setNonCssHint(PROPERTY_X_LINK, CSS_TYPE_INTEGER,
+ Html_set_new_link(html, &url));
+
+ HT2TB(html)->addText("[VIDEO]", html->wordStyle ());
+ }
+ html->InFlags |= IN_MEDIA;
+}
+
+/*
+ * <AUDIO>
+ * Provide a link to the audio.
+ */
+static void Html_tag_open_audio(DilloHtml *html, const char *tag, int tagsize)
+{
+ DilloUrl *url;
+ const char *attrbuf;
+
+ if (html->InFlags & IN_MEDIA) {
+ MSG("<audio> not handled when already inside a media element.\n");
+ return;
+ }
+
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "src"))) {
+ url = a_Html_url_new(html, attrbuf, NULL, 0);
+ dReturn_if_fail ( url != NULL );
+
+ if (a_Capi_get_flags_with_redirection(url) & CAPI_IsCached) {
+ html->styleEngine->setPseudoVisited ();
+ } else {
+ html->styleEngine->setPseudoLink ();
+ }
+
+ html->styleEngine->setNonCssHint(PROPERTY_X_LINK, CSS_TYPE_INTEGER,
+ Html_set_new_link(html, &url));
+
+ HT2TB(html)->addText("[AUDIO]", html->wordStyle ());
+ }
+ html->InFlags |= IN_MEDIA;
+}
+
+/*
+ * <SOURCE>
+ * Media resource; provide a link to its address.
+ */
+static void Html_tag_open_source(DilloHtml *html, const char *tag,
+ int tagsize)
+{
+ const char *attrbuf;
+
+ if (!(html->InFlags & IN_MEDIA)) {
+ BUG_MSG("<source> element not inside a media element.\n");
+ return;
+ }
+ if (!(attrbuf = a_Html_get_attr(html, tag, tagsize, "src"))) {
+ BUG_MSG("src attribute is required in <source> element.\n");
+ return;
+ } else {
+ DilloUrl *url = a_Html_url_new(html, attrbuf, NULL, 0);
+
+ dReturn_if_fail ( url != NULL );
+
+ if (a_Capi_get_flags_with_redirection(url) & CAPI_IsCached) {
+ html->styleEngine->setPseudoVisited ();
+ } else {
+ html->styleEngine->setPseudoLink ();
+ }
+ html->styleEngine->setNonCssHint(PROPERTY_X_LINK, CSS_TYPE_INTEGER,
+ Html_set_new_link(html, &url));
+ }
+}
+
+static void Html_tag_content_source(DilloHtml *html, const char *tag,
+ int tagsize)
+{
+ if ((html->InFlags & IN_MEDIA) && a_Html_get_attr(html, tag, tagsize,"src"))
+ HT2TB(html)->addText("[MEDIA SOURCE]", html->wordStyle ());
+}
+
+/*
+ * Media (AUDIO/VIDEO) close function
+ */
+static void Html_tag_close_media(DilloHtml *html)
+{
+ html->InFlags &= ~IN_MEDIA;
+}
+
+/*
+ * <EMBED>
+ * Provide a link to embedded content.
+ */
+static void Html_tag_open_embed(DilloHtml *html, const char *tag, int tagsize)
+{
+ const char *attrbuf;
+
+ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "src"))) {
+ DilloUrl *url = a_Html_url_new(html, attrbuf, NULL, 0);
+
+ dReturn_if_fail ( url != NULL );
+
+ if (a_Capi_get_flags_with_redirection(url) & CAPI_IsCached) {
+ html->styleEngine->setPseudoVisited ();
+ } else {
+ html->styleEngine->setPseudoLink ();
+ }
+
+ html->styleEngine->setNonCssHint(PROPERTY_X_LINK, CSS_TYPE_INTEGER,
+ Html_set_new_link(html, &url));
+ }
+}
+
+static void Html_tag_content_embed(DilloHtml *html,const char *tag,int tagsize)
+{
+ if (a_Html_get_attr(html, tag, tagsize, "src"))
+ HT2TB(html)->addText("[EMBED]", html->wordStyle ());
}
/*
@@ -2997,8 +3148,11 @@ static void Html_tag_open_meta(DilloHtml *html, const char *tag, int tagsize)
} else {
sprintf(delay_str, ".");
}
- /* Skip to anything after "URL=" */
- while (*content && *(content++) != '=') ;
+ /* Skip to anything after "URL=" or ";" if "URL=" is not found */
+ if ((p = dStriAsciiStr(content, "url=")))
+ content = p + strlen("url=");
+ else if ((p = strstr(content, ";")))
+ content = p + strlen(";");
/* Handle the case of a quoted URL */
if (*content == '"' || *content == '\'') {
if ((p = strchr(content + 1, *content)))
@@ -3280,6 +3434,7 @@ const TagInfo Tags[] = {
NULL},
{"article", B8(011110),'R',2, Html_tag_open_default, NULL, NULL},
{"aside", B8(011110),'R',2, Html_tag_open_default, NULL, NULL},
+ {"audio", B8(011101),'R',2, Html_tag_open_audio, NULL, Html_tag_close_media},
{"b", B8(010101),'R',2, Html_tag_open_default, NULL, NULL},
{"base", B8(100001),'F',0, Html_tag_open_base, NULL, NULL},
/* basefont 010001 -- obsolete in HTML5 */
@@ -3306,6 +3461,7 @@ const TagInfo Tags[] = {
{"dl", B8(011010),'R',2, Html_tag_open_dl, NULL, Html_tag_close_par},
{"dt", B8(010110),'O',1, Html_tag_open_dt, NULL, Html_tag_close_par},
{"em", B8(010101),'R',2, Html_tag_open_default, NULL, NULL},
+ {"embed", B8(010001),'F',0, Html_tag_open_embed, Html_tag_content_embed,NULL},
/* fieldset */
{"figcaption", B8(011110),'R',2, Html_tag_open_default, NULL, NULL},
{"figure", B8(011110),'R',2, Html_tag_open_default, NULL, NULL},
@@ -3349,7 +3505,8 @@ const TagInfo Tags[] = {
{"nav", B8(011110),'R',2, Html_tag_open_default, NULL, NULL},
/* noframes 1011 -- obsolete in HTML5 */
/* noscript 1011 */
- {"object", B8(111101),'R',2, Html_tag_open_object, NULL, NULL},
+ {"object", B8(111101),'R',2, Html_tag_open_object, Html_tag_content_object,
+ NULL},
{"ol", B8(011010),'R',2, Html_tag_open_ol, NULL, NULL},
{"optgroup", B8(010101),'O',1, Html_tag_open_optgroup, NULL,
Html_tag_close_optgroup},
@@ -3364,6 +3521,8 @@ const TagInfo Tags[] = {
{"section", B8(011110),'R',2, Html_tag_open_default, NULL, NULL},
{"select", B8(010101),'R',2, Html_tag_open_select,NULL,Html_tag_close_select},
{"small", B8(010101),'R',2, Html_tag_open_default, NULL, NULL},
+ {"source", B8(010001),'F',0, Html_tag_open_source, Html_tag_content_source,
+ NULL},
{"span", B8(010101),'R',2, Html_tag_open_span, NULL, NULL},
{"strike", B8(010101),'R',2, Html_tag_open_default, NULL, NULL},
{"strong", B8(010101),'R',2, Html_tag_open_default, NULL, NULL},
@@ -3388,6 +3547,7 @@ const TagInfo Tags[] = {
{"u", B8(010101),'R',2, Html_tag_open_default, NULL, NULL},
{"ul", B8(011010),'R',2, Html_tag_open_ul, NULL, NULL},
{"var", B8(010101),'R',2, Html_tag_open_default, NULL, NULL},
+ {"video", B8(011101),'R',2, Html_tag_open_video, NULL, Html_tag_close_media},
{"wbr", B8(010101),'F',0, Html_tag_open_default, Html_tag_content_wbr, NULL}
};
#define NTAGS (sizeof(Tags)/sizeof(Tags[0]))
diff --git a/src/html_common.hh b/src/html_common.hh
index a43d91b7..de3069cb 100644
--- a/src/html_common.hh
+++ b/src/html_common.hh
@@ -87,8 +87,9 @@ typedef enum {
IN_MAP = 1 << 9,
IN_PRE = 1 << 10,
IN_LI = 1 << 11,
- IN_META_HACK = 1 << 12,
- IN_EOF = 1 << 13,
+ IN_MEDIA = 1 << 12,
+ IN_META_HACK = 1 << 13,
+ IN_EOF = 1 << 14,
} DilloHtmlProcessingState;
/*
@@ -233,7 +234,7 @@ public:
{ return styleEngine->wordStyle (bw, base_url); }
inline void restyle () { styleEngine->restyle (bw, base_url); }
-
+
};
/*
@@ -257,7 +258,7 @@ DilloUrl *a_Html_url_new(DilloHtml *html,
const char *url_str, const char *base_url,
int use_base_url);
-void a_Html_image_attrs(DilloHtml *html, const char *tag, int tagsize);
+void a_Html_common_image_attrs(DilloHtml *html, const char *tag, int tagsize);
DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, int tagsize);
char *a_Html_parse_entities(DilloHtml *html, const char *token, int toksize);
diff --git a/src/misc.c b/src/misc.c
index 3e8496e5..00589999 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -115,6 +115,7 @@ static const ContentType_t MimeTypes[] = {
typedef enum {
DT_OCTET_STREAM = 0,
+ DT_PLACEHOLDER,
DT_TEXT_HTML,
DT_TEXT_PLAIN,
DT_IMAGE_GIF,
diff --git a/src/styleengine.cc b/src/styleengine.cc
index 2da9d8f7..ffc0b0f6 100644
--- a/src/styleengine.cc
+++ b/src/styleengine.cc
@@ -65,7 +65,6 @@ StyleEngine::StyleEngine (dw::core::Layout *layout) {
doctree = new Doctree ();
stack = new lout::misc::SimpleVector <Node> (1);
cssContext = new CssContext ();
- buildUserAgentStyle ();
buildUserStyle ();
this->layout = layout;
importDepth = 0;
@@ -548,8 +547,10 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props,
attrs->backgroundImage->connectDeletion
(new StyleImageDeletionReceiver (clientKey));
}
+
+ a_Url_free (imgUrl);
}
- break;
+ break;
case CSS_PROPERTY_BACKGROUND_POSITION:
computeLength (&attrs->backgroundPositionX, p->value.posVal->posX,
attrs->font);
@@ -958,7 +959,7 @@ void StyleEngine::parse (DilloHtml *html, DilloUrl *url, const char *buf,
* The user agent style defines how dillo renders HTML in the absence of
* author or user styles.
*/
-void StyleEngine::buildUserAgentStyle () {
+void StyleEngine::init () {
const char *cssBuf =
"body {margin: 5px}"
"big {font-size: 1.17em}"
@@ -1015,7 +1016,8 @@ void StyleEngine::buildUserAgentStyle () {
*/
"table, caption {font-size: medium; font-weight: normal}";
- CssParser::parse (NULL, NULL, cssContext, cssBuf, strlen (cssBuf),
+ CssContext context;
+ CssParser::parse (NULL, NULL, &context, cssBuf, strlen (cssBuf),
CSS_ORIGIN_USER_AGENT);
}
diff --git a/src/styleengine.hh b/src/styleengine.hh
index 714553ff..bec4875b 100644
--- a/src/styleengine.hh
+++ b/src/styleengine.hh
@@ -38,7 +38,6 @@ class StyleEngine {
void stackPush ();
void stackPop ();
- void buildUserAgentStyle ();
void buildUserStyle ();
dw::core::style::Style *style0 (int i, BrowserWindow *bw, DilloUrl *url);
dw::core::style::Style *wordStyle0 (BrowserWindow *bw, DilloUrl *url);
@@ -64,6 +63,8 @@ class StyleEngine {
dw::core::style::Font *font);
public:
+ static void init ();
+
StyleEngine (dw::core::Layout *layout);
~StyleEngine ();
diff --git a/src/url.c b/src/url.c
index 6780ca8e..9d3e14b2 100644
--- a/src/url.c
+++ b/src/url.c
@@ -688,14 +688,14 @@ static uint_t Url_host_public_internal_dots(const char *host)
if (tld_len > 0) {
/* These TLDs were chosen by examining the current publicsuffix list
- * in September 2013 and picking out those where it was simplest for
+ * in February 2014 and picking out those where it was simplest for
* them to describe the situation by beginning with a "*.[tld]" rule
* or every rule was "[something].[tld]".
*/
- const char *const tlds[] = {"au","bd","bn","ck","cy","er","et","fj",
- "fk","gn","gu","il","jm","ke","kh","kp",
- "kw","lb","lr","mm","mt","mz","ni","np",
- "nz","pg","tr","uk","ye","za","zm","zw"};
+ const char *const tlds[] = {"bd","bn","ck","cy","er","et","fj","fk",
+ "gu","il","jm","ke","kh","kw","mm","mz",
+ "ni","np","nz","pg","tr","uk","ye","za",
+ "zm","zw"};
uint_t i, tld_num = sizeof(tlds) / sizeof(tlds[0]);
for (i = 0; i < tld_num; i++) {
diff --git a/test/dw_image_background.cc b/test/dw_image_background.cc
index 24966850..14cb7b97 100644
--- a/test/dw_image_background.cc
+++ b/test/dw_image_background.cc
@@ -117,7 +117,7 @@ int main(int argc, char **argv)
image1 = StyleImage::create ();
image1->connectDeletion (&isdr);
- layout->setBgImage (image1, BACKGROUND_REPEAT_Y,
+ layout->setBgImage (image1, BACKGROUND_REPEAT_Y,
BACKGROUND_ATTACHMENT_SCROLL, createPerLength (0.5),
createAbsLength (30));