cd8608e79bad82441d283d2c15e1b403c545281d
[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 "InputType.h"
29 #include "MediaControlElements.h"
30 #include "MediaPlayerPrivateBlackBerry.h"
31 #include "Page.h"
32 #include "PaintInfo.h"
33 #include "RenderFullScreen.h"
34 #include "RenderProgress.h"
35 #include "RenderSlider.h"
36 #include "RenderView.h"
37 #include "UserAgentStyleSheets.h"
38
39 #include <BlackBerryPlatformLog.h>
40
41 namespace WebCore {
42
43 // Sizes (unit px)
44 const unsigned smallRadius = 1;
45 const unsigned largeRadius = 3;
46 const unsigned lineWidth = 1;
47 const float marginSize = 4;
48 const float mediaControlsHeight = 44;
49 const float mediaBackButtonHeight = 33;
50 // Scale exit-fullscreen button size.
51 const float mediaFullscreenButtonHeightRatio = 5 / 11.0;
52 const float mediaFullscreenButtonWidthRatio = 3 / 11.0;
53 const float mediaSliderOutlineWidth = 2;
54 const float mediaSliderTrackRadius = 3;
55 const float mediaSliderThumbWidth = 25;
56 const float mediaSliderThumbHeight = 25;
57 const float mediaSliderThumbRadius = 3;
58 const float sliderThumbWidth = 15;
59 const float sliderThumbHeight = 25;
60
61 // Checkbox check scalers
62 const float checkboxLeftX = 7 / 40.0;
63 const float checkboxLeftY = 1 / 2.0;
64 const float checkboxMiddleX = 19 / 50.0;
65 const float checkboxMiddleY = 7 / 25.0;
66 const float checkboxRightX = 33 / 40.0;
67 const float checkboxRightY = 1 / 5.0;
68 const float checkboxStrokeThickness = 6.5;
69
70 // Radio button scaler
71 const float radioButtonCheckStateScaler = 7 / 30.0;
72
73 // Multipliers
74 const unsigned paddingDivisor = 10;
75 const unsigned fullScreenEnlargementFactor = 2;
76 const float scaleFactorThreshold = 2.0;
77
78 // Slice length
79 const int smallSlice = 8;
80 const int mediumSlice = 10;
81 const int largeSlice = 13;
82
83 // Slider Aura, calculated from UX spec
84 const float auraRatio = 1.62;
85
86 // Dropdown arrow position, calculated from UX spec
87 const float xPositionRatio = 3;
88 const float yPositionRatio = 0.38;
89 const float widthRatio = 3;
90 const float heightRatio = 0.23;
91
92 // Colors
93 const RGBA32 caretBottom = 0xff2163bf;
94 const RGBA32 caretTop = 0xff69a5fa;
95
96 const RGBA32 regularBottom = 0xffdcdee4;
97 const RGBA32 regularTop = 0xfff7f2ee;
98 const RGBA32 hoverBottom = 0xffb5d3fc;
99 const RGBA32 hoverTop = 0xffcceaff;
100 const RGBA32 depressedBottom = 0xff3388ff;
101 const RGBA32 depressedTop = 0xff66a0f2;
102 const RGBA32 disabledBottom = 0xffe7e7e7;
103 const RGBA32 disabledTop = 0xffefefef;
104
105 const RGBA32 regularBottomOutline = 0xff6e7073;
106 const RGBA32 regularTopOutline = 0xffb9b8b8;
107 const RGBA32 hoverBottomOutline = 0xff2163bf;
108 const RGBA32 hoverTopOutline = 0xff69befa;
109 const RGBA32 depressedBottomOutline = 0xff0c3d81;
110 const RGBA32 depressedTopOutline = 0xff1d4d70;
111 const RGBA32 disabledOutline = 0xffd5d9de;
112
113 const RGBA32 progressRegularBottom = caretTop;
114 const RGBA32 progressRegularTop = caretBottom;
115
116 const RGBA32 rangeSliderRegularBottom = 0xfff6f2ee;
117 const RGBA32 rangeSliderRegularTop = 0xffdee0e5;
118 const RGBA32 rangeSliderRollBottom = 0xffc9e8fe;
119 const RGBA32 rangeSliderRollTop = 0xffb5d3fc;
120
121 const RGBA32 rangeSliderRegularBottomOutline = 0xffb9babd;
122 const RGBA32 rangeSliderRegularTopOutline = 0xffb7b7b7;
123 const RGBA32 rangeSliderRollBottomOutline = 0xff67abe0;
124 const RGBA32 rangeSliderRollTopOutline = 0xff69adf9;
125
126 const RGBA32 dragRegularLight = 0xfffdfdfd;
127 const RGBA32 dragRegularDark = 0xffbababa;
128 const RGBA32 dragRollLight = 0xfff2f2f2;
129 const RGBA32 dragRollDark = 0xff69a8ff;
130
131 const RGBA32 blackPen = Color::black;
132 const RGBA32 focusRingPen = 0xffa3c8fe;
133
134 const RGBA32 mediaSliderTrackOutline = 0xff848587;
135 const RGBA32 mediaSliderTrackPlayed = 0xff2b8fff;
136 const RGBA32 mediaSliderTrackBuffered = 0xffbbbdbf;
137
138 const RGBA32 selection = 0xff2b8fff;
139
140 float RenderThemeBlackBerry::defaultFontSize = 16;
141
142 const String& RenderThemeBlackBerry::defaultGUIFont()
143 {
144     DEFINE_STATIC_LOCAL(String, fontFace, (ASCIILiteral("Slate Pro")));
145     return fontFace;
146 }
147
148 static PassRefPtr<Gradient> createLinearGradient(RGBA32 top, RGBA32 bottom, const IntPoint& a, const IntPoint& b)
149 {
150     RefPtr<Gradient> gradient = Gradient::create(a, b);
151     gradient->addColorStop(0.0, Color(top));
152     gradient->addColorStop(1.0, Color(bottom));
153     return gradient.release();
154 }
155
156 static RenderSlider* determineRenderSlider(RenderObject* object)
157 {
158     ASSERT(object->isSliderThumb());
159     // The RenderSlider is an ancestor of the slider thumb.
160     while (object && !object->isSlider())
161         object = object->parent();
162     return toRenderSlider(object);
163 }
164
165 static float determineFullScreenMultiplier(Element* element)
166 {
167     float fullScreenMultiplier = 1.0;
168 #if ENABLE(FULLSCREEN_API) && ENABLE(VIDEO)
169     if (element && element->document()->webkitIsFullScreen() && element->document()->webkitCurrentFullScreenElement() == toParentMediaElement(element)) {
170         if (Page* page = element->document()->page()) {
171             if (page->deviceScaleFactor() < scaleFactorThreshold)
172                 fullScreenMultiplier = fullScreenEnlargementFactor;
173
174             // The way the BlackBerry port implements the FULLSCREEN_API for media elements
175             // might result in the controls being oversized, proportionally to the current page
176             // scale. That happens because the fullscreen element gets sized to be as big as the
177             // viewport size, and the viewport size might get outstretched to fit to the screen dimensions.
178             // To fix that, lets strips out the Page scale factor from the media controls multiplier.
179             float scaleFactor = element->document()->view()->hostWindow()->platformPageClient()->currentZoomFactor();
180             float scaleFactorFudge = 1 / page->deviceScaleFactor();
181             fullScreenMultiplier /= scaleFactor * scaleFactorFudge;
182         }
183     }
184 #endif
185     return fullScreenMultiplier;
186 }
187
188 static void drawControl(GraphicsContext* gc, const FloatRect& rect, Image* img)
189 {
190     if (!img)
191         return;
192     FloatRect srcRect(0, 0, img->width(), img->height());
193     gc->drawImage(img, ColorSpaceDeviceRGB, rect, srcRect);
194 }
195
196 static void drawThreeSliceHorizontal(GraphicsContext* gc, const IntRect& rect, Image* img, int slice)
197 {
198     if (!img)
199         return;
200
201     FloatSize dstSlice(rect.height() / 2, rect.height());
202     FloatRect srcRect(0, 0, slice, img->height());
203     FloatRect dstRect(rect.location(), dstSlice);
204
205     gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
206     srcRect.move(img->width() - srcRect.width(), 0);
207     dstRect.move(rect.width() - dstRect.width(), 0);
208     gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
209
210     srcRect = FloatRect(slice, 0, img->width() - 2 * slice, img->height());
211     dstRect = FloatRect(rect.x() + dstSlice.width(), rect.y(), rect.width() - 2 * dstSlice.width(), dstSlice.height());
212     gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
213 }
214
215 static void drawThreeSliceVertical(GraphicsContext* gc, const IntRect& rect, Image* img, int slice)
216 {
217     if (!img)
218         return;
219
220     FloatSize dstSlice(rect.width(), rect.width() / 2);
221     FloatRect srcRect(0, 0, img->width(), slice);
222     FloatRect dstRect(rect.location(), dstSlice);
223
224     gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
225     srcRect.move(0, img->height() - srcRect.height());
226     dstRect.move(0, rect.height() - dstRect.height());
227     gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
228
229     srcRect = FloatRect(0, slice, img->width(), img->height() - 2 * slice);
230     dstRect = FloatRect(rect.x(), rect.y() + dstSlice.height(), dstSlice.width(), rect.height() - 2 * dstSlice.height());
231     gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
232 }
233
234 static void drawNineSlice(GraphicsContext* gc, const IntRect& rect, double scale, Image* img, int slice)
235 {
236     if (!img)
237         return;
238     if (rect.height() * scale < 101.0)
239         scale = 101.0 / rect.height();
240     FloatSize dstSlice(slice / scale, slice / scale);
241     FloatRect srcRect(0, 0, slice, slice);
242     FloatRect dstRect(rect.location(), dstSlice);
243     gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
244     srcRect.move(img->width() - srcRect.width(), 0);
245     dstRect.move(rect.width() - dstRect.width(), 0);
246     gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
247     srcRect.move(0, img->height() - srcRect.height());
248     dstRect.move(0, rect.height() - dstRect.height());
249     gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
250     srcRect.move(-(img->width() - srcRect.width()), 0);
251     dstRect.move(-(rect.width() - dstRect.width()), 0);
252     gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
253
254     srcRect = FloatRect(slice, 0, img->width() - 2 * slice, slice);
255     dstRect = FloatRect(rect.x() + dstSlice.width(), rect.y(), rect.width() - 2 * dstSlice.width(), dstSlice.height());
256     gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
257     srcRect.move(0, img->height() - srcRect.height());
258     dstRect.move(0, rect.height() - dstRect.height());
259     gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
260
261     srcRect = FloatRect(0, slice, slice, img->height() - 2 * slice);
262     dstRect = FloatRect(rect.x(), rect.y() + dstSlice.height(), dstSlice.width(), rect.height() - 2 * dstSlice.height());
263     gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
264     srcRect.move(img->width() - srcRect.width(), 0);
265     dstRect.move(rect.width() - dstRect.width(), 0);
266     gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
267
268     srcRect = FloatRect(slice, slice, img->width() - 2 * slice, img->height() - 2 * slice);
269     dstRect = FloatRect(rect.x() + dstSlice.width(), rect.y() + dstSlice.height(), rect.width() - 2 * dstSlice.width(), rect.height() - 2 * dstSlice.height());
270     gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
271 }
272
273 static RefPtr<Image> loadImage(const char* filename)
274 {
275     RefPtr<Image> resource;
276     resource = Image::loadPlatformResource(filename).leakRef();
277     if (!resource) {
278         BlackBerry::Platform::logAlways(BlackBerry::Platform::LogLevelWarn, "RenderThemeBlackBerry failed to load %s.png", filename);
279         return 0;
280     }
281     return resource;
282 }
283
284 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
285 {
286     static RenderTheme* theme = RenderThemeBlackBerry::create().leakRef();
287     return theme;
288 }
289
290 PassRefPtr<RenderTheme> RenderThemeBlackBerry::create()
291 {
292     return adoptRef(new RenderThemeBlackBerry());
293 }
294
295 RenderThemeBlackBerry::RenderThemeBlackBerry()
296 {
297 }
298
299 RenderThemeBlackBerry::~RenderThemeBlackBerry()
300 {
301 }
302
303 String RenderThemeBlackBerry::extraDefaultStyleSheet()
304 {
305     return String(themeBlackBerryUserAgentStyleSheet, sizeof(themeBlackBerryUserAgentStyleSheet));
306 }
307
308 #if ENABLE(VIDEO)
309 String RenderThemeBlackBerry::extraMediaControlsStyleSheet()
310 {
311     return String(mediaControlsBlackBerryUserAgentStyleSheet, sizeof(mediaControlsBlackBerryUserAgentStyleSheet));
312 }
313 #endif
314
315 #if ENABLE(FULLSCREEN_API)
316 String RenderThemeBlackBerry::extraFullScreenStyleSheet()
317 {
318     return String(mediaControlsBlackBerryFullscreenUserAgentStyleSheet, sizeof(mediaControlsBlackBerryFullscreenUserAgentStyleSheet));
319 }
320 #endif
321
322 double RenderThemeBlackBerry::caretBlinkInterval() const
323 {
324     return 0; // Turn off caret blinking.
325 }
326
327 void RenderThemeBlackBerry::systemFont(int propId, FontDescription& fontDescription) const
328 {
329     float fontSize = defaultFontSize;
330
331     // Both CSSValueWebkitControl and CSSValueWebkitSmallControl should use default font size which looks better on the controls.
332     if (propId == CSSValueWebkitMiniControl) {
333         // Why 2 points smaller? Because that's what Gecko does. Note that we
334         // are assuming a 96dpi screen, which is the default value we use on Windows.
335         static const float pointsPerInch = 72.0f;
336         static const float pixelsPerInch = 96.0f;
337         fontSize -= (2.0f / pointsPerInch) * pixelsPerInch;
338     }
339
340     fontDescription.firstFamily().setFamily(defaultGUIFont());
341     fontDescription.setSpecifiedSize(fontSize);
342     fontDescription.setIsAbsoluteSize(true);
343     fontDescription.setGenericFamily(FontDescription::NoFamily);
344     fontDescription.setWeight(FontWeightNormal);
345     fontDescription.setItalic(false);
346 }
347
348 void RenderThemeBlackBerry::setButtonStyle(RenderStyle* style) const
349 {
350     Length vertPadding(int(style->fontSize() / paddingDivisor), Fixed);
351     style->setPaddingTop(vertPadding);
352     style->setPaddingBottom(vertPadding);
353 }
354
355 void RenderThemeBlackBerry::adjustButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
356 {
357     setButtonStyle(style);
358     style->setCursor(CURSOR_WEBKIT_GRAB);
359 }
360
361 void RenderThemeBlackBerry::adjustTextAreaStyle(StyleResolver*, RenderStyle* style, Element*) const
362 {
363     setButtonStyle(style);
364 }
365
366 bool RenderThemeBlackBerry::paintTextArea(RenderObject* object, const PaintInfo& info, const IntRect& rect)
367 {
368     return paintTextFieldOrTextAreaOrSearchField(object, info, rect);
369 }
370
371 void RenderThemeBlackBerry::adjustTextFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
372 {
373     setButtonStyle(style);
374 }
375
376 bool RenderThemeBlackBerry::paintTextFieldOrTextAreaOrSearchField(RenderObject* object, const PaintInfo& info, const IntRect& rect)
377 {
378     ASSERT(info.context);
379     GraphicsContext* context = info.context;
380
381     static RefPtr<Image> bg, bgDisabled, bgHighlight;
382     if (!bg) {
383         bg = loadImage("core_textinput_bg");
384         bgDisabled = loadImage("core_textinput_bg_disabled");
385         bgHighlight = loadImage("core_textinput_bg_highlight");
386     }
387
388     AffineTransform ctm = context->getCTM();
389     if (isEnabled(object) && bg)
390         drawNineSlice(context, rect, ctm.xScale(), bg.get(), smallSlice);
391     if (!isEnabled(object) && bgDisabled)
392         drawNineSlice(context, rect, ctm.xScale(), bgDisabled.get(), smallSlice);
393
394     if ((isHovered(object) || isFocused(object) || isPressed(object)) && bgHighlight)
395         drawNineSlice(context, rect, ctm.xScale(), bgHighlight.get(), smallSlice);
396
397     return false;
398 }
399
400 bool RenderThemeBlackBerry::paintTextField(RenderObject* object, const PaintInfo& info, const IntRect& rect)
401 {
402     return paintTextFieldOrTextAreaOrSearchField(object, info, rect);
403 }
404
405 void RenderThemeBlackBerry::adjustSearchFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
406 {
407     setButtonStyle(style);
408 }
409
410 void RenderThemeBlackBerry::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
411 {
412     static const float defaultControlFontPixelSize = 10;
413     static const float defaultCancelButtonSize = 13;
414     static const float minCancelButtonSize = 5;
415
416     // Scale the button size based on the font size
417     float fontScale = style->fontSize() / defaultControlFontPixelSize;
418     int cancelButtonSize = lroundf(std::max(minCancelButtonSize, defaultCancelButtonSize * fontScale));
419     Length length(cancelButtonSize, Fixed);
420     style->setWidth(length);
421     style->setHeight(length);
422 }
423
424 bool RenderThemeBlackBerry::paintSearchField(RenderObject* object, const PaintInfo& info, const IntRect& rect)
425 {
426     return paintTextFieldOrTextAreaOrSearchField(object, info, rect);
427 }
428
429 IntRect RenderThemeBlackBerry::convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, LayoutRect partRect, const IntRect& localOffset) const
430 {
431     // Compute an offset between the part renderer and the input renderer.
432     LayoutSize offsetFromInputRenderer = -partRenderer->offsetFromAncestorContainer(inputRenderer);
433     // Move the rect into partRenderer's coords.
434     partRect.move(offsetFromInputRenderer);
435     // Account for the local drawing offset.
436     partRect.move(localOffset.x(), localOffset.y());
437
438     return pixelSnappedIntRect(partRect);
439 }
440
441
442 bool RenderThemeBlackBerry::paintSearchFieldCancelButton(RenderObject* cancelButtonObject, const PaintInfo& paintInfo, const IntRect& r)
443 {
444     Node* input = cancelButtonObject->node()->shadowAncestorNode();
445     if (!input->renderer()->isBox())
446         return false;
447
448     RenderBox* inputRenderBox = toRenderBox(input->renderer());
449     LayoutRect inputContentBox = inputRenderBox->contentBoxRect();
450
451     // Make sure the scaled button stays square and will fit in its parent's box.
452     LayoutUnit cancelButtonSize = std::min(inputContentBox.width(), std::min<LayoutUnit>(inputContentBox.height(), r.height()));
453     // Calculate cancel button's coordinates relative to the input element.
454     // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will
455     // be one pixel closer to the bottom of the field. This tends to look better with the text.
456     LayoutRect cancelButtonRect(cancelButtonObject->offsetFromAncestorContainer(inputRenderBox).width(),
457                                 inputContentBox.y() + (inputContentBox.height() - cancelButtonSize + 1) / 2,
458                                 cancelButtonSize, cancelButtonSize);
459     IntRect paintingRect = convertToPaintingRect(inputRenderBox, cancelButtonObject, cancelButtonRect, r);
460
461     static Image* cancelImage = Image::loadPlatformResource("searchCancel").leakRef();
462     static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").leakRef();
463     paintInfo.context->drawImage(isPressed(cancelButtonObject) ? cancelPressedImage : cancelImage,
464                                  cancelButtonObject->style()->colorSpace(), paintingRect);
465     return false;
466 }
467
468 void RenderThemeBlackBerry::adjustMenuListButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
469 {
470     // These seem to be reasonable padding values from observation.
471     const int paddingLeft = 8;
472     const int paddingRight = 4;
473
474     const int minHeight = style->fontSize() * 2;
475
476     style->resetPadding();
477     style->setMinHeight(Length(minHeight, Fixed));
478     style->setLineHeight(RenderStyle::initialLineHeight());
479
480     style->setPaddingRight(Length(minHeight + paddingRight, Fixed));
481     style->setPaddingLeft(Length(paddingLeft, Fixed));
482     style->setCursor(CURSOR_WEBKIT_GRAB);
483 }
484
485 void RenderThemeBlackBerry::calculateButtonSize(RenderStyle* style) const
486 {
487     int size = style->fontSize();
488     Length length(size, Fixed);
489     if (style->appearance() == CheckboxPart || style->appearance() == RadioPart) {
490         style->setWidth(length);
491         style->setHeight(length);
492         return;
493     }
494
495     // If the width and height are both specified, then we have nothing to do.
496     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
497         return;
498
499     if (style->width().isIntrinsicOrAuto())
500         style->setWidth(length);
501
502     if (style->height().isAuto())
503         style->setHeight(length);
504 }
505
506 bool RenderThemeBlackBerry::paintCheckbox(RenderObject* object, const PaintInfo& info, const IntRect& rect)
507 {
508     ASSERT(info.context);
509     GraphicsContext* context = info.context;
510
511     static RefPtr<Image> disabled, background, inactive, pressed, active, activeMark, disableMark;
512     if (!disabled) {
513         disabled = loadImage("core_checkbox_disabled");
514         background = loadImage("core_checkbox_moat");
515         inactive = loadImage("core_checkbox_inactive");
516         pressed = loadImage("core_checkbox_pressed");
517         active = loadImage("core_checkbox_active");
518         activeMark = loadImage("core_checkbox_active_mark");
519         disableMark = loadImage("core_checkbox_disabled_mark");
520     }
521
522     // Caculate where to put center checkmark.
523     FloatRect tmpRect(rect);
524
525     float centerX = ((float(inactive->width()) - float(activeMark->width())) / float(inactive->width()) * tmpRect.width() / 2) + tmpRect.x();
526     float centerY = ((float(inactive->height()) - float(activeMark->height())) / float(inactive->height()) * tmpRect.height() / 2) + tmpRect.y();
527     float width = float(activeMark->width()) / float(inactive->width()) * tmpRect.width();
528     float height = float(activeMark->height()) / float(inactive->height()) * tmpRect.height();
529     FloatRect centerRect(centerX, centerY, width, height);
530
531     drawControl(context, rect, background.get());
532
533     if (isEnabled(object)) {
534         if (isPressed(object)) {
535             drawControl(context, rect, pressed.get());
536             if (isChecked(object)) {
537                 // FIXME: need opacity 30% on activeMark
538                 drawControl(context, centerRect, activeMark.get());
539             }
540         } else {
541             drawControl(context, rect, inactive.get());
542             if (isChecked(object)) {
543                 drawControl(context, rect, active.get());
544                 drawControl(context, centerRect, activeMark.get());
545             }
546         }
547     } else {
548         drawControl(context, rect, disabled.get());
549         if (isChecked(object))
550             drawControl(context, rect, disableMark.get());
551     }
552     return false;
553 }
554
555 void RenderThemeBlackBerry::setCheckboxSize(RenderStyle* style) const
556 {
557     calculateButtonSize(style);
558 }
559
560 bool RenderThemeBlackBerry::paintRadio(RenderObject* object, const PaintInfo& info, const IntRect& rect)
561 {
562     ASSERT(info.context);
563     GraphicsContext* context = info.context;
564
565     static RefPtr<Image> disabled, disabledActive, inactive, pressed, active, activeMark;
566     if (!disabled) {
567         disabled = loadImage("core_radiobutton_disabled");
568         disabledActive = loadImage("core_radiobutton_disabled_active");
569         inactive = loadImage("core_radiobutton_inactive");
570         pressed = loadImage("core_radiobutton_pressed");
571         active = loadImage("core_radiobutton_active");
572         activeMark = loadImage("core_radiobutton_active_mark");
573     }
574
575     // Caculate where to put center circle.
576     FloatRect tmpRect(rect);
577
578     float centerX = ((float(inactive->width()) - float(activeMark->width())) / float(inactive->width()) * tmpRect.width() / 2)+ tmpRect.x();
579     float centerY = ((float(inactive->height()) - float(activeMark->height())) / float(inactive->height()) * tmpRect.height() / 2) + tmpRect.y();
580     float width = float(activeMark->width()) / float(inactive->width()) * tmpRect.width();
581     float height = float(activeMark->height()) / float(inactive->height()) * tmpRect.height();
582     FloatRect centerRect(centerX, centerY, width, height);
583
584     if (isEnabled(object)) {
585         if (isPressed(object)) {
586             drawControl(context, rect, pressed.get());
587             if (isChecked(object)) {
588                 // FIXME: need opacity 30% on activeMark
589                 drawControl(context, centerRect, activeMark.get());
590             }
591         } else {
592             drawControl(context, rect, inactive.get());
593             if (isChecked(object)) {
594                 drawControl(context, rect, active.get());
595                 drawControl(context, centerRect, activeMark.get());
596             }
597         }
598     } else {
599         drawControl(context, rect, inactive.get());
600         if (isChecked(object))
601             drawControl(context, rect, disabledActive.get());
602         else
603             drawControl(context, rect, disabled.get());
604     }
605     return false;
606 }
607
608 void RenderThemeBlackBerry::setRadioSize(RenderStyle* style) const
609 {
610     calculateButtonSize(style);
611 }
612
613 // If this function returns false, WebCore assumes the button is fully decorated
614 bool RenderThemeBlackBerry::paintButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
615 {
616     ASSERT(info.context);
617     info.context->save();
618     GraphicsContext* context = info.context;
619
620     static RefPtr<Image> disabled, inactive, pressed;
621     if (!disabled) {
622         disabled = loadImage("core_button_disabled");
623         inactive = loadImage("core_button_inactive");
624         pressed = loadImage("core_button_pressed");
625     }
626
627     AffineTransform ctm = context->getCTM();
628     if (!isEnabled(object)) {
629         drawNineSlice(context, rect, ctm.xScale(), inactive.get(), largeSlice);
630         drawNineSlice(context, rect, ctm.xScale(), disabled.get(), largeSlice);
631     } else if (isPressed(object)) {
632         drawNineSlice(context, rect, ctm.xScale(), pressed.get(), largeSlice);
633     } else
634         drawNineSlice(context, rect, ctm.xScale(), inactive.get(), largeSlice);
635
636     context->restore();
637     return false;
638 }
639
640 void RenderThemeBlackBerry::adjustMenuListStyle(StyleResolver* css, RenderStyle* style, Element* element) const
641 {
642     adjustMenuListButtonStyle(css, style, element);
643 }
644
645 static IntRect computeMenuListArrowButtonRect(const IntRect& rect)
646 {
647     // FIXME: The menu list arrow button should have a minimum and maximum width (to ensure usability) or
648     // scale with respect to the font size used in the menu list control or some combination of both.
649     return IntRect(IntPoint(rect.maxX() - rect.height(), rect.y()), IntSize(rect.height(), rect.height()));
650 }
651
652 bool RenderThemeBlackBerry::paintMenuList(RenderObject* object, const PaintInfo& info, const IntRect& rect)
653 {
654     ASSERT(info.context);
655     info.context->save();
656     GraphicsContext* context = info.context;
657
658     static RefPtr<Image> disabled, inactive, pressed, arrowUp, arrowUpPressed;
659     if (!disabled) {
660         disabled = loadImage("core_button_disabled");
661         inactive = loadImage("core_button_inactive");
662         pressed = loadImage("core_button_pressed");
663         arrowUp = loadImage("core_dropdown_button_arrowup");
664         arrowUpPressed = loadImage("core_dropdown_button_arrowup_pressed");
665     }
666
667     FloatRect arrowButtonRectangle(computeMenuListArrowButtonRect(rect));
668     float x = arrowButtonRectangle.x() + arrowButtonRectangle.width() / xPositionRatio;
669     float y = arrowButtonRectangle.y() + arrowButtonRectangle.height() * yPositionRatio;
670     float width = arrowButtonRectangle.width() / widthRatio;
671     float height = arrowButtonRectangle.height() * heightRatio;
672     FloatRect tmpRect(x, y, width, height);
673
674     AffineTransform ctm = context->getCTM();
675     if (!isEnabled(object)) {
676         drawNineSlice(context, rect, ctm.xScale(), inactive.get(), largeSlice);
677         drawNineSlice(context, rect, ctm.xScale(), disabled.get(), largeSlice);
678         drawControl(context, tmpRect, arrowUp.get()); // FIXME: should have a disabled image.
679     } else if (isPressed(object)) {
680         drawNineSlice(context, rect, ctm.xScale(), pressed.get(), largeSlice);
681         drawControl(context, tmpRect, arrowUpPressed.get());
682     } else {
683         drawNineSlice(context, rect, ctm.xScale(), inactive.get(), largeSlice);
684         drawControl(context, tmpRect, arrowUp.get());
685     }
686     context->restore();
687     return false;
688 }
689
690 bool RenderThemeBlackBerry::paintMenuListButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
691 {
692     return paintMenuList(object, info, rect);
693 }
694
695 void RenderThemeBlackBerry::adjustSliderThumbSize(RenderStyle* style, Element* element) const
696 {
697     float fullScreenMultiplier = 1;
698     ControlPart part = style->appearance();
699
700     if (part == MediaSliderThumbPart || part == MediaVolumeSliderThumbPart) {
701         RenderSlider* slider = determineRenderSlider(element->renderer());
702         if (slider)
703             fullScreenMultiplier = determineFullScreenMultiplier(toElement(slider->node()));
704     }
705
706     if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) {
707         style->setWidth(Length((part == SliderThumbVerticalPart ? sliderThumbHeight : sliderThumbWidth) * fullScreenMultiplier, Fixed));
708         style->setHeight(Length((part == SliderThumbVerticalPart ? sliderThumbWidth : sliderThumbHeight) * fullScreenMultiplier, Fixed));
709     } else if (part == MediaVolumeSliderThumbPart || part == MediaSliderThumbPart) {
710         style->setWidth(Length(mediaSliderThumbWidth * fullScreenMultiplier, Fixed));
711         style->setHeight(Length(mediaSliderThumbHeight * fullScreenMultiplier, Fixed));
712     }
713 }
714
715 bool RenderThemeBlackBerry::paintSliderTrack(RenderObject* object, const PaintInfo& info, const IntRect& rect)
716 {
717     const static int SliderTrackHeight = 5;
718     IntRect rect2;
719     if (object->style()->appearance() == SliderHorizontalPart) {
720         rect2.setHeight(SliderTrackHeight);
721         rect2.setWidth(rect.width());
722         rect2.setX(rect.x());
723         rect2.setY(rect.y() + (rect.height() - SliderTrackHeight) / 2);
724     } else {
725         rect2.setHeight(rect.height());
726         rect2.setWidth(SliderTrackHeight);
727         rect2.setX(rect.x() + (rect.width() - SliderTrackHeight) / 2);
728         rect2.setY(rect.y());
729     }
730     return paintSliderTrackRect(object, info, rect2);
731 }
732
733 bool RenderThemeBlackBerry::paintSliderTrackRect(RenderObject* object, const PaintInfo& info, const IntRect& rect)
734 {
735     return paintSliderTrackRect(object, info, rect, rangeSliderRegularTopOutline, rangeSliderRegularBottomOutline, rangeSliderRegularTop, rangeSliderRegularBottom);
736 }
737
738 bool RenderThemeBlackBerry::paintSliderTrackRect(RenderObject* object, const PaintInfo& info, const IntRect& rect, RGBA32 strokeColorStart, RGBA32 strokeColorEnd, RGBA32 fillColorStart, RGBA32 fillColorEnd)
739 {
740     FloatSize smallCorner(mediaSliderTrackRadius, mediaSliderTrackRadius);
741
742     info.context->save();
743     info.context->setStrokeStyle(SolidStroke);
744     info.context->setStrokeThickness(lineWidth);
745
746 #if USE(SKIA)
747     info.context->setStrokeGradient(createLinearGradient(strokeColorStart, strokeColorEnd, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
748     info.context->setFillGradient(createLinearGradient(fillColorStart, fillColorEnd, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
749 #else
750     info.context->setStrokeColor(strokeColorStart, ColorSpaceDeviceRGB);
751     info.context->setFillColor(fillColorStart, ColorSpaceDeviceRGB);
752 #endif
753
754     Path path;
755     path.addRoundedRect(rect, smallCorner);
756     info.context->fillPath(path);
757
758     info.context->restore();
759     return false;
760 }
761
762 bool RenderThemeBlackBerry::paintSliderTrackRect(RenderObject* object, const PaintInfo& info, const IntRect& rect, Image* inactive)
763 {
764     ASSERT(info.context);
765     info.context->save();
766     GraphicsContext* context = info.context;
767
768     static RefPtr<Image> disabled;
769     if (!disabled)
770         disabled = loadImage("core_slider_fill_disabled");
771
772     if (rect.width() > rect.height()) {
773         if (isEnabled(object))
774             drawThreeSliceHorizontal(context, rect, inactive, mediumSlice);
775         else
776             drawThreeSliceHorizontal(context, rect, disabled.get(), (smallSlice - 1));
777     } else {
778         if (isEnabled(object))
779             drawThreeSliceVertical(context, rect, inactive, mediumSlice);
780         else
781             drawThreeSliceVertical(context, rect, disabled.get(), (smallSlice - 1));
782     }
783
784     context->restore();
785     return false;
786 }
787
788 bool RenderThemeBlackBerry::paintSliderThumb(RenderObject* object, const PaintInfo& info, const IntRect& rect)
789 {
790     ASSERT(info.context);
791     info.context->save();
792     GraphicsContext* context = info.context;
793
794     static RefPtr<Image> disabled, inactive, pressed, aura;
795     if (!disabled) {
796         disabled = loadImage("core_slider_handle_disabled");
797         inactive = loadImage("core_slider_handle");
798         pressed = loadImage("core_slider_handle_pressed");
799         aura = loadImage("core_slider_aura");
800     }
801
802     FloatRect tmpRect(rect);
803     float length = std::max(tmpRect.width(), tmpRect.height());
804     if (tmpRect.width() > tmpRect.height()) {
805         tmpRect.setY(tmpRect.y() - (length - tmpRect.height()) / 2);
806         tmpRect.setHeight(length);
807     } else {
808         tmpRect.setX(tmpRect.x() - (length - tmpRect.width()) / 2);
809         tmpRect.setWidth(length);
810     }
811
812     float auraHeight = length * auraRatio;
813     float auraWidth = auraHeight;
814     float auraX = tmpRect.x() - (auraWidth - tmpRect.width()) / 2;
815     float auraY = tmpRect.y() - (auraHeight - tmpRect.height()) / 2;
816     FloatRect auraRect(auraX, auraY, auraWidth, auraHeight);
817
818     if (!isEnabled(object))
819         drawControl(context, tmpRect, disabled.get());
820     else {
821         if (isPressed(object) || isHovered(object) || isFocused(object)) {
822             drawControl(context, tmpRect, pressed.get());
823             drawControl(context, auraRect, aura.get());
824         } else {
825             drawControl(context, tmpRect, inactive.get());
826         }
827     }
828
829     context->restore();
830     return false;
831 }
832
833 void RenderThemeBlackBerry::adjustMediaControlStyle(StyleResolver*, RenderStyle* style, Element* element) const
834 {
835     float fullScreenMultiplier = determineFullScreenMultiplier(element);
836     HTMLMediaElement* mediaElement = toParentMediaElement(element);
837     if (!mediaElement)
838         return;
839
840     // We use multiples of mediaControlsHeight to make all objects scale evenly
841     Length zero(0, Fixed);
842     Length controlsHeight(mediaControlsHeight * fullScreenMultiplier, Fixed);
843     Length halfControlsWidth(mediaControlsHeight / 2 * fullScreenMultiplier, Fixed);
844     Length displayHeight(mediaControlsHeight / 3 * fullScreenMultiplier, Fixed);
845     Length padding(mediaControlsHeight / 10 * fullScreenMultiplier, Fixed);
846     float fontSize = mediaControlsHeight / 3 * fullScreenMultiplier;
847
848     switch (style->appearance()) {
849     case MediaPlayButtonPart:
850         style->setWidth(controlsHeight);
851         style->setHeight(controlsHeight);
852         break;
853     case MediaMuteButtonPart:
854         style->setPaddingLeft(padding);
855         style->setWidth(controlsHeight);
856         style->setHeight(controlsHeight);
857         break;
858     case MediaRewindButtonPart:
859         // We hi-jack the Rewind Button ID to use it for the divider image
860         style->setWidth(halfControlsWidth);
861         style->setHeight(controlsHeight);
862         break;
863     case MediaEnterFullscreenButtonPart:
864         style->setPaddingRight(padding);
865         style->setWidth(controlsHeight);
866         style->setHeight(controlsHeight);
867         break;
868     case MediaExitFullscreenButtonPart:
869         style->setLeft(zero);
870         style->setWidth(controlsHeight);
871         style->setHeight(controlsHeight);
872         break;
873     case MediaCurrentTimePart:
874     case MediaTimeRemainingPart:
875         style->setHeight(displayHeight);
876         style->setPaddingRight(padding);
877         style->setPaddingLeft(padding);
878         style->setPaddingBottom(padding);
879         style->setFontSize(static_cast<int>(fontSize));
880         break;
881     case MediaVolumeSliderContainerPart:
882         style->setHeight(controlsHeight);
883         style->setBottom(controlsHeight);
884         break;
885     default:
886         break;
887     }
888 }
889
890 void RenderThemeBlackBerry::adjustSliderTrackStyle(StyleResolver*, RenderStyle* style, Element* element) const
891 {
892     float fullScreenMultiplier = determineFullScreenMultiplier(element);
893
894     // We use multiples of mediaControlsHeight to make all objects scale evenly
895     Length controlsHeight(mediaControlsHeight / 2 * fullScreenMultiplier, Fixed);
896     switch (style->appearance()) {
897     case MediaSliderPart:
898     case MediaVolumeSliderPart:
899         style->setHeight(controlsHeight);
900         break;
901     default:
902         break;
903     }
904 }
905
906 static bool paintMediaButton(GraphicsContext* context, const IntRect& rect, Image* image)
907 {
908     context->drawImage(image, ColorSpaceDeviceRGB, rect);
909     return false;
910 }
911
912 bool RenderThemeBlackBerry::paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
913 {
914 #if ENABLE(VIDEO)
915     HTMLMediaElement* mediaElement = toParentMediaElement(object);
916
917     if (!mediaElement)
918         return false;
919
920     static Image* mediaPlay = Image::loadPlatformResource("play").leakRef();
921     static Image* mediaPause = Image::loadPlatformResource("pause").leakRef();
922
923     return paintMediaButton(paintInfo.context, rect, mediaElement->canPlay() ? mediaPlay : mediaPause);
924 #else
925     UNUSED_PARAM(object);
926     UNUSED_PARAM(paintInfo);
927     UNUSED_PARAM(rect);
928     return false;
929 #endif
930 }
931
932 // We hi-jack the Rewind Button code to use it for the divider image
933 bool RenderThemeBlackBerry::paintMediaRewindButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
934 {
935 #if ENABLE(VIDEO)
936     HTMLMediaElement* mediaElement = toParentMediaElement(object);
937
938     if (!mediaElement)
939         return false;
940
941     if (!mediaElement->isFullscreen())
942         return false;
943
944     static Image* divider = Image::loadPlatformResource("divider").leakRef();
945
946     return paintMediaButton(paintInfo.context, rect, divider);
947 #else
948     UNUSED_PARAM(object);
949     UNUSED_PARAM(paintInfo);
950     UNUSED_PARAM(rect);
951     return false;
952 #endif
953 }
954
955 bool RenderThemeBlackBerry::paintMediaMuteButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
956 {
957 #if ENABLE(VIDEO)
958     HTMLMediaElement* mediaElement = toParentMediaElement(object);
959
960     if (!mediaElement)
961         return false;
962
963     static Image* divider = Image::loadPlatformResource("speaker").leakRef();
964
965     return paintMediaButton(paintInfo.context, rect, divider);
966 #else
967     UNUSED_PARAM(object);
968     UNUSED_PARAM(paintInfo);
969     UNUSED_PARAM(rect);
970     return false;
971 #endif
972 }
973
974 bool RenderThemeBlackBerry::paintMediaFullscreenButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
975 {
976 #if ENABLE(VIDEO)
977     HTMLMediaElement* mediaElement = toParentMediaElement(object);
978     if (!mediaElement)
979         return false;
980
981     static Image* mediaEnterFullscreen = Image::loadPlatformResource("fullscreen").leakRef();
982     static Image* mediaExitFullscreen = Image::loadPlatformResource("back").leakRef();
983
984     Image* buttonImage = mediaEnterFullscreen;
985     IntRect currentRect(rect);
986 #if ENABLE(FULLSCREEN_API)
987     if (mediaElement->document()->webkitIsFullScreen() && mediaElement->document()->webkitCurrentFullScreenElement() == mediaElement) {
988         buttonImage = mediaExitFullscreen;
989         IntRect fullscreenRect(rect.x() + (1 - mediaFullscreenButtonWidthRatio) * rect.width() / 2, rect.y() + (1 - mediaFullscreenButtonHeightRatio) * rect.height() / 2,
990             rect.width() * mediaFullscreenButtonWidthRatio, rect.height() * mediaFullscreenButtonHeightRatio);
991         currentRect = fullscreenRect;
992     }
993 #endif
994     return paintMediaButton(paintInfo.context, currentRect, buttonImage);
995 #else
996     UNUSED_PARAM(object);
997     UNUSED_PARAM(paintInfo);
998     UNUSED_PARAM(rect);
999     return false;
1000 #endif
1001 }
1002
1003 bool RenderThemeBlackBerry::paintMediaSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1004 {
1005 #if ENABLE(VIDEO)
1006     HTMLMediaElement* mediaElement = toParentMediaElement(object);
1007     if (!mediaElement)
1008         return false;
1009
1010     float fullScreenMultiplier = determineFullScreenMultiplier(mediaElement);
1011     float loaded = mediaElement->percentLoaded();
1012     float position = mediaElement->duration() > 0 ? (mediaElement->currentTime() / mediaElement->duration()) : 0;
1013
1014     int intrinsicHeight = ceil(mediaSliderThumbHeight / 4);
1015     int x = ceil(rect.x() + (mediaControlsHeight - intrinsicHeight) / 2 * fullScreenMultiplier - fullScreenMultiplier / 2);
1016     int y = ceil(rect.y() + (mediaControlsHeight / 2 - intrinsicHeight) / 2 * fullScreenMultiplier + fullScreenMultiplier / 2);
1017     int w = ceil(rect.width() - (mediaControlsHeight - intrinsicHeight) * fullScreenMultiplier + fullScreenMultiplier / 2);
1018     int h = ceil(intrinsicHeight * fullScreenMultiplier);
1019     IntRect rect2(x, y, w, h);
1020
1021     int wPlayed = ceil(w * position);
1022     int wLoaded = ceil((w - mediaSliderThumbWidth * fullScreenMultiplier) * loaded + mediaSliderThumbWidth * fullScreenMultiplier);
1023
1024     IntRect played(x, y, wPlayed, h);
1025     IntRect buffered(x, y, wLoaded, h);
1026 #if USE(SKIA)
1027     // This is to paint main slider bar.
1028     bool result = paintSliderTrackRect(object, paintInfo, rect2);
1029
1030     if (loaded > 0 || position > 0) {
1031         // This is to paint buffered bar.
1032         paintSliderTrackRect(object, paintInfo, buffered, Color::darkGray, Color::darkGray, Color::darkGray, Color::darkGray);
1033
1034         // This is to paint played part of bar (left of slider thumb) using selection color.
1035         paintSliderTrackRect(object, paintInfo, played, selection, selection, selection, selection);
1036     }
1037 #else // GL renderer
1038     static Image* mediaBackground = Image::loadPlatformResource("core_slider_video_bg").leakRef();
1039     static Image* mediaPlayer = Image::loadPlatformResource("core_slider_played_bg").leakRef();
1040     static Image* mediaCache = Image::loadPlatformResource("core_slider_cache").leakRef();
1041
1042     bool result = paintSliderTrackRect(object, paintInfo, rect2, mediaBackground);
1043
1044     if (loaded > 0 || position > 0) {
1045         // This is to paint buffered bar.
1046         paintSliderTrackRect(object, paintInfo, buffered, mediaCache);
1047
1048         // This is to paint played part of bar (left of slider thumb) using selection color.
1049         paintSliderTrackRect(object, paintInfo, played, mediaPlayer);
1050     }
1051 #endif // USE(SKIA)
1052     return result;
1053 #else
1054     UNUSED_PARAM(object);
1055     UNUSED_PARAM(paintInfo);
1056     UNUSED_PARAM(rect);
1057     return false;
1058 #endif
1059 }
1060
1061 bool RenderThemeBlackBerry::paintMediaSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1062 {
1063 #if ENABLE(VIDEO)
1064 #if USE(SKIA)
1065     RenderSlider* slider = determineRenderSlider(object);
1066     if (!slider)
1067         return false;
1068
1069     float fullScreenMultiplier = determineFullScreenMultiplier(toElement(slider->node()));
1070
1071     paintInfo.context->save();
1072     Path mediaThumbRoundedRectangle;
1073     mediaThumbRoundedRectangle.addRoundedRect(rect, FloatSize(mediaSliderThumbRadius * fullScreenMultiplier, mediaSliderThumbRadius * fullScreenMultiplier));
1074     paintInfo.context->setStrokeStyle(SolidStroke);
1075     paintInfo.context->setStrokeThickness(0.5);
1076     paintInfo.context->setStrokeColor(Color::black, ColorSpaceDeviceRGB);
1077
1078     if (isPressed(object) || isHovered(object) || slider->inDragMode())
1079         paintInfo.context->setFillGradient(createLinearGradient(selection, Color(selection).dark().rgb(), rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
1080     else
1081         paintInfo.context->setFillGradient(createLinearGradient(Color::white, Color(Color::white).dark().rgb(), rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
1082
1083     paintInfo.context->fillPath(mediaThumbRoundedRectangle);
1084     paintInfo.context->restore();
1085
1086     return true;
1087 #else // GL renderer
1088     static Image* disabledMediaSliderThumb = Image::loadPlatformResource("core_slider_handle_disabled").leakRef();
1089     static Image* pressedMediaSliderThumb = Image::loadPlatformResource("core_slider_handle_pressed").leakRef();
1090     static Image* mediaSliderThumb = Image::loadPlatformResource("core_media_handle").leakRef();
1091
1092     if (!isEnabled(object))
1093         return paintMediaButton(paintInfo.context, rect, disabledMediaSliderThumb);
1094     if (isPressed(object) || isHovered(object) || isFocused(object))
1095         return paintMediaButton(paintInfo.context, rect, pressedMediaSliderThumb);
1096     return paintMediaButton(paintInfo.context, rect, mediaSliderThumb);
1097 #endif // USE(SKIA)
1098 #else
1099     UNUSED_PARAM(object);
1100     UNUSED_PARAM(paintInfo);
1101     UNUSED_PARAM(rect);
1102     return false;
1103 #endif
1104 }
1105
1106 bool RenderThemeBlackBerry::paintMediaVolumeSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1107 {
1108 #if ENABLE(VIDEO)
1109     HTMLMediaElement* mediaElement = toParentMediaElement(object);
1110     if (!mediaElement)
1111         return false;
1112
1113     float fullScreenMultiplier = determineFullScreenMultiplier(mediaElement);
1114     float volume = mediaElement->volume() > 0 ? mediaElement->volume() : 0;
1115
1116     int intrinsicHeight = ceil(mediaSliderThumbHeight / 4);
1117     int x = ceil(rect.x() + (mediaControlsHeight - intrinsicHeight) / 2 * fullScreenMultiplier - fullScreenMultiplier / 2);
1118     int y = ceil(rect.y() + (mediaControlsHeight / 2 - intrinsicHeight) / 2 * fullScreenMultiplier + fullScreenMultiplier / 2);
1119     int w = ceil(rect.width() - (mediaControlsHeight - intrinsicHeight) * fullScreenMultiplier + fullScreenMultiplier / 2);
1120     int h = ceil(intrinsicHeight * fullScreenMultiplier);
1121     IntRect rect2(x, y, w, h);
1122     IntRect volumeRect(x, y, ceil(w * volume), h);
1123
1124 #if USE(SKIA)
1125     // This is to paint main volume slider bar.
1126     bool result = paintSliderTrackRect(object, paintInfo, rect2, Color(mediaSliderTrackOutline).rgb(), Color(mediaSliderTrackOutline).rgb(), rangeSliderRegularTop, rangeSliderRegularTop);
1127
1128     if (volume > 0) {
1129         // This is to paint volume bar (left of volume slider thumb) using selection color.
1130         result |= paintSliderTrackRect(object, paintInfo, volumeRect, Color(mediaSliderTrackOutline).rgb(), Color(mediaSliderTrackOutline).rgb(), selection, selection);
1131     }
1132 #else // GL renderer
1133     static Image* volumeBackground = Image::loadPlatformResource("core_slider_video_bg").leakRef();
1134     static Image* volumeBar = Image::loadPlatformResource("core_slider_played_bg").leakRef();
1135
1136     // This is to paint main volume slider bar.
1137     bool result = paintSliderTrackRect(object, paintInfo, rect2, volumeBackground);
1138
1139     if (volume > 0) {
1140         // This is to paint volume bar (left of volume slider thumb) using selection color.
1141         result |= paintSliderTrackRect(object, paintInfo, volumeRect, volumeBar);
1142     }
1143 #endif // USE(SKIA)
1144     return result;
1145 #else
1146     UNUSED_PARAM(object);
1147     UNUSED_PARAM(paintInfo);
1148     UNUSED_PARAM(rect);
1149     return false;
1150 #endif
1151 }
1152
1153 bool RenderThemeBlackBerry::paintMediaVolumeSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1154 {
1155 #if ENABLE(VIDEO)
1156 #if USE(SKIA)
1157     RenderSlider* slider = determineRenderSlider(object);
1158     if (!slider)
1159         return false;
1160
1161     float fullScreenMultiplier = determineFullScreenMultiplier(toElement(slider->node()));
1162
1163     paintInfo.context->save();
1164     Path mediaThumbRoundedRectangle;
1165     mediaThumbRoundedRectangle.addRoundedRect(rect, FloatSize(mediaSliderThumbHeight / 2 * fullScreenMultiplier, mediaSliderThumbHeight / 2 * fullScreenMultiplier));
1166
1167     if (isPressed(object) || isHovered(object) || slider->inDragMode())
1168         paintInfo.context->setFillGradient(createLinearGradient(selection, Color(selection).dark().rgb(), rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
1169     else
1170         paintInfo.context->setFillGradient(createLinearGradient(mediaSliderTrackOutline, Color::black, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
1171
1172     paintInfo.context->fillPath(mediaThumbRoundedRectangle);
1173     paintInfo.context->restore();
1174
1175     return true;
1176 #else // GL renderer
1177     return paintMediaSliderThumb(object, paintInfo, rect);
1178 #endif // USE(SKIA)
1179 #else
1180     UNUSED_PARAM(object);
1181     UNUSED_PARAM(paintInfo);
1182     UNUSED_PARAM(rect);
1183     return false;
1184 #endif
1185 }
1186
1187 Color RenderThemeBlackBerry::platformFocusRingColor() const
1188 {
1189     return focusRingPen;
1190 }
1191
1192 #if ENABLE(TOUCH_EVENTS)
1193 Color RenderThemeBlackBerry::platformTapHighlightColor() const
1194 {
1195     return Color(0, 168, 223, 50);
1196 }
1197 #endif
1198
1199 Color RenderThemeBlackBerry::platformActiveSelectionBackgroundColor() const
1200 {
1201     return Color(0, 168, 223, 50);
1202 }
1203
1204 double RenderThemeBlackBerry::animationRepeatIntervalForProgressBar(RenderProgress* renderProgress) const
1205 {
1206     return renderProgress->isDeterminate() ? 0.0 : 0.1;
1207 }
1208
1209 double RenderThemeBlackBerry::animationDurationForProgressBar(RenderProgress* renderProgress) const
1210 {
1211     return renderProgress->isDeterminate() ? 0.0 : 2.0;
1212 }
1213
1214 bool RenderThemeBlackBerry::paintProgressBar(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1215 {
1216     if (!object->isProgress())
1217         return true;
1218
1219     RenderProgress* renderProgress = toRenderProgress(object);
1220
1221     FloatSize smallCorner(smallRadius, smallRadius);
1222
1223     info.context->save();
1224     info.context->setStrokeStyle(SolidStroke);
1225     info.context->setStrokeThickness(lineWidth);
1226
1227     info.context->setStrokeGradient(createLinearGradient(rangeSliderRegularTopOutline, rangeSliderRegularBottomOutline, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
1228     info.context->setFillGradient(createLinearGradient(rangeSliderRegularTop, rangeSliderRegularBottom, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
1229
1230     Path path;
1231     path.addRoundedRect(rect, smallCorner);
1232     info.context->fillPath(path);
1233
1234     IntRect rect2 = rect;
1235     rect2.setX(rect2.x() + 1);
1236     rect2.setHeight(rect2.height() - 2);
1237     rect2.setY(rect2.y() + 1);
1238     info.context->setStrokeStyle(NoStroke);
1239     info.context->setStrokeThickness(0);
1240     if (renderProgress->isDeterminate()) {
1241         rect2.setWidth(rect2.width() * renderProgress->position() - 2);
1242         info.context->setFillGradient(createLinearGradient(progressRegularTop, progressRegularBottom, rect2.maxXMinYCorner(), rect2.maxXMaxYCorner()));
1243     } else {
1244         // Animating
1245         rect2.setWidth(rect2.width() - 2);
1246         RefPtr<Gradient> gradient = Gradient::create(rect2.minXMaxYCorner(), rect2.maxXMaxYCorner());
1247         gradient->addColorStop(0.0, Color(progressRegularBottom));
1248         gradient->addColorStop(renderProgress->animationProgress(), Color(progressRegularTop));
1249         gradient->addColorStop(1.0, Color(progressRegularBottom));
1250         info.context->setFillGradient(gradient);
1251     }
1252     Path path2;
1253     path2.addRoundedRect(rect2, smallCorner);
1254     info.context->fillPath(path2);
1255
1256     info.context->restore();
1257     return false;
1258 }
1259
1260 Color RenderThemeBlackBerry::platformActiveTextSearchHighlightColor() const
1261 {
1262     return Color(255, 150, 50); // Orange.
1263 }
1264
1265 Color RenderThemeBlackBerry::platformInactiveTextSearchHighlightColor() const
1266 {
1267     return Color(255, 255, 0); // Yellow.
1268 }
1269
1270 } // namespace WebCore