1/*
2 * This file is part of the WebKit project.
3 *
4 * Copyright (C) 2006, 2007 Apple Inc.
5 * Copyright (C) 2007-2009 Torch Mobile, Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB.  If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#include "config.h"
25#include "RenderThemeWinCE.h"
26
27#include "CSSStyleSheet.h"
28#include "CSSValueKeywords.h"
29#include "Document.h"
30#include "FontMetrics.h"
31#include "GraphicsContext.h"
32#if ENABLE(VIDEO)
33#include "HTMLMediaElement.h"
34#endif
35#include "NotImplemented.h"
36#include "PaintInfo.h"
37
38#include <windows.h>
39
40/*
41 * The following constants are used to determine how a widget is drawn using
42 * Windows' Theme API. For more information on theme parts and states see
43 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/topics/partsandstates.asp
44 */
45#define THEME_COLOR 204
46#define THEME_FONT  210
47
48// Generic state constants
49#define TS_NORMAL    1
50#define TS_HOVER     2
51#define TS_ACTIVE    3
52#define TS_DISABLED  4
53#define TS_FOCUSED   5
54
55// Button constants
56#define BP_BUTTON    1
57#define BP_RADIO     2
58#define BP_CHECKBOX  3
59
60// Textfield constants
61#define TFP_TEXTFIELD 1
62#define TFS_READONLY  6
63
64typedef HANDLE (WINAPI*openThemeDataPtr)(HWND hwnd, LPCWSTR pszClassList);
65typedef HRESULT (WINAPI*closeThemeDataPtr)(HANDLE hTheme);
66typedef HRESULT (WINAPI*drawThemeBackgroundPtr)(HANDLE hTheme, HDC hdc, int iPartId,
67                                          int iStateId, const RECT *pRect,
68                                          const RECT* pClipRect);
69typedef HRESULT (WINAPI*drawThemeEdgePtr)(HANDLE hTheme, HDC hdc, int iPartId,
70                                          int iStateId, const RECT *pRect,
71                                          unsigned uEdge, unsigned uFlags,
72                                          const RECT* pClipRect);
73typedef HRESULT (WINAPI*getThemeContentRectPtr)(HANDLE hTheme, HDC hdc, int iPartId,
74                                          int iStateId, const RECT* pRect,
75                                          RECT* pContentRect);
76typedef HRESULT (WINAPI*getThemePartSizePtr)(HANDLE hTheme, HDC hdc, int iPartId,
77                                       int iStateId, RECT* prc, int ts,
78                                       SIZE* psz);
79typedef HRESULT (WINAPI*getThemeSysFontPtr)(HANDLE hTheme, int iFontId, OUT LOGFONT* pFont);
80typedef HRESULT (WINAPI*getThemeColorPtr)(HANDLE hTheme, HDC hdc, int iPartId,
81                                   int iStateId, int iPropId, OUT COLORREF* pFont);
82
83namespace WebCore {
84
85static const int dropDownButtonWidth = 17;
86static const int trackWidth = 4;
87
88PassRefPtr<RenderTheme> RenderThemeWinCE::create()
89{
90    return adoptRef(new RenderThemeWinCE);
91}
92
93PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
94{
95    static RenderTheme* winceTheme = RenderThemeWinCE::create().leakRef();
96    return winceTheme;
97}
98
99RenderThemeWinCE::RenderThemeWinCE()
100{
101}
102
103RenderThemeWinCE::~RenderThemeWinCE()
104{
105}
106
107Color RenderThemeWinCE::platformActiveSelectionBackgroundColor() const
108{
109    COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
110    return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
111}
112
113Color RenderThemeWinCE::platformInactiveSelectionBackgroundColor() const
114{
115    COLORREF color = GetSysColor(COLOR_GRAYTEXT);
116    return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
117}
118
119Color RenderThemeWinCE::platformActiveSelectionForegroundColor() const
120{
121    COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
122    return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
123}
124
125Color RenderThemeWinCE::platformInactiveSelectionForegroundColor() const
126{
127    return Color::white;
128}
129
130bool RenderThemeWinCE::supportsFocus(ControlPart appearance) const
131{
132    switch (appearance) {
133    case PushButtonPart:
134    case ButtonPart:
135    case TextFieldPart:
136    case TextAreaPart:
137        return true;
138    default:
139        return false;
140    }
141
142    return false;
143}
144
145bool RenderThemeWinCE::supportsFocusRing(const RenderStyle *style) const
146{
147    return supportsFocus(style->appearance());
148}
149
150unsigned RenderThemeWinCE::determineClassicState(RenderObject* o)
151{
152    unsigned result = 0;
153    if (!isEnabled(o) || isReadOnlyControl(o))
154        result = DFCS_INACTIVE;
155    else if (isPressed(o)) // Active supersedes hover
156        result = DFCS_PUSHED;
157
158    if (isChecked(o))
159        result |= DFCS_CHECKED;
160    return result;
161}
162
163ThemeData RenderThemeWinCE::getThemeData(RenderObject* o)
164{
165    ThemeData result;
166    switch (o->style().appearance()) {
167    case PushButtonPart:
168    case ButtonPart:
169        result.m_part = BP_BUTTON;
170        result.m_classicState = DFCS_BUTTONPUSH;
171        break;
172    case CheckboxPart:
173        result.m_part = BP_CHECKBOX;
174        result.m_classicState = DFCS_BUTTONCHECK;
175        break;
176    case RadioPart:
177        result.m_part = BP_RADIO;
178        result.m_classicState = DFCS_BUTTONRADIO;
179        break;
180    case ListboxPart:
181    case MenulistPart:
182    case TextFieldPart:
183    case TextAreaPart:
184        result.m_part = TFP_TEXTFIELD;
185        break;
186    }
187
188    result.m_classicState |= determineClassicState(o);
189
190    return result;
191}
192
193bool RenderThemeWinCE::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& r)
194{
195    // Get the correct theme data for a button
196    ThemeData themeData = getThemeData(o);
197
198    // Now paint the button.
199    i.context->drawFrameControl(r, DFC_BUTTON, themeData.m_classicState);
200    if (isFocused(o)) {
201        if (themeData.m_part == BP_BUTTON) {
202            IntRect focusRect(r);
203            focusRect.inflate(-2);
204            i.context->drawFocusRect(focusRect);
205        } else
206            i.context->drawFocusRect(r);
207    }
208
209    return false;
210}
211
212void RenderThemeWinCE::setCheckboxSize(RenderStyle* style) const
213{
214    // If the width and height are both specified, then we have nothing to do.
215    if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
216        return;
217
218    // FIXME:  A hard-coded size of 13 is used.  This is wrong but necessary for now.  It matches Firefox.
219    // At different DPI settings on Windows, querying the theme gives you a larger size that accounts for
220    // the higher DPI.  Until our entire engine honors a DPI setting other than 96, we can't rely on the theme's
221    // metrics.
222    if (style->width().isIntrinsicOrAuto())
223        style->setWidth(Length(13, Fixed));
224    if (style->height().isAuto())
225        style->setHeight(Length(13, Fixed));
226}
227
228bool RenderThemeWinCE::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& r)
229{
230    // Get the correct theme data for a textfield
231    ThemeData themeData = getThemeData(o);
232
233    // Now paint the text field.
234    i.context->paintTextField(r, themeData.m_classicState);
235
236    return false;
237}
238
239void RenderThemeWinCE::adjustMenuListStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
240{
241    style->resetBorder();
242    adjustMenuListButtonStyle(styleResolver, style, e);
243}
244
245bool RenderThemeWinCE::paintMenuList(RenderObject* renderer, const PaintInfo& paintInfo, const IntRect& rect)
246{
247    paintTextField(renderer, paintInfo, rect);
248    paintMenuListButtonDecorations(renderer, paintInfo, rect);
249    return true;
250}
251
252bool RenderThemeWinCE::paintMenuListButtonDecorations(RenderObject* renderer, const PaintInfo& paintInfo, const IntRect& rect)
253{
254    IntRect buttonRect(rect.maxX() - dropDownButtonWidth - 1, rect.y(), dropDownButtonWidth, rect.height());
255    buttonRect.inflateY(-1);
256    paintInfo.context->drawFrameControl(buttonRect, DFC_SCROLL, DFCS_SCROLLCOMBOBOX | determineClassicState(renderer));
257    return true;
258}
259
260void RenderThemeWinCE::systemFont(CSSValueID, FontDescription& fontDescription) const
261{
262    notImplemented();
263}
264
265void RenderThemeWinCE::themeChanged()
266{
267}
268
269String RenderThemeWinCE::extraDefaultStyleSheet()
270{
271    notImplemented();
272    return String();
273}
274
275String RenderThemeWinCE::extraQuirksStyleSheet()
276{
277    notImplemented();
278    return String();
279}
280
281bool RenderThemeWinCE::supportsHover(const RenderStyle*) const
282{
283    return false;
284}
285
286// Map a CSSValue* system color to an index understood by GetSysColor
287static int cssValueIdToSysColorIndex(CSSValueID cssValueId)
288{
289    switch (cssValueId) {
290    case CSSValueActiveborder: return COLOR_ACTIVEBORDER;
291    case CSSValueActivecaption: return COLOR_ACTIVECAPTION;
292    case CSSValueAppworkspace: return COLOR_APPWORKSPACE;
293    case CSSValueBackground: return COLOR_BACKGROUND;
294    case CSSValueButtonface: return COLOR_BTNFACE;
295    case CSSValueButtonhighlight: return COLOR_BTNHIGHLIGHT;
296    case CSSValueButtonshadow: return COLOR_BTNSHADOW;
297    case CSSValueButtontext: return COLOR_BTNTEXT;
298    case CSSValueCaptiontext: return COLOR_CAPTIONTEXT;
299    case CSSValueGraytext: return COLOR_GRAYTEXT;
300    case CSSValueHighlight: return COLOR_HIGHLIGHT;
301    case CSSValueHighlighttext: return COLOR_HIGHLIGHTTEXT;
302    case CSSValueInactiveborder: return COLOR_INACTIVEBORDER;
303    case CSSValueInactivecaption: return COLOR_INACTIVECAPTION;
304    case CSSValueInactivecaptiontext: return COLOR_INACTIVECAPTIONTEXT;
305    case CSSValueInfobackground: return COLOR_INFOBK;
306    case CSSValueInfotext: return COLOR_INFOTEXT;
307    case CSSValueMenu: return COLOR_MENU;
308    case CSSValueMenutext: return COLOR_MENUTEXT;
309    case CSSValueScrollbar: return COLOR_SCROLLBAR;
310    case CSSValueThreeddarkshadow: return COLOR_3DDKSHADOW;
311    case CSSValueThreedface: return COLOR_3DFACE;
312    case CSSValueThreedhighlight: return COLOR_3DHIGHLIGHT;
313    case CSSValueThreedlightshadow: return COLOR_3DLIGHT;
314    case CSSValueThreedshadow: return COLOR_3DSHADOW;
315    case CSSValueWindow: return COLOR_WINDOW;
316    case CSSValueWindowframe: return COLOR_WINDOWFRAME;
317    case CSSValueWindowtext: return COLOR_WINDOWTEXT;
318    default: return -1; // Unsupported CSSValue
319    }
320}
321
322Color RenderThemeWinCE::systemColor(CSSValueID cssValueId) const
323{
324    int sysColorIndex = cssValueIdToSysColorIndex(cssValueId);
325    if (sysColorIndex == -1)
326        return RenderTheme::systemColor(cssValueId);
327
328    COLORREF color = GetSysColor(sysColorIndex);
329    return Color(GetRValue(color), GetGValue(color), GetBValue(color));
330}
331
332const int sliderThumbWidth = 7;
333const int sliderThumbHeight = 15;
334
335void RenderThemeWinCE::adjustSliderThumbSize(RenderStyle* style, Element*) const
336{
337    if (style->appearance() == SliderThumbVerticalPart) {
338        style->setWidth(Length(sliderThumbHeight, Fixed));
339        style->setHeight(Length(sliderThumbWidth, Fixed));
340    } else if (style->appearance() == SliderThumbHorizontalPart) {
341        style->setWidth(Length(sliderThumbWidth, Fixed));
342        style->setHeight(Length(sliderThumbHeight, Fixed));
343    }
344}
345
346#if 0
347void RenderThemeWinCE::adjustButtonInnerStyle(RenderStyle* style) const
348{
349    // This inner padding matches Firefox.
350    style->setPaddingTop(Length(1, Fixed));
351    style->setPaddingRight(Length(3, Fixed));
352    style->setPaddingBottom(Length(1, Fixed));
353    style->setPaddingLeft(Length(3, Fixed));
354}
355
356void RenderThemeWinCE::adjustSearchFieldStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
357{
358    // Override padding size to match AppKit text positioning.
359    const int padding = 1;
360    style->setPaddingLeft(Length(padding, Fixed));
361    style->setPaddingRight(Length(padding, Fixed));
362    style->setPaddingTop(Length(padding, Fixed));
363    style->setPaddingBottom(Length(padding, Fixed));
364}
365#endif
366
367bool RenderThemeWinCE::paintSearchField(RenderObject* o, const PaintInfo& i, const IntRect& r)
368{
369    return paintTextField(o, i, r);
370}
371
372bool RenderThemeWinCE::paintSearchFieldCancelButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
373{
374    Color buttonColor = (o->node() && o->node()->isElementNode() && toElement(o->node())->active()) ? Color(138, 138, 138) : Color(186, 186, 186);
375
376    IntSize cancelSize(10, 10);
377    IntSize cancelRadius(cancelSize.width() / 2, cancelSize.height() / 2);
378    int x = r.x() + (r.width() - cancelSize.width()) / 2;
379    int y = r.y() + (r.height() - cancelSize.height()) / 2 + 1;
380    IntRect cancelBounds(IntPoint(x, y), cancelSize);
381    paintInfo.context->save();
382    paintInfo.context->clipRoundedRect(RoundedRect(cancelBounds, cancelRadius, cancelRadius, cancelRadius, cancelRadius));
383    paintInfo.context->fillRect(cancelBounds, buttonColor, ColorSpaceDeviceRGB);
384
385    // Draw the 'x'
386    IntSize xSize(3, 3);
387    IntRect xBounds(cancelBounds.location() + IntSize(3, 3), xSize);
388    paintInfo.context->setStrokeColor(Color::white, ColorSpaceDeviceRGB);
389    paintInfo.context->drawLine(xBounds.location(),  xBounds.location() + xBounds.size());
390    paintInfo.context->drawLine(IntPoint(xBounds.maxX(), xBounds.y()),  IntPoint(xBounds.x(), xBounds.maxY()));
391
392    paintInfo.context->restore();
393    return false;
394}
395
396void RenderThemeWinCE::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
397{
398    IntSize cancelSize(13, 11);
399    style->setWidth(Length(cancelSize.width(), Fixed));
400    style->setHeight(Length(cancelSize.height(), Fixed));
401}
402
403void RenderThemeWinCE::adjustSearchFieldDecorationPartStyle(StyleResolver*, RenderStyle* style, Element*) const
404{
405    IntSize emptySize(1, 11);
406    style->setWidth(Length(emptySize.width(), Fixed));
407    style->setHeight(Length(emptySize.height(), Fixed));
408}
409
410void RenderThemeWinCE::adjustSearchFieldResultsDecorationPartStyle(StyleResolver*, RenderStyle* style, Element*) const
411{
412    IntSize magnifierSize(15, 11);
413    style->setWidth(Length(magnifierSize.width(), Fixed));
414    style->setHeight(Length(magnifierSize.height(), Fixed));
415}
416
417bool RenderThemeWinCE::paintSearchFieldResultsDecorationPart(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
418{
419    notImplemented();
420    return false;
421}
422
423void RenderThemeWinCE::adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
424{
425    IntSize magnifierSize(15, 11);
426    style->setWidth(Length(magnifierSize.width(), Fixed));
427    style->setHeight(Length(magnifierSize.height(), Fixed));
428}
429
430bool RenderThemeWinCE::paintSearchFieldResultsButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
431{
432    paintSearchFieldResultsDecorationPart(o, paintInfo, r);
433    return false;
434}
435
436void RenderThemeWinCE::adjustMenuListButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
437{
438    // These are the paddings needed to place the text correctly in the <select> box
439    const int dropDownBoxPaddingTop    = 2;
440    const int dropDownBoxPaddingRight  = style->direction() == LTR ? 4 + dropDownButtonWidth : 4;
441    const int dropDownBoxPaddingBottom = 2;
442    const int dropDownBoxPaddingLeft   = style->direction() == LTR ? 4 : 4 + dropDownButtonWidth;
443    // The <select> box must be at least 12px high for the button to render nicely on Windows
444    const int dropDownBoxMinHeight = 12;
445
446    // Position the text correctly within the select box and make the box wide enough to fit the dropdown button
447    style->setPaddingTop(Length(dropDownBoxPaddingTop, Fixed));
448    style->setPaddingRight(Length(dropDownBoxPaddingRight, Fixed));
449    style->setPaddingBottom(Length(dropDownBoxPaddingBottom, Fixed));
450    style->setPaddingLeft(Length(dropDownBoxPaddingLeft, Fixed));
451
452    // Height is locked to auto
453    style->setHeight(Length(Auto));
454
455    // Calculate our min-height
456    int minHeight = style->fontMetrics().height();
457    minHeight = std::max(minHeight, dropDownBoxMinHeight);
458
459    style->setMinHeight(Length(minHeight, Fixed));
460
461    // White-space is locked to pre
462    style->setWhiteSpace(PRE);
463
464    DWORD colorMenu = GetSysColor(COLOR_MENU);
465    DWORD colorMenuText = GetSysColor(COLOR_MENUTEXT);
466    Color bgColor(GetRValue(colorMenu), GetGValue(colorMenu), GetBValue(colorMenu), 255);
467    Color textColor(GetRValue(colorMenuText), GetGValue(colorMenuText), GetBValue(colorMenuText), 255);
468    if (bgColor == textColor)
469        textColor.setRGB((~bgColor.rgb()) | 0xFF000000);
470    style->clearBackgroundLayers();
471    style->accessBackgroundLayers()->setClip(ContentFillBox);
472    style->setBackgroundColor(bgColor);
473    style->setColor(textColor);
474}
475
476#if ENABLE(VIDEO)
477// Attempt to retrieve a HTMLMediaElement from a Node. Returns 0 if one cannot be found.
478static HTMLMediaElement* mediaElementParent(Node* node)
479{
480    if (!node)
481        return 0;
482    Node* mediaNode = node->shadowHost();
483    if (!mediaNode)
484        mediaNode = node;
485    if (!mediaNode || !mediaNode->isElementNode() || !toElement(mediaNode)->isMediaElement())
486        return 0;
487
488    return toHTMLMediaElement(mediaNode);
489}
490#endif
491
492bool RenderThemeWinCE::paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& r)
493{
494    bool rc = RenderTheme::paintSliderTrack(o, i, r);
495    IntPoint left = IntPoint(r.x() + 2, (r.y() + r.maxY()) / 2);
496    i.context->save();
497    i.context->setStrokeColor(Color::gray, ColorSpaceDeviceRGB);
498    i.context->setFillColor(Color::gray, ColorSpaceDeviceRGB);
499    i.context->fillRect(r);
500#if ENABLE(VIDEO)
501    HTMLMediaElement* mediaElement = mediaElementParent(o->node());
502    if (mediaElement) {
503        i.context->setStrokeColor(Color(0, 0xff, 0));
504        IntPoint right = IntPoint(left.x() + mediaElement->percentLoaded() * (r.maxX() - r.x() - 4), (r.y() + r.maxY()) / 2);
505        i.context->drawLine(left, right);
506        left = right;
507    }
508#endif
509    i.context->setStrokeColor(Color::black, ColorSpaceDeviceRGB);
510    i.context->drawLine(left, IntPoint(r.maxX() - 2, left.y()));
511    i.context->restore();
512    return false;
513}
514
515bool RenderThemeWinCE::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& r)
516{
517    bool rc = RenderTheme::paintSliderThumb(o, i, r);
518    i.context->save();
519    i.context->setStrokeColor(Color::black, ColorSpaceDeviceRGB);
520    i.context->setFillColor(Color::black, ColorSpaceDeviceRGB);
521    i.context->fillRect(r);
522#if ENABLE(VIDEO)
523    HTMLMediaElement* mediaElement = mediaElementParent(o->node());
524    if (mediaElement) {
525        float pt = mediaElement->currentTime() / mediaElement->duration();
526        FloatRect intRect = r;
527        intRect.setX(intRect.x() + intRect.width() * pt - 2);
528        intRect.setWidth(5);
529        i.context->fillRect(intRect);
530    }
531#endif
532    i.context->restore();
533    return false;
534}
535
536void RenderThemeWinCE::adjustSearchFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
537{
538    const int padding = 1;
539    style->setPaddingLeft(Length(padding, Fixed));
540    style->setPaddingRight(Length(padding, Fixed));
541    style->setPaddingTop(Length(padding, Fixed));
542    style->setPaddingBottom(Length(padding, Fixed));
543}
544
545#if ENABLE(VIDEO)
546
547bool RenderThemeWinCE::paintMediaFullscreenButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
548{
549    bool rc = paintButton(o, paintInfo, r);
550    FloatRect imRect = r;
551    imRect.inflate(-2);
552    paintInfo.context->save();
553    paintInfo.context->setStrokeColor(Color::black);
554    paintInfo.context->setFillColor(Color::gray);
555    paintInfo.context->fillRect(imRect);
556    paintInfo.context->restore();
557    return rc;
558}
559
560bool RenderThemeWinCE::paintMediaMuteButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
561{
562    bool rc = paintButton(o, paintInfo, r);
563    HTMLMediaElement* mediaElement = mediaElementParent(o->node());
564    bool muted = !mediaElement || mediaElement->muted();
565    FloatRect imRect = r;
566    imRect.inflate(-2);
567    paintInfo.context->save();
568    paintInfo.context->setStrokeColor(Color::black);
569    paintInfo.context->setFillColor(Color::black);
570    FloatPoint pts[6] = {
571        FloatPoint(imRect.x() + 1, imRect.y() + imRect.height() / 3.0),
572        FloatPoint(imRect.x() + 1 + imRect.width() / 2.0, imRect.y() + imRect.height() / 3.0),
573        FloatPoint(imRect.maxX() - 1, imRect.y()),
574        FloatPoint(imRect.maxX() - 1, imRect.maxY()),
575        FloatPoint(imRect.x() + 1 + imRect.width() / 2.0, imRect.y() + 2.0 * imRect.height() / 3.0),
576        FloatPoint(imRect.x() + 1, imRect.y() + 2.0 * imRect.height() / 3.0)
577    };
578    paintInfo.context->drawConvexPolygon(6, pts);
579    if (muted)
580        paintInfo.context->drawLine(IntPoint(imRect.maxX(), imRect.y()), IntPoint(imRect.x(), imRect.maxY()));
581    paintInfo.context->restore();
582    return rc;
583}
584
585bool RenderThemeWinCE::paintMediaPlayButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
586{
587    bool rc = paintButton(o, paintInfo, r);
588    FloatRect imRect = r;
589    imRect.inflate(-3);
590    paintInfo.context->save();
591    paintInfo.context->setStrokeColor(Color::black);
592    paintInfo.context->setFillColor(Color::black);
593    HTMLMediaElement* mediaElement = mediaElementParent(o->node());
594    bool paused = !mediaElement || mediaElement->paused();
595    if (paused) {
596        float width = imRect.width();
597        imRect.setWidth(width / 3.0);
598        paintInfo.context->fillRect(imRect);
599        imRect.move(2.0 * width / 3.0, 0);
600        paintInfo.context->fillRect(imRect);
601    } else {
602        FloatPoint pts[3] = { FloatPoint(imRect.x(), imRect.y()), FloatPoint(imRect.maxX(), (imRect.y() + imRect.maxY()) / 2.0), FloatPoint(imRect.x(), imRect.maxY()) };
603        paintInfo.context->drawConvexPolygon(3, pts);
604    }
605    paintInfo.context->restore();
606    return rc;
607}
608
609bool RenderThemeWinCE::paintMediaSeekBackButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
610{
611    bool rc = paintButton(o, paintInfo, r);
612    FloatRect imRect = r;
613    imRect.inflate(-3);
614    FloatPoint pts[3] = { FloatPoint((imRect.x() + imRect.maxX()) / 2.0, imRect.y()), FloatPoint(imRect.x(), (imRect.y() + imRect.maxY()) / 2.0), FloatPoint((imRect.x() + imRect.maxX()) / 2.0, imRect.maxY()) };
615    FloatPoint pts2[3] = { FloatPoint(imRect.maxX(), imRect.y()), FloatPoint((imRect.x() + imRect.maxX()) / 2.0, (imRect.y() + imRect.maxY()) / 2.0), FloatPoint(imRect.maxX(), imRect.maxY()) };
616    paintInfo.context->save();
617    paintInfo.context->setStrokeColor(Color::black);
618    paintInfo.context->setFillColor(Color::black);
619    paintInfo.context->drawConvexPolygon(3, pts);
620    paintInfo.context->drawConvexPolygon(3, pts2);
621    paintInfo.context->restore();
622    return rc;
623}
624
625bool RenderThemeWinCE::paintMediaSeekForwardButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
626{
627    bool rc = paintButton(o, paintInfo, r);
628    FloatRect imRect = r;
629    imRect.inflate(-3);
630    FloatPoint pts[3] = { FloatPoint(imRect.x(), imRect.y()), FloatPoint((imRect.x() + imRect.maxX()) / 2.0, (imRect.y() + imRect.maxY()) / 2.0), FloatPoint(imRect.x(), imRect.maxY()) };
631    FloatPoint pts2[3] = { FloatPoint((imRect.x() + imRect.maxX()) / 2.0, imRect.y()), FloatPoint(imRect.maxX(), (imRect.y() + imRect.maxY()) / 2.0), FloatPoint((imRect.x() + imRect.maxX()) / 2.0, imRect.maxY()) };
632    paintInfo.context->save();
633    paintInfo.context->setStrokeColor(Color::black);
634    paintInfo.context->setFillColor(Color::black);
635    paintInfo.context->drawConvexPolygon(3, pts);
636    paintInfo.context->drawConvexPolygon(3, pts2);
637    paintInfo.context->restore();
638    return rc;
639}
640
641bool RenderThemeWinCE::paintMediaSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
642{
643    return paintSliderTrack(o, paintInfo, r);
644}
645
646bool RenderThemeWinCE::paintMediaSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
647{
648    return paintSliderThumb(o, paintInfo, r);
649}
650#endif
651
652void RenderThemeWinCE::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
653{
654    int width = ::GetSystemMetrics(SM_CXVSCROLL);
655    if (width <= 0)
656        width = 17; // Vista's default.
657    style->setWidth(Length(width, Fixed));
658    style->setMinWidth(Length(width, Fixed));
659}
660
661bool RenderThemeWinCE::paintInnerSpinButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
662{
663    // We split the specified rectangle into two vertically. We can't draw a
664    // spin button of which height is less than 2px.
665    if (r.height() < 2)
666        return false;
667    IntRect upRect(r);
668    upRect.setHeight(r.height() / 2);
669    IntRect downRect(r);
670    downRect.setY(upRect.maxY());
671    downRect.setHeight(r.height() - upRect.height());
672
673    unsigned stateUp = DFCS_SCROLLUP;
674    unsigned stateDown = DFCS_SCROLLDOWN;
675
676    if (!isEnabled(o) || isReadOnlyControl(o)) {
677        stateUp |= DFCS_INACTIVE;
678        stateDown |= DFCS_INACTIVE;
679    } else if (isPressed(o)) {
680        if (isSpinUpButtonPartPressed(o))
681            stateUp |= DFCS_PUSHED;
682        else
683            stateDown |= DFCS_PUSHED;
684    }
685
686    paintInfo.context->drawFrameControl(upRect, DFC_SCROLL, stateUp);
687    paintInfo.context->drawFrameControl(downRect, DFC_SCROLL, stateDown);
688
689    return false;
690}
691
692} // namespace WebCore
693