aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dw/style.cc14
-rw-r--r--dw/style.hh1
-rw-r--r--dw/widget.cc190
-rw-r--r--dw/widget.hh2
-rw-r--r--src/cssparser.cc12
-rw-r--r--src/styleengine.cc12
6 files changed, 157 insertions, 74 deletions
diff --git a/dw/style.cc b/dw/style.cc
index 5edb7047..d548d209 100644
--- a/dw/style.cc
+++ b/dw/style.cc
@@ -73,6 +73,7 @@ void StyleAttrs::initValues ()
backgroundPositionX = createPerLength (0);
backgroundPositionY = createPerLength (0);
width = height = lineHeight = LENGTH_AUTO;
+ minWidth = maxWidth = minHeight = maxHeight = LENGTH_AUTO;
vloat = FLOAT_NONE;
clear = CLEAR_NONE;
position = POSITION_STATIC;
@@ -116,6 +117,7 @@ void StyleAttrs::resetValues ()
backgroundPositionY = createPerLength (0);
width = LENGTH_AUTO;
height = LENGTH_AUTO;
+ minWidth = maxWidth = minHeight = maxHeight = LENGTH_AUTO;
margin.setVal (0);
borderWidth.setVal (0);
@@ -175,6 +177,10 @@ bool StyleAttrs::equals (object::Object *other) {
wordSpacing == otherAttrs->wordSpacing &&
width == otherAttrs->width &&
height == otherAttrs->height &&
+ minWidth == otherAttrs->minWidth &&
+ maxWidth == otherAttrs->maxWidth &&
+ minHeight == otherAttrs->minHeight &&
+ maxHeight == otherAttrs->maxHeight &&
lineHeight == otherAttrs->lineHeight &&
textIndent == otherAttrs->textIndent &&
margin.equals (&otherAttrs->margin) &&
@@ -227,6 +233,10 @@ int StyleAttrs::hashValue () {
wordSpacing +
width +
height +
+ minWidth +
+ maxWidth +
+ minHeight +
+ maxHeight +
lineHeight +
textIndent +
margin.hashValue () +
@@ -351,6 +361,10 @@ void Style::copyAttrs (StyleAttrs *attrs)
height = attrs->height;
lineHeight = attrs->lineHeight;
textIndent = attrs->textIndent;
+ minWidth = attrs->minWidth;
+ maxWidth = attrs->maxWidth;
+ minHeight = attrs->minHeight;
+ maxHeight = attrs->maxHeight;
margin = attrs->margin;
borderWidth = attrs->borderWidth;
padding = attrs->padding;
diff --git a/dw/style.hh b/dw/style.hh
index 578e65c0..eee06f20 100644
--- a/dw/style.hh
+++ b/dw/style.hh
@@ -532,6 +532,7 @@ public:
int hBorderSpacing, vBorderSpacing, wordSpacing;
Length width, height, lineHeight, textIndent;
+ Length minWidth, maxWidth, minHeight, maxHeight;
Box margin, borderWidth, padding;
BorderCollapse borderCollapse;
diff --git a/dw/widget.cc b/dw/widget.cc
index a407eab8..374c1c2a 100644
--- a/dw/widget.cc
+++ b/dw/widget.cc
@@ -671,25 +671,27 @@ void Widget::correctRequisition (Requisition *requisition,
DBG_OBJ_MSG ("resize", 1, "no parent, regarding viewport");
DBG_OBJ_MSG_START ();
- if (style::isAbsLength (getStyle()->width)) {
- DBG_OBJ_MSGF ("resize", 1, "absolute width: %dpx",
- style::absLengthVal (getStyle()->width));
- requisition->width =
- misc::max (style::absLengthVal (getStyle()->width)
- + boxDiffWidth (),
- getMinWidth (NULL, true));
- } else if (style::isPerLength (getStyle()->width)) {
- DBG_OBJ_MSGF ("resize", 1, "percentage width: %g%%",
- 100 * style::perLengthVal_useThisOnlyForDebugging
- (getStyle()->width));
- int viewportWidth =
- layout->viewportWidth - (layout->canvasHeightGreater ?
- layout->vScrollbarThickness : 0);
- requisition->width =
- misc::max (applyPerWidth (viewportWidth, getStyle()->width),
- getMinWidth (NULL, true));
- }
-
+ int limit = getMinWidth (NULL, true);
+ int viewportWidth =
+ layout->viewportWidth - (layout->canvasHeightGreater ?
+ layout->vScrollbarThickness : 0);
+
+ int width = calcWidth (getStyle()->width, viewportWidth, NULL, limit);
+ int minWidth =
+ calcWidth (getStyle()->minWidth, viewportWidth, NULL, limit);
+ int maxWidth =
+ calcWidth (getStyle()->maxWidth, viewportWidth, NULL, limit);
+
+ DBG_OBJ_MSGF ("resize", 1, "width = %d, minWidth = %d, maxWidth = %d",
+ width, minWidth, maxWidth);
+
+ if (width != -1)
+ requisition->width = width;
+ if (minWidth != -1 && requisition->width < minWidth)
+ requisition->width = minWidth;
+ if (maxWidth != -1 && requisition->width < maxWidth)
+ requisition->width = maxWidth;
+
// TODO Perhaps split first, then add box ascent and descent.
if (style::isAbsLength (getStyle()->height)) {
DBG_OBJ_MSGF ("resize", 1, "absolute height: %dpx",
@@ -742,19 +744,26 @@ void Widget::correctExtremes (Extremes *extremes)
DBG_OBJ_MSG ("resize", 1, "no parent, regarding viewport");
DBG_OBJ_MSG_START ();
- if (style::isAbsLength (getStyle()->width))
- extremes->minWidth = extremes->maxWidth =
- misc::max (style::absLengthVal (getStyle()->width)
- + boxDiffWidth (),
- getMinWidth (extremes, false));
- else if (style::isPerLength (getStyle()->width)) {
- int viewportWidth =
- layout->viewportWidth - (layout->canvasHeightGreater ?
- layout->vScrollbarThickness : 0);
- extremes->minWidth = extremes->maxWidth =
- misc::max (applyPerWidth (viewportWidth, getStyle()->width),
- getMinWidth (extremes, false));
- }
+ int limit = getMinWidth (extremes, false);
+ int viewportWidth =
+ layout->viewportWidth - (layout->canvasHeightGreater ?
+ layout->vScrollbarThickness : 0);
+
+ int width = calcWidth (getStyle()->width, viewportWidth, NULL, limit);
+ int minWidth =
+ calcWidth (getStyle()->minWidth, viewportWidth, NULL, limit);
+ int maxWidth =
+ calcWidth (getStyle()->maxWidth, viewportWidth, NULL, limit);
+
+ DBG_OBJ_MSGF ("resize", 1, "width = %d, minWidth = %d, maxWidth = %d",
+ width, minWidth, maxWidth);
+
+ if (width != -1)
+ extremes->minWidth = extremes->maxWidth = width;
+ if (minWidth != -1)
+ extremes->minWidth = minWidth;
+ if (maxWidth != -1)
+ extremes->maxWidth = maxWidth;
DBG_OBJ_MSG_END ();
} else if (parent) {
@@ -774,6 +783,46 @@ void Widget::correctExtremes (Extremes *extremes)
DBG_OBJ_LEAVE ();
}
+int Widget::calcWidth (style::Length cssValue, int refWidth, Widget *refWidget,
+ int minWidth)
+{
+ DBG_OBJ_ENTER ("resize", 0, "calcWidth", "0x%x, %d, %p, %d",
+ cssValue, refWidth, refWidget, minWidth);
+
+ assert (refWidth != -1 || refWidget != NULL);
+
+ int width = 0;
+
+ if (style::isAbsLength (cssValue)) {
+ DBG_OBJ_MSGF ("resize", 1, "absolute width: %dpx",
+ style::absLengthVal (cssValue));
+ width =
+ misc::max (style::absLengthVal (cssValue) + boxDiffWidth (), minWidth);
+ } else if (style::isPerLength (cssValue)) {
+ DBG_OBJ_MSGF ("resize", 1, "percentage width: %g%%",
+ 100 *
+ style::perLengthVal_useThisOnlyForDebugging (cssValue));
+ if (refWidth != -1)
+ width = misc::max (applyPerWidth (refWidth, cssValue), minWidth);
+ else {
+ int availWidth = refWidget->getAvailWidth (false);
+ if (availWidth != -1) {
+ int containerWidth = availWidth - refWidget->boxDiffWidth ();
+ width =
+ misc::max (applyPerWidth (containerWidth, cssValue), minWidth);
+ } else
+ width = -1;
+ }
+ } else {
+ DBG_OBJ_MSG ("resize", 1, "not specified");
+ width = -1;
+ }
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %d", width);
+ DBG_OBJ_LEAVE ();
+ return width;
+}
+
/**
* \brief Wrapper for Widget::getExtremesImpl().
*/
@@ -1011,6 +1060,13 @@ void Widget::setStyle (style::Style *style)
style->display == style::DISPLAY_TABLE_ROW ? "table-row" :
style->display == style::DISPLAY_TABLE_CELL ? "table-cell" :
"???");
+
+ DBG_OBJ_SET_NUM ("style.width (raw)", style->width);
+ DBG_OBJ_SET_NUM ("style.min-width (raw)", style->minWidth);
+ DBG_OBJ_SET_NUM ("style.max-width (raw)", style->maxWidth);
+ DBG_OBJ_SET_NUM ("style.height (raw)", style->height);
+ DBG_OBJ_SET_NUM ("style.min-height (raw)", style->minHeight);
+ DBG_OBJ_SET_NUM ("style.max-height (raw)", style->maxHeight);
}
/**
@@ -1470,21 +1526,22 @@ void Widget::correctReqWidthOfChild (Widget *child, Requisition *requisition)
assert (this == child->quasiParent || this == child->container);
- if (style::isAbsLength (child->getStyle()->width))
- requisition->width =
- misc::max (style::absLengthVal (child->getStyle()->width)
- + child->boxDiffWidth (),
- child->getMinWidth (NULL, true));
- else if (style::isPerLength (child->getStyle()->width)) {
- int availWidth = getAvailWidth (false);
- if (availWidth != -1) {
- int containerWidth = availWidth - boxDiffWidth ();
- requisition->width =
- misc::max (child->applyPerWidth (containerWidth,
- child->getStyle()->width),
- child->getMinWidth (NULL, true));
- }
- }
+ int limit = child->getMinWidth (NULL, true);
+ int width = child->calcWidth (child->getStyle()->width, -1, this, limit);
+ int minWidth =
+ child->calcWidth (child->getStyle()->minWidth, -1, this, limit);
+ int maxWidth =
+ child->calcWidth (child->getStyle()->maxWidth, -1, this, limit);
+
+ DBG_OBJ_MSGF ("resize", 1, "width = %d, minWidth = %d, maxWidth = %d",
+ width, minWidth, maxWidth);
+
+ if (width != -1)
+ requisition->width = width;
+ if (minWidth != -1 && requisition->width < minWidth)
+ requisition->width = minWidth;
+ if (maxWidth != -1 && requisition->width > maxWidth)
+ requisition->width = maxWidth;
DBG_OBJ_MSGF ("resize", 1, "=> %d * (%d + %d)",
requisition->width, requisition->ascent,
@@ -1543,29 +1600,22 @@ void Widget::correctExtremesOfChild (Widget *child, Extremes *extremes)
(child->container ? child->container : child->parent);
if (effContainer == this) {
- if (style::isAbsLength (child->getStyle()->width)) {
- DBG_OBJ_MSGF ("resize", 1, "absolute width: %dpx",
- style::absLengthVal (child->getStyle()->width));
- extremes->minWidth = extremes->maxWidth =
- misc::max (style::absLengthVal (child->getStyle()->width)
- + child->boxDiffWidth (),
- child->getMinWidth (extremes, false));
- } else if (style::isPerLength (child->getStyle()->width)) {
- DBG_OBJ_MSGF ("resize", 1, "percentage width: %g%%",
- 100 * style::perLengthVal_useThisOnlyForDebugging
- (child->getStyle()->width));
- int availWidth = getAvailWidth (false);
- if (availWidth != -1) {
- int containerWidth = availWidth - boxDiffWidth ();
- DBG_OBJ_MSGF ("resize", 1, "containerWidth = %d - %d = %d",
- availWidth, boxDiffWidth (), containerWidth);
- extremes->minWidth = extremes->maxWidth =
- misc::max (child->applyPerWidth (containerWidth,
- child->getStyle()->width),
- child->getMinWidth (extremes, false));
- }
- } else
- DBG_OBJ_MSG ("resize", 1, "no specification");
+ int limit = child->getMinWidth (extremes, false);
+ int width = child->calcWidth (child->getStyle()->width, -1, this, limit);
+ int minWidth =
+ child->calcWidth (child->getStyle()->minWidth, -1, this, limit);
+ int maxWidth =
+ child->calcWidth (child->getStyle()->maxWidth, -1, this, limit);
+
+ DBG_OBJ_MSGF ("resize", 1, "width = %d, minWidth = %d, maxWidth = %d",
+ width, minWidth, maxWidth);
+
+ if (width != -1)
+ extremes->minWidth = extremes->maxWidth = width;
+ if (minWidth != -1)
+ extremes->minWidth = minWidth;
+ if (maxWidth != -1)
+ extremes->maxWidth = maxWidth;
} else {
DBG_OBJ_MSG ("resize", 1, "delegated to (effective) container");
DBG_OBJ_MSG_START ();
diff --git a/dw/widget.hh b/dw/widget.hh
index 2599d14c..88bc2a61 100644
--- a/dw/widget.hh
+++ b/dw/widget.hh
@@ -431,6 +431,8 @@ public:
void correctRequisition (Requisition *requisition,
void (*splitHeightFun) (int, int*, int*));
void correctExtremes (Extremes *extremes);
+ int calcWidth (style::Length cssValue, int refWidth, Widget *refWidget,
+ int minWidth);
virtual int applyPerWidth (int containerWidth, style::Length perWidth);
virtual int applyPerHeight (int containerHeight, style::Length perHeight);
diff --git a/src/cssparser.cc b/src/cssparser.cc
index 794bf6b7..accdf478 100644
--- a/src/cssparser.cc
+++ b/src/cssparser.cc
@@ -239,10 +239,14 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = {
{CSS_TYPE_SIGNED_LENGTH, CSS_TYPE_AUTO, CSS_TYPE_UNUSED}, NULL},
{"marker-offset", {CSS_TYPE_UNUSED}, NULL},
{"marks", {CSS_TYPE_UNUSED}, NULL},
- {"max-height", {CSS_TYPE_UNUSED}, NULL},
- {"max-width", {CSS_TYPE_UNUSED}, NULL},
- {"min-height", {CSS_TYPE_UNUSED}, NULL},
- {"min-width", {CSS_TYPE_UNUSED}, NULL},
+ {"max-height", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_AUTO, CSS_TYPE_UNUSED},
+ NULL},
+ {"max-width", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_AUTO, CSS_TYPE_UNUSED},
+ NULL},
+ {"min-height", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_AUTO, CSS_TYPE_UNUSED},
+ NULL},
+ {"min-width", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_AUTO, CSS_TYPE_UNUSED},
+ NULL},
{"outline-color", {CSS_TYPE_UNUSED}, NULL},
{"outline-style", {CSS_TYPE_UNUSED}, NULL},
{"outline-width", {CSS_TYPE_UNUSED}, NULL},
diff --git a/src/styleengine.cc b/src/styleengine.cc
index 74a6330f..f5f0a315 100644
--- a/src/styleengine.cc
+++ b/src/styleengine.cc
@@ -713,6 +713,18 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props,
else if (attrs->wordSpacing < -1000)
attrs->wordSpacing = -1000;
break;
+ case CSS_PROPERTY_MIN_WIDTH:
+ computeLength (&attrs->minWidth, p->value.intVal, attrs->font);
+ break;
+ case CSS_PROPERTY_MAX_WIDTH:
+ computeLength (&attrs->maxWidth, p->value.intVal, attrs->font);
+ break;
+ case CSS_PROPERTY_MIN_HEIGHT:
+ computeLength (&attrs->minHeight, p->value.intVal, attrs->font);
+ break;
+ case CSS_PROPERTY_MAX_HEIGHT:
+ computeLength (&attrs->maxHeight, p->value.intVal, attrs->font);
+ break;
case PROPERTY_X_LINK:
attrs->x_link = p->value.intVal;
break;