2 * This file is part of the CSS implementation for KDE.
4 * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
5 * (C) David Carson <dacarson@gmail.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
24 #include "khtmllayout.h"
25 #include <QtCore/QMap>
26 #include <QtGui/QPainter>
27 #include <dom/dom_string.h>
28 #include <xml/dom_stringimpl.h>
29 #include <rendering/render_object.h>
31 #include <ksharedconfig.h>
32 #include <kconfiggroup.h>
33 #include <QtGui/QToolTip>
34 #include "css/cssvalues.h"
37 using namespace khtml
;
41 QPainter
*printpainter
;
43 void setPrintPainter( QPainter
*printer
)
45 printpainter
= printer
;
48 void findWordBoundary(QChar
*chars
, int len
, int position
, int *start
, int *end
)
50 if (chars
[position
].isSpace()) {
52 while (chars
[pos
].isSpace() && pos
>= 0)
56 while (chars
[pos
].isSpace() && pos
< (int)len
)
59 } else if (chars
[position
].isPunct()) {
61 while (chars
[pos
].isPunct() && pos
>= 0)
65 while (chars
[pos
].isPunct() && pos
< (int)len
)
70 while (!chars
[pos
].isSpace() && !chars
[pos
].isPunct() && pos
>= 0)
74 while (!chars
[pos
].isSpace() && !chars
[pos
].isPunct() && pos
< (int)len
)
88 static const colorMap cmap
[] = {
89 { CSS_VAL_AQUA
, 0xFF00FFFF },
90 { CSS_VAL_BLACK
, 0xFF000000 },
91 { CSS_VAL_BLUE
, 0xFF0000FF },
92 { CSS_VAL_CRIMSON
, 0xFFDC143C },
93 { CSS_VAL_FUCHSIA
, 0xFFFF00FF },
94 { CSS_VAL_GRAY
, 0xFF808080 },
95 { CSS_VAL_GREEN
, 0xFF008000 },
96 { CSS_VAL_INDIGO
, 0xFF4B0082 },
97 { CSS_VAL_LIME
, 0xFF00FF00 },
98 { CSS_VAL_MAROON
, 0xFF800000 },
99 { CSS_VAL_NAVY
, 0xFF000080 },
100 { CSS_VAL_OLIVE
, 0xFF808000 },
101 { CSS_VAL_ORANGE
, 0xFFFFA500 },
102 { CSS_VAL_PURPLE
, 0xFF800080 },
103 { CSS_VAL_RED
, 0xFFFF0000 },
104 { CSS_VAL_SILVER
, 0xFFC0C0C0 },
105 { CSS_VAL_TEAL
, 0xFF008080 },
106 { CSS_VAL_WHITE
, 0xFFFFFFFF },
107 { CSS_VAL_YELLOW
, 0xFFFFFF00 },
108 { CSS_VAL_TRANSPARENT
, transparentColor
},
109 { CSS_VAL_GREY
, 0xff808080 },
115 const char * configGroup
;
116 const char * configEntry
;
117 QPalette::ColorGroup group
;
118 QPalette::ColorRole role
;
121 const char * const wmgroup
= "WM";
122 const char * const generalgroup
= "General";
124 /* Mapping system settings to CSS 2
125 * Tried hard to get an appropriate mapping - schlpbch
127 static const uiColors uimap
[] = {
128 // Active window border.
129 { CSS_VAL_ACTIVEBORDER
, wmgroup
, "background", QPalette::Active
, QPalette::Light
},
130 // Active window caption.
131 { CSS_VAL_ACTIVECAPTION
, wmgroup
, "background", QPalette::Active
, QPalette::Text
},
132 // Text in caption, size box, and scrollbar arrow box.
133 { CSS_VAL_CAPTIONTEXT
, wmgroup
, "activeForeground", QPalette::Active
, QPalette::Text
},
134 // Face color for three-dimensional display elements.
135 { CSS_VAL_BUTTONFACE
, wmgroup
, 0, QPalette::Inactive
, QPalette::Button
},
136 // Dark shadow for three-dimensional display elements (for edges facing away from the light source).
137 { CSS_VAL_BUTTONHIGHLIGHT
, wmgroup
, 0, QPalette::Inactive
, QPalette::Light
},
138 // Shadow color for three-dimensional display elements.
139 { CSS_VAL_BUTTONSHADOW
, wmgroup
, 0, QPalette::Inactive
, QPalette::Shadow
},
140 // Text on push buttons.
141 { CSS_VAL_BUTTONTEXT
, wmgroup
, "buttonForeground", QPalette::Inactive
, QPalette::ButtonText
},
142 // Dark shadow for three-dimensional display elements.
143 { CSS_VAL_THREEDDARKSHADOW
, wmgroup
, 0, QPalette::Inactive
, QPalette::Dark
},
144 // Face color for three-dimensional display elements.
145 { CSS_VAL_THREEDFACE
, wmgroup
, 0, QPalette::Inactive
, QPalette::Button
},
146 // Highlight color for three-dimensional display elements.
147 { CSS_VAL_THREEDHIGHLIGHT
, wmgroup
, 0, QPalette::Inactive
, QPalette::Light
},
148 // Light color for three-dimensional display elements (for edges facing the light source).
149 { CSS_VAL_THREEDLIGHTSHADOW
, wmgroup
, 0, QPalette::Inactive
, QPalette::Midlight
},
150 // Dark shadow for three-dimensional display elements.
151 { CSS_VAL_THREEDSHADOW
, wmgroup
, 0, QPalette::Inactive
, QPalette::Shadow
},
153 // Inactive window border.
154 { CSS_VAL_INACTIVEBORDER
, wmgroup
, "background", QPalette::Disabled
, QPalette::Background
},
155 // Inactive window caption.
156 { CSS_VAL_INACTIVECAPTION
, wmgroup
, "inactiveBackground", QPalette::Disabled
, QPalette::Background
},
157 // Color of text in an inactive caption.
158 { CSS_VAL_INACTIVECAPTIONTEXT
, wmgroup
, "inactiveForeground", QPalette::Disabled
, QPalette::Text
},
159 { CSS_VAL_GRAYTEXT
, wmgroup
, 0, QPalette::Disabled
, QPalette::Text
},
162 { CSS_VAL_MENU
, generalgroup
, "background", QPalette::Inactive
, QPalette::Background
},
164 { CSS_VAL_MENUTEXT
, generalgroup
, "foreground", QPalette::Inactive
, QPalette::Background
},
166 // Text of item(s) selected in a control.
167 { CSS_VAL_HIGHLIGHT
, generalgroup
, "selectBackground", QPalette::Inactive
, QPalette::Background
},
169 // Text of item(s) selected in a control.
170 { CSS_VAL_HIGHLIGHTTEXT
, generalgroup
, "selectForeground", QPalette::Inactive
, QPalette::Background
},
172 // Background color of multiple document interface.
173 { CSS_VAL_APPWORKSPACE
, generalgroup
, "background", QPalette::Inactive
, QPalette::Text
},
175 // Scroll bar gray area.
176 { CSS_VAL_SCROLLBAR
, generalgroup
, "background", QPalette::Inactive
, QPalette::Background
},
178 // Window background.
179 { CSS_VAL_WINDOW
, generalgroup
, "windowBackground", QPalette::Inactive
, QPalette::Base
},
181 { CSS_VAL_WINDOWFRAME
, generalgroup
, "windowBackground", QPalette::Inactive
, QPalette::Background
},
183 { CSS_VAL_WINDOWTEXT
, generalgroup
, "windowForeground", QPalette::Inactive
, QPalette::Text
},
184 { CSS_VAL_TEXT
, generalgroup
, 0, QPalette::Inactive
, QPalette::Text
},
185 { 0, 0, 0, QPalette::NColorGroups
, QPalette::NColorRoles
}
188 QColor
khtml::colorForCSSValue( int css_value
)
190 // try the regular ones first
191 const colorMap
*col
= cmap
;
192 while ( col
->css_value
&& col
->css_value
!= css_value
)
194 if ( col
->css_value
)
195 return QColor::fromRgba(col
->color
);
196 else if ( css_value
== CSS_VAL_INVERT
)
199 const uiColors
*uicol
= uimap
;
200 while ( uicol
->css_value
&& uicol
->css_value
!= css_value
)
202 #ifndef APPLE_CHANGES
203 if ( !uicol
->css_value
) {
204 if ( css_value
== CSS_VAL_INFOBACKGROUND
)
205 return QToolTip::palette().color( QPalette::Inactive
, QPalette::Background
);
206 else if ( css_value
== CSS_VAL_INFOTEXT
)
207 return QToolTip::palette().color( QPalette::Inactive
, QPalette::Foreground
);
208 else if ( css_value
== CSS_VAL_BACKGROUND
) {
209 KConfig
bckgrConfig("kdesktoprc", KConfig::NoGlobals
);
210 // Desktop background.
211 return bckgrConfig
.group( "Desktop0" ).readEntry("Color1", qApp
->palette().color( QPalette::Disabled
, QPalette::Background
) );
217 const QPalette
&pal
= qApp
->palette();
218 QColor c
= pal
.color( uicol
->group
, uicol
->role
);
219 #ifndef APPLE_CHANGES
220 if ( uicol
->configEntry
) {
221 KSharedConfig::Ptr globalConfig
= KGlobal::config();
222 c
= globalConfig
->group( uicol
->configGroup
).readEntry( uicol
->configEntry
, c
);
230 double calcHue(double temp1
, double temp2
, double hueVal
)
237 return temp1
+ (temp2
- temp1
) * hueVal
* 6;
241 return temp1
+ (temp2
- temp1
) * (2.0 / 3.0 - hueVal
) * 6;
245 // Explanation of this algorithm can be found in the CSS3 Color Module
246 // specification at http://www.w3.org/TR/css3-color/#hsl-color with further
247 // explanation available at http://en.wikipedia.org/wiki/HSL_color_space
249 // all values are in the range of 0 to 1.0
250 QRgb
khtml::qRgbaFromHsla(double h
, double s
, double l
, double a
)
252 double temp2
= l
< 0.5 ? l
* (1.0 + s
) : l
+ s
- l
* s
;
253 double temp1
= 2.0 * l
- temp2
;
255 return qRgba(static_cast<int>(calcHue(temp1
, temp2
, h
+ 1.0 / 3.0) * 255),
256 static_cast<int>(calcHue(temp1
, temp2
, h
) * 255),
257 static_cast<int>(calcHue(temp1
, temp2
, h
- 1.0 / 3.0) * 255),
258 static_cast<int>(a
* 255));
261 /** finds out the background color of an element
262 * @param obj render object
263 * @return the background color. It is guaranteed that a valid color is returned.
265 QColor
khtml::retrieveBackgroundColor(const RenderObject
*obj
)
268 while (!obj
->isCanvas()) {
269 result
= obj
->style()->backgroundColor();
270 if (result
.isValid()) return result
;
272 obj
= obj
->container();
275 // everything transparent? Use base then.
276 return obj
->style()->palette().color( QPalette::Active
, QPalette::Base
);
279 /** checks whether the given colors have enough contrast
280 * @returns @p true if contrast is ok.
282 bool khtml::hasSufficientContrast(const QColor
&c1
, const QColor
&c2
)
284 // New version from Germain Garand, better suited for contrast measurement
287 #define HUE_DISTANCE 40
288 #define CONTRAST_DISTANCE 10
290 int h1
, s1
, v1
, h2
, s2
, v2
;
291 int hdist
= -CONTRAST_DISTANCE
;
292 c1
.getHsv(&h1
,&s1
,&v1
);
293 c2
.getHsv(&h2
,&s2
,&v2
);
294 if(h1
!=-1 && h2
!=-1) { // grey values have no hue
296 if (hdist
> 180) hdist
= 360-hdist
;
297 if (hdist
< HUE_DISTANCE
) {
298 hdist
-= HUE_DISTANCE
;
299 // see if they are high key or low key colours
300 bool hk1
= h1
>=45 && h1
<=225;
301 bool hk2
= h2
>=45 && h2
<=225;
304 else if (!hk1
&& !hk2
)
307 hdist
= qMin(hdist
, HUE_DISTANCE
*2);
309 return hdist
+ (qAbs(s1
-s2
)*128)/(160+qMin(s1
,s2
)) + qAbs(v1
-v2
) > CONTRAST_DISTANCE
;
311 #undef CONTRAST_DISTANCE
314 #else // orginal fast but primitive version by me (LS)
316 // ### arbitrary value, to be adapted if necessary (LS)
317 #define CONTRAST_DISTANCE 32
319 if (qAbs(c1
.Qt::red() - c2
.Qt::red()) > CONTRAST_DISTANCE
) return true;
320 if (qAbs(c1
.Qt::green() - c2
.Qt::green()) > CONTRAST_DISTANCE
) return true;
321 if (qAbs(c1
.Qt::blue() - c2
.Qt::blue()) > CONTRAST_DISTANCE
) return true;
325 #undef CONTRAST_DISTANCE