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.
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.
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.
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
22
#include "RenderThemeBlackBerry.h"
24
#include "CSSValueKeywords.h"
26
#include "HTMLMediaElement.h"
27
#include "HostWindow.h"
28
#include "MediaControlElements.h"
29
#include "MediaPlayerPrivateBlackBerry.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"
38
#include <BlackBerryPlatformLog.h>
43
const unsigned smallRadius = 1;
44
const unsigned largeRadius = 3;
45
const unsigned lineWidth = 1;
46
const float marginSize = 4;
47
const float mediaControlsHeight = 32;
48
const float mediaSliderThumbWidth = 40;
49
const float mediaSliderThumbHeight = 13;
50
const float mediaSliderThumbRadius = 5;
51
const float sliderThumbWidth = 15;
52
const float sliderThumbHeight = 25;
54
// Checkbox check scalers
55
const float checkboxLeftX = 7 / 40.0;
56
const float checkboxLeftY = 1 / 2.0;
57
const float checkboxMiddleX = 19 / 50.0;
58
const float checkboxMiddleY = 7 / 25.0;
59
const float checkboxRightX = 33 / 40.0;
60
const float checkboxRightY = 1 / 5.0;
61
const float checkboxStrokeThickness = 6.5;
63
// Radio button scaler
64
const float radioButtonCheckStateScaler = 7 / 30.0;
67
const unsigned paddingDivisor = 10;
68
const unsigned fullScreenEnlargementFactor = 2;
69
const float scaleFactorThreshold = 2.0;
72
const int smallSlice = 8;
73
const int mediumSlice = 10;
74
const int largeSlice = 13;
76
// Slider Aura, calculated from UX spec
77
const float auraRatio = 1.62;
79
// Dropdown arrow position, calculated from UX spec
80
const float xPositionRatio = 3;
81
const float yPositionRatio = 0.38;
82
const float widthRatio = 3;
83
const float heightRatio = 0.23;
86
const RGBA32 caretBottom = 0xff2163bf;
87
const RGBA32 caretTop = 0xff69a5fa;
89
const RGBA32 regularBottom = 0xffdcdee4;
90
const RGBA32 regularTop = 0xfff7f2ee;
91
const RGBA32 hoverBottom = 0xffb5d3fc;
92
const RGBA32 hoverTop = 0xffcceaff;
93
const RGBA32 depressedBottom = 0xff3388ff;
94
const RGBA32 depressedTop = 0xff66a0f2;
95
const RGBA32 disabledBottom = 0xffe7e7e7;
96
const RGBA32 disabledTop = 0xffefefef;
98
const RGBA32 regularBottomOutline = 0xff6e7073;
99
const RGBA32 regularTopOutline = 0xffb9b8b8;
100
const RGBA32 hoverBottomOutline = 0xff2163bf;
101
const RGBA32 hoverTopOutline = 0xff69befa;
102
const RGBA32 depressedBottomOutline = 0xff0c3d81;
103
const RGBA32 depressedTopOutline = 0xff1d4d70;
104
const RGBA32 disabledOutline = 0xffd5d9de;
106
const RGBA32 progressRegularBottom = caretTop;
107
const RGBA32 progressRegularTop = caretBottom;
109
const RGBA32 rangeSliderRegularBottom = 0xfff6f2ee;
110
const RGBA32 rangeSliderRegularTop = 0xffdee0e5;
111
const RGBA32 rangeSliderRollBottom = 0xffc9e8fe;
112
const RGBA32 rangeSliderRollTop = 0xffb5d3fc;
114
const RGBA32 rangeSliderRegularBottomOutline = 0xffb9babd;
115
const RGBA32 rangeSliderRegularTopOutline = 0xffb7b7b7;
116
const RGBA32 rangeSliderRollBottomOutline = 0xff67abe0;
117
const RGBA32 rangeSliderRollTopOutline = 0xff69adf9;
119
const RGBA32 dragRegularLight = 0xfffdfdfd;
120
const RGBA32 dragRegularDark = 0xffbababa;
121
const RGBA32 dragRollLight = 0xfff2f2f2;
122
const RGBA32 dragRollDark = 0xff69a8ff;
124
const RGBA32 blackPen = Color::black;
125
const RGBA32 focusRingPen = 0xffa3c8fe;
127
float RenderThemeBlackBerry::defaultFontSize = 16;
129
const String& RenderThemeBlackBerry::defaultGUIFont()
131
DEFINE_STATIC_LOCAL(String, fontFace, (ASCIILiteral("Slate Pro")));
135
static PassRefPtr<Gradient> createLinearGradient(RGBA32 top, RGBA32 bottom, const IntPoint& a, const IntPoint& b)
137
RefPtr<Gradient> gradient = Gradient::create(a, b);
138
gradient->addColorStop(0.0, Color(top));
139
gradient->addColorStop(1.0, Color(bottom));
140
return gradient.release();
143
static RenderSlider* determineRenderSlider(RenderObject* object)
145
ASSERT(object->isSliderThumb());
146
// The RenderSlider is an ancestor of the slider thumb.
147
while (object && !object->isSlider())
148
object = object->parent();
149
return toRenderSlider(object);
152
static float determineFullScreenMultiplier(Element* element)
154
float fullScreenMultiplier = 1.0;
155
#if ENABLE(FULLSCREEN_API) && ENABLE(VIDEO)
156
if (element && element->document()->webkitIsFullScreen() && element->document()->webkitCurrentFullScreenElement() == toParentMediaElement(element)) {
157
if (element->document()->page()->deviceScaleFactor() < scaleFactorThreshold)
158
fullScreenMultiplier = fullScreenEnlargementFactor;
160
// The way the BlackBerry port implements the FULLSCREEN_API for media elements
161
// might result in the controls being oversized, proportionally to the current page
162
// scale. That happens because the fullscreen element gets sized to be as big as the
163
// viewport size, and the viewport size might get outstretched to fit to the screen dimensions.
164
// To fix that, lets strips out the Page scale factor from the media controls multiplier.
165
float scaleFactor = element->document()->view()->hostWindow()->platformPageClient()->currentZoomFactor();
166
static ViewportArguments defaultViewportArguments;
167
float scaleFactorFudge = 1 / element->document()->page()->deviceScaleFactor();
168
fullScreenMultiplier /= scaleFactor * scaleFactorFudge;
171
return fullScreenMultiplier;
174
static void drawControl(GraphicsContext* gc, const FloatRect& rect, Image* img)
178
FloatRect srcRect(0, 0, img->width(), img->height());
179
gc->drawImage(img, ColorSpaceDeviceRGB, rect, srcRect);
182
static void drawThreeSliceHorizontal(GraphicsContext* gc, const IntRect& rect, Image* img, int slice)
187
FloatSize dstSlice(rect.height() / 2, rect.height());
188
FloatRect srcRect(0, 0, slice, img->height());
189
FloatRect dstRect(rect.location(), dstSlice);
191
gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
192
srcRect.move(img->width() - srcRect.width(), 0);
193
dstRect.move(rect.width() - dstRect.width(), 0);
194
gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
196
srcRect = FloatRect(slice, 0, img->width() - 2 * slice, img->height());
197
dstRect = FloatRect(rect.x() + dstSlice.width(), rect.y(), rect.width() - 2 * dstSlice.width(), dstSlice.height());
198
gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
201
static void drawThreeSliceVertical(GraphicsContext* gc, const IntRect& rect, Image* img, int slice)
206
FloatSize dstSlice(rect.width(), rect.width() / 2);
207
FloatRect srcRect(0, 0, img->width(), slice);
208
FloatRect dstRect(rect.location(), dstSlice);
210
gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
211
srcRect.move(0, img->height() - srcRect.height());
212
dstRect.move(0, rect.height() - dstRect.height());
213
gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
215
srcRect = FloatRect(0, slice, img->width(), img->height() - 2 * slice);
216
dstRect = FloatRect(rect.x(), rect.y() + dstSlice.height(), dstSlice.width(), rect.height() - 2 * dstSlice.height());
217
gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
220
static void drawNineSlice(GraphicsContext* gc, const IntRect& rect, double scale, Image* img, int slice)
224
if (rect.height() * scale < 101.0)
225
scale = 101.0 / rect.height();
226
FloatSize dstSlice(slice / scale, slice / scale);
227
FloatRect srcRect(0, 0, slice, slice);
228
FloatRect dstRect(rect.location(), dstSlice);
229
gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
230
srcRect.move(img->width() - srcRect.width(), 0);
231
dstRect.move(rect.width() - dstRect.width(), 0);
232
gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
233
srcRect.move(0, img->height() - srcRect.height());
234
dstRect.move(0, rect.height() - dstRect.height());
235
gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
236
srcRect.move(-(img->width() - srcRect.width()), 0);
237
dstRect.move(-(rect.width() - dstRect.width()), 0);
238
gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
240
srcRect = FloatRect(slice, 0, img->width() - 2 * slice, slice);
241
dstRect = FloatRect(rect.x() + dstSlice.width(), rect.y(), rect.width() - 2 * dstSlice.width(), dstSlice.height());
242
gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
243
srcRect.move(0, img->height() - srcRect.height());
244
dstRect.move(0, rect.height() - dstRect.height());
245
gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
247
srcRect = FloatRect(0, slice, slice, img->height() - 2 * slice);
248
dstRect = FloatRect(rect.x(), rect.y() + dstSlice.height(), dstSlice.width(), rect.height() - 2 * dstSlice.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);
254
srcRect = FloatRect(slice, slice, img->width() - 2 * slice, img->height() - 2 * slice);
255
dstRect = FloatRect(rect.x() + dstSlice.width(), rect.y() + dstSlice.height(), rect.width() - 2 * dstSlice.width(), rect.height() - 2 * dstSlice.height());
256
gc->drawImage(img, ColorSpaceDeviceRGB, dstRect, srcRect);
259
static RefPtr<Image> loadImage(const char* filename)
261
RefPtr<Image> resource;
262
resource = Image::loadPlatformResource(filename).leakRef();
264
BlackBerry::Platform::logAlways(BlackBerry::Platform::LogLevelWarn, "RenderThemeBlackBerry failed to load %s.png", filename);
270
PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
272
static RenderTheme* theme = RenderThemeBlackBerry::create().leakRef();
276
PassRefPtr<RenderTheme> RenderThemeBlackBerry::create()
278
return adoptRef(new RenderThemeBlackBerry());
281
RenderThemeBlackBerry::RenderThemeBlackBerry()
285
RenderThemeBlackBerry::~RenderThemeBlackBerry()
289
String RenderThemeBlackBerry::extraDefaultStyleSheet()
291
return String(themeBlackBerryUserAgentStyleSheet, sizeof(themeBlackBerryUserAgentStyleSheet));
295
String RenderThemeBlackBerry::extraMediaControlsStyleSheet()
297
return String(mediaControlsBlackBerryUserAgentStyleSheet, sizeof(mediaControlsBlackBerryUserAgentStyleSheet));
300
String RenderThemeBlackBerry::formatMediaControlsRemainingTime(float, float duration) const
302
// This is a workaround to make the appearance of media time controller in
303
// in-page mode the same as in fullscreen mode.
304
return formatMediaControlsTime(duration);
308
double RenderThemeBlackBerry::caretBlinkInterval() const
310
return 0; // Turn off caret blinking.
313
void RenderThemeBlackBerry::systemFont(int propId, FontDescription& fontDescription) const
315
float fontSize = defaultFontSize;
317
// Both CSSValueWebkitControl and CSSValueWebkitSmallControl should use default font size which looks better on the controls.
318
if (propId == CSSValueWebkitMiniControl) {
319
// Why 2 points smaller? Because that's what Gecko does. Note that we
320
// are assuming a 96dpi screen, which is the default value we use on Windows.
321
static const float pointsPerInch = 72.0f;
322
static const float pixelsPerInch = 96.0f;
323
fontSize -= (2.0f / pointsPerInch) * pixelsPerInch;
326
fontDescription.firstFamily().setFamily(defaultGUIFont());
327
fontDescription.setSpecifiedSize(fontSize);
328
fontDescription.setIsAbsoluteSize(true);
329
fontDescription.setGenericFamily(FontDescription::NoFamily);
330
fontDescription.setWeight(FontWeightNormal);
331
fontDescription.setItalic(false);
334
void RenderThemeBlackBerry::setButtonStyle(RenderStyle* style) const
336
Length vertPadding(int(style->fontSize() / paddingDivisor), Fixed);
337
style->setPaddingTop(vertPadding);
338
style->setPaddingBottom(vertPadding);
341
void RenderThemeBlackBerry::adjustButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
343
setButtonStyle(style);
344
style->setCursor(CURSOR_WEBKIT_GRAB);
347
void RenderThemeBlackBerry::adjustTextAreaStyle(StyleResolver*, RenderStyle* style, Element*) const
349
setButtonStyle(style);
352
bool RenderThemeBlackBerry::paintTextArea(RenderObject* object, const PaintInfo& info, const IntRect& rect)
354
return paintTextFieldOrTextAreaOrSearchField(object, info, rect);
357
void RenderThemeBlackBerry::adjustTextFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
359
setButtonStyle(style);
362
bool RenderThemeBlackBerry::paintTextFieldOrTextAreaOrSearchField(RenderObject* object, const PaintInfo& info, const IntRect& rect)
364
ASSERT(info.context);
365
GraphicsContext* context = info.context;
367
static RefPtr<Image> bg, bgDisabled, bgHighlight;
369
bg = loadImage("core_textinput_bg");
370
bgDisabled = loadImage("core_textinput_bg_disabled");
371
bgHighlight = loadImage("core_textinput_bg_highlight");
374
AffineTransform ctm = context->getCTM();
375
if (isEnabled(object) && bg)
376
drawNineSlice(context, rect, ctm.xScale(), bg.get(), smallSlice);
377
if (!isEnabled(object) && bgDisabled)
378
drawNineSlice(context, rect, ctm.xScale(), bgDisabled.get(), smallSlice);
380
if ((isHovered(object) || isFocused(object) || isPressed(object)) && bgHighlight)
381
drawNineSlice(context, rect, ctm.xScale(), bgHighlight.get(), smallSlice);
386
bool RenderThemeBlackBerry::paintTextField(RenderObject* object, const PaintInfo& info, const IntRect& rect)
388
return paintTextFieldOrTextAreaOrSearchField(object, info, rect);
391
void RenderThemeBlackBerry::adjustSearchFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
393
setButtonStyle(style);
396
void RenderThemeBlackBerry::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
398
static const float defaultControlFontPixelSize = 10;
399
static const float defaultCancelButtonSize = 13;
400
static const float minCancelButtonSize = 5;
402
// Scale the button size based on the font size
403
float fontScale = style->fontSize() / defaultControlFontPixelSize;
404
int cancelButtonSize = lroundf(std::max(minCancelButtonSize, defaultCancelButtonSize * fontScale));
405
Length length(cancelButtonSize, Fixed);
406
style->setWidth(length);
407
style->setHeight(length);
410
bool RenderThemeBlackBerry::paintSearchField(RenderObject* object, const PaintInfo& info, const IntRect& rect)
412
return paintTextFieldOrTextAreaOrSearchField(object, info, rect);
415
IntRect RenderThemeBlackBerry::convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, LayoutRect partRect, const IntRect& localOffset) const
417
// Compute an offset between the part renderer and the input renderer.
418
LayoutSize offsetFromInputRenderer = -partRenderer->offsetFromAncestorContainer(inputRenderer);
419
// Move the rect into partRenderer's coords.
420
partRect.move(offsetFromInputRenderer);
421
// Account for the local drawing offset.
422
partRect.move(localOffset.x(), localOffset.y());
424
return pixelSnappedIntRect(partRect);
428
bool RenderThemeBlackBerry::paintSearchFieldCancelButton(RenderObject* cancelButtonObject, const PaintInfo& paintInfo, const IntRect& r)
430
Node* input = cancelButtonObject->node()->shadowAncestorNode();
431
if (!input->renderer()->isBox())
434
RenderBox* inputRenderBox = toRenderBox(input->renderer());
435
LayoutRect inputContentBox = inputRenderBox->contentBoxRect();
437
// Make sure the scaled button stays square and will fit in its parent's box.
438
LayoutUnit cancelButtonSize = std::min(inputContentBox.width(), std::min<LayoutUnit>(inputContentBox.height(), r.height()));
439
// Calculate cancel button's coordinates relative to the input element.
440
// Center the button vertically. Round up though, so if it has to be one pixel off-center, it will
441
// be one pixel closer to the bottom of the field. This tends to look better with the text.
442
LayoutRect cancelButtonRect(cancelButtonObject->offsetFromAncestorContainer(inputRenderBox).width(),
443
inputContentBox.y() + (inputContentBox.height() - cancelButtonSize + 1) / 2,
444
cancelButtonSize, cancelButtonSize);
445
IntRect paintingRect = convertToPaintingRect(inputRenderBox, cancelButtonObject, cancelButtonRect, r);
447
static Image* cancelImage = Image::loadPlatformResource("searchCancel").leakRef();
448
static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").leakRef();
449
paintInfo.context->drawImage(isPressed(cancelButtonObject) ? cancelPressedImage : cancelImage,
450
cancelButtonObject->style()->colorSpace(), paintingRect);
454
void RenderThemeBlackBerry::adjustMenuListButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
456
// These seem to be reasonable padding values from observation.
457
const int paddingLeft = 8;
458
const int paddingRight = 4;
460
const int minHeight = style->fontSize() * 2;
462
style->resetPadding();
463
style->setMinHeight(Length(minHeight, Fixed));
464
style->setLineHeight(RenderStyle::initialLineHeight());
466
style->setPaddingRight(Length(minHeight + paddingRight, Fixed));
467
style->setPaddingLeft(Length(paddingLeft, Fixed));
468
style->setCursor(CURSOR_WEBKIT_GRAB);
471
void RenderThemeBlackBerry::calculateButtonSize(RenderStyle* style) const
473
int size = style->fontSize();
474
Length length(size, Fixed);
475
if (style->appearance() == CheckboxPart || style->appearance() == RadioPart) {
476
style->setWidth(length);
477
style->setHeight(length);
481
// If the width and height are both specified, then we have nothing to do.
482
if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
485
if (style->width().isIntrinsicOrAuto())
486
style->setWidth(length);
488
if (style->height().isAuto())
489
style->setHeight(length);
492
bool RenderThemeBlackBerry::paintCheckbox(RenderObject* object, const PaintInfo& info, const IntRect& rect)
494
ASSERT(info.context);
495
GraphicsContext* context = info.context;
497
static RefPtr<Image> disabled, background, inactive, pressed, active, activeMark, disableMark;
499
disabled = loadImage("core_checkbox_disabled");
500
background = loadImage("core_checkbox_moat");
501
inactive = loadImage("core_checkbox_inactive");
502
pressed = loadImage("core_checkbox_pressed");
503
active = loadImage("core_checkbox_active");
504
activeMark = loadImage("core_checkbox_active_mark");
505
disableMark = loadImage("core_checkbox_disabled_mark");
508
// Caculate where to put center checkmark.
509
FloatRect tmpRect(rect);
511
float centerX = ((float(inactive->width()) - float(activeMark->width())) / float(inactive->width()) * tmpRect.width() / 2) + tmpRect.x();
512
float centerY = ((float(inactive->height()) - float(activeMark->height())) / float(inactive->height()) * tmpRect.height() / 2) + tmpRect.y();
513
float width = float(activeMark->width()) / float(inactive->width()) * tmpRect.width();
514
float height = float(activeMark->height()) / float(inactive->height()) * tmpRect.height();
515
FloatRect centerRect(centerX, centerY, width, height);
517
drawControl(context, rect, background.get());
519
if (isEnabled(object)) {
520
if (isPressed(object)) {
521
drawControl(context, rect, pressed.get());
522
if (isChecked(object)) {
523
// FIXME: need opacity 30% on activeMark
524
drawControl(context, centerRect, activeMark.get());
527
drawControl(context, rect, inactive.get());
528
if (isChecked(object)) {
529
drawControl(context, rect, active.get());
530
drawControl(context, centerRect, activeMark.get());
534
drawControl(context, rect, disabled.get());
535
if (isChecked(object))
536
drawControl(context, rect, disableMark.get());
541
void RenderThemeBlackBerry::setCheckboxSize(RenderStyle* style) const
543
calculateButtonSize(style);
546
bool RenderThemeBlackBerry::paintRadio(RenderObject* object, const PaintInfo& info, const IntRect& rect)
548
ASSERT(info.context);
549
GraphicsContext* context = info.context;
551
static RefPtr<Image> disabled, disabledActive, inactive, pressed, active, activeMark;
553
disabled = loadImage("core_radiobutton_disabled");
554
disabledActive = loadImage("core_radiobutton_disabled_active");
555
inactive = loadImage("core_radiobutton_inactive");
556
pressed = loadImage("core_radiobutton_pressed");
557
active = loadImage("core_radiobutton_active");
558
activeMark = loadImage("core_radiobutton_active_mark");
561
// Caculate where to put center circle.
562
FloatRect tmpRect(rect);
564
float centerX = ((float(inactive->width()) - float(activeMark->width())) / float(inactive->width()) * tmpRect.width() / 2)+ tmpRect.x();
565
float centerY = ((float(inactive->height()) - float(activeMark->height())) / float(inactive->height()) * tmpRect.height() / 2) + tmpRect.y();
566
float width = float(activeMark->width()) / float(inactive->width()) * tmpRect.width();
567
float height = float(activeMark->height()) / float(inactive->height()) * tmpRect.height();
568
FloatRect centerRect(centerX, centerY, width, height);
570
if (isEnabled(object)) {
571
if (isPressed(object)) {
572
drawControl(context, rect, pressed.get());
573
if (isChecked(object)) {
574
// FIXME: need opacity 30% on activeMark
575
drawControl(context, centerRect, activeMark.get());
578
drawControl(context, rect, inactive.get());
579
if (isChecked(object)) {
580
drawControl(context, rect, active.get());
581
drawControl(context, centerRect, activeMark.get());
585
drawControl(context, rect, inactive.get());
586
if (isChecked(object))
587
drawControl(context, rect, disabledActive.get());
589
drawControl(context, rect, disabled.get());
594
void RenderThemeBlackBerry::setRadioSize(RenderStyle* style) const
596
calculateButtonSize(style);
599
// If this function returns false, WebCore assumes the button is fully decorated
600
bool RenderThemeBlackBerry::paintButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
602
ASSERT(info.context);
603
info.context->save();
604
GraphicsContext* context = info.context;
606
static RefPtr<Image> disabled, inactive, pressed;
608
disabled = loadImage("core_button_disabled");
609
inactive = loadImage("core_button_inactive");
610
pressed = loadImage("core_button_pressed");
613
AffineTransform ctm = context->getCTM();
614
if (!isEnabled(object)) {
615
drawNineSlice(context, rect, ctm.xScale(), inactive.get(), largeSlice);
616
drawNineSlice(context, rect, ctm.xScale(), disabled.get(), largeSlice);
617
} else if (isPressed(object)) {
618
drawNineSlice(context, rect, ctm.xScale(), pressed.get(), largeSlice);
620
drawNineSlice(context, rect, ctm.xScale(), inactive.get(), largeSlice);
626
void RenderThemeBlackBerry::adjustMenuListStyle(StyleResolver* css, RenderStyle* style, Element* element) const
628
adjustMenuListButtonStyle(css, style, element);
631
static IntRect computeMenuListArrowButtonRect(const IntRect& rect)
633
// FIXME: The menu list arrow button should have a minimum and maximum width (to ensure usability) or
634
// scale with respect to the font size used in the menu list control or some combination of both.
635
return IntRect(IntPoint(rect.maxX() - rect.height(), rect.y()), IntSize(rect.height(), rect.height()));
638
bool RenderThemeBlackBerry::paintMenuList(RenderObject* object, const PaintInfo& info, const IntRect& rect)
640
ASSERT(info.context);
641
info.context->save();
642
GraphicsContext* context = info.context;
644
static RefPtr<Image> disabled, inactive, pressed, arrowUp, arrowUpPressed;
646
disabled = loadImage("core_button_disabled");
647
inactive = loadImage("core_button_inactive");
648
pressed = loadImage("core_button_pressed");
649
arrowUp = loadImage("core_dropdown_button_arrowup");
650
arrowUpPressed = loadImage("core_dropdown_button_arrowup_pressed");
653
FloatRect arrowButtonRectangle(computeMenuListArrowButtonRect(rect));
654
float x = arrowButtonRectangle.x() + arrowButtonRectangle.width() / xPositionRatio;
655
float y = arrowButtonRectangle.y() + arrowButtonRectangle.height() * yPositionRatio;
656
float width = arrowButtonRectangle.width() / widthRatio;
657
float height = arrowButtonRectangle.height() * heightRatio;
658
FloatRect tmpRect(x, y, width, height);
660
AffineTransform ctm = context->getCTM();
661
if (!isEnabled(object)) {
662
drawNineSlice(context, rect, ctm.xScale(), inactive.get(), largeSlice);
663
drawNineSlice(context, rect, ctm.xScale(), disabled.get(), largeSlice);
664
drawControl(context, tmpRect, arrowUp.get()); // FIXME: should have a disabled image.
665
} else if (isPressed(object)) {
666
drawNineSlice(context, rect, ctm.xScale(), pressed.get(), largeSlice);
667
drawControl(context, tmpRect, arrowUpPressed.get());
669
drawNineSlice(context, rect, ctm.xScale(), inactive.get(), largeSlice);
670
drawControl(context, tmpRect, arrowUp.get());
676
bool RenderThemeBlackBerry::paintMenuListButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
678
return paintMenuList(object, info, rect);
681
void RenderThemeBlackBerry::adjustSliderThumbSize(RenderStyle* style, Element* element) const
683
float fullScreenMultiplier = 1;
684
ControlPart part = style->appearance();
686
if (part == MediaSliderThumbPart || part == MediaVolumeSliderThumbPart) {
687
RenderSlider* slider = determineRenderSlider(element->renderer());
689
fullScreenMultiplier = determineFullScreenMultiplier(toElement(slider->node()));
692
if (part == MediaVolumeSliderThumbPart || part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) {
693
style->setWidth(Length((part == SliderThumbVerticalPart ? sliderThumbHeight : sliderThumbWidth) * fullScreenMultiplier, Fixed));
694
style->setHeight(Length((part == SliderThumbVerticalPart ? sliderThumbWidth : sliderThumbHeight) * fullScreenMultiplier, Fixed));
695
} else if (part == MediaSliderThumbPart) {
696
style->setWidth(Length(mediaSliderThumbWidth * fullScreenMultiplier, Fixed));
697
style->setHeight(Length(mediaSliderThumbHeight * fullScreenMultiplier, Fixed));
701
bool RenderThemeBlackBerry::paintSliderTrack(RenderObject* object, const PaintInfo& info, const IntRect& rect)
703
const static int SliderTrackHeight = 5;
705
if (object->style()->appearance() == SliderHorizontalPart) {
706
rect2.setHeight(SliderTrackHeight);
707
rect2.setWidth(rect.width());
708
rect2.setX(rect.x());
709
rect2.setY(rect.y() + (rect.height() - SliderTrackHeight) / 2);
711
rect2.setHeight(rect.height());
712
rect2.setWidth(SliderTrackHeight);
713
rect2.setX(rect.x() + (rect.width() - SliderTrackHeight) / 2);
714
rect2.setY(rect.y());
716
return paintSliderTrackRect(object, info, rect2);
719
bool RenderThemeBlackBerry::paintSliderTrackRect(RenderObject* object, const PaintInfo& info, const IntRect& rect)
721
static RefPtr<Image> background;
723
background = loadImage("core_slider_bg");
724
return paintSliderTrackRect(object, info, rect, background.get());
727
bool RenderThemeBlackBerry::paintSliderTrackRect(RenderObject* object, const PaintInfo& info, const IntRect& rect, Image* inactive)
729
ASSERT(info.context);
730
info.context->save();
731
GraphicsContext* context = info.context;
733
static RefPtr<Image> disabled;
735
disabled = loadImage("core_slider_fill_disabled");
737
if (rect.width() > rect.height()) {
738
if (isEnabled(object))
739
drawThreeSliceHorizontal(context, rect, inactive, mediumSlice);
741
drawThreeSliceHorizontal(context, rect, disabled.get(), (smallSlice - 1));
743
if (isEnabled(object))
744
drawThreeSliceVertical(context, rect, inactive, mediumSlice);
746
drawThreeSliceVertical(context, rect, disabled.get(), (smallSlice - 1));
753
bool RenderThemeBlackBerry::paintSliderThumb(RenderObject* object, const PaintInfo& info, const IntRect& rect)
755
ASSERT(info.context);
756
info.context->save();
757
GraphicsContext* context = info.context;
759
static RefPtr<Image> disabled, inactive, pressed, aura;
761
disabled = loadImage("core_slider_handle_disabled");
762
inactive = loadImage("core_slider_handle");
763
pressed = loadImage("core_slider_handle_pressed");
764
aura = loadImage("core_slider_aura");
767
FloatRect tmpRect(rect);
768
float length = std::max(tmpRect.width(), tmpRect.height());
769
if (tmpRect.width() > tmpRect.height()) {
770
tmpRect.setY(tmpRect.y() - (length - tmpRect.height()) / 2);
771
tmpRect.setHeight(length);
773
tmpRect.setX(tmpRect.x() - (length - tmpRect.width()) / 2);
774
tmpRect.setWidth(length);
777
float auraHeight = length * auraRatio;
778
float auraWidth = auraHeight;
779
float auraX = tmpRect.x() - (auraWidth - tmpRect.width()) / 2;
780
float auraY = tmpRect.y() - (auraHeight - tmpRect.height()) / 2;
781
FloatRect auraRect(auraX, auraY, auraWidth, auraHeight);
783
if (!isEnabled(object))
784
drawControl(context, tmpRect, disabled.get());
786
if (isPressed(object) || isHovered(object) || isFocused(object)) {
787
drawControl(context, tmpRect, pressed.get());
788
drawControl(context, auraRect, aura.get());
790
drawControl(context, tmpRect, inactive.get());
798
void RenderThemeBlackBerry::adjustMediaControlStyle(StyleResolver*, RenderStyle* style, Element* element) const
800
float fullScreenMultiplier = determineFullScreenMultiplier(element);
801
HTMLMediaElement* mediaElement = toParentMediaElement(element);
805
// We use multiples of mediaControlsHeight to make all objects scale evenly
806
Length zero(0, Fixed);
807
Length controlsHeight(mediaControlsHeight * fullScreenMultiplier, Fixed);
808
Length timeWidth(mediaControlsHeight * 3 / 2 * fullScreenMultiplier, Fixed);
809
Length volumeHeight(mediaControlsHeight * 4 * fullScreenMultiplier, Fixed);
810
Length padding(mediaControlsHeight / 8 * fullScreenMultiplier, Fixed);
811
float fontSize = mediaControlsHeight / 2 * fullScreenMultiplier;
813
switch (style->appearance()) {
814
case MediaPlayButtonPart:
815
case MediaEnterFullscreenButtonPart:
816
case MediaExitFullscreenButtonPart:
817
case MediaMuteButtonPart:
818
style->setWidth(controlsHeight);
819
style->setHeight(controlsHeight);
821
case MediaCurrentTimePart:
822
case MediaTimeRemainingPart:
823
style->setWidth(timeWidth);
824
style->setHeight(controlsHeight);
825
style->setPaddingRight(padding);
826
style->setFontSize(static_cast<int>(fontSize));
828
case MediaVolumeSliderContainerPart:
829
style->setWidth(controlsHeight);
830
style->setHeight(volumeHeight);
831
style->setBottom(controlsHeight);
837
if (!isfinite(mediaElement->duration())) {
838
// Live streams have infinite duration with no timeline. Force the mute
839
// and fullscreen buttons to the right. This is needed when webkit does
840
// not render the timeline container because it has a webkit-box-flex
841
// of 1 and normally allows those buttons to be on the right.
842
switch (style->appearance()) {
843
case MediaEnterFullscreenButtonPart:
844
case MediaExitFullscreenButtonPart:
845
style->setPosition(AbsolutePosition);
846
style->setBottom(zero);
847
style->setRight(controlsHeight);
849
case MediaMuteButtonPart:
850
style->setPosition(AbsolutePosition);
851
style->setBottom(zero);
852
style->setRight(zero);
860
void RenderThemeBlackBerry::adjustSliderTrackStyle(StyleResolver*, RenderStyle* style, Element* element) const
862
float fullScreenMultiplier = determineFullScreenMultiplier(element);
864
// We use multiples of mediaControlsHeight to make all objects scale evenly
865
Length controlsHeight(mediaControlsHeight * fullScreenMultiplier, Fixed);
866
Length volumeHeight(mediaControlsHeight * 4 * fullScreenMultiplier, Fixed);
867
switch (style->appearance()) {
868
case MediaSliderPart:
869
style->setHeight(controlsHeight);
871
case MediaVolumeSliderPart:
872
style->setWidth(controlsHeight);
873
style->setHeight(volumeHeight);
875
case MediaFullScreenVolumeSliderPart:
881
static bool paintMediaButton(GraphicsContext* context, const IntRect& rect, Image* image)
883
context->drawImage(image, ColorSpaceDeviceRGB, rect);
887
bool RenderThemeBlackBerry::paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
890
HTMLMediaElement* mediaElement = toParentMediaElement(object);
895
static Image* mediaPlay = Image::loadPlatformResource("play").leakRef();
896
static Image* mediaPause = Image::loadPlatformResource("pause").leakRef();
898
return paintMediaButton(paintInfo.context, rect, mediaElement->canPlay() ? mediaPlay : mediaPause);
900
UNUSED_PARAM(object);
901
UNUSED_PARAM(paintInfo);
907
bool RenderThemeBlackBerry::paintMediaMuteButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
910
HTMLMediaElement* mediaElement = toParentMediaElement(object);
915
static Image* mediaMute = Image::loadPlatformResource("speaker").leakRef();
916
static Image* mediaUnmute = Image::loadPlatformResource("speaker_mute").leakRef();
918
return paintMediaButton(paintInfo.context, rect, mediaElement->muted() || !mediaElement->volume() ? mediaUnmute : mediaMute);
920
UNUSED_PARAM(object);
921
UNUSED_PARAM(paintInfo);
927
bool RenderThemeBlackBerry::paintMediaFullscreenButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
930
HTMLMediaElement* mediaElement = toParentMediaElement(object);
934
static Image* mediaEnterFullscreen = Image::loadPlatformResource("fullscreen").leakRef();
935
static Image* mediaExitFullscreen = Image::loadPlatformResource("exit_fullscreen").leakRef();
937
Image* buttonImage = mediaEnterFullscreen;
938
#if ENABLE(FULLSCREEN_API)
939
if (mediaElement->document()->webkitIsFullScreen() && mediaElement->document()->webkitCurrentFullScreenElement() == mediaElement)
940
buttonImage = mediaExitFullscreen;
942
return paintMediaButton(paintInfo.context, rect, buttonImage);
944
UNUSED_PARAM(object);
945
UNUSED_PARAM(paintInfo);
951
bool RenderThemeBlackBerry::paintMediaSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
954
HTMLMediaElement* mediaElement = toParentMediaElement(object);
958
float fullScreenMultiplier = determineFullScreenMultiplier(mediaElement);
959
float loaded = mediaElement->percentLoaded();
960
float position = mediaElement->duration() > 0 ? (mediaElement->currentTime() / mediaElement->duration()) : 0;
962
int x = ceil(rect.x() + 2 * fullScreenMultiplier - fullScreenMultiplier / 2);
963
int y = ceil(rect.y() + 14 * fullScreenMultiplier + fullScreenMultiplier / 2);
964
int w = ceil(rect.width() - 4 * fullScreenMultiplier + fullScreenMultiplier / 2);
965
int h = ceil(2 * fullScreenMultiplier);
966
IntRect rect2(x, y, w, h);
968
int wPlayed = ceil(w * position);
969
int wLoaded = ceil((w - mediaSliderThumbWidth * fullScreenMultiplier) * loaded + mediaSliderThumbWidth * fullScreenMultiplier);
971
IntRect played(x, y, wPlayed, h);
972
IntRect buffered(x, y, wLoaded, h);
974
// This is to paint main slider bar.
975
static RefPtr<Image> trackImage;
977
trackImage = loadImage("core_slider_media_bg");
978
bool result = paintSliderTrackRect(object, paintInfo, rect2, trackImage.get());
980
if (loaded > 0 || position > 0) {
981
// This is to paint buffered bar.
982
static RefPtr<Image> bufferedImage, playedImage;
983
if (!bufferedImage) {
984
bufferedImage = loadImage("core_slider_buffered_bg");
985
playedImage = loadImage("core_slider_played_bg");
987
paintSliderTrackRect(object, paintInfo, buffered, bufferedImage.get());
989
// This is to paint played part of bar (left of slider thumb) using selection color.
990
paintSliderTrackRect(object, paintInfo, played, playedImage.get());
995
UNUSED_PARAM(object);
996
UNUSED_PARAM(paintInfo);
1002
bool RenderThemeBlackBerry::paintMediaSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1005
RenderSlider* slider = determineRenderSlider(object);
1009
static Image* mediaVolumeThumb = Image::loadPlatformResource("volume_thumb").leakRef();
1011
drawControl(paintInfo.context, rect, mediaVolumeThumb);
1015
UNUSED_PARAM(object);
1016
UNUSED_PARAM(paintInfo);
1022
bool RenderThemeBlackBerry::paintMediaVolumeSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1025
float pad = rect.width() * 0.45;
1026
float x = rect.x() + pad;
1027
float y = rect.y() + pad;
1028
float width = rect.width() * 0.1;
1029
float height = rect.height() - (2.0 * pad);
1031
IntRect rect2(x, y, width, height);
1033
static RefPtr<Image> trackImage;
1035
trackImage = loadImage("core_slider_media_bg");
1037
return paintSliderTrackRect(object, paintInfo, rect2, trackImage.get());
1039
UNUSED_PARAM(object);
1040
UNUSED_PARAM(paintInfo);
1046
bool RenderThemeBlackBerry::paintMediaVolumeSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1049
static Image* mediaVolumeThumb = Image::loadPlatformResource("volume_thumb").leakRef();
1051
return paintMediaButton(paintInfo.context, rect, mediaVolumeThumb);
1053
UNUSED_PARAM(object);
1054
UNUSED_PARAM(paintInfo);
1060
Color RenderThemeBlackBerry::platformFocusRingColor() const
1062
return focusRingPen;
1065
#if ENABLE(TOUCH_EVENTS)
1066
Color RenderThemeBlackBerry::platformTapHighlightColor() const
1068
return Color(0, 168, 223, 50);
1072
Color RenderThemeBlackBerry::platformActiveSelectionBackgroundColor() const
1074
return Color(0, 168, 223, 50);
1077
double RenderThemeBlackBerry::animationRepeatIntervalForProgressBar(RenderProgress* renderProgress) const
1079
return renderProgress->isDeterminate() ? 0.0 : 0.1;
1082
double RenderThemeBlackBerry::animationDurationForProgressBar(RenderProgress* renderProgress) const
1084
return renderProgress->isDeterminate() ? 0.0 : 2.0;
1087
bool RenderThemeBlackBerry::paintProgressBar(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1089
if (!object->isProgress())
1092
RenderProgress* renderProgress = toRenderProgress(object);
1094
FloatSize smallCorner(smallRadius, smallRadius);
1096
info.context->save();
1097
info.context->setStrokeStyle(SolidStroke);
1098
info.context->setStrokeThickness(lineWidth);
1100
info.context->setStrokeGradient(createLinearGradient(rangeSliderRegularTopOutline, rangeSliderRegularBottomOutline, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
1101
info.context->setFillGradient(createLinearGradient(rangeSliderRegularTop, rangeSliderRegularBottom, rect.maxXMinYCorner(), rect.maxXMaxYCorner()));
1104
path.addRoundedRect(rect, smallCorner);
1105
info.context->fillPath(path);
1107
IntRect rect2 = rect;
1108
rect2.setX(rect2.x() + 1);
1109
rect2.setHeight(rect2.height() - 2);
1110
rect2.setY(rect2.y() + 1);
1111
info.context->setStrokeStyle(NoStroke);
1112
info.context->setStrokeThickness(0);
1113
if (renderProgress->isDeterminate()) {
1114
rect2.setWidth(rect2.width() * renderProgress->position() - 2);
1115
info.context->setFillGradient(createLinearGradient(progressRegularTop, progressRegularBottom, rect2.maxXMinYCorner(), rect2.maxXMaxYCorner()));
1118
rect2.setWidth(rect2.width() - 2);
1119
RefPtr<Gradient> gradient = Gradient::create(rect2.minXMaxYCorner(), rect2.maxXMaxYCorner());
1120
gradient->addColorStop(0.0, Color(progressRegularBottom));
1121
gradient->addColorStop(renderProgress->animationProgress(), Color(progressRegularTop));
1122
gradient->addColorStop(1.0, Color(progressRegularBottom));
1123
info.context->setFillGradient(gradient);
1126
path2.addRoundedRect(rect2, smallCorner);
1127
info.context->fillPath(path2);
1129
info.context->restore();
1133
Color RenderThemeBlackBerry::platformActiveTextSearchHighlightColor() const
1135
return Color(255, 150, 50); // Orange.
1138
Color RenderThemeBlackBerry::platformInactiveTextSearchHighlightColor() const
1140
return Color(255, 255, 0); // Yellow.
1143
} // namespace WebCore