summaryrefslogtreecommitdiff
path: root/dw/image.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dw/image.cc')
-rw-r--r--dw/image.cc171
1 files changed, 119 insertions, 52 deletions
diff --git a/dw/image.cc b/dw/image.cc
index e71c8f2f..fd959695 100644
--- a/dw/image.cc
+++ b/dw/image.cc
@@ -149,11 +149,15 @@ Image::Image(const char *altText)
this->altText = altText ? strdup (altText) : NULL;
altTextWidth = -1; // not yet calculated
buffer = NULL;
+ bufWidth = bufHeight = -1;
clicking = false;
currLink = -1;
mapList = NULL;
mapKey = NULL;
isMap = false;
+
+ DBG_OBJ_SET_NUM ("bufWidth", bufWidth);
+ DBG_OBJ_SET_NUM ("bufHeight", bufHeight);
}
Image::~Image()
@@ -170,25 +174,11 @@ Image::~Image()
void Image::sizeRequestImpl (core::Requisition *requisition)
{
+ DBG_OBJ_ENTER0 ("resize", 0, "sizeRequestImpl");
+
if (buffer) {
- if (getStyle ()->height == core::style::LENGTH_AUTO &&
- core::style::isAbsLength (getStyle ()->width) &&
- buffer->getRootWidth () > 0) {
- // preserve aspect ratio when only width is given
- requisition->width = core::style::absLengthVal (getStyle ()->width);
- requisition->ascent = buffer->getRootHeight () *
- requisition->width / buffer->getRootWidth ();
- } else if (getStyle ()->width == core::style::LENGTH_AUTO &&
- core::style::isAbsLength (getStyle ()->height) &&
- buffer->getRootHeight () > 0) {
- // preserve aspect ratio when only height is given
- requisition->ascent = core::style::absLengthVal (getStyle ()->height);
- requisition->width = buffer->getRootWidth () *
- requisition->ascent / buffer->getRootHeight ();
- } else {
- requisition->width = buffer->getRootWidth ();
- requisition->ascent = buffer->getRootHeight ();
- }
+ requisition->width = buffer->getRootWidth ();
+ requisition->ascent = buffer->getRootHeight ();
requisition->descent = 0;
} else {
if (altText && altText[0]) {
@@ -206,45 +196,116 @@ void Image::sizeRequestImpl (core::Requisition *requisition)
}
}
- requisition->width += getStyle()->boxDiffWidth ();
- requisition->ascent += getStyle()->boxOffsetY ();
- requisition->descent += getStyle()->boxRestHeight ();
+ requisition->width += boxDiffWidth ();
+ requisition->ascent += boxOffsetY ();
+ requisition->descent += boxRestHeight ();
+
+ correctRequisition (requisition, core::splitHeightPreserveDescent);
+
+ if (buffer) {
+ // If one dimension is set, preserve the aspect ratio (without
+ // extraSpace/margin/border/padding). Notice that
+ // requisition->descent could have been changed in
+ // core::splitHeightPreserveDescent, so we do not make any
+ // assumtions here about it (and requisition->ascent).
+
+ // TODO Check again possible overflows. (Aren't buffer
+ // dimensions limited to 2^15?)
+
+ bool widthSpecified = getStyle()->width != core::style::LENGTH_AUTO ||
+ getStyle()->minWidth != core::style::LENGTH_AUTO ||
+ getStyle()->maxWidth != core::style::LENGTH_AUTO;
+ bool heightSpecified = getStyle()->height != core::style::LENGTH_AUTO ||
+ getStyle()->minHeight != core::style::LENGTH_AUTO ||
+ getStyle()->maxHeight != core::style::LENGTH_AUTO;
+
+ if (!widthSpecified && heightSpecified)
+ requisition->width =
+ (requisition->ascent + requisition->descent - boxDiffHeight ())
+ * buffer->getRootWidth () / buffer->getRootHeight ()
+ + boxDiffWidth ();
+ else if (widthSpecified && !heightSpecified) {
+ requisition->ascent = (requisition->width + boxDiffWidth ())
+ * buffer->getRootHeight () / buffer->getRootWidth ()
+ + boxOffsetY ();
+ requisition->descent = boxRestHeight ();
+ }
+ }
+
+ DBG_OBJ_MSGF ("resize", 1, "=> %d * (%d + %d)",
+ requisition->width, requisition->ascent, requisition->descent);
+ DBG_OBJ_LEAVE ();
+}
+
+void Image::getExtremesImpl (core::Extremes *extremes)
+{
+ int contentWidth;
+ if (buffer)
+ contentWidth = buffer->getRootWidth ();
+ else {
+ if (altText && altText[0]) {
+ if (altTextWidth == -1)
+ altTextWidth =
+ layout->textWidth (getStyle()->font, altText, strlen (altText));
+ contentWidth = altTextWidth;
+ } else
+ contentWidth = 0;
+ }
+
+ int width = contentWidth + boxDiffWidth ();
+
+ // With percentage width, the image may be narrower than the buffer.
+ extremes->minWidth =
+ core::style::isPerLength (getStyle()->width) ? boxDiffWidth () : width;
+
+ // (We ignore the same effect for the maximal width.)
+ extremes->maxWidth = width;
+
+ extremes->minWidthIntrinsic = extremes->minWidth;
+ extremes->maxWidthIntrinsic = extremes->maxWidth;
+
+ correctExtremes (extremes, false);
+
+ extremes->adjustmentWidth =
+ misc::min (extremes->minWidthIntrinsic, extremes->minWidth);
}
void Image::sizeAllocateImpl (core::Allocation *allocation)
{
- core::Imgbuf *oldBuffer;
- int dx, dy;
+ DBG_OBJ_ENTER ("resize", 0, "sizeAllocateImpl", "%d, %d; %d * (%d + %d)",
+ allocation->x, allocation->y, allocation->width,
+ allocation->ascent, allocation->descent);
+
- /* if image is moved only */
- if (allocation->width == this->allocation.width &&
- allocation->ascent + allocation->descent == getHeight ())
- return;
-
- dx = getStyle()->boxDiffWidth ();
- dy = getStyle()->boxDiffHeight ();
-#if 0
- MSG("boxDiffHeight = %d + %d, buffer=%p\n",
- getStyle()->boxOffsetY(), getStyle()->boxRestHeight(), buffer);
- MSG("getContentWidth() = allocation.width - style->boxDiffWidth ()"
- " = %d - %d = %d\n",
- this->allocation.width, getStyle()->boxDiffWidth(),
- this->allocation.width - getStyle()->boxDiffWidth());
- MSG("getContentHeight() = getHeight() - style->boxDiffHeight ()"
- " = %d - %d = %d\n", this->getHeight(), getStyle()->boxDiffHeight(),
- this->getHeight() - getStyle()->boxDiffHeight());
-#endif
- if (buffer &&
- (allocation->width - dx > 0 ||
- allocation->ascent + allocation->descent - dy > 0)) {
- // Zero content size : simply wait...
- // Only one dimension: naturally scale
- oldBuffer = buffer;
- buffer = oldBuffer->getScaledBuf (allocation->width - dx,
- allocation->ascent
- + allocation->descent - dy);
+ int newBufWidth = allocation->width - boxDiffWidth ();
+ int newBufHeight =
+ allocation->ascent + allocation->descent - boxDiffHeight ();
+
+ if (buffer && newBufWidth > 0 && newBufHeight > 0 &&
+ // Save some time when size did not change:
+ (newBufWidth != bufWidth || newBufHeight != bufHeight)) {
+ DBG_OBJ_MSG ("resize", 1, "replacing buffer");
+
+ core::Imgbuf *oldBuffer = buffer;
+ buffer = oldBuffer->getScaledBuf (newBufWidth, newBufHeight);
oldBuffer->unref ();
+
+ bufWidth = newBufWidth;
+ bufHeight = newBufHeight;
+
+ DBG_OBJ_ASSOC_CHILD (this->buffer);
+ DBG_OBJ_SET_NUM ("bufWidth", bufWidth);
+ DBG_OBJ_SET_NUM ("bufHeight", bufHeight);
}
+
+ DBG_OBJ_LEAVE ();
+}
+
+void Image::containerSizeChangedForChildren ()
+{
+ DBG_OBJ_ENTER0 ("resize", 0, "containerSizeChangedForChildren");
+ // Nothing to do.
+ DBG_OBJ_LEAVE ();
}
void Image::enterNotifyImpl (core::EventCrossing *event)
@@ -429,15 +490,21 @@ void Image::setBuffer (core::Imgbuf *buffer, bool resize)
getContentWidth () > 0 && getContentHeight () > 0) {
// Don't create a new buffer for the transition from alt text to img,
// and only scale when both dimensions are known.
- this->buffer =
- buffer->getScaledBuf (getContentWidth (), getContentHeight ());
+
+ bufWidth = getContentWidth ();
+ bufHeight = getContentHeight ();
+ this->buffer = buffer->getScaledBuf (bufWidth, bufHeight);
} else {
this->buffer = buffer;
+ bufWidth = buffer->getRootWidth ();
+ bufHeight = buffer->getRootHeight ();
buffer->ref ();
}
queueResize (0, true);
DBG_OBJ_ASSOC_CHILD (this->buffer);
+ DBG_OBJ_SET_NUM ("bufWidth", bufWidth);
+ DBG_OBJ_SET_NUM ("bufHeight", bufHeight);
if (oldBuf)
oldBuf->unref ();