diff options
author | Sebastian Geerken <devnull@localhost> | 2014-03-01 21:26:25 +0100 |
---|---|---|
committer | Sebastian Geerken <devnull@localhost> | 2014-03-01 21:26:25 +0100 |
commit | 975ba73389d2de0cd2bb50183bd988eab6ba0e06 (patch) | |
tree | 67947a7e22dd049685dc034223c212e2ae14c902 | |
parent | 6369c18d186d52f0f3f5082ff6c9fdcf5c9285d1 (diff) | |
parent | 8818cda9ca4e4c19c4c5fcee68460d5ba0cd5ba2 (diff) |
Merge with main repo.
39 files changed, 565 insertions, 282 deletions
@@ -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; @@ -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(); }; @@ -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); } } } @@ -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); @@ -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 (); @@ -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)); |