• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 Apple Inc.
3  * Copyright (C) 2007 Alp Toker <alp@atoker.com>
4  * Copyright (C) 2008 Collabora Ltd.
5  * Copyright (C) 2008, 2009 Google 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 "core/rendering/RenderThemeChromiumSkia.h"
26 
27 #include "UserAgentStyleSheets.h"
28 #include "core/rendering/PaintInfo.h"
29 #include "core/rendering/RenderBox.h"
30 #include "core/rendering/RenderMediaControls.h"
31 #include "core/rendering/RenderObject.h"
32 #include "core/rendering/RenderProgress.h"
33 #include "core/rendering/RenderThemeChromiumFontProvider.h"
34 #include "platform/LayoutTestSupport.h"
35 #include "platform/graphics/GraphicsContext.h"
36 #include "platform/graphics/Image.h"
37 #include "platform/scroll/ScrollbarTheme.h"
38 #include "wtf/CurrentTime.h"
39 #include "wtf/StdLibExtras.h"
40 
41 namespace WebCore {
42 
43 enum PaddingType {
44     TopPadding,
45     RightPadding,
46     BottomPadding,
47     LeftPadding
48 };
49 
50 static const int styledMenuListInternalPadding[4] = { 1, 4, 1, 4 };
51 
52 // These values all match Safari/Win.
53 static const float defaultControlFontPixelSize = 13;
54 static const float defaultCancelButtonSize = 9;
55 static const float minCancelButtonSize = 5;
56 static const float maxCancelButtonSize = 21;
57 static const float defaultSearchFieldResultsDecorationSize = 13;
58 static const float minSearchFieldResultsDecorationSize = 9;
59 static const float maxSearchFieldResultsDecorationSize = 30;
60 
RenderThemeChromiumSkia()61 RenderThemeChromiumSkia::RenderThemeChromiumSkia()
62 {
63 }
64 
~RenderThemeChromiumSkia()65 RenderThemeChromiumSkia::~RenderThemeChromiumSkia()
66 {
67 }
68 
69 // Use the Windows style sheets to match their metrics.
extraDefaultStyleSheet()70 String RenderThemeChromiumSkia::extraDefaultStyleSheet()
71 {
72     return RenderTheme::extraDefaultStyleSheet() +
73         String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet)) +
74         String(themeChromiumSkiaUserAgentStyleSheet, sizeof(themeChromiumSkiaUserAgentStyleSheet)) +
75         String(themeChromiumUserAgentStyleSheet, sizeof(themeChromiumUserAgentStyleSheet));
76 }
77 
extraQuirksStyleSheet()78 String RenderThemeChromiumSkia::extraQuirksStyleSheet()
79 {
80     return String(themeWinQuirksUserAgentStyleSheet, sizeof(themeWinQuirksUserAgentStyleSheet));
81 }
82 
supportsHover(const RenderStyle * style) const83 bool RenderThemeChromiumSkia::supportsHover(const RenderStyle* style) const
84 {
85     return true;
86 }
87 
supportsFocusRing(const RenderStyle * style) const88 bool RenderThemeChromiumSkia::supportsFocusRing(const RenderStyle* style) const
89 {
90     // This causes WebKit to draw the focus rings for us.
91     return false;
92 }
93 
supportsClosedCaptioning() const94 bool RenderThemeChromiumSkia::supportsClosedCaptioning() const
95 {
96     return true;
97 }
98 
platformActiveSelectionBackgroundColor() const99 Color RenderThemeChromiumSkia::platformActiveSelectionBackgroundColor() const
100 {
101     return Color(0x1e, 0x90, 0xff);
102 }
103 
platformInactiveSelectionBackgroundColor() const104 Color RenderThemeChromiumSkia::platformInactiveSelectionBackgroundColor() const
105 {
106     return Color(0xc8, 0xc8, 0xc8);
107 }
108 
platformActiveSelectionForegroundColor() const109 Color RenderThemeChromiumSkia::platformActiveSelectionForegroundColor() const
110 {
111     return Color::black;
112 }
113 
platformInactiveSelectionForegroundColor() const114 Color RenderThemeChromiumSkia::platformInactiveSelectionForegroundColor() const
115 {
116     return Color(0x32, 0x32, 0x32);
117 }
118 
platformFocusRingColor() const119 Color RenderThemeChromiumSkia::platformFocusRingColor() const
120 {
121     static Color focusRingColor(229, 151, 0, 255);
122     return focusRingColor;
123 }
124 
caretBlinkInterval() const125 double RenderThemeChromiumSkia::caretBlinkInterval() const
126 {
127     // Disable the blinking caret in layout test mode, as it introduces
128     // a race condition for the pixel tests. http://b/1198440
129     if (isRunningLayoutTest())
130         return 0;
131 
132     return caretBlinkIntervalInternal();
133 }
134 
systemFont(CSSValueID valueID,FontDescription & fontDescription) const135 void RenderThemeChromiumSkia::systemFont(CSSValueID valueID, FontDescription& fontDescription) const
136 {
137     RenderThemeChromiumFontProvider::systemFont(valueID, fontDescription);
138 }
139 
minimumMenuListSize(RenderStyle * style) const140 int RenderThemeChromiumSkia::minimumMenuListSize(RenderStyle* style) const
141 {
142     return 0;
143 }
144 
145 // These are the default dimensions of radio buttons and checkboxes.
146 static const int widgetStandardWidth = 13;
147 static const int widgetStandardHeight = 13;
148 
149 // Return a rectangle that has the same center point as |original|, but with a
150 // size capped at |width| by |height|.
center(const IntRect & original,int width,int height)151 IntRect center(const IntRect& original, int width, int height)
152 {
153     width = std::min(original.width(), width);
154     height = std::min(original.height(), height);
155     int x = original.x() + (original.width() - width) / 2;
156     int y = original.y() + (original.height() - height) / 2;
157 
158     return IntRect(x, y, width, height);
159 }
160 
setCheckboxSize(RenderStyle * style) const161 void RenderThemeChromiumSkia::setCheckboxSize(RenderStyle* style) const
162 {
163     // If the width and height are both specified, then we have nothing to do.
164     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
165         return;
166 
167     // FIXME:  A hard-coded size of 13 is used.  This is wrong but necessary
168     // for now.  It matches Firefox.  At different DPI settings on Windows,
169     // querying the theme gives you a larger size that accounts for the higher
170     // DPI.  Until our entire engine honors a DPI setting other than 96, we
171     // can't rely on the theme's metrics.
172     const IntSize size(widgetStandardWidth, widgetStandardHeight);
173     setSizeIfAuto(style, size);
174 }
175 
setRadioSize(RenderStyle * style) const176 void RenderThemeChromiumSkia::setRadioSize(RenderStyle* style) const
177 {
178     // Use same sizing for radio box as checkbox.
179     setCheckboxSize(style);
180 }
181 
adjustButtonStyle(RenderStyle * style,Element *) const182 void RenderThemeChromiumSkia::adjustButtonStyle(RenderStyle* style, Element*) const
183 {
184     if (style->appearance() == PushButtonPart) {
185         // Ignore line-height.
186         style->setLineHeight(RenderStyle::initialLineHeight());
187     }
188 }
189 
paintTextArea(RenderObject * o,const PaintInfo & i,const IntRect & r)190 bool RenderThemeChromiumSkia::paintTextArea(RenderObject* o, const PaintInfo& i, const IntRect& r)
191 {
192     return paintTextField(o, i, r);
193 }
194 
adjustSearchFieldStyle(RenderStyle * style,Element *) const195 void RenderThemeChromiumSkia::adjustSearchFieldStyle(RenderStyle* style, Element*) const
196 {
197      // Ignore line-height.
198      style->setLineHeight(RenderStyle::initialLineHeight());
199 }
200 
paintSearchField(RenderObject * o,const PaintInfo & i,const IntRect & r)201 bool RenderThemeChromiumSkia::paintSearchField(RenderObject* o, const PaintInfo& i, const IntRect& r)
202 {
203     return paintTextField(o, i, r);
204 }
205 
adjustSearchFieldCancelButtonStyle(RenderStyle * style,Element *) const206 void RenderThemeChromiumSkia::adjustSearchFieldCancelButtonStyle(RenderStyle* style, Element*) const
207 {
208     // Scale the button size based on the font size
209     float fontScale = style->fontSize() / defaultControlFontPixelSize;
210     int cancelButtonSize = lroundf(std::min(std::max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize));
211     style->setWidth(Length(cancelButtonSize, Fixed));
212     style->setHeight(Length(cancelButtonSize, Fixed));
213 }
214 
convertToPaintingRect(RenderObject * inputRenderer,const RenderObject * partRenderer,LayoutRect partRect,const IntRect & localOffset) const215 IntRect RenderThemeChromiumSkia::convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, LayoutRect partRect, const IntRect& localOffset) const
216 {
217     // Compute an offset between the part renderer and the input renderer.
218     LayoutSize offsetFromInputRenderer = -partRenderer->offsetFromAncestorContainer(inputRenderer);
219     // Move the rect into partRenderer's coords.
220     partRect.move(offsetFromInputRenderer);
221     // Account for the local drawing offset.
222     partRect.move(localOffset.x(), localOffset.y());
223 
224     return pixelSnappedIntRect(partRect);
225 }
226 
paintSearchFieldCancelButton(RenderObject * cancelButtonObject,const PaintInfo & paintInfo,const IntRect & r)227 bool RenderThemeChromiumSkia::paintSearchFieldCancelButton(RenderObject* cancelButtonObject, const PaintInfo& paintInfo, const IntRect& r)
228 {
229     // Get the renderer of <input> element.
230     Node* input = cancelButtonObject->node()->shadowHost();
231     RenderObject* baseRenderer = input ? input->renderer() : cancelButtonObject;
232     if (!baseRenderer->isBox())
233         return false;
234     RenderBox* inputRenderBox = toRenderBox(baseRenderer);
235     LayoutRect inputContentBox = inputRenderBox->contentBoxRect();
236 
237     // Make sure the scaled button stays square and will fit in its parent's box.
238     LayoutUnit cancelButtonSize = std::min(inputContentBox.width(), std::min<LayoutUnit>(inputContentBox.height(), r.height()));
239     // Calculate cancel button's coordinates relative to the input element.
240     // Center the button vertically.  Round up though, so if it has to be one pixel off-center, it will
241     // be one pixel closer to the bottom of the field.  This tends to look better with the text.
242     LayoutRect cancelButtonRect(cancelButtonObject->offsetFromAncestorContainer(inputRenderBox).width(),
243                                 inputContentBox.y() + (inputContentBox.height() - cancelButtonSize + 1) / 2,
244                                 cancelButtonSize, cancelButtonSize);
245     IntRect paintingRect = convertToPaintingRect(inputRenderBox, cancelButtonObject, cancelButtonRect, r);
246 
247     DEFINE_STATIC_REF(Image, cancelImage, (Image::loadPlatformResource("searchCancel")));
248     DEFINE_STATIC_REF(Image, cancelPressedImage, (Image::loadPlatformResource("searchCancelPressed")));
249     paintInfo.context->drawImage(isPressed(cancelButtonObject) ? cancelPressedImage : cancelImage, paintingRect);
250     return false;
251 }
252 
adjustSearchFieldDecorationStyle(RenderStyle * style,Element *) const253 void RenderThemeChromiumSkia::adjustSearchFieldDecorationStyle(RenderStyle* style, Element*) const
254 {
255     IntSize emptySize(1, 11);
256     style->setWidth(Length(emptySize.width(), Fixed));
257     style->setHeight(Length(emptySize.height(), Fixed));
258 }
259 
adjustSearchFieldResultsDecorationStyle(RenderStyle * style,Element *) const260 void RenderThemeChromiumSkia::adjustSearchFieldResultsDecorationStyle(RenderStyle* style, Element*) const
261 {
262     // Scale the decoration size based on the font size
263     float fontScale = style->fontSize() / defaultControlFontPixelSize;
264     int magnifierSize = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
265                                          maxSearchFieldResultsDecorationSize));
266     style->setWidth(Length(magnifierSize, Fixed));
267     style->setHeight(Length(magnifierSize, Fixed));
268 }
269 
paintSearchFieldResultsDecoration(RenderObject * magnifierObject,const PaintInfo & paintInfo,const IntRect & r)270 bool RenderThemeChromiumSkia::paintSearchFieldResultsDecoration(RenderObject* magnifierObject, const PaintInfo& paintInfo, const IntRect& r)
271 {
272     // Get the renderer of <input> element.
273     Node* input = magnifierObject->node()->shadowHost();
274     RenderObject* baseRenderer = input ? input->renderer() : magnifierObject;
275     if (!baseRenderer->isBox())
276         return false;
277     RenderBox* inputRenderBox = toRenderBox(baseRenderer);
278     LayoutRect inputContentBox = inputRenderBox->contentBoxRect();
279 
280     // Make sure the scaled decoration stays square and will fit in its parent's box.
281     LayoutUnit magnifierSize = std::min(inputContentBox.width(), std::min<LayoutUnit>(inputContentBox.height(), r.height()));
282     // Calculate decoration's coordinates relative to the input element.
283     // Center the decoration vertically.  Round up though, so if it has to be one pixel off-center, it will
284     // be one pixel closer to the bottom of the field.  This tends to look better with the text.
285     LayoutRect magnifierRect(magnifierObject->offsetFromAncestorContainer(inputRenderBox).width(),
286                              inputContentBox.y() + (inputContentBox.height() - magnifierSize + 1) / 2,
287                              magnifierSize, magnifierSize);
288     IntRect paintingRect = convertToPaintingRect(inputRenderBox, magnifierObject, magnifierRect, r);
289 
290     DEFINE_STATIC_REF(Image, magnifierImage, (Image::loadPlatformResource("searchMagnifier")));
291     paintInfo.context->drawImage(magnifierImage, paintingRect);
292     return false;
293 }
294 
paintMediaSliderTrack(RenderObject * object,const PaintInfo & paintInfo,const IntRect & rect)295 bool RenderThemeChromiumSkia::paintMediaSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
296 {
297     return RenderMediaControls::paintMediaControlsPart(MediaSlider, object, paintInfo, rect);
298 }
299 
paintMediaVolumeSliderTrack(RenderObject * object,const PaintInfo & paintInfo,const IntRect & rect)300 bool RenderThemeChromiumSkia::paintMediaVolumeSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
301 {
302     return RenderMediaControls::paintMediaControlsPart(MediaVolumeSlider, object, paintInfo, rect);
303 }
304 
adjustSliderThumbSize(RenderStyle * style,Element *) const305 void RenderThemeChromiumSkia::adjustSliderThumbSize(RenderStyle* style, Element*) const
306 {
307     RenderMediaControls::adjustMediaSliderThumbSize(style);
308 }
309 
paintMediaSliderThumb(RenderObject * object,const PaintInfo & paintInfo,const IntRect & rect)310 bool RenderThemeChromiumSkia::paintMediaSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
311 {
312     return RenderMediaControls::paintMediaControlsPart(MediaSliderThumb, object, paintInfo, rect);
313 }
314 
paintMediaToggleClosedCaptionsButton(RenderObject * o,const PaintInfo & paintInfo,const IntRect & r)315 bool RenderThemeChromiumSkia::paintMediaToggleClosedCaptionsButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
316 {
317     return RenderMediaControls::paintMediaControlsPart(MediaShowClosedCaptionsButton, o, paintInfo, r);
318 }
319 
paintMediaVolumeSliderThumb(RenderObject * object,const PaintInfo & paintInfo,const IntRect & rect)320 bool RenderThemeChromiumSkia::paintMediaVolumeSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
321 {
322     return RenderMediaControls::paintMediaControlsPart(MediaVolumeSliderThumb, object, paintInfo, rect);
323 }
324 
paintMediaPlayButton(RenderObject * object,const PaintInfo & paintInfo,const IntRect & rect)325 bool RenderThemeChromiumSkia::paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
326 {
327     return RenderMediaControls::paintMediaControlsPart(MediaPlayButton, object, paintInfo, rect);
328 }
329 
paintMediaMuteButton(RenderObject * object,const PaintInfo & paintInfo,const IntRect & rect)330 bool RenderThemeChromiumSkia::paintMediaMuteButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
331 {
332     return RenderMediaControls::paintMediaControlsPart(MediaMuteButton, object, paintInfo, rect);
333 }
334 
formatMediaControlsTime(float time) const335 String RenderThemeChromiumSkia::formatMediaControlsTime(float time) const
336 {
337     return RenderMediaControls::formatMediaControlsTime(time);
338 }
339 
formatMediaControlsCurrentTime(float currentTime,float duration) const340 String RenderThemeChromiumSkia::formatMediaControlsCurrentTime(float currentTime, float duration) const
341 {
342     return RenderMediaControls::formatMediaControlsCurrentTime(currentTime, duration);
343 }
344 
paintMediaFullscreenButton(RenderObject * object,const PaintInfo & paintInfo,const IntRect & rect)345 bool RenderThemeChromiumSkia::paintMediaFullscreenButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
346 {
347     return RenderMediaControls::paintMediaControlsPart(MediaEnterFullscreenButton, object, paintInfo, rect);
348 }
349 
adjustMenuListStyle(RenderStyle * style,WebCore::Element *) const350 void RenderThemeChromiumSkia::adjustMenuListStyle(RenderStyle* style, WebCore::Element*) const
351 {
352     // Height is locked to auto on all browsers.
353     style->setLineHeight(RenderStyle::initialLineHeight());
354 }
355 
adjustMenuListButtonStyle(RenderStyle * style,Element * e) const356 void RenderThemeChromiumSkia::adjustMenuListButtonStyle(RenderStyle* style, Element* e) const
357 {
358     adjustMenuListStyle(style, e);
359 }
360 
361 // Used to paint styled menulists (i.e. with a non-default border)
paintMenuListButton(RenderObject * o,const PaintInfo & i,const IntRect & rect)362 bool RenderThemeChromiumSkia::paintMenuListButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
363 {
364     return paintMenuList(o, i, rect);
365 }
366 
popupInternalPaddingLeft(RenderStyle * style) const367 int RenderThemeChromiumSkia::popupInternalPaddingLeft(RenderStyle* style) const
368 {
369     return menuListInternalPadding(style, LeftPadding);
370 }
371 
popupInternalPaddingRight(RenderStyle * style) const372 int RenderThemeChromiumSkia::popupInternalPaddingRight(RenderStyle* style) const
373 {
374     return menuListInternalPadding(style, RightPadding);
375 }
376 
popupInternalPaddingTop(RenderStyle * style) const377 int RenderThemeChromiumSkia::popupInternalPaddingTop(RenderStyle* style) const
378 {
379     return menuListInternalPadding(style, TopPadding);
380 }
381 
popupInternalPaddingBottom(RenderStyle * style) const382 int RenderThemeChromiumSkia::popupInternalPaddingBottom(RenderStyle* style) const
383 {
384     return menuListInternalPadding(style, BottomPadding);
385 }
386 
387 // static
setDefaultFontSize(int fontSize)388 void RenderThemeChromiumSkia::setDefaultFontSize(int fontSize)
389 {
390     RenderThemeChromiumFontProvider::setDefaultFontSize(fontSize);
391 }
392 
caretBlinkIntervalInternal() const393 double RenderThemeChromiumSkia::caretBlinkIntervalInternal() const
394 {
395     return RenderTheme::caretBlinkInterval();
396 }
397 
menuListArrowPadding() const398 int RenderThemeChromiumSkia::menuListArrowPadding() const
399 {
400     return ScrollbarTheme::theme()->scrollbarThickness();
401 }
402 
menuListInternalPadding(RenderStyle * style,int paddingType) const403 int RenderThemeChromiumSkia::menuListInternalPadding(RenderStyle* style, int paddingType) const
404 {
405     // This internal padding is in addition to the user-supplied padding.
406     // Matches the FF behavior.
407     int padding = styledMenuListInternalPadding[paddingType];
408 
409     // Reserve the space for right arrow here. The rest of the padding is
410     // set by adjustMenuListStyle, since PopMenuWin.cpp uses the padding from
411     // RenderMenuList to lay out the individual items in the popup.
412     // If the MenuList actually has appearance "NoAppearance", then that means
413     // we don't draw a button, so don't reserve space for it.
414     const int barType = style->direction() == LTR ? RightPadding : LeftPadding;
415     if (paddingType == barType && style->appearance() != NoControlPart)
416         padding += menuListArrowPadding();
417 
418     return padding;
419 }
420 
shouldShowPlaceholderWhenFocused() const421 bool RenderThemeChromiumSkia::shouldShowPlaceholderWhenFocused() const
422 {
423     return true;
424 }
425 
426 //
427 // Following values are come from default of GTK+
428 //
429 static const int progressActivityBlocks = 5;
430 static const int progressAnimationFrames = 10;
431 static const double progressAnimationInterval = 0.125;
432 
determinateProgressValueRectFor(RenderProgress * renderProgress,const IntRect & rect) const433 IntRect RenderThemeChromiumSkia::determinateProgressValueRectFor(RenderProgress* renderProgress, const IntRect& rect) const
434 {
435     int dx = rect.width() * renderProgress->position();
436     return IntRect(rect.x(), rect.y(), dx, rect.height());
437 }
438 
indeterminateProgressValueRectFor(RenderProgress * renderProgress,const IntRect & rect) const439 IntRect RenderThemeChromiumSkia::indeterminateProgressValueRectFor(RenderProgress* renderProgress, const IntRect& rect) const
440 {
441 
442     int valueWidth = rect.width() / progressActivityBlocks;
443     int movableWidth = rect.width() - valueWidth;
444     if (movableWidth <= 0)
445         return IntRect();
446 
447     double progress = renderProgress->animationProgress();
448     if (progress < 0.5)
449         return IntRect(rect.x() + progress * 2 * movableWidth, rect.y(), valueWidth, rect.height());
450     return IntRect(rect.x() + (1.0 - progress) * 2 * movableWidth, rect.y(), valueWidth, rect.height());
451 }
452 
animationRepeatIntervalForProgressBar(RenderProgress *) const453 double RenderThemeChromiumSkia::animationRepeatIntervalForProgressBar(RenderProgress*) const
454 {
455     return progressAnimationInterval;
456 }
457 
animationDurationForProgressBar(RenderProgress * renderProgress) const458 double RenderThemeChromiumSkia::animationDurationForProgressBar(RenderProgress* renderProgress) const
459 {
460     return progressAnimationInterval * progressAnimationFrames * 2; // "2" for back and forth
461 }
462 
progressValueRectFor(RenderProgress * renderProgress,const IntRect & rect) const463 IntRect RenderThemeChromiumSkia::progressValueRectFor(RenderProgress* renderProgress, const IntRect& rect) const
464 {
465     return renderProgress->isDeterminate() ? determinateProgressValueRectFor(renderProgress, rect) : indeterminateProgressValueRectFor(renderProgress, rect);
466 }
467 
DirectionFlippingScope(RenderObject * renderer,const PaintInfo & paintInfo,const IntRect & rect)468 RenderThemeChromiumSkia::DirectionFlippingScope::DirectionFlippingScope(RenderObject* renderer, const PaintInfo& paintInfo, const IntRect& rect)
469     : m_needsFlipping(!renderer->style()->isLeftToRightDirection())
470     , m_paintInfo(paintInfo)
471 {
472     if (!m_needsFlipping)
473         return;
474     m_paintInfo.context->save();
475     m_paintInfo.context->translate(2 * rect.x() + rect.width(), 0);
476     m_paintInfo.context->scale(FloatSize(-1, 1));
477 }
478 
~DirectionFlippingScope()479 RenderThemeChromiumSkia::DirectionFlippingScope::~DirectionFlippingScope()
480 {
481     if (!m_needsFlipping)
482         return;
483     m_paintInfo.context->restore();
484 }
485 
486 } // namespace WebCore
487