dillo  3.0.5
About: dillo is a small, fast, extensible Web browser particularly suitable for older or smaller computers and embedded systems (but only limited or no support for frames, CSS, JavaScript, Java).
  Fossies Dox: dillo-3.0.5.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

style.cc
Go to the documentation of this file.
1 /*
2  * Dillo Widget
3  *
4  * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 
21 
22 #include <stdio.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <ctype.h>
26 #include <math.h>
27 
28 #include "core.hh"
29 #include "../lout/msg.h"
30 
31 using namespace lout;
32 
33 namespace dw {
34 namespace core {
35 namespace style {
36 
37 const bool drawBackgroundLineByLine = false;
38 
39 const int MIN_BG_IMG_W = 10;
40 const int MIN_BG_IMG_H = 10;
41 const int OPT_BG_IMG_W = 50;
42 const int OPT_BG_IMG_H = 50;
43 
44 static void calcBackgroundRelatedValues (StyleImage *backgroundImage,
45  BackgroundRepeat backgroundRepeat,
47  backgroundAttachment,
48  Length backgroundPositionX,
49  Length backgroundPositionY,
50  int xDraw, int yDraw, int widthDraw,
51  int heightDraw, int xRef, int yRef,
52  int widthRef, int heightRef,
53  bool *repeatX, bool *repeatY,
54  int *origX, int *origY,
55  int *tileX1, int *tileX2, int *tileY1,
56  int *tileY2, bool *doDraw);
57 
58 void StyleAttrs::initValues ()
59 {
60  x_link = -1;
61  x_lang[0] = x_lang[1] = 0;
62  x_img = -1;
63  x_tooltip = NULL;
64  textDecoration = TEXT_DECORATION_NONE;
65  textAlign = TEXT_ALIGN_LEFT;
66  textAlignChar = '.';
67  textTransform = TEXT_TRANSFORM_NONE;
68  listStylePosition = LIST_STYLE_POSITION_OUTSIDE;
69  listStyleType = LIST_STYLE_TYPE_DISC;
70  valign = VALIGN_BASELINE;
71  backgroundColor = NULL;
72  backgroundImage = NULL;
73  backgroundRepeat = BACKGROUND_REPEAT;
74  backgroundAttachment = BACKGROUND_ATTACHMENT_SCROLL;
75  backgroundPositionX = createPerLength (0);
76  backgroundPositionY = createPerLength (0);
77  width = height = lineHeight = LENGTH_AUTO;
78  textIndent = 0;
79  margin.setVal (0);
80  borderWidth.setVal (0);
81  padding.setVal (0);
82  borderCollapse = BORDER_MODEL_SEPARATE;
83  setBorderColor (NULL);
84  setBorderStyle (BORDER_NONE);
85  hBorderSpacing = 0;
86  vBorderSpacing = 0;
87  wordSpacing = 0;
88 
89  display = DISPLAY_INLINE;
90  whiteSpace = WHITE_SPACE_NORMAL;
91  cursor = CURSOR_DEFAULT;
92 }
93 
98 void StyleAttrs::resetValues ()
99 {
100  x_img = -1;
101 
102  valign = VALIGN_BASELINE;
103  textAlignChar = '.';
104  backgroundColor = NULL;
105  backgroundImage = NULL;
106  backgroundRepeat = BACKGROUND_REPEAT;
107  backgroundAttachment = BACKGROUND_ATTACHMENT_SCROLL;
108  backgroundPositionX = createPerLength (0);
109  backgroundPositionY = createPerLength (0);
110  width = LENGTH_AUTO;
111  height = LENGTH_AUTO;
112 
113  margin.setVal (0);
114  borderWidth.setVal (0);
115  padding.setVal (0);
116  setBorderColor (NULL);
117  setBorderStyle (BORDER_NONE);
118  hBorderSpacing = 0;
119  vBorderSpacing = 0;
120 
121  display = DISPLAY_INLINE;
122 }
123 
137 bool StyleAttrs::sizeDiffs (StyleAttrs *otherStyle)
138 {
139  return false;
140 }
141 
142 bool StyleAttrs::equals (object::Object *other) {
143  StyleAttrs *otherAttrs = (StyleAttrs *) other;
144 
145  return this == otherAttrs ||
146  (font == otherAttrs->font &&
147  textDecoration == otherAttrs->textDecoration &&
148  color == otherAttrs->color &&
149  backgroundColor == otherAttrs->backgroundColor &&
150  backgroundImage == otherAttrs->backgroundImage &&
151  backgroundRepeat == otherAttrs->backgroundRepeat &&
152  backgroundAttachment == otherAttrs->backgroundAttachment &&
153  backgroundPositionX == otherAttrs->backgroundPositionX &&
154  backgroundPositionY == otherAttrs->backgroundPositionY &&
155  textAlign == otherAttrs->textAlign &&
156  valign == otherAttrs->valign &&
157  textAlignChar == otherAttrs->textAlignChar &&
158  textTransform == otherAttrs->textTransform &&
159  hBorderSpacing == otherAttrs->hBorderSpacing &&
160  vBorderSpacing == otherAttrs->vBorderSpacing &&
161  wordSpacing == otherAttrs->wordSpacing &&
162  width == otherAttrs->width &&
163  height == otherAttrs->height &&
164  lineHeight == otherAttrs->lineHeight &&
165  textIndent == otherAttrs->textIndent &&
166  margin.equals (&otherAttrs->margin) &&
167  borderWidth.equals (&otherAttrs->borderWidth) &&
168  padding.equals (&otherAttrs->padding) &&
169  borderCollapse == otherAttrs->borderCollapse &&
170  borderColor.top == otherAttrs->borderColor.top &&
171  borderColor.right == otherAttrs->borderColor.right &&
172  borderColor.bottom == otherAttrs->borderColor.bottom &&
173  borderColor.left == otherAttrs->borderColor.left &&
174  borderStyle.top == otherAttrs->borderStyle.top &&
175  borderStyle.right == otherAttrs->borderStyle.right &&
176  borderStyle.bottom == otherAttrs->borderStyle.bottom &&
177  borderStyle.left == otherAttrs->borderStyle.left &&
178  display == otherAttrs->display &&
179  whiteSpace == otherAttrs->whiteSpace &&
180  listStylePosition == otherAttrs->listStylePosition &&
181  listStyleType == otherAttrs->listStyleType &&
182  cursor == otherAttrs->cursor &&
183  x_link == otherAttrs->x_link &&
184  x_lang[0] == otherAttrs->x_lang[0] &&
185  x_lang[1] == otherAttrs->x_lang[1] &&
186  x_img == otherAttrs->x_img &&
187  x_tooltip == otherAttrs->x_tooltip);
188 }
189 
190 int StyleAttrs::hashValue () {
191  return (intptr_t) font +
192  textDecoration +
193  (intptr_t) color +
194  (intptr_t) backgroundColor +
195  (intptr_t) backgroundImage +
196  backgroundRepeat +
197  backgroundAttachment +
198  backgroundPositionX +
199  backgroundPositionY +
200  textAlign +
201  valign +
202  textAlignChar +
203  textTransform +
204  hBorderSpacing +
205  vBorderSpacing +
206  wordSpacing +
207  width +
208  height +
209  lineHeight +
210  textIndent +
211  margin.hashValue () +
212  borderWidth.hashValue () +
213  padding.hashValue () +
214  borderCollapse +
215  (intptr_t) borderColor.top +
216  (intptr_t) borderColor.right +
217  (intptr_t) borderColor.bottom +
218  (intptr_t) borderColor.left +
219  borderStyle.top +
220  borderStyle.right +
221  borderStyle.bottom +
222  borderStyle.left +
223  display +
224  whiteSpace +
225  listStylePosition +
226  listStyleType +
227  cursor +
228  x_link +
229  x_lang[0] + x_lang[1] +
230  x_img +
231  (intptr_t) x_tooltip;
232 }
233 
234 int Style::totalRef = 0;
236  new container::typed::HashTable <StyleAttrs, Style> (false, false, 1024);
237 
238 Style::Style (StyleAttrs *attrs)
239 {
240  DBG_OBJ_CREATE ("dw::core::style::Style");
241 
242  copyAttrs (attrs);
243 
244  DBG_OBJ_ASSOC_CHILD (font);
245  DBG_OBJ_ASSOC_CHILD (color);
246  DBG_OBJ_ASSOC_CHILD (backgroundColor);
247  DBG_OBJ_ASSOC_CHILD (backgroundImage);
248  DBG_OBJ_ASSOC_CHILD (borderColor.top);
249  DBG_OBJ_ASSOC_CHILD (borderColor.bottom);
250  DBG_OBJ_ASSOC_CHILD (borderColor.left);
251  DBG_OBJ_ASSOC_CHILD (borderColor.right);
252  //DBG_OBJ_ASSOC_CHILD (x_tooltip);
253 
254  refCount = 1;
255 
256  font->ref ();
257  if (color)
258  color->ref ();
259  if (backgroundColor)
260  backgroundColor->ref ();
261  if (backgroundImage)
262  backgroundImage->ref ();
263  if (borderColor.top)
264  borderColor.top->ref();
265  if (borderColor.bottom)
266  borderColor.bottom->ref();
267  if (borderColor.left)
268  borderColor.left->ref();
269  if (borderColor.right)
270  borderColor.right->ref();
271  if (x_tooltip)
272  x_tooltip->ref();
273 
274  totalRef++;
275 }
276 
277 Style::~Style ()
278 {
279  font->unref ();
280 
281  if (color)
282  color->unref ();
283  if (backgroundColor)
284  backgroundColor->unref ();
285  if (backgroundImage)
286  backgroundImage->unref ();
287  if (borderColor.top)
288  borderColor.top->unref();
289  if (borderColor.bottom)
290  borderColor.bottom->unref();
291  if (borderColor.left)
292  borderColor.left->unref();
293  if (borderColor.right)
294  borderColor.right->unref();
295  if (x_tooltip)
296  x_tooltip->unref();
297 
298  styleTable->remove (this);
299  totalRef--;
300 
301  DBG_OBJ_DELETE ();
302 }
303 
304 void Style::copyAttrs (StyleAttrs *attrs)
305 {
306  font = attrs->font;
307  textDecoration = attrs->textDecoration;
308  color = attrs->color;
309  backgroundColor = attrs->backgroundColor;
310  backgroundImage = attrs->backgroundImage;
311  backgroundRepeat = attrs->backgroundRepeat;
312  backgroundAttachment = attrs->backgroundAttachment;
313  backgroundPositionX = attrs->backgroundPositionX;
314  backgroundPositionY = attrs->backgroundPositionY;
315  textAlign = attrs->textAlign;
316  valign = attrs->valign;
317  textAlignChar = attrs->textAlignChar;
318  textTransform = attrs->textTransform;
319  hBorderSpacing = attrs->hBorderSpacing;
320  vBorderSpacing = attrs->vBorderSpacing;
321  wordSpacing = attrs->wordSpacing;
322  width = attrs->width;
323  height = attrs->height;
324  lineHeight = attrs->lineHeight;
325  textIndent = attrs->textIndent;
326  margin = attrs->margin;
327  borderWidth = attrs->borderWidth;
328  padding = attrs->padding;
329  borderCollapse = attrs->borderCollapse;
330  borderColor = attrs->borderColor;
331  borderStyle = attrs->borderStyle;
332  display = attrs->display;
333  whiteSpace = attrs->whiteSpace;
334  listStylePosition = attrs->listStylePosition;
335  listStyleType = attrs->listStyleType;
336  cursor = attrs->cursor;
337  x_link = attrs->x_link;
338  x_lang[0] = attrs->x_lang[0];
339  x_lang[1] = attrs->x_lang[1];
340  x_img = attrs->x_img;
341  x_tooltip = attrs->x_tooltip;
342 }
343 
344 // ----------------------------------------------------------------------
345 
346 bool FontAttrs::equals(object::Object *other)
347 {
348  FontAttrs *otherAttrs = (FontAttrs*)other;
349  return
350  this == otherAttrs ||
351  (size == otherAttrs->size &&
352  weight == otherAttrs->weight &&
353  style == otherAttrs->style &&
354  letterSpacing == otherAttrs->letterSpacing &&
355  fontVariant == otherAttrs->fontVariant &&
356  strcmp (name, otherAttrs->name) == 0);
357 }
358 
359 int FontAttrs::hashValue()
360 {
361  int h = object::String::hashValue (name);
362  h = (h << 5) - h + size;
363  h = (h << 5) - h + weight;
364  h = (h << 5) - h + style;
365  h = (h << 5) - h + letterSpacing;
366  h = (h << 5) - h + fontVariant;
367  return h;
368 }
369 
370 Font::~Font ()
371 {
372  free ((char*)name);
373  DBG_OBJ_DELETE ();
374 }
375 
376 void Font::copyAttrs (FontAttrs *attrs)
377 {
378  name = strdup (attrs->name);
379  size = attrs->size;
380  weight = attrs->weight;
381  style = attrs->style;
382  letterSpacing = attrs->letterSpacing;
383  fontVariant = attrs->fontVariant;
384 }
385 
386 Font *Font::create0 (Layout *layout, FontAttrs *attrs,
387  bool tryEverything)
388 {
389  return layout->createFont (attrs, tryEverything);
390 }
391 
392 Font *Font::create (Layout *layout, FontAttrs *attrs)
393 {
394  return create0 (layout, attrs, false);
395 }
396 
397 bool Font::exists (Layout *layout, const char *name)
398 {
399  return layout->fontExists (name);
400 }
401 
402 // ----------------------------------------------------------------------
403 
404 bool ColorAttrs::equals(object::Object *other)
405 {
406  ColorAttrs *oc = (ColorAttrs*)other;
407  return this == oc || (color == oc->color);
408 }
409 
410 int ColorAttrs::hashValue()
411 {
412  return color;
413 }
414 
415 Color::~Color ()
416 {
417  DBG_OBJ_DELETE ();
418 }
419 
420 int Color::shadeColor (int color, int d)
421 {
422  int red = (color >> 16) & 255;
423  int green = (color >> 8) & 255;
424  int blue = color & 255;
425 
426  double oldLightness = ((double) misc::max (red, green, blue)) / 255;
427  double newLightness;
428 
429  if (oldLightness > 0.8) {
430  if (d > 0)
431  newLightness = oldLightness - 0.2;
432  else
433  newLightness = oldLightness - 0.4;
434  } else if (oldLightness < 0.2) {
435  if (d > 0)
436  newLightness = oldLightness + 0.4;
437  else
438  newLightness = oldLightness + 0.2;
439  } else
440  newLightness = oldLightness + d * 0.2;
441 
442  if (oldLightness) {
443  double f = (newLightness / oldLightness);
444  red = (int)(red * f);
445  green = (int)(green * f);
446  blue = (int)(blue * f);
447  } else {
448  red = green = blue = (int)(newLightness * 255);
449  }
450 
451  return (red << 16) | (green << 8) | blue;
452 }
453 
454 int Color::shadeColor (int color, Shading shading)
455 {
456  switch (shading) {
457  case SHADING_NORMAL:
458  return color;
459 
460  case SHADING_LIGHT:
461  return shadeColor(color, +1);
462 
463  case SHADING_INVERSE:
464  return color ^ 0xffffff;
465 
466  case SHADING_DARK:
467  return shadeColor(color, -1);
468 
469  default:
470  // compiler happiness
472  return -1;
473  }
474 }
475 
476 
477 Color *Color::create (Layout *layout, int col)
478 {
479  ColorAttrs attrs(col);
480 
481  return layout->createColor (col);
482 }
483 
484 Tooltip *Tooltip::create (Layout *layout, const char *text)
485 {
486  return layout->createTooltip (text);
487 }
488 
489 // ----------------------------------------------------------------------
490 
491 void StyleImage::StyleImgRenderer::setBuffer (core::Imgbuf *buffer, bool resize)
492 {
493  if (image->imgbufSrc)
494  image->imgbufSrc->unref ();
495  if (image->imgbufTiled)
496  image->imgbufTiled->unref ();
497 
498  image->imgbufTiled = NULL;
499 
500  image->imgbufSrc = buffer;
501  DBG_OBJ_ASSOC (image, image->imgbufSrc);
502 
503  if (image->imgbufSrc) {
504  image->imgbufSrc->ref ();
505 
506  // If the image is too small, drawing a background will cause
507  // many calls of View::drawImgbuf. For this reason, we create
508  // another image buffer, the "tiled" image buffer, which is
509  // larger (the "optimal" size is defined as OPT_BG_IMG_W *
510  // OPT_BG_IMG_H) and contains the "source" buffer several times.
511  //
512  // This "tiled" buffer is not used when 'background-repeat' has
513  // another value than 'repeat', for obvious reasons. Image
514  // buffers only "tiled" in one dimension (to optimize 'repeat-x'
515  // and 'repeat-y') are not supported.
516 
517  if (image->imgbufSrc->getRootWidth() * image->imgbufSrc->getRootHeight()
519  image->tilesX =
520  misc::max (OPT_BG_IMG_W / image->imgbufSrc->getRootWidth(), 1);
521  image->tilesY =
522  misc::max (OPT_BG_IMG_H / image->imgbufSrc->getRootHeight(), 1);
523  image->imgbufTiled =
524  image->imgbufSrc->createSimilarBuf
525  (image->tilesX * image->imgbufSrc->getRootWidth(),
526  image->tilesY * image->imgbufSrc->getRootHeight());
527 
528  DBG_OBJ_ASSOC (image, image->imgbufTiled);
529  }
530  }
531 }
532 
533 void StyleImage::StyleImgRenderer::drawRow (int row)
534 {
535  if (image->imgbufTiled) {
536  // A row of data has been copied to the source buffer, here it
537  // is copied into the tiled buffer.
538 
539  // Unfortunately, this code may be called *after* some other
540  // implementations of ImgRenderer::drawRow, which actually
541  // *draw* the tiled buffer, which is so not up to date
542  // (ImgRendererDist does not define an order). OTOH, these
543  // drawing implementations calle Widget::queueResize, so the
544  // actual drawing (and so access to the tiled buffer) is done
545  // later.
546 
547  int w = image->imgbufSrc->getRootWidth ();
548  int h = image->imgbufSrc->getRootHeight ();
549 
550  for (int x = 0; x < image->tilesX; x++)
551  for (int y = 0; y < image->tilesX; y++)
552  image->imgbufSrc->copyTo (image->imgbufTiled, x * w, y * h,
553  0, row, w, 1);
554  }
555 }
556 
557 void StyleImage::StyleImgRenderer::finish ()
558 {
559  // Nothing to do.
560 }
561 
562 void StyleImage::StyleImgRenderer::fatal ()
563 {
564  // Nothing to do.
565 }
566 
567 StyleImage::StyleImage ()
568 {
569  DBG_OBJ_CREATE ("dw::core::style::StyleImage");
570 
571  refCount = 0;
572  imgbufSrc = NULL;
573  imgbufTiled = NULL;
574 
575  imgRendererDist = new ImgRendererDist ();
576  styleImgRenderer = new StyleImgRenderer (this);
577  imgRendererDist->put (styleImgRenderer);
578 }
579 
580 StyleImage::~StyleImage ()
581 {
582  if (imgbufSrc)
583  imgbufSrc->unref ();
584  if (imgbufTiled)
585  imgbufTiled->unref ();
586 
587  delete imgRendererDist;
588  delete styleImgRenderer;
589 
590  DBG_OBJ_DELETE ();
591 }
592 
593 void StyleImage::ExternalImgRenderer::setBuffer (core::Imgbuf *buffer,
594  bool resize)
595 {
596  // Nothing to do?
597 }
598 
599 void StyleImage::ExternalImgRenderer::drawRow (int row)
600 {
602  StyleImage *backgroundImage;
603  if (readyToDraw () && (backgroundImage = getBackgroundImage ())) {
604  // All single rows are drawn.
605 
606  Imgbuf *imgbuf = backgroundImage->getImgbufSrc();
607  int imgWidth = imgbuf->getRootWidth ();
608  int imgHeight = imgbuf->getRootHeight ();
609 
610  int x, y, width, height;
611  getBgArea (&x, &y, &width, &height);
612 
613  int xRef, yRef, widthRef, heightRef;
614  getRefArea (&xRef, &yRef, &widthRef, &heightRef);
615 
616  bool repeatX, repeatY, doDraw;
617  int origX, origY, tileX1, tileX2, tileY1, tileY2;
618 
619  calcBackgroundRelatedValues (backgroundImage,
620  getBackgroundRepeat (),
621  getBackgroundAttachment (),
622  getBackgroundPositionX (),
623  getBackgroundPositionY (),
624  x, y, width, height, xRef, yRef, widthRef,
625  heightRef, &repeatX, &repeatY, &origX,
626  &origY, &tileX1, &tileX2, &tileY1,
627  &tileY2, &doDraw);
628 
629  //printf ("tileX1 = %d, tileX2 = %d, tileY1 = %d, tileY2 = %d\n",
630  // tileX1, tileX2, tileY1, tileY2);
631 
632  if (doDraw)
633  // Only iterate over y, because the rows can be combined
634  // horizontally.
635  for (int tileY = tileY1; tileY <= tileY2; tileY++) {
636  int x1 = misc::max (origX + tileX1 * imgWidth, x);
637  int x2 = misc::min (origX + (tileX2 + 1) * imgWidth, x + width);
638 
639  int yt = origY + tileY * imgHeight + row;
640  if (yt >= y && yt < y + height)
641  draw (x1, yt, x2 - x1, 1);
642  }
643  }
644  }
645 }
646 
647 void StyleImage::ExternalImgRenderer::finish ()
648 {
650  if (readyToDraw ()) {
651  // Draw total area, as a whole.
652  int x, y, width, height;
653  getBgArea (&x, &y, &width, &height);
654  draw (x, y, width, height);
655  }
656  }
657 }
658 
659 void StyleImage::ExternalImgRenderer::fatal ()
660 {
661  // Nothing to do.
662 }
663 
664 // ----------------------------------------------------------------------
665 
666 StyleImage *StyleImage::ExternalWidgetImgRenderer::getBackgroundImage ()
667 {
668  Style *style = getStyle ();
669  return style ? style->backgroundImage : NULL;
670 }
671 
672 BackgroundRepeat StyleImage::ExternalWidgetImgRenderer::getBackgroundRepeat ()
673 {
674  Style *style = getStyle ();
675  return style ? style->backgroundRepeat : BACKGROUND_REPEAT;
676 }
677 
679  StyleImage::ExternalWidgetImgRenderer::getBackgroundAttachment ()
680 {
681  Style *style = getStyle ();
682  return style ? style->backgroundAttachment : BACKGROUND_ATTACHMENT_SCROLL;
683 }
684 
685 Length StyleImage::ExternalWidgetImgRenderer::getBackgroundPositionX ()
686 {
687  Style *style = getStyle ();
688  return style ? style->backgroundPositionX : createPerLength (0);
689 }
690 
691 Length StyleImage::ExternalWidgetImgRenderer::getBackgroundPositionY ()
692 {
693  Style *style = getStyle ();
694  return style ? style->backgroundPositionY : createPerLength (0);
695 }
696 
697 // ----------------------------------------------------------------------
698 
699 /*
700  * The drawBorder{Top,Bottom,Left,Right} functions are similar. They
701  * use a trapezium as draw polygon, or drawTypedLine() for dots and dashes.
702  * Although the concept is simple, achieving pixel accuracy is laborious [1].
703  *
704  * [1] http://www.dillo.org/css_compat/tests/border-style.html
705  */
706 static void drawBorderTop(View *view, Style *style,
707  int x1, int y1, int x2, int y2)
708 
709 {
710  int d, w;
711  Point points[4];
712  const bool filled = true, convex = true;
713  bool ridge = false, inset = false, dotted = false;
714  Color::Shading shading = Color::SHADING_NORMAL;
715 
716  if (!style->borderColor.top || style->borderWidth.top == 0)
717  return;
718 
719  switch (style->borderStyle.top) {
720  case BORDER_NONE:
721  case BORDER_HIDDEN:
722  break;
723  case BORDER_DOTTED:
724  dotted = true;
725  case BORDER_DASHED:
726  w = style->borderWidth.top;
727  view->drawTypedLine(style->borderColor.top, shading,
728  dotted ? LINE_DOTTED : LINE_DASHED,
729  w, x1+w/2, y1+w/2, x2-w/2, y2+w/2);
730  break;
731  case BORDER_SOLID:
732  case BORDER_INSET:
733  inset = true;
734  case BORDER_OUTSET:
735  if (style->borderStyle.top != BORDER_SOLID)
736  shading = (inset) ? Color::SHADING_DARK : Color::SHADING_LIGHT;
737 
738  if (style->borderWidth.top == 1) {
739  view->drawLine(style->borderColor.top, shading, x1, y1, x2, y2);
740  } else {
741  points[0].x = x1;
742  points[1].x = x2 + 1;
743  points[0].y = points[1].y = y1;
744  points[2].x = points[1].x - style->borderWidth.right;
745  points[3].x = x1 + style->borderWidth.left;
746  points[2].y = points[3].y = points[0].y + style->borderWidth.top;
747  view->drawPolygon (style->borderColor.top, shading, filled, convex,
748  points, 4);
749  }
750  break;
751  case BORDER_RIDGE:
752  ridge = true;
753  case BORDER_GROOVE:
754  d = style->borderWidth.top & 1;
755  points[0].x = x1;
756  points[1].x = x2 + 1;
757  points[0].y = points[1].y = y1;
758  points[2].x = x2 - style->borderWidth.right / 2;
759  points[3].x = x1 + style->borderWidth.left / 2;
760  points[2].y = points[3].y = y1 + style->borderWidth.top / 2 + d;
761  shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK;
762  view->drawPolygon (style->borderColor.top, shading, filled, convex,
763  points, 4);
764  points[0].x = x1 + style->borderWidth.left / 2 + d;
765  points[1].x = x2 - style->borderWidth.right / 2 + 1 - d;
766  points[0].y = points[1].y = y1 + style->borderWidth.top / 2 + d;
767  points[2].x = x2 - style->borderWidth.right + 1 - d;
768  points[3].x = x1 + style->borderWidth.left;
769  points[2].y = points[3].y = y1 + style->borderWidth.top;
770  shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT;
771  view->drawPolygon (style->borderColor.top, shading, filled, convex,
772  points, 4);
773  break;
774  case BORDER_DOUBLE:
775  w = (int) rint(style->borderWidth.top / 3.0);
776  d = w ? style->borderWidth.top - 2 * w : 0;
777  int w_l = (int) rint(style->borderWidth.left / 3.0);
778  int w_r = (int) rint(style->borderWidth.right / 3.0);
779  if (style->borderWidth.top == 1) {
780  view->drawLine(style->borderColor.top, shading, x1, y1, x2, y2);
781  break;
782  }
783  points[0].x = x1;
784  points[1].x = x2 + 1;
785  points[0].y = points[1].y = y1;
786  points[2].x = points[1].x - w_r;
787  points[3].x = points[0].x + w_l;
788  points[2].y = points[3].y = points[0].y + w;
789  view->drawPolygon (style->borderColor.top, shading, filled, convex,
790  points, 4);
791  points[0].x = x1 + style->borderWidth.left - w_l;
792  points[1].x = x2 + 1 - style->borderWidth.right + w_r;
793  points[0].y = points[1].y = y1 + w + d;
794  points[2].x = x2 + 1 - style->borderWidth.right;
795  points[3].x = x1 + style->borderWidth.left;
796  points[2].y = points[3].y = y1 + style->borderWidth.top;
797  view->drawPolygon (style->borderColor.top, shading, filled, convex,
798  points, 4);
799  break;
800  }
801 }
802 
803 static void drawBorderBottom(View *view, Style *style,
804  int x1, int y1, int x2, int y2)
805 
806 {
807  int d, w;
808  Point points[4];
809  const bool filled = true, convex = true;
810  bool ridge = false, inset = false, dotted = false;
811  Color::Shading shading = Color::SHADING_NORMAL;
812 
813  if (!style->borderColor.bottom || style->borderWidth.bottom == 0)
814  return;
815 
816  switch (style->borderStyle.bottom) {
817  case BORDER_NONE:
818  case BORDER_HIDDEN:
819  break;
820  case BORDER_DOTTED:
821  dotted = true;
822  case BORDER_DASHED:
823  w = style->borderWidth.bottom;
824  view->drawTypedLine(style->borderColor.bottom, shading,
825  dotted ? LINE_DOTTED : LINE_DASHED,
826  w, x1+w/2, y1-w/2, x2-w/2, y2-w/2);
827  break;
828  case BORDER_SOLID:
829  case BORDER_INSET:
830  inset = true;
831  case BORDER_OUTSET:
832  if (style->borderStyle.bottom != BORDER_SOLID)
833  shading = (inset) ? Color::SHADING_LIGHT : Color::SHADING_DARK;
834 
835  if (style->borderWidth.bottom == 1) { /* 1 pixel line */
836  view->drawLine(style->borderColor.bottom, shading, x1, y1, x2, y2);
837  } else {
838  points[0].x = x1 - 1;
839  points[1].x = x2 + 2;
840  points[0].y = points[1].y = y1 + 1;
841  points[2].x = points[1].x - style->borderWidth.right;
842  points[3].x = points[0].x + style->borderWidth.left;
843  points[2].y = points[3].y = points[0].y-style->borderWidth.bottom;
844  view->drawPolygon (style->borderColor.bottom, shading, filled, convex,
845  points, 4);
846  }
847  break;
848  case BORDER_RIDGE:
849  ridge = true;
850  case BORDER_GROOVE:
851  w = style->borderWidth.bottom;
852  d = w & 1;
853  points[0].x = x1 - 1;
854  points[1].x = x2 + 2 - d;
855  points[0].y = points[1].y = y1 + 1;
856  points[2].x = points[1].x - style->borderWidth.right / 2;
857  points[3].x = points[0].x + style->borderWidth.left / 2 + d;
858  points[2].y = points[3].y = points[0].y - w/2 - d;
859  shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT;
860  view->drawPolygon (style->borderColor.bottom, shading, filled, convex,
861  points, 4);
862  // clockwise
863  points[0].x = x1 + style->borderWidth.left - 1;
864  points[1].x = x2 + 1 - style->borderWidth.right + 1;
865  points[0].y = points[1].y = y1 - w + 1;
866  points[2].x = points[1].x + style->borderWidth.right / 2;
867  points[3].x = points[0].x - style->borderWidth.left / 2;
868  points[2].y = points[3].y = points[0].y + w/2;
869  shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK;
870  view->drawPolygon (style->borderColor.bottom, shading, filled, convex,
871  points, 4);
872  break;
873  case BORDER_DOUBLE:
874  w = (int) rint(style->borderWidth.bottom / 3.0);
875  d = w ? style->borderWidth.bottom - 2 * w : 0;
876  int w_l = (int) rint(style->borderWidth.left / 3.0);
877  int w_r = (int) rint(style->borderWidth.right / 3.0);
878  if (style->borderWidth.bottom == 1) {
879  view->drawLine(style->borderColor.bottom, shading, x1, y1, x2, y2);
880  break;
881  }
882  points[0].x = x2 + 2;
883  points[1].x = x1 - 1;
884  points[0].y = points[1].y = y1 + 1;
885  points[2].x = points[1].x + w_l;
886  points[3].x = points[0].x - w_r;
887  points[2].y = points[3].y = points[0].y - w;
888  view->drawPolygon (style->borderColor.bottom, shading, filled, convex,
889  points, 4);
890  points[0].x = x2 + 2 - style->borderWidth.right + w_r;
891  points[1].x = x1 - 1 + style->borderWidth.left - w_l;
892  points[0].y = points[1].y = y1 + 1 - w - d;
893  points[2].x = x1 - 1 + style->borderWidth.left;
894  points[3].x = x2 + 2 - style->borderWidth.right;
895  points[2].y = points[3].y = y1 + 1 - style->borderWidth.bottom;
896  view->drawPolygon (style->borderColor.bottom, shading, filled, convex,
897  points, 4);
898  break;
899  }
900 }
901 
902 static void drawBorderLeft(View *view, Style *style,
903  int x1, int y1, int x2, int y2)
904 
905 {
906  int d, w;
907  Point points[4];
908  bool filled = true, convex = true;
909  bool ridge = false, inset = false, dotted = false;
910  Color::Shading shading = Color::SHADING_NORMAL;
911 
912  if (!style->borderColor.left || style->borderWidth.left == 0)
913  return;
914 
915  switch (style->borderStyle.left) {
916  case BORDER_NONE:
917  case BORDER_HIDDEN:
918  break;
919  case BORDER_DOTTED:
920  dotted = true;
921  case BORDER_DASHED:
922  w = style->borderWidth.left;
923  view->drawTypedLine(style->borderColor.left, shading,
924  dotted ? LINE_DOTTED : LINE_DASHED,
925  w, x1+w/2, y1+w/2, x1+w/2, y2-w/2);
926  break;
927  case BORDER_SOLID:
928  case BORDER_INSET:
929  inset = true;
930  case BORDER_OUTSET:
931  if (style->borderStyle.left != BORDER_SOLID)
932  shading = (inset) ? Color::SHADING_DARK : Color::SHADING_LIGHT;
933  if (style->borderWidth.left == 1) { /* 1 pixel line */
934  view->drawLine(style->borderColor.left, shading, x1, y1, x2, y2);
935  } else {
936  points[0].x = points[1].x = x1;
937  points[0].y = y1 - 1;
938  points[1].y = y2 + 1;
939  points[2].x = points[3].x = points[0].x + style->borderWidth.left;
940  points[2].y = points[1].y - style->borderWidth.bottom;
941  points[3].y = points[0].y + style->borderWidth.top;
942  view->drawPolygon (style->borderColor.left, shading, filled, convex,
943  points, 4);
944  }
945  break;
946  case BORDER_RIDGE:
947  ridge = true;
948  case BORDER_GROOVE:
949  w = style->borderWidth.left;
950  d = w & 1;
951  points[0].x = points[1].x = x1;
952  points[0].y = y1;
953  points[1].y = y2;
954  points[2].x = points[3].x = x1 + w / 2 + d;
955  points[2].y = y2 - style->borderWidth.bottom / 2;
956  points[3].y = y1 + style->borderWidth.top / 2;
957  shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK;
958  view->drawPolygon (style->borderColor.left, shading, filled, convex,
959  points, 4);
960  points[0].x = points[1].x = x1 + w / 2 + d;
961  points[0].y = y1 + style->borderWidth.top / 2;
962  points[1].y = y2 - style->borderWidth.bottom / 2;
963  points[2].x = points[3].x = x1 + w;
964  points[2].y = y2 - style->borderWidth.bottom;
965  points[3].y = y1 + style->borderWidth.top;
966  shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT;
967  view->drawPolygon (style->borderColor.left, shading, filled, convex,
968  points, 4);
969  break;
970  case BORDER_DOUBLE:
971  w = (int) rint(style->borderWidth.left / 3.0);
972  d = w ? style->borderWidth.left - 2 * w : 0;
973  int w_b = (int) rint(style->borderWidth.bottom / 3.0);
974  int w_t = (int) rint(style->borderWidth.top / 3.0);
975  if (style->borderWidth.left == 1) {
976  view->drawLine(style->borderColor.left, shading, x1, y1, x2, y2-1);
977  break;
978  }
979  points[0].x = points[1].x = x1;
980  points[0].y = y1 - 1;
981  points[1].y = y2 + 1;
982  points[2].x = points[3].x = points[0].x + w;
983  points[2].y = points[1].y - w_b;
984  points[3].y = points[0].y + w_t;
985  view->drawPolygon (style->borderColor.left, shading, filled, convex,
986  points, 4);
987  points[0].x = points[1].x = x1 + w + d;
988  points[0].y = y1 - 1 + style->borderWidth.top - w_t;
989  points[1].y = y2 + 1 - style->borderWidth.bottom + w_b;
990  points[2].x = points[3].x = points[0].x + w;
991  points[2].y = y2 + 1 - style->borderWidth.bottom;
992  points[3].y = y1 - 1 + style->borderWidth.top;
993  view->drawPolygon (style->borderColor.left, shading, filled, convex,
994  points, 4);
995  break;
996  }
997 }
998 
999 static void drawBorderRight(View *view, Style *style,
1000  int x1, int y1, int x2, int y2)
1001 
1002 {
1003  int d, w;
1004  Point points[4];
1005  const bool filled = true, convex = true;
1006  bool ridge = false, inset = false, dotted = false;
1007  Color::Shading shading = Color::SHADING_NORMAL;
1008 
1009  if (!style->borderColor.right || style->borderWidth.right == 0)
1010  return;
1011 
1012  switch (style->borderStyle.right) {
1013  case BORDER_NONE:
1014  case BORDER_HIDDEN:
1015  break;
1016  case BORDER_DOTTED:
1017  dotted = true;
1018  case BORDER_DASHED:
1019  w = style->borderWidth.right;
1020  view->drawTypedLine(style->borderColor.right, shading,
1021  dotted ? LINE_DOTTED : LINE_DASHED,
1022  w, x1 - w/2, y1 + w/2, x1 - w/2, y2 - w/2);
1023  break;
1024  case BORDER_SOLID:
1025  case BORDER_INSET:
1026  inset = true;
1027  case BORDER_OUTSET:
1028  if (style->borderStyle.right != BORDER_SOLID)
1029  shading = (inset) ? Color::SHADING_LIGHT : Color::SHADING_DARK;
1030  if (style->borderWidth.right == 1) { /* 1 pixel line */
1031  view->drawLine(style->borderColor.right, shading, x1, y1, x2, y2);
1032  } else {
1033  points[0].x = points[1].x = x1 + 1;
1034  points[0].y = y1 - 1;
1035  points[1].y = y2 + 1;
1036  points[2].x = points[3].x = points[0].x-style->borderWidth.right;
1037  points[2].y = points[1].y - style->borderWidth.bottom;
1038  points[3].y = points[0].y + style->borderWidth.top;
1039  view->drawPolygon (style->borderColor.right, shading, filled, convex,
1040  points,4);
1041  }
1042  break;
1043  case BORDER_RIDGE:
1044  ridge = true;
1045  case BORDER_GROOVE:
1046  w = style->borderWidth.right;
1047  d = w & 1;
1048  points[0].x = points[1].x = x1 + 1;
1049  points[0].y = y1;
1050  points[1].y = y2;
1051  points[2].x = points[3].x = points[0].x - w / 2 - d;
1052  points[2].y = y2 - style->borderWidth.bottom / 2;
1053  points[3].y = points[0].y + style->borderWidth.top / 2;
1054  shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT;
1055  view->drawPolygon (style->borderColor.right, shading, filled, convex,
1056  points, 4);
1057  points[0].x = points[1].x = x1 + 1 - w / 2 - d;
1058  points[0].y = y1 + style->borderWidth.top / 2;
1059  points[1].y = y2 - style->borderWidth.bottom / 2;
1060  points[2].x = points[3].x = x1 + 1 - w;
1061  points[2].y = y2 - style->borderWidth.bottom;
1062  points[3].y = y1 + style->borderWidth.top;
1063  shading = (ridge) ? Color::SHADING_LIGHT: Color::SHADING_DARK;
1064  view->drawPolygon (style->borderColor.right, shading, filled, convex,
1065  points, 4);
1066  break;
1067  case BORDER_DOUBLE:
1068  w = (int) rint(style->borderWidth.right / 3.0);
1069  d = w ? style->borderWidth.right - 2 * w : 0;
1070  int w_b = (int) rint(style->borderWidth.bottom / 3.0);
1071  int w_t = (int) rint(style->borderWidth.top / 3.0);
1072  if (style->borderWidth.right == 1) {
1073  view->drawLine(style->borderColor.right, shading, x1, y1, x2, y2);
1074  break;
1075  }
1076  points[0].x = points[1].x = x1 + 1;
1077  points[0].y = y1 - 1;
1078  points[1].y = y2 + 1;
1079  points[2].x = points[3].x = points[0].x - w;
1080  points[2].y = points[1].y - w_b;
1081  points[3].y = points[0].y + w_t;
1082  view->drawPolygon (style->borderColor.right, shading, filled, convex,
1083  points, 4);
1084  points[0].x = points[1].x = x1 + 1 - w - d;
1085  points[0].y = y1 - 1 + style->borderWidth.top - w_t;
1086  points[1].y = y2 + 1 - style->borderWidth.bottom + w_b;
1087  points[2].x = points[3].x = points[0].x - w;
1088  points[2].y = y2 + 1 - style->borderWidth.bottom;
1089  points[3].y = y1 - 1 + style->borderWidth.top;
1090  view->drawPolygon (style->borderColor.right, shading, filled, convex,
1091  points, 4);
1092  break;
1093  }
1094 }
1095 
1104 void drawBorder (View *view, Layout *layout, Rectangle *area,
1105  int x, int y, int width, int height,
1106  Style *style, bool inverse)
1107 {
1109  int xb1, yb1, xb2, yb2;
1110 
1111  // top left and bottom right point of outer border boundary
1112  xb1 = x + style->margin.left;
1113  yb1 = y + style->margin.top;
1114  xb2 = x + (width > 0 ? width - 1 : 0) - style->margin.right;
1115  yb2 = y + (height > 0 ? height - 1 : 0) - style->margin.bottom;
1116 
1117  /*
1118  // top left and bottom right point of inner border boundary
1119  xp1 = xb1 + style->borderWidth.left;
1120  yp1 = yb1 + style->borderWidth.top;
1121  xp2 = xb2 - style->borderWidth.right;
1122  yp2 = yb2 - style->borderWidth.bottom;
1123 
1124  light = inverse ? Color::SHADING_DARK : Color::SHADING_LIGHT;
1125  dark = inverse ? Color::SHADING_LIGHT : Color::SHADING_DARK;
1126  normal = inverse ? Color::SHADING_INVERSE : Color::SHADING_NORMAL;
1127  */
1128 
1129  drawBorderRight(view, style, xb2, yb1, xb2, yb2);
1130  drawBorderLeft(view, style, xb1, yb1, xb1, yb2);
1131  drawBorderTop(view, style, xb1, yb1, xb2, yb1);
1132  drawBorderBottom(view, style, xb1, yb2, xb2, yb2);
1133 }
1134 
1135 
1161 void drawBackground (View *view, Layout *layout, Rectangle *area,
1162  int x, int y, int width, int height,
1163  int xRef, int yRef, int widthRef, int heightRef,
1164  Style *style, bool inverse, bool atTop)
1165 {
1166  bool bgColor = style->backgroundColor != NULL &&
1167  // The test for background colors is rather simple, since only the color
1168  // has to be compared, ...
1169  (!atTop || layout->getBgColor () != style->backgroundColor);
1170  bool bgImage = (style->backgroundImage != NULL &&
1171  style->backgroundImage->getImgbufSrc() != NULL) &&
1172  // ... but for backgrounds, it would be rather complicated. To handle the
1173  // two cases (normal HTML in a viewport, where the layout background
1174  // image is set, and contents of <button> within a flat view, where the
1175  // background image of the toplevel widget is set), only the background
1176  // images are compared. A full test, which also deals with all other
1177  // attributes related to background images (repeat, position etc.) would
1178  // be complicated and useless, so not worth the work.
1179  (!atTop || layout->getBgImage () != style->backgroundImage);
1180 
1181  // Since widgets are always drawn from top to bottom, it is *not*
1182  // necessary to draw the background if background color and image
1183  // are not set (NULL), i. e. shining through.
1184 
1185  if (bgColor || bgImage) {
1186  Rectangle bgArea, intersection;
1187  bgArea.x = x;
1188  bgArea.y = y;
1189  bgArea.width = width;
1190  bgArea.height = height;
1191 
1192  if (area->intersectsWith (&bgArea, &intersection)) {
1193  if (bgColor)
1194  view->drawRectangle (style->backgroundColor,
1195  inverse ?
1196  Color::SHADING_INVERSE : Color::SHADING_NORMAL,
1197  true, intersection.x, intersection.y,
1198  intersection.width, intersection.height);
1199 
1200  if (bgImage)
1201  drawBackgroundImage (view, style->backgroundImage,
1202  style->backgroundRepeat,
1203  style->backgroundAttachment,
1204  style->backgroundPositionX,
1205  style->backgroundPositionY,
1206  intersection.x, intersection.y,
1207  intersection.width, intersection.height,
1208  xRef, yRef, widthRef, heightRef);
1209 
1210  }
1211  }
1212 }
1213 
1214 void drawBackgroundImage (View *view, StyleImage *backgroundImage,
1215  BackgroundRepeat backgroundRepeat,
1216  BackgroundAttachment backgroundAttachment,
1217  Length backgroundPositionX,
1218  Length backgroundPositionY,
1219  int x, int y, int width, int height,
1220  int xRef, int yRef, int widthRef, int heightRef)
1221 {
1222  //printf ("drawBackgroundImage (..., [img: %d, %d], ..., (%d, %d), %d x %d, "
1223  // "(%d, %d), %d x %d)\n", imgWidth, imgHeight, x, y, width, height,
1224  // xRef, yRef, widthRef, heightRef);
1225 
1226  bool repeatX, repeatY, doDraw;
1227  int origX, origY, tileX1, tileX2, tileY1, tileY2;
1228 
1229  calcBackgroundRelatedValues (backgroundImage, backgroundRepeat,
1230  backgroundAttachment, backgroundPositionX,
1231  backgroundPositionY, x, y, width, height,
1232  xRef, yRef, widthRef, heightRef,
1233  &repeatX, &repeatY, &origX, &origY,
1234  &tileX1, &tileX2, &tileY1, &tileY2, &doDraw);
1235 
1236  //printf ("tileX1 = %d, tileX2 = %d, tileY1 = %d, tileY2 = %d\n",
1237  // tileX1, tileX2, tileY1, tileY2);
1238 
1239  if (doDraw) {
1240  // Drawing is done with the "tiled" buffer, but all calculations
1241  // before have been done with the "source" buffer.
1242 
1243  Imgbuf *imgbufS = backgroundImage->getImgbufSrc();
1244  int imgWidthS = imgbufS->getRootWidth ();
1245  int imgHeightS = imgbufS->getRootHeight ();
1246 
1247  Imgbuf *imgbufT = backgroundImage->getImgbufTiled(repeatX, repeatY);
1248  int imgWidthT = imgbufT->getRootWidth ();
1249  int imgHeightT = imgbufT->getRootHeight ();
1250  int tilesX = backgroundImage->getTilesX (repeatX, repeatY);
1251  int tilesY = backgroundImage->getTilesY (repeatX, repeatY);
1252 
1253  for (int tileX = tileX1; tileX <= tileX2; tileX += tilesX)
1254  for (int tileY = tileY1; tileY <= tileY2; tileY += tilesY) {
1255  int xt = origX + tileX * imgWidthS;
1256  int x1 = misc::max (xt, x);
1257  int x2 = misc::min (xt + imgWidthT, x + width);
1258  int yt = origY + tileY * imgHeightS;
1259  int y1 = misc::max (yt, y);
1260  int y2 = misc::min (yt + imgHeightT, y + height);
1261 
1262  view->drawImage (imgbufT, xt, yt, x1 - xt, y1 - yt,
1263  x2 - x1, y2 - y1);
1264  }
1265  }
1266 }
1267 
1269  BackgroundRepeat backgroundRepeat,
1270  BackgroundAttachment backgroundAttachment,
1271  Length backgroundPositionX,
1272  Length backgroundPositionY,
1273  int xDraw, int yDraw, int widthDraw,
1274  int heightDraw, int xRef, int yRef,
1275  int widthRef, int heightRef, bool *repeatX,
1276  bool *repeatY, int *origX, int *origY,
1277  int *tileX1, int *tileX2, int *tileY1,
1278  int *tileY2, bool *doDraw)
1279 {
1280  Imgbuf *imgbuf = backgroundImage->getImgbufSrc();
1281  int imgWidth = imgbuf->getRootWidth ();
1282  int imgHeight = imgbuf->getRootHeight ();
1283 
1284  *repeatX = backgroundRepeat == BACKGROUND_REPEAT ||
1285  backgroundRepeat == BACKGROUND_REPEAT_X;
1286  *repeatY = backgroundRepeat == BACKGROUND_REPEAT ||
1287  backgroundRepeat == BACKGROUND_REPEAT_Y;
1288 
1289  *origX = xRef +
1290  (isPerLength (backgroundPositionX) ?
1291  multiplyWithPerLength (widthRef - imgWidth, backgroundPositionX) :
1292  absLengthVal (backgroundPositionX));
1293  *origY = yRef +
1294  (isPerLength (backgroundPositionY) ?
1295  multiplyWithPerLength (heightRef - imgHeight, backgroundPositionY) :
1296  absLengthVal (backgroundPositionY));
1297 
1298  *tileX1 = xDraw < *origX ?
1299  - (*origX - xDraw + imgWidth - 1) / imgWidth :
1300  (xDraw - *origX) / imgWidth;
1301  *tileX2 = *origX < xDraw + widthDraw ?
1302  (xDraw + widthDraw - *origX - 1) / imgWidth :
1303  - (*origX - (xDraw + widthDraw) + imgWidth - 1) / imgWidth;
1304  *tileY1 = yDraw < *origY ?
1305  - (*origY - yDraw + imgHeight - 1) / imgHeight :
1306  (yDraw - *origY) / imgHeight;
1307  *tileY2 = *origY < yDraw + heightDraw ?
1308  (yDraw + heightDraw - *origY - 1) / imgHeight :
1309  - (*origY - (yDraw + heightDraw) + imgHeight - 1) / imgHeight;
1310 
1311  *doDraw = true;
1312  if (!*repeatX) {
1313  // Only center tile (tileX = 0) is drawn, ...
1314  if (*tileX1 <= 0 && *tileX2 >= 0)
1315  // ... and is visible.
1316  *tileX1 = *tileX2 = 0;
1317  else
1318  // ... but is not visible.
1319  *doDraw = false;
1320  }
1321 
1322  if (!*repeatY) {
1323  // Analogue.
1324  if (*tileY1 <= 0 && *tileY2 >= 0)
1325  *tileY1 = *tileY2 = 0;
1326  else
1327  *doDraw = false;
1328  }
1329 }
1330 
1331 // ----------------------------------------------------------------------
1332 
1333 static const char
1334  *const roman_I0[] = { "","I","II","III","IV","V","VI","VII","VIII","IX" },
1335  *const roman_I1[] = { "","X","XX","XXX","XL","L","LX","LXX","LXXX","XC" },
1336  *const roman_I2[] = { "","C","CC","CCC","CD","D","DC","DCC","DCCC","CM" },
1337  *const roman_I3[] = { "","M","MM","MMM","MMMM" };
1338 
1339 static void strAsciiTolower (char *s)
1340 {
1341  for ( ; *s; s++)
1342  *s = misc::AsciiTolower (*s);
1343 }
1344 
1350 void numtostr (int num, char *buf, int buflen, ListStyleType listStyleType)
1351 {
1352  int i3, i2, i1, i0;
1353  bool low = false;
1354  int start_ch = 'A';
1355 
1356  if (buflen <= 0)
1357  return;
1358 
1359  switch(listStyleType){
1362  start_ch = 'a';
1365  i0 = num - 1;
1366  i1 = i0/26 - 1; i2 = i1/26 - 1;
1367  if (i2 > 25) /* more than 26+26^2+26^3=18278 elements ? */
1368  snprintf(buf, buflen, "****.");
1369  else
1370  snprintf(buf, buflen, "%c%c%c.",
1371  i2<0 ? ' ' : start_ch + i2%26,
1372  i1<0 ? ' ' : start_ch + i1%26,
1373  i0<0 ? ' ' : start_ch + i0%26);
1374  break;
1376  low = true;
1378  i0 = num;
1379  i1 = i0/10; i2 = i1/10; i3 = i2/10;
1380  i0 %= 10; i1 %= 10; i2 %= 10;
1381  if (num < 0 || i3 > 4) /* more than 4999 elements ? */
1382  snprintf(buf, buflen, "****.");
1383  else
1384  snprintf(buf, buflen, "%s%s%s%s.", roman_I3[i3], roman_I2[i2],
1385  roman_I1[i1], roman_I0[i0]);
1386  break;
1388  default:
1389  snprintf(buf, buflen, "%d.", num);
1390  break;
1391  }
1392 
1393  // ensure termination
1394  buf[buflen - 1] = '\0';
1395 
1396  if (low)
1397  strAsciiTolower(buf);
1398 
1399 }
1400 
1401 } // namespace style
1402 } // namespace core
1403 } // namespace dw
dw::core::style::Tooltip
Definition: style.hh:615
DBG_OBJ_DELETE
#define DBG_OBJ_DELETE()
Definition: debug.hh:176
dw::core::Layout::createColor
style::Color * createColor(int color)
Definition: layout.hh:372
dw::core::style::StyleAttrs::textTransform
TextTransform textTransform
Definition: style.hh:505
dw::core::style::drawBorderLeft
static void drawBorderLeft(View *view, Style *style, int x1, int y1, int x2, int y2)
Definition: style.cc:902
dw::core::Point
Definition: types.hh:49
dw::core::style::StyleAttrs::top
Color * top
Definition: style.hh:512
dw::core::style::StyleAttrs::backgroundPositionY
Length backgroundPositionY
Definition: style.hh:500
dw::core::style::BORDER_DOUBLE
Definition: style.hh:227
dw::core::style::TEXT_TRANSFORM_NONE
Definition: style.hh:266
dw::core::style::TEXT_ALIGN_LEFT
Definition: style.hh:247
dw::core::style::isPerLength
bool isPerLength(Length l)
Returns true if l is a percentage.
Definition: style.hh:406
dw::core::style::LIST_STYLE_TYPE_DISC
Definition: style.hh:301
dw::core::style::StyleAttrs::right
Color * right
Definition: style.hh:512
dw::core::style::absLengthVal
int absLengthVal(Length l)
Returns the value of a length in pixels, as an integer.
Definition: style.hh:412
dw::core::style::StyleImage::getTilesX
int getTilesX(bool repeatX, bool repeatY)
Definition: style.hh:838
dw::core::style::FontAttrs::style
FontStyle style
Definition: style.hh:646
DBG_OBJ_CREATE
#define DBG_OBJ_CREATE(klass)
Definition: debug.hh:175
dw::core::style::DISPLAY_INLINE
Definition: style.hh:277
dw::core::style::StyleAttrs::height
Length height
Definition: style.hh:508
dw::core::style::WHITE_SPACE_NORMAL
Definition: style.hh:344
dw::core::style::drawBorderBottom
static void drawBorderBottom(View *view, Style *style, int x1, int y1, int x2, int y2)
Definition: style.cc:803
dw::core::style::StyleAttrs::width
Length width
Definition: style.hh:508
dw::core::style::LINE_DASHED
Definition: style.hh:292
dw::core::style::LENGTH_AUTO
Represents "auto" lengths.
Definition: style.hh:454
dw::core::style::LIST_STYLE_TYPE_UPPER_ROMAN
Definition: style.hh:307
DBG_OBJ_ASSOC
#define DBG_OBJ_ASSOC(parent, child)
Definition: debug.hh:180
dw::core::style::StyleAttrs::hashValue
int hashValue()
Return a hash value for the object.
Definition: style.cc:190
dw::core::style::StyleAttrs::textAlignChar
char textAlignChar
Definition: style.hh:504
dw::core::style::drawBackgroundLineByLine
const bool drawBackgroundLineByLine
Definition: style.cc:37
dw::core::style::StyleAttrs::margin
Box margin
Definition: style.hh:510
dw::core::style::StyleAttrs::x_lang
char x_lang[2]
Definition: style.hh:524
dw::core::style::Color
Definition: style.hh:709
dw::core::style::StyleAttrs::backgroundColor
Color * backgroundColor
Definition: style.hh:495
dw::core::style::StyleAttrs::cursor
Cursor cursor
Definition: style.hh:519
dw::core::style::StyleAttrs::borderCollapse
BorderCollapse borderCollapse
Definition: style.hh:511
dw::core::style::LIST_STYLE_TYPE_LOWER_ROMAN
Definition: style.hh:306
dw::core::ImgRendererDist
Implementation of ImgRenderer, which distributes all calls to a set of other implementations of ImgRe...
Definition: imgrenderer.hh:59
dw::core::style::StyleAttrs::lineHeight
Length lineHeight
Definition: style.hh:508
dw::core::style::FontAttrs::weight
int weight
Definition: style.hh:643
dw::core::style::StyleAttrs::display
DisplayType display
Definition: style.hh:515
dw::core::style::BACKGROUND_REPEAT
Definition: style.hh:235
dw::core::style::Tooltip::unref
void unref()
Definition: style.hh:626
dw::core::style::StyleAttrs::listStylePosition
ListStylePosition listStylePosition
Definition: style.hh:517
dw::core::style::StyleAttrs::whiteSpace
WhiteSpace whiteSpace
Definition: style.hh:516
lout::misc::assertNotReached
void assertNotReached()
Definition: misc.hh:35
dw::core::style::drawBorder
void drawBorder(View *view, Layout *layout, Rectangle *area, int x, int y, int width, int height, Style *style, bool inverse)
Draw the border of a region in window, according to style.
Definition: style.cc:1104
dw::core::Rectangle::intersectsWith
bool intersectsWith(Rectangle *otherRect, Rectangle *dest)
Definition: types.cc:53
dw::core::style::LIST_STYLE_POSITION_OUTSIDE
Definition: style.hh:297
dw::core::style::LIST_STYLE_TYPE_DECIMAL
Definition: style.hh:304
dw::core::style::BACKGROUND_REPEAT_Y
Definition: style.hh:237
dw::core::style::StyleAttrs::backgroundRepeat
BackgroundRepeat backgroundRepeat
Definition: style.hh:497
dw::core::style::roman_I0
static const char *const roman_I0[]
Definition: style.cc:1334
dw::core::Rectangle::x
int x
Definition: types.hh:72
dw::core::style::Box::right
int right
Definition: style.hh:467
dw::core::style::roman_I2
static const char *const *const *const roman_I2[]
Definition: style.cc:1336
dw::core::style::FontAttrs::letterSpacing
int letterSpacing
Definition: style.hh:644
dw::core::Layout::createFont
style::Font * createFont(style::FontAttrs *attrs, bool tryEverything)
Definition: layout.hh:362
dw::core::style::multiplyWithPerLength
int multiplyWithPerLength(int x, Length l)
Multiply an int with a percentage length, returning int.
Definition: style.hh:433
dw::core::View::drawRectangle
virtual void drawRectangle(style::Color *color, style::Color::Shading shading, bool filled, int x, int y, int width, int height)=0
dw::core::style::numtostr
void numtostr(int num, char *buf, int buflen, ListStyleType listStyleType)
Convert a number into a string, in a given list style.
Definition: style.cc:1350
dw::core::style::FontAttrs
Definition: style.hh:638
dw::core::View::drawImage
virtual void drawImage(Imgbuf *imgbuf, int xRoot, int yRoot, int x, int y, int width, int height)=0
dw::core::style::BORDER_INSET
Definition: style.hh:230
dw::core::style::LINE_DOTTED
Definition: style.hh:291
dw::core::style::TEXT_DECORATION_NONE
Definition: style.hh:336
lout::misc::max
T max(T a, T b)
Definition: misc.hh:20
DBG_OBJ_ASSOC_CHILD
#define DBG_OBJ_ASSOC_CHILD(child)
Definition: debug.hh:179
dw::core::style::BackgroundAttachment
BackgroundAttachment
Definition: style.hh:241
lout::misc::min
T min(T a, T b)
Definition: misc.hh:19
dw::core::style::Color::Shading
Shading
Definition: style.hh:725
dw::core::style::BORDER_DASHED
Definition: style.hh:225
dw::core::style::ColorAttrs
Definition: style.hh:688
dw::core::style::StyleAttrs::listStyleType
ListStyleType listStyleType
Definition: style.hh:518
dw::core::style::FontAttrs::name
const char * name
Definition: style.hh:641
dw::core::style::BACKGROUND_REPEAT_X
Definition: style.hh:236
dw::core::style::ColorAttrs::color
int color
Definition: style.hh:691
dw::core::style::StyleAttrs::borderStyle
struct dw::core::style::StyleAttrs::@14 borderStyle
dw::core::style::LIST_STYLE_TYPE_LOWER_LATIN
Definition: style.hh:310
dw::core::style::StyleAttrs::padding
Box padding
Definition: style.hh:510
dw::core::style::StyleAttrs::vBorderSpacing
int vBorderSpacing
Definition: style.hh:507
dw::core::Point::y
int y
Definition: types.hh:52
dw::core::style::OPT_BG_IMG_H
const int OPT_BG_IMG_H
Definition: style.cc:42
lout::container::typed::HashTable
Typed version of container::untyped::HashTable.
Definition: container.hh:475
dw::core::style::roman_I1
static const char *const *const roman_I1[]
Definition: style.cc:1335
lout::object::Object
This is the base class for many other classes, which defines very common virtual methods.
Definition: object.hh:24
dw::core::Layout::fontExists
bool fontExists(const char *name)
Definition: layout.hh:367
dw::core::style::Font
Definition: style.hh:656
dw::core::Rectangle::height
int height
Definition: types.hh:75
dw::core::style::calcBackgroundRelatedValues
static void calcBackgroundRelatedValues(StyleImage *backgroundImage, BackgroundRepeat backgroundRepeat, BackgroundAttachment backgroundAttachment, Length backgroundPositionX, Length backgroundPositionY, int xDraw, int yDraw, int widthDraw, int heightDraw, int xRef, int yRef, int widthRef, int heightRef, bool *repeatX, bool *repeatY, int *origX, int *origY, int *tileX1, int *tileX2, int *tileY1, int *tileY2, bool *doDraw)
Definition: style.cc:1268
dw::core::View::drawTypedLine
virtual void drawTypedLine(style::Color *color, style::Color::Shading shading, style::LineType type, int width, int x1, int y1, int x2, int y2)=0
lout
Definition: container.cc:26
dw::core::style::StyleAttrs::borderColor
struct dw::core::style::StyleAttrs::@13 borderColor
dw::core::style::StyleAttrs::backgroundAttachment
BackgroundAttachment backgroundAttachment
Definition: style.hh:498
dw::core::Imgbuf::getRootHeight
virtual int getRootHeight()=0
dw::core::style::LIST_STYLE_TYPE_UPPER_ALPHA
Definition: style.hh:311
dw::core::style::StyleAttrs::textAlign
TextAlignType textAlign
Definition: style.hh:502
dw::core::Layout
The central class for managing and drawing a widget tree.
Definition: layout.hh:16
dw::core::style::BORDER_OUTSET
Definition: style.hh:231
dw::core::Imgbuf::getRootWidth
virtual int getRootWidth()=0
dw::core::Imgbuf
The platform independent interface for image buffers.
Definition: imgbuf.hh:161
dw::core::style::createPerLength
Length createPerLength(double v)
Returns a percentage, v is relative to 1, not to 100.
Definition: style.hh:395
dw::core::Rectangle
dw::core::Shape implemtation for simple rectangles.
Definition: types.hh:69
dw::core::style::StyleImage::getTilesY
int getTilesY(bool repeatX, bool repeatY)
Definition: style.hh:840
dw::core::Point::x
int x
Definition: types.hh:51
dw::core::Layout::getBgColor
style::Color * getBgColor()
Definition: layout.hh:420
dw::core::style::StyleAttrs::left
Color * left
Definition: style.hh:512
dw::core::style::BORDER_DOTTED
Definition: style.hh:224
dw::core::View
An interface to encapsulate platform dependent drawing.
Definition: view.hh:16
dw::core::Layout::createTooltip
style::Tooltip * createTooltip(const char *text)
Definition: layout.hh:377
dw::core::style::StyleAttrs::hBorderSpacing
int hBorderSpacing
Definition: style.hh:507
dw::core::style::Box::top
int top
Definition: style.hh:467
dw::core::style::StyleAttrs::x_tooltip
Tooltip * x_tooltip
Definition: style.hh:523
dw::core::style::StyleAttrs::textDecoration
int textDecoration
Definition: style.hh:493
dw::core::style::StyleAttrs::borderWidth
Box borderWidth
Definition: style.hh:510
dw::core::style::drawBackgroundImage
void drawBackgroundImage(View *view, StyleImage *backgroundImage, BackgroundRepeat backgroundRepeat, BackgroundAttachment backgroundAttachment, Length backgroundPositionX, Length backgroundPositionY, int x, int y, int width, int height, int xRef, int yRef, int widthRef, int heightRef)
Definition: style.cc:1214
dw::core::style::BACKGROUND_ATTACHMENT_SCROLL
Definition: style.hh:242
dw::core::style::StyleAttrs::font
Font * font
Definition: style.hh:492
dw::core::style::drawBorderRight
static void drawBorderRight(View *view, Style *style, int x1, int y1, int x2, int y2)
Definition: style.cc:999
lout::object::ConstString::hashValue
int hashValue()
Return a hash value for the object.
Definition: object.cc:211
dw::core::style::StyleAttrs::wordSpacing
int wordSpacing
Definition: style.hh:507
dw::core::style::StyleAttrs::bottom
Color * bottom
Definition: style.hh:512
dw::core::style::Length
int Length
Type for representing all lengths within dw::core::style.
Definition: style.hh:389
dw::core::style::StyleAttrs::backgroundImage
StyleImage * backgroundImage
Definition: style.hh:496
dw::core::style::StyleAttrs::x_img
int x_img
Definition: style.hh:522
core.hh
dw::core::style::MIN_BG_IMG_W
const int MIN_BG_IMG_W
Definition: style.cc:39
dw::core::style::drawBorderTop
static void drawBorderTop(View *view, Style *style, int x1, int y1, int x2, int y2)
Definition: style.cc:706
dw::core::style::StyleAttrs::color
Color * color
Definition: style.hh:495
dw::core::style::StyleAttrs::x_link
int x_link
Definition: style.hh:521
dw::core::style::StyleAttrs
Definition: style.hh:489
dw::core::style::LIST_STYLE_TYPE_UPPER_LATIN
Definition: style.hh:312
dw::core::View::drawPolygon
virtual void drawPolygon(style::Color *color, style::Color::Shading shading, bool filled, bool convex, Point *points, int npoints)=0
dw::core::style::BORDER_MODEL_SEPARATE
Definition: style.hh:217
dw::core::style::FontAttrs::size
int size
Definition: style.hh:642
dw::core::style::BORDER_SOLID
Definition: style.hh:226
dw::core::style::OPT_BG_IMG_W
const int OPT_BG_IMG_W
Definition: style.cc:41
dw::core::style::VALIGN_BASELINE
Definition: style.hh:258
dw::core::style::Box::bottom
int bottom
Definition: style.hh:467
dw::core::style::BORDER_RIDGE
Definition: style.hh:229
dw::core::style::StyleImage::getImgbufTiled
Imgbuf * getImgbufTiled(bool repeatX, bool repeatY)
Definition: style.hh:836
dw
Dw is in this namespace, or sub namespaces of this one.
Definition: alignedtextblock.cc:26
dw::core::style::CURSOR_DEFAULT
Definition: style.hh:200
dw::core::style::StyleImage::StyleImgRenderer
Definition: style.hh:743
dw::core::style::strAsciiTolower
static void strAsciiTolower(char *s)
Definition: style.cc:1339
dw::core::View::drawLine
virtual void drawLine(style::Color *color, style::Color::Shading shading, int x1, int y1, int x2, int y2)=0
dw::core::Layout::getBgImage
style::StyleImage * getBgImage()
Definition: layout.hh:421
dw::core::style::StyleAttrs::backgroundPositionX
Length backgroundPositionX
Definition: style.hh:499
dw::core::style::roman_I3
static const char *const *const *const *const roman_I3[]
Definition: style.cc:1337
dw::core::style::StyleAttrs::textIndent
Length textIndent
Definition: style.hh:508
dw::core::style::BackgroundRepeat
BackgroundRepeat
Definition: style.hh:234
dw::core::style::StyleImage::getImgbufSrc
Imgbuf * getImgbufSrc()
Definition: style.hh:835
dw::core::style::Box::left
int left
Definition: style.hh:467
dw::core::Rectangle::width
int width
Definition: types.hh:74
dw::core::style::BORDER_GROOVE
Definition: style.hh:228
dw::core::style::MIN_BG_IMG_H
const int MIN_BG_IMG_H
Definition: style.cc:40
dw::core::style::FontAttrs::fontVariant
FontVariant fontVariant
Definition: style.hh:645
lout::misc::AsciiTolower
int AsciiTolower(char c)
Definition: misc.hh:46
dw::core::style::Style
Definition: style.hh:571
dw::core::Rectangle::y
int y
Definition: types.hh:73
dw::core::style::drawBackground
void drawBackground(View *view, Layout *layout, Rectangle *area, int x, int y, int width, int height, int xRef, int yRef, int widthRef, int heightRef, Style *style, bool inverse, bool atTop)
Draw the background (content plus padding) of a region in window, according to style.
Definition: style.cc:1161
dw::core::style::BORDER_HIDDEN
Definition: style.hh:223
dw::core::style::StyleAttrs::valign
VAlignType valign
Definition: style.hh:503
dw::core::style::ListStyleType
ListStyleType
Definition: style.hh:300
dw::core::style::BORDER_NONE
Definition: style.hh:222
dw::core::style::StyleImage
Definition: style.hh:740
dw::core::style::LIST_STYLE_TYPE_LOWER_ALPHA
Definition: style.hh:309