changeset 1762:433a380f83a1

merge
author Jorge Arellano Cid <jcid@dillo.org>
date Mon, 15 Nov 2010 17:08:26 -0300
parents d247a3e0d41a (current diff) f5b91fafcbd4 (diff)
children 96852273c0bc
files dw/style.cc dw/style.hh
diffstat 9 files changed, 458 insertions(+), 79 deletions(-) [+]
line wrap: on
line diff
--- a/dw/fltkviewbase.cc	Tue Nov 09 10:20:43 2010 -0300
+++ b/dw/fltkviewbase.cc	Mon Nov 15 17:08:26 2010 -0300
@@ -369,6 +369,39 @@
              translateCanvasXToViewX (x2), translateCanvasYToViewY (y2));
 }
 
+void FltkViewBase::drawTypedLine (core::style::Color *color,
+                                  core::style::Color::Shading shading,
+                                  core::style::LineType type, int width,
+                                  int x1, int y1, int x2, int y2)
+{
+   char dashes[3], w, ng, d, gap, len;
+   const int f = 2;
+
+   w = (width == 1) ? 0 : width;
+   if (type == core::style::LINE_DOTTED) {
+      /* customized drawing for dotted lines */
+      len = (x2 == x1) ? y2 - y1 + 1 : (y2 == y1) ? x2 - x1 + 1 : 0;
+      ng = len / f*width;
+      d = len % f*width;
+      gap = ng ? d/ng + (w > 3 ? 2 : 0) : 0;
+      dashes[0] = 1; dashes[1] = f*width-gap; dashes[2] = 0;
+      line_style(::fltk::DASH + ::fltk::CAP_ROUND, w, dashes);
+
+      /* These formulas also work, but ain't pretty ;)
+       * line_style(::fltk::DOT + ::fltk::CAP_ROUND, w);
+       * dashes[0] = 1; dashes[1] = 3*width-2; dashes[2] = 0;
+       */
+   } else if (type == core::style::LINE_DASHED) {
+      line_style(::fltk::DASH + ::fltk::CAP_ROUND, w);
+   }
+
+   setcolor(((FltkColor*)color)->colors[shading]);
+   drawLine (color, shading, x1, y1, x2, y2);
+
+   if (type != core::style::LINE_NORMAL)
+      line_style(::fltk::SOLID);
+}
+
 void FltkViewBase::drawRectangle (core::style::Color *color,
                                   core::style::Color::Shading shading,
                                   bool filled,
--- a/dw/fltkviewbase.hh	Tue Nov 09 10:20:43 2010 -0300
+++ b/dw/fltkviewbase.hh	Mon Nov 15 17:08:26 2010 -0300
@@ -72,6 +72,10 @@
    void drawLine (core::style::Color *color,
                   core::style::Color::Shading shading,
                   int x1, int y1, int x2, int y2);
+   void drawTypedLine (core::style::Color *color,
+                       core::style::Color::Shading shading,
+                       core::style::LineType type, int width,
+                       int x1, int y1, int x2, int y2);
    void drawRectangle (core::style::Color *color,
                        core::style::Color::Shading shading, bool filled,
                        int x, int y, int width, int height);
--- a/dw/style.cc	Tue Nov 09 10:20:43 2010 -0300
+++ b/dw/style.cc	Mon Nov 15 17:08:26 2010 -0300
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <ctype.h>
+#include <math.h>
 
 #include "core.hh"
 #include "../lout/msg.h"
@@ -51,7 +52,6 @@
    borderWidth.setVal (0);
    padding.setVal (0);
    borderCollapse = BORDER_MODEL_SEPARATE;
-   collapseStyleSet = false;
    setBorderColor (NULL);
    setBorderStyle (BORDER_NONE);
    hBorderSpacing = 0;
@@ -128,7 +128,6 @@
        borderWidth.equals (&otherAttrs->borderWidth) &&
        padding.equals (&otherAttrs->padding) &&
        borderCollapse == otherAttrs->borderCollapse &&
-       collapseStyleSet == otherAttrs->collapseStyleSet &&
        borderColor.top == otherAttrs->borderColor.top &&
        borderColor.right == otherAttrs->borderColor.right &&
        borderColor.bottom == otherAttrs->borderColor.bottom &&
@@ -166,7 +165,6 @@
       borderWidth.hashValue () +
       padding.hashValue () +
       borderCollapse +
-      collapseStyleSet +
       (intptr_t) borderColor.top +
       (intptr_t) borderColor.right +
       (intptr_t) borderColor.bottom  +
@@ -257,7 +255,6 @@
    borderWidth = attrs->borderWidth;
    padding = attrs->padding;
    borderCollapse = attrs->borderCollapse;
-   collapseStyleSet = attrs->collapseStyleSet;
    borderColor = attrs->borderColor;
    borderStyle = attrs->borderStyle;
    display = attrs->display;
@@ -415,18 +412,373 @@
 
 // ----------------------------------------------------------------------
 
-static void drawTriangle (View *view, Color *color, Color::Shading shading,
-                          int x1, int y1, int x2, int y2, int x3, int y3) {
-   int points[3][2];
+/*
+ * The drawBorder{Top,Bottom,Left,Right} functions are similar. They
+ * use a trapezium as draw polygon, or drawTypedLine() for dots and dashes.
+ * Although the concept is simple, achieving pixel accuracy is laborious [1].
+ *
+ * [1] http://www.dillo.org/css_compat/tests/border-style.html
+ */
+static void drawBorderTop(View *view, Style *style,
+                          int x1, int y1, int x2, int y2)
 
-   points[0][0] = x1;
-   points[0][1] = y1;
-   points[1][0] = x2;
-   points[1][1] = y2;
-   points[2][0] = x3;
-   points[2][1] = y3;
+{
+   int points[4][2], d, w;
+   bool ridge = false, inset = false, dotted = false;
+   Color::Shading shading = Color::SHADING_NORMAL;
 
-   view->drawPolygon (color, shading, true, points, 3);
+   if (!style->borderColor.top)
+      return;
+
+   switch (style->borderStyle.top) {
+   case BORDER_NONE:
+   case BORDER_HIDDEN:
+      break;
+   case BORDER_DOTTED:
+      dotted = true;
+   case BORDER_DASHED:
+      w = style->borderWidth.top;
+      view->drawTypedLine(style->borderColor.top, shading,
+                          dotted ? LINE_DOTTED : LINE_DASHED,
+                          w, x1+w/2, y1+w/2, x2-w/2, y2+w/2);
+      break;
+   case BORDER_SOLID:
+   case BORDER_INSET:
+      inset = true;
+   case BORDER_OUTSET:
+      if (style->borderStyle.top != BORDER_SOLID)
+         shading = (inset) ? Color::SHADING_DARK : Color::SHADING_LIGHT;
+
+      if (style->borderWidth.top == 1) {
+         view->drawLine(style->borderColor.top, shading, x1, y1, x2, y2);
+      } else {
+         points[0][0] = x1;
+         points[1][0] = x2 + 1;
+         points[0][1] = points[1][1] = y1;
+         points[2][0] = points[1][0] - style->borderWidth.right;
+         points[3][0] = x1 + style->borderWidth.left;
+         points[2][1] = points[3][1] = points[0][1] + style->borderWidth.top;
+         view->drawPolygon (style->borderColor.top, shading, true, points, 4);
+      }
+      break;
+   case BORDER_RIDGE:
+      ridge = true;
+   case BORDER_GROOVE:
+      d = style->borderWidth.top & 1;
+      points[0][0] = x1;
+      points[1][0] = x2 + 1;
+      points[0][1] = points[1][1] = y1;
+      points[2][0] = x2 - style->borderWidth.right / 2;
+      points[3][0] = x1 + style->borderWidth.left / 2;
+      points[2][1] = points[3][1] = y1 + style->borderWidth.top / 2 + d;
+      shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK;
+      view->drawPolygon (style->borderColor.top, shading, true, points, 4);
+      points[0][0] = x1 + style->borderWidth.left / 2 + d;
+      points[1][0] = x2 - style->borderWidth.right / 2 + 1 - d;
+      points[0][1] = points[1][1] = y1 + style->borderWidth.top / 2 + d;
+      points[2][0] = x2 - style->borderWidth.right + 1 - d;
+      points[3][0] = x1 + style->borderWidth.left;
+      points[2][1] = points[3][1] = y1 + style->borderWidth.top;
+      shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT;
+      view->drawPolygon (style->borderColor.top, shading, true, points, 4);
+      break;
+   case BORDER_DOUBLE:
+      w = (int) rint(style->borderWidth.top / 3.0);
+      d = w ? style->borderWidth.top - 2 * w : 0;
+      int w_l = (int) rint(style->borderWidth.left / 3.0);
+      int w_r = (int) rint(style->borderWidth.right / 3.0);
+      if (style->borderWidth.top == 1) {
+         view->drawLine(style->borderColor.top, shading, x1, y1, x2, y2);
+         break;
+      }
+      points[0][0] = x1;
+      points[1][0] = x2 + 1;
+      points[0][1] = points[1][1] = y1;
+      points[2][0] = points[1][0] - w_r;
+      points[3][0] = points[0][0] + w_l;
+      points[2][1] = points[3][1] = points[0][1] + w;
+      view->drawPolygon (style->borderColor.top, shading, true, points, 4);
+      points[0][0] = x1 + style->borderWidth.left - w_l;
+      points[1][0] = x2 + 1 - style->borderWidth.right + w_r;
+      points[0][1] = points[1][1] = y1 + w + d;
+      points[2][0] = x2 + 1 - style->borderWidth.right;
+      points[3][0] = x1 + style->borderWidth.left;
+      points[2][1] = points[3][1] = y1 + style->borderWidth.top;
+      view->drawPolygon (style->borderColor.top, shading, true, points, 4);
+      break;
+   }
+}
+
+static void drawBorderBottom(View *view, Style *style,
+                             int x1, int y1, int x2, int y2)
+
+{
+   int points[4][2], d, w;
+   bool ridge = false, inset = false, dotted = false;
+   Color::Shading shading = Color::SHADING_NORMAL;
+
+   if (!style->borderColor.bottom)
+      return;
+
+   switch (style->borderStyle.bottom) {
+   case BORDER_NONE:
+   case BORDER_HIDDEN:
+      break;
+   case BORDER_DOTTED:
+      dotted = true;
+   case BORDER_DASHED:
+      w = style->borderWidth.bottom;
+      view->drawTypedLine(style->borderColor.top, shading,
+                          dotted ? LINE_DOTTED : LINE_DASHED,
+                          w, x1+w/2, y1-w/2, x2-w/2, y2-w/2);
+      break;
+   case BORDER_SOLID:
+   case BORDER_INSET:
+      inset = true;
+   case BORDER_OUTSET:
+      if (style->borderStyle.bottom != BORDER_SOLID)
+         shading = (inset) ? Color::SHADING_LIGHT : Color::SHADING_DARK;
+
+      if (style->borderWidth.bottom == 1) { /* 1 pixel line */
+         view->drawLine(style->borderColor.bottom, shading, x1, y1, x2, y2);
+      } else {
+         points[0][0] = x1 - 1;
+         points[1][0] = x2 + 2;
+         points[0][1] = points[1][1] = y1 + 1;
+         points[2][0] = points[1][0] - style->borderWidth.right;
+         points[3][0] = points[0][0] + style->borderWidth.left;
+         points[2][1] = points[3][1] = points[0][1]-style->borderWidth.bottom;
+         view->drawPolygon (style->borderColor.top, shading, true, points, 4);
+      }
+      break;
+   case BORDER_RIDGE:
+      ridge = true;
+   case BORDER_GROOVE:
+      w = style->borderWidth.bottom;
+      d = w & 1;
+      points[0][0] = x1 - 1;
+      points[1][0] = x2 + 2 - d;
+      points[0][1] = points[1][1] = y1 + 1;
+      points[2][0] = points[1][0] - style->borderWidth.right / 2;
+      points[3][0] = points[0][0] + style->borderWidth.left / 2 + d;
+      points[2][1] = points[3][1] = points[0][1] - w/2 - d;
+      shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT;
+      view->drawPolygon (style->borderColor.bottom, shading, true, points, 4);
+      // clockwise
+      points[0][0] = x1 + style->borderWidth.left - 1;
+      points[1][0] = x2 + 1 - style->borderWidth.right + 1;
+      points[0][1] = points[1][1] = y1 - w + 1;
+      points[2][0] = points[1][0] + style->borderWidth.right / 2;
+      points[3][0] = points[0][0] - style->borderWidth.left / 2;
+      points[2][1] = points[3][1] = points[0][1] + w/2;
+      shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK;
+      view->drawPolygon (style->borderColor.top, shading, true, points, 4);
+      break;
+   case BORDER_DOUBLE:
+      w = (int) rint(style->borderWidth.bottom / 3.0);
+      d = w ? style->borderWidth.bottom - 2 * w : 0;
+      int w_l = (int) rint(style->borderWidth.left / 3.0);
+      int w_r = (int) rint(style->borderWidth.right / 3.0);
+      if (style->borderWidth.bottom == 1) {
+         view->drawLine(style->borderColor.bottom, shading, x1, y1, x2, y2);
+         break;
+      }
+      points[0][0] = x2 + 2;
+      points[1][0] = x1 - 1;
+      points[0][1] = points[1][1] = y1 + 1;
+      points[2][0] = points[1][0] + w_l;
+      points[3][0] = points[0][0] - w_r;
+      points[2][1] = points[3][1] = points[0][1] - w;
+      view->drawPolygon (style->borderColor.top, shading, true, points, 4);
+      points[0][0] = x2 + 2 - style->borderWidth.right + w_r;
+      points[1][0] = x1 - 1 + style->borderWidth.left - w_l;
+      points[0][1] = points[1][1] = y1 + 1 - w - d;
+      points[2][0] = x1 - 1 + style->borderWidth.left;
+      points[3][0] = x2 + 2 - style->borderWidth.right;
+      points[2][1] = points[3][1] = y1 + 1 - style->borderWidth.bottom;
+      view->drawPolygon (style->borderColor.top, shading, true, points, 4);
+      break;
+   }
+}
+
+static void drawBorderLeft(View *view, Style *style,
+                           int x1, int y1, int x2, int y2)
+
+{
+   int points[4][2], d, w;
+   bool ridge = false, inset = false, dotted = false;
+   Color::Shading shading = Color::SHADING_NORMAL;
+
+   if (!style->borderColor.left)
+      return;
+
+   switch (style->borderStyle.left) {
+   case BORDER_NONE:
+   case BORDER_HIDDEN:
+      break;
+   case BORDER_DOTTED:
+      dotted = true;
+   case BORDER_DASHED:
+      w = style->borderWidth.left;
+      view->drawTypedLine(style->borderColor.left, shading,
+                          dotted ? LINE_DOTTED : LINE_DASHED,
+                          w, x1+w/2, y1+w/2, x1+w/2, y2-w/2);
+      break;
+   case BORDER_SOLID:
+   case BORDER_INSET:
+      inset = true;
+   case BORDER_OUTSET:
+      if (style->borderStyle.left != BORDER_SOLID)
+         shading = (inset) ? Color::SHADING_DARK : Color::SHADING_LIGHT;
+      if (style->borderWidth.left == 1) { /* 1 pixel line */
+         view->drawLine(style->borderColor.left, shading, x1, y1, x2, y2);
+      } else {
+         points[0][0] = points[1][0] = x1;
+         points[0][1] = y1 - 1;
+         points[1][1] = y2 + 1;
+         points[2][0] = points[3][0] = points[0][0] + style->borderWidth.left;
+         points[2][1] = points[1][1] - style->borderWidth.bottom;
+         points[3][1] = points[0][1] + style->borderWidth.top;
+         view->drawPolygon (style->borderColor.left, shading, true, points, 4);
+      }
+      break;
+   case BORDER_RIDGE:
+      ridge = true;
+   case BORDER_GROOVE:
+      w = style->borderWidth.left;
+      d = w & 1;
+      points[0][0] = points[1][0] = x1;
+      points[0][1] = y1;
+      points[1][1] = y2;
+      points[2][0] = points[3][0] = x1 + w / 2 + d;
+      points[2][1] = y2 - style->borderWidth.bottom / 2;
+      points[3][1] = y1 + style->borderWidth.top / 2;
+      shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK;
+      view->drawPolygon (style->borderColor.top, shading, true, points, 4);
+      points[0][0] = points[1][0] = x1 + w / 2 + d;
+      points[0][1] = y1 + style->borderWidth.top / 2;
+      points[1][1] = y2 - style->borderWidth.bottom / 2;
+      points[2][0] = points[3][0] = x1 + w;
+      points[2][1] = y2 - style->borderWidth.bottom;
+      points[3][1] = y1 + style->borderWidth.top;
+      shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT;
+      view->drawPolygon (style->borderColor.top, shading, true, points, 4);
+      break;
+   case BORDER_DOUBLE:
+      w = (int) rint(style->borderWidth.left / 3.0);
+      d = w ? style->borderWidth.left - 2 * w : 0;
+      int w_b = (int) rint(style->borderWidth.bottom / 3.0);
+      int w_t = (int) rint(style->borderWidth.top / 3.0);
+      if (style->borderWidth.left == 1) {
+         view->drawLine(style->borderColor.left, shading, x1, y1, x2, y2-1);
+         break;
+      }
+      points[0][0] = points[1][0] = x1;
+      points[0][1] = y1 - 1;
+      points[1][1] = y2 + 1;
+      points[2][0] = points[3][0] = points[0][0] + w;
+      points[2][1] = points[1][1] - w_b;
+      points[3][1] = points[0][1] + w_t;
+      view->drawPolygon (style->borderColor.left, shading, true, points, 4);
+      points[0][0] = points[1][0] = x1 + w + d;
+      points[0][1] = y1 - 1 + style->borderWidth.top - w_t;
+      points[1][1] = y2 + 1 - style->borderWidth.bottom + w_b;
+      points[2][0] = points[3][0] = points[0][0] + w;
+      points[2][1] = y2 + 1 - style->borderWidth.bottom;
+      points[3][1] = y1 - 1 + style->borderWidth.top;
+      view->drawPolygon (style->borderColor.left, shading, true, points, 4);
+      break;
+   }
+}
+
+static void drawBorderRight(View *view, Style *style,
+                            int x1, int y1, int x2, int y2)
+
+{
+   int points[4][2], d, w;
+   bool ridge = false, inset = false, dotted = false;
+   Color::Shading shading = Color::SHADING_NORMAL;
+
+   if (!style->borderColor.right)
+      return;
+
+   switch (style->borderStyle.right) {
+   case BORDER_NONE:
+   case BORDER_HIDDEN:
+      break;
+   case BORDER_DOTTED:
+      dotted = true;
+   case BORDER_DASHED:
+      w = style->borderWidth.right;
+      view->drawTypedLine(style->borderColor.right, shading,
+                          dotted ? LINE_DOTTED : LINE_DASHED,
+                          w, x1 - w/2, y1 + w/2, x1 - w/2, y2 - w/2);
+      break;
+   case BORDER_SOLID:
+   case BORDER_INSET:
+      inset = true;
+   case BORDER_OUTSET:
+      if (style->borderStyle.right != BORDER_SOLID)
+         shading = (inset) ? Color::SHADING_LIGHT : Color::SHADING_DARK;
+      if (style->borderWidth.right == 1) { /* 1 pixel line */
+         view->drawLine(style->borderColor.right, shading, x1, y1, x2, y2);
+      } else {
+         points[0][0] = points[1][0] = x1 + 1;
+         points[0][1] = y1 - 1;
+         points[1][1] = y2 + 1;
+         points[2][0] = points[3][0] = points[0][0]-style->borderWidth.right;
+         points[2][1] = points[1][1] - style->borderWidth.bottom;
+         points[3][1] = points[0][1] + style->borderWidth.top;
+         view->drawPolygon (style->borderColor.right, shading, true,points,4);
+      }
+      break;
+   case BORDER_RIDGE:
+      ridge = true;
+   case BORDER_GROOVE:
+      w = style->borderWidth.right;
+      d = w & 1;
+      points[0][0] = points[1][0] = x1 + 1;
+      points[0][1] = y1;
+      points[1][1] = y2;
+      points[2][0] = points[3][0] = points[0][0] - w / 2 - d;
+      points[2][1] = y2 - style->borderWidth.bottom / 2;
+      points[3][1] = points[0][1] + style->borderWidth.top / 2;
+      shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT;
+      view->drawPolygon (style->borderColor.right, shading, true, points, 4);
+      points[0][0] = points[1][0] = x1 + 1 - w / 2 - d;
+      points[0][1] = y1 + style->borderWidth.top / 2;
+      points[1][1] = y2 - style->borderWidth.bottom / 2;
+      points[2][0] = points[3][0] = x1 + 1 - w;
+      points[2][1] = y2 - style->borderWidth.bottom;
+      points[3][1] = y1 + style->borderWidth.top;
+      shading = (ridge) ? Color::SHADING_LIGHT: Color::SHADING_DARK;
+      view->drawPolygon (style->borderColor.right, shading, true, points, 4);
+      break;
+   case BORDER_DOUBLE:
+      w = (int) rint(style->borderWidth.right / 3.0);
+      d = w ? style->borderWidth.right - 2 * w : 0;
+      int w_b = (int) rint(style->borderWidth.bottom / 3.0);
+      int w_t = (int) rint(style->borderWidth.top / 3.0);
+      if (style->borderWidth.right == 1) {
+         view->drawLine(style->borderColor.right, shading, x1, y1, x2, y2);
+         break;
+      }
+      points[0][0] = points[1][0] = x1 + 1;
+      points[0][1] = y1 - 1;
+      points[1][1] = y2 + 1;
+      points[2][0] = points[3][0] = points[0][0] - w;
+      points[2][1] = points[1][1] - w_b;
+      points[3][1] = points[0][1] + w_t;
+      view->drawPolygon (style->borderColor.right, shading, true, points, 4);
+      points[0][0] = points[1][0] = x1 + 1 - w - d;
+      points[0][1] = y1 - 1 + style->borderWidth.top - w_t;
+      points[1][1] = y2 + 1 - style->borderWidth.bottom + w_b;
+      points[2][0] = points[3][0] = points[0][0] - w;
+      points[2][1] = y2 + 1 - style->borderWidth.bottom;
+      points[3][1] = y1 - 1 + style->borderWidth.top;
+      view->drawPolygon (style->borderColor.right, shading, true, points, 4);
+      break;
+   }
 }
 
 /**
@@ -440,14 +792,13 @@
 {
    /** \todo a lot! */
    Color::Shading dark, light, normal;
-   Color::Shading top, right, bottom, left;
    int xb1, yb1, xb2, yb2, xp1, yp1, xp2, yp2;
 
    // top left and bottom right point of outer border boundary
    xb1 = x + style->margin.left;
    yb1 = y + style->margin.top;
-   xb2 = x + width - style->margin.right;
-   yb2 = y + height - style->margin.bottom;
+   xb2 = x + (width > 0 ? width - 1 : 0) - style->margin.right;
+   yb2 = y + (height > 0 ? height - 1 : 0) - style->margin.bottom;
 
    // top left and bottom right point of inner border boundary
    xp1 = xb1 + style->borderWidth.left;
@@ -459,63 +810,10 @@
    dark = inverse ? Color::SHADING_LIGHT : Color::SHADING_DARK;
    normal = inverse ? Color::SHADING_INVERSE : Color::SHADING_NORMAL;
 
-   switch (style->borderStyle.top) {
-   case BORDER_INSET:
-      top = left = dark;
-      right = bottom = light;
-      break;
-
-   case BORDER_OUTSET:
-      top = left = light;
-      right = bottom = dark;
-      break;
-
-   default:
-      top = right = bottom = left = normal;
-      break;
-   }
-
-   if (style->borderStyle.top != BORDER_NONE && style->borderColor.top)
-      view->drawRectangle(style->borderColor.top, top, true,
-                          xb1, yb1, xb2 - xb1, style->borderWidth.top);
-
-   if (style->borderStyle.bottom != BORDER_NONE && style->borderColor.bottom)
-      view->drawRectangle(style->borderColor.bottom, bottom, true,
-                          xb1, yb2, xb2 - xb1, - style->borderWidth.bottom);
-
-   if (style->borderStyle.left != BORDER_NONE && style->borderColor.left)
-      view->drawRectangle(style->borderColor.left, left, true,
-                          xb1, yp1, style->borderWidth.left, yp2 - yp1);
-
-   if (style->borderWidth.left > 1) {
-      if (style->borderWidth.top > 1 &&
-          (style->borderColor.left != style->borderColor.top ||
-           left != top))
-         drawTriangle (view, style->borderColor.left, left,
-                       xb1, yp1, xp1, yp1, xb1, yb1);
-      if (style->borderWidth.bottom > 1 &&
-          (style->borderColor.left != style->borderColor.bottom ||
-           left != bottom))
-         drawTriangle (view, style->borderColor.left, left,
-                       xb1, yp2, xp1, yp2, xb1, yb2);
-   }
-
-   if (style->borderStyle.right != BORDER_NONE && style->borderColor.right)
-      view->drawRectangle(style->borderColor.right, right, true,
-                          xb2, yp1, - style->borderWidth.right, yp2 - yp1);
-
-   if (style->borderWidth.right > 1) {
-      if (style->borderWidth.top > 1 &&
-          (style->borderColor.right != style->borderColor.top ||
-           right != top))
-         drawTriangle (view, style->borderColor.right, right,
-                       xb2, yp1, xp2, yp1, xb2, yb1);
-      if (style->borderWidth.bottom > 1 &&
-          (style->borderColor.right != style->borderColor.bottom ||
-           right != bottom))
-         drawTriangle (view, style->borderColor.right, right,
-                       xb2, yp2, xp2, yp2, xb2, yb2);
-   }
+   drawBorderRight(view, style, xb2, yb1, xb2, yb2);
+   drawBorderLeft(view, style, xb1, yb1, xb1, yb2);
+   drawBorderTop(view, style, xb1, yb1, xb2, yb1);
+   drawBorderBottom(view, style, xb1, yb2, xb2, yb2);
 }
 
 
--- a/dw/style.hh	Tue Nov 09 10:20:43 2010 -0300
+++ b/dw/style.hh	Mon Nov 15 17:08:26 2010 -0300
@@ -263,6 +263,12 @@
    DISPLAY_TABLE_CELL
 };
 
