[BlackBerry] Some media controls are mispositioned for dynamic live streams (HLS)
[WebKit-https.git] / Source / WebCore / platform / blackberry / RenderThemeBlackBerry.cpp
1 /*
2  * Copyright (C) 2006, 2007 Apple Inc.
3  * Copyright (C) 2009 Google Inc.
4  * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21 #include "config.h"
22 #include "RenderThemeBlackBerry.h"
23
24 #include "CSSValueKeywords.h"
25 #include "Frame.h"
26 #include "HTMLMediaElement.h"
27 #include "HostWindow.h"
28 #include "MediaControlElements.h"
29 #include "MediaPlayerPrivateBlackBerry.h"
30 #include "Page.h"
31 #include "PaintInfo.h"
32 #include "RenderFullScreen.h"
33 #include "RenderProgress.h"
34 #include "RenderSlider.h"
35 #include "RenderView.h"
36 #include "UserAgentStyleSheets.h"
37
38 namespace WebCore {
39
40 // Sizes (unit px)
41 const unsigned smallRadius = 1;
42 const unsigned largeRadius = 3;
43 const unsigned lineWidth = 1;
44 const float marginSize = 4;
45 const float mediaControlsHeight = 32;
46 const float mediaSliderThumbWidth = 40;
47 const float mediaSliderThumbHeight = 13;
48 const float mediaSliderThumbRadius = 5;
49 const float sliderThumbWidth = 15;
50 const float sliderThumbHeight = 25;
51
52 // Checkbox check scalers
53 const float checkboxLeftX = 7 / 40.0;
54 const float checkboxLeftY = 1 / 2.0;
55 const float checkboxMiddleX = 19 / 50.0;
56 const float checkboxMiddleY = 7 / 25.0;
57 const float checkboxRightX = 33 / 40.0;
58 const float checkboxRightY = 1 / 5.0;
59 const float checkboxStrokeThickness = 6.5;
60
61 // Radio button scaler
62 const float radioButtonCheckStateScaler = 7 / 30.0;
63
64 // Multipliers
65 const unsigned paddingDivisor = 5;
66 const unsigned fullScreenEnlargementFactor = 2;
67 const float scaleFactorThreshold = 2.0;
68
69 // Colors
70 const RGBA32 caretBottom = 0xff2163bf;
71 const RGBA32 caretTop = 0xff69a5fa;
72
73 const RGBA32 regularBottom = 0xffdcdee4;
74 const RGBA32 regularTop = 0xfff7f2ee;
75 const RGBA32 hoverBottom = 0xffb5d3fc;
76 const RGBA32 hoverTop = 0xffcceaff;
77 const RGBA32 depressedBottom = 0xff3388ff;
78 const RGBA32 depressedTop = 0xff66a0f2;
79 const RGBA32 disabledBottom = 0xffe7e7e7;
80 const RGBA32 disabledTop = 0xffefefef;
81
82 const RGBA32 regularBottomOutline = 0xff6e7073;
83 const RGBA32 regularTopOutline = 0xffb9b8b8;
84 const RGBA32 hoverBottomOutline = 0xff2163bf;
85 const RGBA32 hoverTopOutline = 0xff69befa;
86 const RGBA32 depressedBottomOutline = 0xff0c3d81;
87 const RGBA32 depressedTopOutline = 0xff1d4d70;
88 const RGBA32 disabledOutline = 0xffd5d9de;
89
90 const RGBA32 progressRegularBottom = caretTop;
91 const RGBA32 progressRegularTop = caretBottom;
92
93 const RGBA32 rangeSliderRegularBottom = 0xfff6f2ee;
94 const RGBA32 rangeSliderRegularTop = 0xffdee0e5;
95 const RGBA32 rangeSliderRollBottom = 0xffc9e8fe;
96 const RGBA32 rangeSliderRollTop = 0xffb5d3fc;
97
98 const RGBA32 rangeSliderRegularBottomOutline = 0xffb9babd;
99 const RGBA32 rangeSliderRegularTopOutline = 0xffb7b7b7;
100 const RGBA32 rangeSliderRollBottomOutline = 0xff67abe0;
101 const RGBA32 rangeSliderRollTopOutline = 0xff69adf9;
102
103 const RGBA32 dragRegularLight = 0xfffdfdfd;
104 const RGBA32 dragRegularDark = 0xffbababa;
105 const RGBA32 dragRollLight = 0xfff2f2f2;
106 const RGBA32 dragRollDark = 0xff69a8ff;
107
108 const RGBA32 selection = 0xff2b8fff;
109
110 const RGBA32 blackPen = Color::black;
111 const RGBA32 focusRingPen = 0xffa3c8fe;
112
113 float RenderThemeBlackBerry::defaultFontSize = 16;
114
115 // We aim to match IE here.
116 // -IE uses a font based on the encoding as the default font for form controls.
117 // -Gecko uses MS Shell Dlg (actually calls GetStockObject(DEFAULT_GUI_FONT),
118 // which returns MS Shell Dlg)
119 // -Safari uses Lucida Grande.
120 //
121 // FIXME: The only case where we know we don't match IE is for ANSI encodings.
122 // IE uses MS Shell Dlg there, which we render incorrectly at certain pixel
123 // sizes (e.g. 15px). So we just use Arial for now.
124 const String& RenderThemeBlackBerry::defaultGUIFont()
125 {
126     DEFINE_STATIC_LOCAL(String, fontFace, ("Arial"));
127     return fontFace;
128 }
129
130 static PassRefPtr<Gradient> createLinearGradient(RGBA32 top, RGBA32 bottom, const IntPoint& a, const IntPoint& b)
131 {
132     RefPtr<Gradient> gradient = Gradient::create(a, b);
133     gradient->addColorStop(0.0, Color(top));
134     gradient->addColorStop(1.0, Color(bottom));
135     return gradient.release();
136 }
137
138 static Path roundedRectForBorder(RenderObject* object, const IntRect& rect)
139 {
140     RenderStyle* style = object->style();
141     LengthSize topLeftRadius = style->borderTopLeftRadius();
142     LengthSize topRightRadius = style->borderTopRightRadius();
143     LengthSize bottomLeftRadius = style->borderBottomLeftRadius();
144     LengthSize bottomRightRadius = style->borderBottomRightRadius();
145
146     Path roundedRect;
147     roundedRect.addRoundedRect(rect, IntSize(topLeftRadius.width().value(), topLeftRadius.height().value()),
148                                      IntSize(topRightRadius.width().value(), topRightRadius.height().value()),
149                                      IntSize(bottomLeftRadius.width().value(), bottomLeftRadius.height().value()),
150                                      IntSize(bottomRightRadius.width().value(), bottomRightRadius.height().value()));
151     return roundedRect;
152 }
153
154 static RenderSlider* determineRenderSlider(RenderObject* object)
155 {
156     ASSERT(object->isSliderThumb());
157     // The RenderSlider is an ancestor of the slider thumb.
158     while (object && !object->isSlider())
159         object = object->parent();
160     return toRenderSlider(object);
161 }
162
163 static float determineFullScreenMultiplier(Element* element)
164 {
165     float fullScreenMultiplier = 1.0;
166 #if ENABLE(FULLSCREEN_API) && ENABLE(VIDEO)
167     if (element && element->document()->webkitIsFullScreen() && element->document()->webkitCurrentFullScreenElement() == toParentMediaElement(element)) {
168         if (element->document()->page()->deviceScaleFactor() < scaleFactorThreshold)
169             fullScreenMultiplier = fullScreenEnlargementFactor;
170
171         // The way the BlackBerry port implements the FULLSCREEN_API for media elements
172         // might result in the controls being oversized, proportionally to the current page
173         // scale. That happens because the fullscreen element gets sized to be as big as the
174         // viewport size, and the viewport size might get outstretched to fit to the screen dimensions.
175         // To fix that, lets strips out the Page scale factor from the media controls multiplier.
176         float scaleFactor = element->document()->view()->hostWindow()->platformPageClient()->currentZoomFactor();
177         static ViewportArguments defaultViewportArguments;
178         float scaleFactorFudge = 1 / element->document()->page()->deviceScaleFactor();
179         fullScreenMultiplier /= scaleFactor * scaleFactorFudge;
180     }
181 #endif
182     return fullScreenMultiplier;
183 }
184
185 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
186 {
187     static RenderTheme* theme = RenderThemeBlackBerry::create().leakRef();
188     return theme;
189 }
190
191 PassRefPtr<RenderTheme> RenderThemeBlackBerry::create()
192 {
193     return adoptRef(new RenderThemeBlackBerry());
194 }
195
196 RenderThemeBlackBerry::RenderThemeBlackBerry()
197 {
198 }
199
200 RenderThemeBlackBerry::~RenderThemeBlackBerry()
201 {
202 }
203
204 String RenderThemeBlackBerry::extraDefaultStyleSheet()
205 {
206     return String(themeBlackBerryUserAgentStyleSheet, sizeof(themeBlackBerryUserAgentStyleSheet));
207 }
208
209 #if ENABLE(VIDEO)
210 String RenderThemeBlackBerry::extraMediaControlsStyleSheet()
211 {
212     return String(mediaControlsBlackBerryUserAgentStyleSheet, sizeof(mediaControlsBlackBerryUserAgentStyleSheet));
213 }
214
215 String RenderThemeBlackBerry::formatMediaControlsRemainingTime(float, float duration) const
216 {
217     // This is a workaround to make the appearance of media time controller in
218     // in-page mode the same as in fullscreen mode.
219     return formatMediaControlsTime(duration);
220 }
221 #endif
222
223 double RenderThemeBlackBerry::caretBlinkInterval() const
224 {
225     return 0; // Turn off caret blinking.
226 }
227
228 void RenderThemeBlackBerry::systemFont(int propId, FontDescription& fontDescription) const
229 {
230     float fontSize = defaultFontSize;
231
232     if (propId == CSSValueWebkitMiniControl || propId ==  CSSValueWebkitSmallControl || propId == CSSValueWebkitControl) {
233         // Why 2 points smaller? Because that's what Gecko does. Note that we
234         // are assuming a 96dpi screen, which is the default value we use on Windows.
235         static const float pointsPerInch = 72.0f;
236         static const float pixelsPerInch = 96.0f;
237         fontSize -= (2.0f / pointsPerInch) * pixelsPerInch;
238     }
239
240     fontDescription.firstFamily().setFamily(defaultGUIFont());
241     fontDescription.setSpecifiedSize(fontSize);
242     fontDescription.setIsAbsoluteSize(true);
243     fontDescription.setGenericFamily(FontDescription::NoFamily);
244     fontDescription.setWeight(FontWeightNormal);
245     fontDescription.setItalic(false);
246 }
247
248 void RenderThemeBlackBerry::setButtonStyle(RenderStyle* style) const
249 {
250     Length vertPadding(int(style->fontSize() / paddingDivisor), Fixed);
251     style->setPaddingTop(vertPadding);
252     style->setPaddingBottom(vertPadding);
253 }
254
255 void RenderThemeBlackBerry::adjustButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
256 {
257     setButtonStyle(style);
258     style->setCursor(CURSOR_WEBKIT_GRAB);
259 }
260
261 void RenderThemeBlackBerry::adjustTextAreaStyle(StyleResolver*, RenderStyle* style, Element*) const
262 {
263     setButtonStyle(style);
264 }
265
266 bool RenderThemeBlackBerry::paintTextArea(RenderObject* object, const PaintInfo& info, const IntRect& rect)
267 {
268     return paintTextFieldOrTextAreaOrSearchField(object, info, rect);
269 }
270
271 void RenderThemeBlackBerry::adjustTextFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
272 {
273     setButtonStyle(style);
274 }
275
276 bool RenderThemeBlackBerry::paintTextFieldOrTextAreaOrSearchField(RenderObject* object, const PaintInfo& info, const IntRect& rect)
277 {
278     ASSERT(info.context);
279     GraphicsContext* context = info.context;
280
281     context->save();
282     context->setStrokeStyle(SolidStroke);
283     context->setStrokeThickness(lineWidth);
284     if (!isEnabled(object))
285         context->setStrokeColor(disabledOutline, ColorSpaceDeviceRGB);
286     else if (isPressed(object))
287         info.context->setStrokeGradient(createLinearGradient(depressedTopOutline, depressedBottomOutline, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
288     else if (isHovered(object) || isFocused(object))
289         context->setStrokeGradient(createLinearGradient(hoverTopOutline, hoverBottomOutline, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
290     else
291         context->setStrokeGradient(createLinearGradient(regularTopOutline, regularBottomOutline, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
292
293     Path textFieldRoundedRectangle = roundedRectForBorder(object, rect);
294     if (object->style()->appearance() == SearchFieldPart) {
295         // We force the fill color to White so as to match the background color of the search cancel button graphic.
296         context->setFillColor(Color::white, ColorSpaceDeviceRGB);
297         context->fillPath(textFieldRoundedRectangle);
298         context->strokePath(textFieldRoundedRectangle);
299     } else
300         context->strokePath(textFieldRoundedRectangle);
301     context->restore();
302     return false;
303 }
304
305 bool RenderThemeBlackBerry::paintTextField(RenderObject* object, const PaintInfo& info, const IntRect& rect)
306 {
307     return paintTextFieldOrTextAreaOrSearchField(object, info, rect);
308 }
309
310 void RenderThemeBlackBerry::adjustSearchFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
311 {
312     setButtonStyle(style);
313 }
314
315 void RenderThemeBlackBerry::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
316 {
317     static const float defaultControlFontPixelSize = 13;
318     static const float defaultCancelButtonSize = 9;
319     static const float minCancelButtonSize = 5;
320     static const float maxCancelButtonSize = 21;
321
322     // Scale the button size based on the font size
323     float fontScale = style->fontSize() / defaultControlFontPixelSize;
324     int cancelButtonSize = lroundf(std::min(std::max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize));
325     Length length(cancelButtonSize, Fixed);
326     style->setWidth(length);
327     style->setHeight(length);
328 }
329
330 bool RenderThemeBlackBerry::paintSearchField(RenderObject* object, const PaintInfo& info, const IntRect& rect)
331 {
332     return paintTextFieldOrTextAreaOrSearchField(object, info, rect);
333 }
334
335 bool RenderThemeBlackBerry::paintSearchFieldCancelButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
336 {
337     ASSERT(object->parent());
338     if (!object->parent() || !object->parent()->isBox())
339         return false;
340
341     RenderBox* parentRenderBox = toRenderBox(object->parent());
342
343     IntRect parentBox = parentRenderBox->absoluteContentBox();
344     IntRect bounds = rect;
345     // Make sure the scaled button stays square and fits in its parent's box.
346     bounds.setHeight(std::min(parentBox.width(), std::min(parentBox.height(), bounds.height())));
347     bounds.setWidth(bounds.height());
348
349     // Put the button in the middle vertically, and round up the value.
350     // So if it has to be one pixel off-center, it would be one pixel closer
351     // to the bottom of the field. This would look better with the text.
352     bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
353
354     static Image* cancelImage = Image::loadPlatformResource("searchCancel").leakRef();
355     static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").leakRef();
356     paintInfo.context->drawImage(isPressed(object) ? cancelPressedImage : cancelImage, object->style()->colorSpace(), bounds);
357     return false;
358 }
359
360 void RenderThemeBlackBerry::adjustMenuListButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
361 {
362     // These seem to be reasonable padding values from observation.
363     const int paddingLeft = 8;
364     const int paddingRight = 4;
365
366     const int minHeight = style->fontSize() * 2;
367
368     style->resetPadding();
369     style->setHeight(Length(Auto));
370
371     style->setPaddingRight(Length(minHeight + paddingRight, Fixed));
372     style->setPaddingLeft(Length(paddingLeft, Fixed));
373     style->setCursor(CURSOR_WEBKIT_GRAB);
374 }
375
376 void RenderThemeBlackBerry::calculateButtonSize(RenderStyle* style) const
377 {
378     int size = style->fontSize();
379     Length length(size, Fixed);
380     if (style->appearance() == CheckboxPart || style->appearance() == RadioPart) {
381         style->setWidth(length);
382         style->setHeight(length);
383         return;
384     }
385
386     // If the width and height are both specified, then we have nothing to do.
387     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
388         return;
389
390     if (style->width().isIntrinsicOrAuto())
391         style->setWidth(length);
392
393     if (style->height().isAuto())
394         style->setHeight(length);
395 }
396
397 bool RenderThemeBlackBerry::paintCheckbox(RenderObject* object, const PaintInfo& info, const IntRect& rect)
398 {
399     return paintButton(object, info, rect);
400 }
401
402 void RenderThemeBlackBerry::setCheckboxSize(RenderStyle* style) const
403 {
404     calculateButtonSize(style);
405 }
406
407 bool RenderThemeBlackBerry::paintRadio(RenderObject* object, const PaintInfo& info, const IntRect& rect)
408 {
409     return paintButton(object, info, rect);
410 }
411
412 void RenderThemeBlackBerry::setRadioSize(RenderStyle* style) const
413 {
414     calculateButtonSize(style);
415 }
416
417 // If this function returns false, WebCore assumes the button is fully decorated
418 bool RenderThemeBlackBerry::paintButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
419 {
420     ASSERT(info.context);
421     info.context->save();
422
423     info.context->setStrokeStyle(SolidStroke);
424     info.context->setStrokeThickness(lineWidth);
425
426     Color check(blackPen);
427     if (!isEnabled(object)) {
428         info.context->setFillGradient(createLinearGradient(disabledTop, disabledBottom, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
429         info.context->setStrokeColor(disabledOutline, ColorSpaceDeviceRGB);
430     } else if (isPressed(object)) {
431         info.context->setFillGradient(createLinearGradient(depressedTop, depressedBottom, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
432         info.context->setStrokeGradient(createLinearGradient(depressedTopOutline, depressedBottomOutline, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
433     } else if (isHovered(object)) {
434         info.context->setFillGradient(createLinearGradient(hoverTop, hoverBottom, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
435         info.context->setStrokeGradient(createLinearGradient(hoverTopOutline, hoverBottomOutline, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
436     } else {
437         info.context->setFillGradient(createLinearGradient(regularTop, regularBottom, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
438         info.context->setStrokeGradient(createLinearGradient(regularTopOutline, regularBottomOutline, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
439     }
440
441     ControlPart part = object->style()->appearance();
442     switch (part) {
443     case CheckboxPart: {
444         FloatSize smallCorner(smallRadius, smallRadius);
445         Path path;
446         path.addRoundedRect(rect, smallCorner);
447         info.context->fillPath(path);
448         info.context->strokePath(path);
449
450         if (isChecked(object)) {
451             Path checkPath;
452             IntRect rect2 = rect;
453             rect2.inflate(-1);
454             checkPath.moveTo(FloatPoint(rect2.x() + rect2.width() * checkboxLeftX, rect2.y() + rect2.height() * checkboxLeftY));
455             checkPath.addLineTo(FloatPoint(rect2.x() + rect2.width() * checkboxMiddleX, rect2.maxY() - rect2.height() * checkboxMiddleY));
456             checkPath.addLineTo(FloatPoint(rect2.x() + rect2.width() * checkboxRightX, rect2.y() + rect2.height() * checkboxRightY));
457             info.context->setLineCap(RoundCap);
458             info.context->setStrokeColor(blackPen, ColorSpaceDeviceRGB);
459             info.context->setStrokeThickness(rect2.width() / checkboxStrokeThickness);
460             info.context->fillPath(checkPath);
461             info.context->strokePath(checkPath);
462         }
463         break;
464     }
465     case RadioPart:
466         info.context->drawEllipse(rect);
467         if (isChecked(object)) {
468             IntRect rect2 = rect;
469             rect2.inflate(-rect.width() * radioButtonCheckStateScaler);
470             info.context->setFillColor(check, ColorSpaceDeviceRGB);
471             info.context->setStrokeColor(check, ColorSpaceDeviceRGB);
472             info.context->drawEllipse(rect2);
473         }
474         break;
475     case ButtonPart:
476     case PushButtonPart: {
477         FloatSize largeCorner(largeRadius, largeRadius);
478         Path path;
479         path.addRoundedRect(rect, largeCorner);
480         info.context->fillPath(path);
481         info.context->strokePath(path);
482         break;
483     }
484     case SquareButtonPart: {
485         Path path;
486         path.addRect(rect);
487         info.context->fillPath(path);
488         info.context->strokePath(path);
489         break;
490     }
491     default:
492         info.context->restore();
493         return true;
494     }
495
496     info.context->restore();
497     return false;
498 }
499
500 void RenderThemeBlackBerry::adjustMenuListStyle(StyleResolver* css, RenderStyle* style, Element* element) const
501 {
502     adjustMenuListButtonStyle(css, style, element);
503 }
504
505 void RenderThemeBlackBerry::adjustCheckboxStyle(StyleResolver*, RenderStyle* style, Element*) const
506 {
507     setCheckboxSize(style);
508     style->setBoxShadow(nullptr);
509     Length margin(marginSize, Fixed);
510     style->setMarginBottom(margin);
511     style->setMarginRight(margin);
512     style->setCursor(CURSOR_WEBKIT_GRAB);
513 }
514
515 void RenderThemeBlackBerry::adjustRadioStyle(StyleResolver*, RenderStyle* style, Element*) const
516 {
517     setRadioSize(style);
518     style->setBoxShadow(nullptr);
519     Length margin(marginSize, Fixed);
520     style->setMarginBottom(margin);
521     style->setMarginRight(margin);
522     style->setCursor(CURSOR_WEBKIT_GRAB);
523 }
524
525 void RenderThemeBlackBerry::paintMenuListButtonGradientAndArrow(GraphicsContext* context, RenderObject* object, IntRect buttonRect, const Path& clipPath)
526 {
527     ASSERT(context);
528     context->save();
529     if (!isEnabled(object))
530         context->setFillGradient(createLinearGradient(disabledTop, disabledBottom, buttonRect.maxXMinYCorner(), buttonRect.maxXMaxYCorner()));
531     else if (isPressed(object))
532         context->setFillGradient(createLinearGradient(depressedTop, depressedBottom, buttonRect.maxXMinYCorner(), buttonRect.maxXMaxYCorner()));
533     else if (isHovered(object))
534         context->setFillGradient(createLinearGradient(hoverTop, hoverBottom, buttonRect.maxXMinYCorner(), buttonRect.maxXMaxYCorner()));
535     else
536         context->setFillGradient(createLinearGradient(regularTop, regularBottom, buttonRect.maxXMinYCorner(), buttonRect.maxXMaxYCorner()));
537
538     // 1. Paint the background of the button.
539     context->clip(clipPath);
540     context->drawRect(buttonRect);
541     context->restore();
542
543     // 2. Paint the button arrow.
544     buttonRect.inflate(-buttonRect.width() / 3);
545     buttonRect.move(0, buttonRect.height() * 7 / 20);
546     Path path;
547     path.moveTo(FloatPoint(buttonRect.x(), buttonRect.y()));
548     path.addLineTo(FloatPoint(buttonRect.x() + buttonRect.width(), buttonRect.y()));
549     path.addLineTo(FloatPoint(buttonRect.x() + buttonRect.width() / 2.0, buttonRect.y() + buttonRect.height() / 2.0));
550     path.closeSubpath();
551
552     context->save();
553     context->setStrokeStyle(SolidStroke);
554     context->setStrokeThickness(lineWidth);
555     context->setStrokeColor(Color::black, ColorSpaceDeviceRGB);
556     context->setFillColor(Color::black, ColorSpaceDeviceRGB);
557     context->setLineJoin(BevelJoin);
558     context->fillPath(path);
559     context->restore();
560 }
561
562 static IntRect computeMenuListArrowButtonRect(const IntRect& rect)
563 {
564     // FIXME: The menu list arrow button should have a minimum and maximum width (to ensure usability) or
565     // scale with respect to the font size used in the menu list control or some combination of both.
566     return IntRect(IntPoint(rect.maxX() - rect.height(), rect.y()), IntSize(rect.height(), rect.height()));
567 }
568
569 static void paintMenuListBackground(GraphicsContext* context, const Path& menuListPath, const Color& backgroundColor)
570 {
571     ASSERT(context);
572     context->save();
573     context->setFillColor(backgroundColor, ColorSpaceDeviceRGB);
574     context->fillPath(menuListPath);
575     context->restore();
576 }
577
578 bool RenderThemeBlackBerry::paintMenuList(RenderObject* object, const PaintInfo& info, const IntRect& rect)
579 {
580     // Note, this method is not called if the menu list explicitly specifies either a border or background color.
581     // Instead, RenderThemeBlackBerry::paintMenuListButton is called. Therefore, when this method is called, we don't
582     // have to adjust rect with respect to the border dimensions.
583
584     ASSERT(info.context);
585     GraphicsContext* context = info.context;
586
587     Path menuListRoundedRectangle = roundedRectForBorder(object, rect);
588
589     // 1. Paint the background of the entire control.
590     paintMenuListBackground(context, menuListRoundedRectangle, Color::white);
591
592     // 2. Paint the background of the button and its arrow.
593     IntRect arrowButtonRectangle = computeMenuListArrowButtonRect(rect);
594     paintMenuListButtonGradientAndArrow(context, object, arrowButtonRectangle, menuListRoundedRectangle);
595
596     // 4. Stroke an outline around the entire control.
597     context->save();
598     context->setStrokeStyle(SolidStroke);
599     context->setStrokeThickness(lineWidth);
600     if (!isEnabled(object))
601         context->setStrokeColor(disabledOutline, ColorSpaceDeviceRGB);
602     else if (isPressed(object))
603         context->setStrokeGradient(createLinearGradient(depressedTopOutline, depressedBottomOutline, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
604     else if (isHovered(object))
605         context->setStrokeGradient(createLinearGradient(hoverTopOutline, hoverBottomOutline, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
606     else
607         context->setStrokeGradient(createLinearGradient(regularTopOutline, regularBottomOutline, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
608
609     context->strokePath(menuListRoundedRectangle);
610     context->restore();
611     return false;
612 }
613
614 bool RenderThemeBlackBerry::paintMenuListButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
615 {
616     // Note, this method is only called if the menu list explicitly specifies either a border or background color.
617     // Otherwise, RenderThemeBlackBerry::paintMenuList is called. We need to fit the arrow button with the border box
618     // of the menu-list so as to not occlude the custom border.
619
620     // We compute menuListRoundedRectangle with respect to the dimensions of the entire menu-list control (i.e. rect) and
621     // its border radius so that we clip the contour of the arrow button (when we paint it below) to match the contour of
622     // the control.
623     Path menuListRoundedRectangle = roundedRectForBorder(object, rect);
624
625     // 1. Paint the background of the entire control.
626     Color fillColor = object->style()->visitedDependentColor(CSSPropertyBackgroundColor);
627     if (!fillColor.isValid())
628         fillColor = Color::white;
629     paintMenuListBackground(info.context, menuListRoundedRectangle, fillColor);
630
631     // 2. Paint the background of the button and its arrow.
632     IntRect bounds = IntRect(rect.x() + object->style()->borderLeftWidth(),
633                          rect.y() + object->style()->borderTopWidth(),
634                          rect.width() - object->style()->borderLeftWidth() - object->style()->borderRightWidth(),
635                          rect.height() - object->style()->borderTopWidth() - object->style()->borderBottomWidth());
636
637     IntRect arrowButtonRectangle = computeMenuListArrowButtonRect(bounds); // Fit the arrow button within the border box of the menu-list.
638     paintMenuListButtonGradientAndArrow(info.context, object, arrowButtonRectangle, menuListRoundedRectangle);
639     return false;
640 }
641
642 void RenderThemeBlackBerry::adjustSliderThumbSize(RenderStyle* style, Element* element) const
643 {
644     float fullScreenMultiplier = 1;
645     ControlPart part = style->appearance();
646
647     if (part == MediaSliderThumbPart || part == MediaVolumeSliderThumbPart) {
648         RenderSlider* slider = determineRenderSlider(element->renderer());
649         if (slider)
650             fullScreenMultiplier = determineFullScreenMultiplier(toElement(slider->node()));
651     }
652
653     if (part == MediaVolumeSliderThumbPart || part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) {
654         style->setWidth(Length((part == SliderThumbVerticalPart ? sliderThumbHeight : sliderThumbWidth) * fullScreenMultiplier, Fixed));
655         style->setHeight(Length((part == SliderThumbVerticalPart ? sliderThumbWidth : sliderThumbHeight) * fullScreenMultiplier, Fixed));
656     } else if (part == MediaSliderThumbPart) {
657         style->setWidth(Length(mediaSliderThumbWidth * fullScreenMultiplier, Fixed));
658         style->setHeight(Length(mediaSliderThumbHeight * fullScreenMultiplier, Fixed));
659     }
660 }
661
662 bool RenderThemeBlackBerry::paintSliderTrack(RenderObject* object, const PaintInfo& info, const IntRect& rect)
663 {
664     const static int SliderTrackHeight = 5;
665     IntRect rect2;
666     if (object->style()->appearance() == SliderHorizontalPart) {
667         rect2.setHeight(SliderTrackHeight);
668         rect2.setWidth(rect.width());
669         rect2.setX(rect.x());
670         rect2.setY(rect.y() + (rect.height() - SliderTrackHeight) / 2);
671     } else {
672         rect2.setHeight(rect.height());
673         rect2.setWidth(SliderTrackHeight);
674         rect2.setX(rect.x() + (rect.width() - SliderTrackHeight) / 2);
675         rect2.setY(rect.y());
676     }
677     return paintSliderTrackRect(object, info, rect2);
678 }
679
680 bool RenderThemeBlackBerry::paintSliderTrackRect(RenderObject* object, const PaintInfo& info, const IntRect& rect)
681 {
682     return paintSliderTrackRect(object, info, rect, rangeSliderRegularTopOutline, rangeSliderRegularBottomOutline,
683                 rangeSliderRegularTop, rangeSliderRegularBottom);
684 }
685
686 bool RenderThemeBlackBerry::paintSliderTrackRect(RenderObject* object, const PaintInfo& info, const IntRect& rect,
687         RGBA32 strokeColorStart, RGBA32 strokeColorEnd, RGBA32 fillColorStart, RGBA32 fillColorEnd)
688 {
689     FloatSize smallCorner(smallRadius, smallRadius);
690
691     info.context->save();
692     info.context->setStrokeStyle(SolidStroke);
693     info.context->setStrokeThickness(lineWidth);
694
695     info.context->setStrokeGradient(createLinearGradient(strokeColorStart, strokeColorEnd, rect.maxXMinYCorner(), rect. maxXMaxYCorner()));
696     info.context->setFillGradient(createLinearGradient(fillColorStart, fillColorEnd, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
697
698     Path path;
699     path.addRoundedRect(rect, smallCorner);
700     info.context->fillPath(path);
701
702     info.context->restore();
703     return false;
704 }
705
706 bool RenderThemeBlackBerry::paintSliderThumb(RenderObject* object, const PaintInfo& info, const IntRect& rect)
707 {
708     FloatSize largeCorner(largeRadius, largeRadius);
709
710     info.context->save();
711     info.context->setStrokeStyle(SolidStroke);
712     info.context->setStrokeThickness(lineWidth);
713
714     if (isPressed(object) || isHovered(object)) {
715         info.context->setStrokeGradient(createLinearGradient(hoverTopOutline, hoverBottomOutline, rect.maxXMinYCorner(), rect. maxXMaxYCorner()));
716         info.context->setFillGradient(createLinearGradient(hoverTop, hoverBottom, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
717     } else {
718         info.context->setStrokeGradient(createLinearGradient(regularTopOutline, regularBottomOutline, rect.maxXMinYCorner(), rect. maxXMaxYCorner()));
719         info.context->setFillGradient(createLinearGradient(regularTop, regularBottom, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
720     }
721
722     Path path;
723     path.addRoundedRect(rect, largeCorner);
724     info.context->fillPath(path);
725
726     bool isVertical = rect.width() > rect.height();
727     IntPoint startPoint(rect.x() + (isVertical ? 5 : 2), rect.y() + (isVertical ? 2 : 5));
728     IntPoint endPoint(rect.x() + (isVertical ? 20 : 2), rect.y() + (isVertical ? 2 : 20));
729     const int lineOffset = 2;
730     const int shadowOffset = 1;
731
732     for (int i = 0; i < 3; i++) {
733         if (isVertical) {
734             startPoint.setY(startPoint.y() + lineOffset);
735             endPoint.setY(endPoint.y() + lineOffset);
736         } else {
737             startPoint.setX(startPoint.x() + lineOffset);
738             endPoint.setX(endPoint.x() + lineOffset);
739         }
740         if (isPressed(object) || isHovered(object))
741             info.context->setStrokeColor(dragRollLight, ColorSpaceDeviceRGB);
742         else
743             info.context->setStrokeColor(dragRegularLight, ColorSpaceDeviceRGB);
744         info.context->drawLine(startPoint, endPoint);
745
746         if (isVertical) {
747             startPoint.setY(startPoint.y() + shadowOffset);
748             endPoint.setY(endPoint.y() + shadowOffset);
749         } else {
750             startPoint.setX(startPoint.x() + shadowOffset);
751             endPoint.setX(endPoint.x() + shadowOffset);
752         }
753         if (isPressed(object) || isHovered(object))
754             info.context->setStrokeColor(dragRollDark, ColorSpaceDeviceRGB);
755         else
756             info.context->setStrokeColor(dragRegularDark, ColorSpaceDeviceRGB);
757         info.context->drawLine(startPoint, endPoint);
758     }
759     info.context->restore();
760     return false;
761 }
762
763 void RenderThemeBlackBerry::adjustMediaControlStyle(StyleResolver*, RenderStyle* style, Element* element) const
764 {
765     float fullScreenMultiplier = determineFullScreenMultiplier(element);
766     HTMLMediaElement* mediaElement = toParentMediaElement(element);
767     if (!mediaElement)
768         return;
769
770     // We use multiples of mediaControlsHeight to make all objects scale evenly
771     Length zero(0, Fixed);
772     Length controlsHeight(mediaControlsHeight * fullScreenMultiplier, Fixed);
773     Length timeWidth(mediaControlsHeight * 3 / 2 * fullScreenMultiplier, Fixed);
774     Length volumeHeight(mediaControlsHeight * 4 * fullScreenMultiplier, Fixed);
775     Length padding(mediaControlsHeight / 8 * fullScreenMultiplier, Fixed);
776     float fontSize = mediaControlsHeight / 2 * fullScreenMultiplier;
777
778     switch (style->appearance()) {
779     case MediaPlayButtonPart:
780     case MediaEnterFullscreenButtonPart:
781     case MediaExitFullscreenButtonPart:
782     case MediaMuteButtonPart:
783         style->setWidth(controlsHeight);
784         style->setHeight(controlsHeight);
785         break;
786     case MediaCurrentTimePart:
787     case MediaTimeRemainingPart:
788         style->setWidth(timeWidth);
789         style->setHeight(controlsHeight);
790         style->setPaddingRight(padding);
791         style->setBlendedFontSize(fontSize);
792         break;
793     case MediaVolumeSliderContainerPart:
794         style->setWidth(controlsHeight);
795         style->setHeight(volumeHeight);
796         style->setBottom(controlsHeight);
797         break;
798     default:
799         break;
800     }
801
802     if (!isfinite(mediaElement->duration())) {
803         // Live streams have infinite duration with no timeline. Force the mute
804         // and fullscreen buttons to the right. This is needed when webkit does
805         // not render the timeline container because it has a webkit-box-flex
806         // of 1 and normally allows those buttons to be on the right.
807         switch (style->appearance()) {
808         case MediaEnterFullscreenButtonPart:
809         case MediaExitFullscreenButtonPart:
810             style->setPosition(AbsolutePosition);
811             style->setBottom(zero);
812             style->setRight(controlsHeight);
813             break;
814         case MediaMuteButtonPart:
815             style->setPosition(AbsolutePosition);
816             style->setBottom(zero);
817             style->setRight(zero);
818             break;
819         default:
820             break;
821         }
822     }
823 }
824
825 void RenderThemeBlackBerry::adjustSliderTrackStyle(StyleResolver*, RenderStyle* style, Element* element) const
826 {
827     float fullScreenMultiplier = determineFullScreenMultiplier(element);
828
829     // We use multiples of mediaControlsHeight to make all objects scale evenly
830     Length controlsHeight(mediaControlsHeight * fullScreenMultiplier, Fixed);
831     Length volumeHeight(mediaControlsHeight * 4 * fullScreenMultiplier, Fixed);
832     switch (style->appearance()) {
833     case MediaSliderPart:
834         style->setHeight(controlsHeight);
835         break;
836     case MediaVolumeSliderPart:
837         style->setWidth(controlsHeight);
838         style->setHeight(volumeHeight);
839         break;
840     case MediaFullScreenVolumeSliderPart:
841     default:
842         break;
843     }
844 }
845
846 static bool paintMediaButton(GraphicsContext* context, const IntRect& rect, Image* image)
847 {
848     context->drawImage(image, ColorSpaceDeviceRGB, rect);
849     return false;
850 }
851
852 bool RenderThemeBlackBerry::paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
853 {
854 #if ENABLE(VIDEO)
855     HTMLMediaElement* mediaElement = toParentMediaElement(object);
856
857     if (!mediaElement)
858         return false;
859
860     static Image* mediaPlay = Image::loadPlatformResource("play").leakRef();
861     static Image* mediaPause = Image::loadPlatformResource("pause").leakRef();
862
863     return paintMediaButton(paintInfo.context, rect, mediaElement->canPlay() ? mediaPlay : mediaPause);
864 #else
865     UNUSED_PARAM(object);
866     UNUSED_PARAM(paintInfo);
867     UNUSED_PARAM(rect);
868     return false;
869 #endif
870 }
871
872 bool RenderThemeBlackBerry::paintMediaMuteButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
873 {
874 #if ENABLE(VIDEO)
875     HTMLMediaElement* mediaElement = toParentMediaElement(object);
876
877     if (!mediaElement)
878         return false;
879
880     static Image* mediaMute = Image::loadPlatformResource("speaker").leakRef();
881     static Image* mediaUnmute = Image::loadPlatformResource("speaker_mute").leakRef();
882
883     return paintMediaButton(paintInfo.context, rect, mediaElement->muted() || !mediaElement->volume() ? mediaUnmute : mediaMute);
884 #else
885     UNUSED_PARAM(object);
886     UNUSED_PARAM(paintInfo);
887     UNUSED_PARAM(rect);
888     return false;
889 #endif
890 }
891
892 bool RenderThemeBlackBerry::paintMediaFullscreenButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
893 {
894 #if ENABLE(VIDEO)
895     HTMLMediaElement* mediaElement = toParentMediaElement(object);
896     if (!mediaElement)
897         return false;
898
899     static Image* mediaEnterFullscreen = Image::loadPlatformResource("fullscreen").leakRef();
900     static Image* mediaExitFullscreen = Image::loadPlatformResource("exit_fullscreen").leakRef();
901
902     Image* buttonImage = mediaEnterFullscreen;
903 #if ENABLE(FULLSCREEN_API)
904     if (mediaElement->document()->webkitIsFullScreen() && mediaElement->document()->webkitCurrentFullScreenElement() == mediaElement)
905         buttonImage = mediaExitFullscreen;
906 #endif
907     return paintMediaButton(paintInfo.context, rect, buttonImage);
908 #else
909     UNUSED_PARAM(object);
910     UNUSED_PARAM(paintInfo);
911     UNUSED_PARAM(rect);
912     return false;
913 #endif
914 }
915
916 bool RenderThemeBlackBerry::paintMediaSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
917 {
918 #if ENABLE(VIDEO)
919     HTMLMediaElement* mediaElement = toParentMediaElement(object);
920     if (!mediaElement)
921         return false;
922
923     float fullScreenMultiplier = determineFullScreenMultiplier(mediaElement);
924     float loaded = 0;
925     // FIXME: replace loaded with commented out one when buffer bug is fixed (see comment in
926     // MediaPlayerPrivateMMrenderer::percentLoaded).
927     // loaded = mediaElement->percentLoaded();
928     if (mediaElement->player() && mediaElement->player()->implementation())
929         loaded = static_cast<MediaPlayerPrivate *>(mediaElement->player()->implementation())->percentLoaded();
930     float position = mediaElement->duration() > 0 ? (mediaElement->currentTime() / mediaElement->duration()) : 0;
931
932     int x = ceil(rect.x() + 2 * fullScreenMultiplier - fullScreenMultiplier / 2);
933     int y = ceil(rect.y() + 14 * fullScreenMultiplier + fullScreenMultiplier / 2);
934     int w = ceil(rect.width() - 4 * fullScreenMultiplier + fullScreenMultiplier / 2);
935     int h = ceil(2 * fullScreenMultiplier);
936     IntRect rect2(x, y, w, h);
937
938     int wPlayed = ceil(w * position);
939     int wLoaded = ceil((w - mediaSliderThumbWidth * fullScreenMultiplier) * loaded + mediaSliderThumbWidth * fullScreenMultiplier);
940
941     IntRect played(x, y, wPlayed, h);
942     IntRect buffered(x, y, wLoaded, h);
943
944     // This is to paint main slider bar.
945     bool result = paintSliderTrackRect(object, paintInfo, rect2);
946
947     if (loaded > 0 || position > 0) {
948         // This is to paint buffered bar.
949         paintSliderTrackRect(object, paintInfo, buffered, Color::darkGray, Color::darkGray, Color::darkGray, Color::darkGray);
950
951         // This is to paint played part of bar (left of slider thumb) using selection color.
952         paintSliderTrackRect(object, paintInfo, played, selection, selection, selection, selection);
953     }
954     return result;
955
956 #else
957     UNUSED_PARAM(object);
958     UNUSED_PARAM(paintInfo);
959     UNUSED_PARAM(rect);
960     return false;
961 #endif
962 }
963
964 bool RenderThemeBlackBerry::paintMediaSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
965 {
966 #if ENABLE(VIDEO)
967     RenderSlider* slider = determineRenderSlider(object);
968     if (!slider)
969         return false;
970
971     float fullScreenMultiplier = determineFullScreenMultiplier(toElement(slider->node()));
972
973     paintInfo.context->save();
974     Path mediaThumbRoundedRectangle;
975     mediaThumbRoundedRectangle.addRoundedRect(rect, FloatSize(mediaSliderThumbRadius * fullScreenMultiplier, mediaSliderThumbRadius * fullScreenMultiplier));
976     paintInfo.context->setStrokeStyle(SolidStroke);
977     paintInfo.context->setStrokeThickness(0.5);
978     paintInfo.context->setStrokeColor(Color::black, ColorSpaceDeviceRGB);
979
980     if (isPressed(object) || isHovered(object) || slider->inDragMode()) {
981         paintInfo.context->setFillGradient(createLinearGradient(selection, Color(selection).dark().rgb(),
982                 rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
983     } else {
984         paintInfo.context->setFillGradient(createLinearGradient(Color::white, Color(Color::white).dark().rgb(),
985                 rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
986     }
987     paintInfo.context->fillPath(mediaThumbRoundedRectangle);
988     paintInfo.context->restore();
989
990     return true;
991 #else
992     UNUSED_PARAM(object);
993     UNUSED_PARAM(paintInfo);
994     UNUSED_PARAM(rect);
995     return false;
996 #endif
997 }
998
999 bool RenderThemeBlackBerry::paintMediaVolumeSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1000 {
1001 #if ENABLE(VIDEO)
1002     float pad = rect.width() * 0.45;
1003     float x = rect.x() + pad;
1004     float y = rect.y() + pad;
1005     float width = rect.width() * 0.1;
1006     float height = rect.height() - (2.0 * pad);
1007
1008     IntRect rect2(x, y, width, height);
1009
1010     return paintSliderTrackRect(object, paintInfo, rect2);
1011 #else
1012     UNUSED_PARAM(object);
1013     UNUSED_PARAM(paintInfo);
1014     UNUSED_PARAM(rect);
1015     return false;
1016 #endif
1017 }
1018
1019 bool RenderThemeBlackBerry::paintMediaVolumeSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1020 {
1021 #if ENABLE(VIDEO)
1022     static Image* mediaVolumeThumb = Image::loadPlatformResource("volume_thumb").leakRef();
1023
1024     return paintMediaButton(paintInfo.context, rect, mediaVolumeThumb);
1025 #else
1026     UNUSED_PARAM(object);
1027     UNUSED_PARAM(paintInfo);
1028     UNUSED_PARAM(rect);
1029     return false;
1030 #endif
1031 }
1032
1033 Color RenderThemeBlackBerry::platformFocusRingColor() const
1034 {
1035     return focusRingPen;
1036 }
1037
1038 #if ENABLE(TOUCH_EVENTS)
1039 Color RenderThemeBlackBerry::platformTapHighlightColor() const
1040 {
1041     return Color(0, 168, 223, 50);
1042 }
1043 #endif
1044
1045 Color RenderThemeBlackBerry::platformActiveSelectionBackgroundColor() const
1046 {
1047     return Color(0, 168, 223, 50);
1048 }
1049
1050 double RenderThemeBlackBerry::animationRepeatIntervalForProgressBar(RenderProgress* renderProgress) const
1051 {
1052     return renderProgress->isDeterminate() ? 0.0 : 0.1;
1053 }
1054
1055 double RenderThemeBlackBerry::animationDurationForProgressBar(RenderProgress* renderProgress) const
1056 {
1057     return renderProgress->isDeterminate() ? 0.0 : 2.0;
1058 }
1059
1060 bool RenderThemeBlackBerry::paintProgressBar(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1061 {
1062     if (!object->isProgress())
1063         return true;
1064
1065     RenderProgress* renderProgress = toRenderProgress(object);
1066
1067     FloatSize smallCorner(smallRadius, smallRadius);
1068
1069     info.context->save();
1070     info.context->setStrokeStyle(SolidStroke);
1071     info.context->setStrokeThickness(lineWidth);
1072
1073     info.context->setStrokeGradient(createLinearGradient(rangeSliderRegularTopOutline, rangeSliderRegularBottomOutline, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
1074     info.context->setFillGradient(createLinearGradient(rangeSliderRegularTop, rangeSliderRegularBottom, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
1075
1076     Path path;
1077     path.addRoundedRect(rect, smallCorner);
1078     info.context->fillPath(path);
1079
1080     IntRect rect2 = rect;
1081     rect2.setX(rect2.x() + 1);
1082     rect2.setHeight(rect2.height() - 2);
1083     rect2.setY(rect2.y() + 1);
1084     info.context->setStrokeStyle(NoStroke);
1085     info.context->setStrokeThickness(0);
1086     if (renderProgress->isDeterminate()) {
1087         rect2.setWidth(rect2.width() * renderProgress->position() - 2);
1088         info.context->setFillGradient(createLinearGradient(progressRegularTop, progressRegularBottom, rect2.maxXMinYCorner(), rect2.maxXMaxYCorner()));
1089     } else {
1090         // Animating
1091         rect2.setWidth(rect2.width() - 2);
1092         RefPtr<Gradient> gradient = Gradient::create(rect2.minXMaxYCorner(), rect2.maxXMaxYCorner());
1093         gradient->addColorStop(0.0, Color(progressRegularBottom));
1094         gradient->addColorStop(renderProgress->animationProgress(), Color(progressRegularTop));
1095         gradient->addColorStop(1.0, Color(progressRegularBottom));
1096         info.context->setFillGradient(gradient);
1097     }
1098     Path path2;
1099     path2.addRoundedRect(rect2, smallCorner);
1100     info.context->fillPath(path2);
1101
1102     info.context->restore();
1103     return false;
1104 }
1105
1106 Color RenderThemeBlackBerry::platformActiveTextSearchHighlightColor() const
1107 {
1108     return Color(255, 150, 50); // Orange.
1109 }
1110
1111 Color RenderThemeBlackBerry::platformInactiveTextSearchHighlightColor() const
1112 {
1113     return Color(255, 255, 0); // Yellow.
1114 }
1115
1116 } // namespace WebCore