+enum LineType {
+   LINE_NORMAL,
+   LINE_DOTTED,
+   LINE_DASHED
+};
+
 enum ListStylePosition {
    LIST_STYLE_POSITION_INSIDE,
    LIST_STYLE_POSITION_OUTSIDE
@@ -441,7 +447,6 @@
 
    Box margin, borderWidth, padding;
    BorderCollapse borderCollapse;
-   bool collapseStyleSet;
    struct { Color *top, *right, *bottom, *left; } borderColor;
    struct { BorderStyle top, right, bottom, left; } borderStyle;
 
--- a/dw/view.hh	Tue Nov 09 10:20:43 2010 -0300
+++ b/dw/view.hh	Mon Nov 15 17:08:26 2010 -0300
@@ -166,6 +166,10 @@
    virtual void drawLine      (style::Color *color,
                                style::Color::Shading shading,
                                int x1, int y1, int x2, int y2) = 0;
+   virtual void drawTypedLine (style::Color *color,
+                               style::Color::Shading shading,
+                               style::LineType type, int width,
+                               int x1, int y1, int x2, int y2) = 0;
    virtual void drawRectangle (style::Color *color,
                                style::Color::Shading shading, bool filled,
                                int x, int y, int width, int height) = 0;
--- a/src/css.cc	Tue Nov 09 10:20:43 2010 -0300
+++ b/src/css.cc	Mon Nov 15 17:08:26 2010 -0300
@@ -609,7 +609,7 @@
      "sub {vertical-align: sub}"
      "sup {vertical-align: super}"
      "s, strike, del {text-decoration: line-through}"
-     "table {border-spacing: 1px}"
+     "table {border-spacing: 2px}"
      "td, th {padding: 2px}"
      "thead, tbody, tfoot {vertical-align: middle}"
      "th {font-weight: bolder; text-align: center}"
--- a/src/html.cc	Tue Nov 09 10:20:43 2010 -0300
+++ b/src/html.cc	Mon Nov 15 17:08:26 2010 -0300
@@ -428,6 +428,7 @@
    stack->increase();
    stack->getRef(0)->parse_mode = DILLO_HTML_PARSE_MODE_INIT;
    stack->getRef(0)->table_mode = DILLO_HTML_TABLE_MODE_NONE;
+   stack->getRef(0)->table_border_mode = DILLO_HTML_TABLE_BORDER_SEPARATE;
    stack->getRef(0)->cell_text_align_set = false;
    stack->getRef(0)->list_type = HTML_LIST_NONE;
    stack->getRef(0)->list_number = 0;
--- a/src/html_common.hh	Tue Nov 09 10:20:43 2010 -0300
+++ b/src/html_common.hh	Mon Nov 15 17:08:26 2010 -0300
@@ -64,6 +64,11 @@
 } DilloHtmlTableMode;
 
 typedef enum {
+   DILLO_HTML_TABLE_BORDER_SEPARATE,
+   DILLO_HTML_TABLE_BORDER_COLLAPSE
+} DilloHtmlTableBorderMode;
+
+typedef enum {
    HTML_LIST_NONE,
    HTML_LIST_UNORDERED,
    HTML_LIST_ORDERED
@@ -96,6 +101,7 @@
 struct _DilloHtmlState {
    DilloHtmlParseMode parse_mode;
    DilloHtmlTableMode table_mode;
+   DilloHtmlTableBorderMode table_border_mode;
    bool cell_text_align_set;
 
    DilloHtmlListMode list_type;
--- a/src/table.cc	Tue Nov 09 10:20:43 2010 -0300
+++ b/src/table.cc	Mon Nov 15 17:08:26 2010 -0300
@@ -139,6 +139,7 @@
    HT2TB(html)->addWidget (table, html->styleEngine->style ());
 
    S_TOP(html)->table_mode = DILLO_HTML_TABLE_MODE_TOP;
+   S_TOP(html)->table_border_mode = DILLO_HTML_TABLE_BORDER_SEPARATE;
    S_TOP(html)->cell_text_align_set = FALSE;
    S_TOP(html)->table = table;
 }
@@ -216,6 +217,34 @@
  * Utilities
  */
 
+/*
+ * The table border model is stored in the table's stack item
+ */ 
+static int Html_table_get_border_model(DilloHtml *html)
+{
+   static int i_TABLE = -1;
+   if (i_TABLE == -1)
+      i_TABLE = a_Html_tag_index("table");
+
+   int s_idx = html->stack->size();
+   while (--s_idx > 0 && html->stack->getRef(s_idx)->tag_idx != i_TABLE)
+      ;
+   return html->stack->getRef(s_idx)->table_border_mode;
+}
+
+/*
+ * Set current table's border model
+ */
+static void Html_table_set_border_model(DilloHtml *html,
+                                        DilloHtmlTableBorderMode mode)
+{
+   int s_idx = html->stack->size(), i_TABLE = a_Html_tag_index("table");
+
+   while (--s_idx > 0 && html->stack->getRef(s_idx)->tag_idx != i_TABLE) ;
+   if (s_idx > 0)
+      html->stack->getRef(s_idx)->table_border_mode = mode;
+}
+
 /* WORKAROUND: collapsing border model requires moving rendering code from
  *             the cell to the table, and making table-code aware of each
  *             cell style.
@@ -243,11 +272,10 @@
    collapseStyle = Style::create(HT2LT(html), &collapseCellAttrs);
    col_tb->setStyle (collapseStyle);
 
-   if (!tableStyle->collapseStyleSet) {
+   if (Html_table_get_border_model(html) != DILLO_HTML_TABLE_BORDER_COLLAPSE) {
+      Html_table_set_border_model(html, DILLO_HTML_TABLE_BORDER_COLLAPSE);
       collapseTableAttrs = *tableStyle;
-      collapseTableAttrs.collapseStyleSet = true;
       collapseTableAttrs.margin.setVal (marginWidth);
-      _MSG("COLLAPSING table margin set to %d\n", marginWidth);
       collapseTableAttrs.borderWidth.left = borderWidth;
       collapseTableAttrs.borderWidth.top = borderWidth;
       collapseTableAttrs.borderWidth.right = 0;