diff options
author | brettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-06 17:03:15 +0000 |
---|---|---|
committer | brettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-06 17:03:15 +0000 |
commit | a8f643b401ec655adbe20d98dc862f168b25b17a (patch) | |
tree | a9a8d414ea876a71f8f5b5a9f8d72ee9b812f75a /webkit | |
parent | e32306c541215cf71e9464abc2f786f064dfff9a (diff) | |
download | chromium_src-a8f643b401ec655adbe20d98dc862f168b25b17a.zip chromium_src-a8f643b401ec655adbe20d98dc862f168b25b17a.tar.gz chromium_src-a8f643b401ec655adbe20d98dc862f168b25b17a.tar.bz2 |
Add support for arbitrarily transformed Windows buttons text fields, and select boxes (but does not affect scroll bars). I created a helper class, ThemeHelperWin, which automatically wraps the logic necessary to do this. There are three modes: draw the form control normally, draw it at a different size (for scaling, just tell Windows it's a different size and don't transform the graphics coordinates), or arbitrary transforms (where it's drawn to an offscreen buffer and transformed by our graphics layer.
Review URL: http://codereview.chromium.org/9008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4890 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r-- | webkit/build/port/port.vcproj | 8 | ||||
-rw-r--r-- | webkit/port/platform/graphics/ThemeHelperWin.cpp | 133 | ||||
-rw-r--r-- | webkit/port/platform/graphics/ThemeHelperWin.h | 97 | ||||
-rw-r--r-- | webkit/port/rendering/RenderThemeWin.cpp | 51 |
4 files changed, 264 insertions, 25 deletions
diff --git a/webkit/build/port/port.vcproj b/webkit/build/port/port.vcproj index 7464c87..b18530a 100644 --- a/webkit/build/port/port.vcproj +++ b/webkit/build/port/port.vcproj @@ -974,6 +974,14 @@ RelativePath="..\..\port\platform\graphics\SkiaUtils.h" > </File> + <File + RelativePath="..\..\port\platform\graphics\ThemeHelperWin.cpp" + > + </File> + <File + RelativePath="..\..\port\platform\graphics\ThemeHelperWin.h" + > + </File> <Filter Name="svg" > diff --git a/webkit/port/platform/graphics/ThemeHelperWin.cpp b/webkit/port/platform/graphics/ThemeHelperWin.cpp new file mode 100644 index 0000000..10916e6 --- /dev/null +++ b/webkit/port/platform/graphics/ThemeHelperWin.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2008 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "FloatRect.h" +#include "GraphicsContext.h" +#include "ThemeHelperWin.h" + +namespace WebCore { + +static void IntRectToRECT(const IntRect& ir, RECT* r) +{ + r->left = ir.x(); + r->top = ir.y(); + r->right = ir.right(); + r->bottom = ir.bottom(); +} + +ThemeHelperWin::ThemeHelperWin(GraphicsContext* context, + const IntRect& rect) + : m_orgContext(context) + , m_orgMatrix(context->getCTM()) + , m_orgRect(rect) +{ + if (m_orgMatrix.b() != 0 || // Y skew + m_orgMatrix.c() != 0) { // X skew + // Complicated effects, make a copy and draw the bitmap there. + m_type = COPY; + m_rect.left = 0; + m_rect.top = 0; + m_rect.right = rect.width(); + m_rect.bottom = rect.height(); + + m_newBuffer.set(ImageBuffer::create(rect.size(), false).release()); + + // Theme drawing messes with the transparency. + // TODO(brettw) Ideally, we would leave this transparent, but I was + // having problems with button drawing, so we fill with white. Buttons + // looked good with transparent here and no fixing up of the alpha + // later, but text areas didn't. This makes text areas look good but + // gives buttons a white halo. Is there a way to fix this? I think + // buttons actually have antialised edges which is just not possible + // to handle on a transparent background given that it messes with the + // alpha channel. + FloatRect newContextRect(0, 0, rect.width(), rect.height()); + GraphicsContext* newContext = m_newBuffer->context(); + newContext->setFillColor(Color::white); + newContext->fillRect(newContextRect); + + return; + } + + if (m_orgMatrix.a() != 1.0 || // X scale + m_orgMatrix.d() != 1.0) { // Y scale + // Only a scaling is applied. + m_type = SCALE; + + // Save the transformed coordinates to draw. + IntRectToRECT(m_orgMatrix.mapRect(rect), &m_rect); + + m_orgContext->save(); + m_orgContext->concatCTM(m_orgContext->getCTM().inverse()); + return; + } + + // Nothing interesting. + IntRectToRECT(rect, &m_rect); + m_type = ORIGINAL; +} + +ThemeHelperWin::~ThemeHelperWin() +{ + switch (m_type) { + case SCALE: + m_orgContext->restore(); + break; + case COPY: { + // Copy the duplicate bitmap with our control to the original canvas. + FloatRect destRect(m_orgRect); + m_newBuffer->context()->platformContext()->canvas()-> + getTopPlatformDevice().fixupAlphaBeforeCompositing(); + m_orgContext->drawImage(m_newBuffer->image(), destRect); + break; + } + case ORIGINAL: + break; + } +} + +RECT ThemeHelperWin::transformRect(const RECT& r) const +{ + IntRect src(r.left, r.top, r.right - r.left, r.bottom - r.top); + IntRect dest; + switch (m_type) { + case SCALE: + dest = m_orgMatrix.mapRect(src); + break; + case COPY: + dest = src; + dest.move(-m_orgRect.x(), -m_orgRect.y()); + break; + case ORIGINAL: + break; + } + + RECT output; + IntRectToRECT(dest, &output); + return output; +} + +} // namespace WebCore
\ No newline at end of file diff --git a/webkit/port/platform/graphics/ThemeHelperWin.h b/webkit/port/platform/graphics/ThemeHelperWin.h new file mode 100644 index 0000000..3d7caf1 --- /dev/null +++ b/webkit/port/platform/graphics/ThemeHelperWin.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2008 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ThemeHelperWin_h +#define ThemeHelperWin_h + +#include <windows.h> + +#include "AffineTransform.h" +#include "ImageBuffer.h" +#include "IntRect.h" +#include "WTF/OwnPtr.h" + +namespace WebCore { + +class GraphicsContext; +class IntRect; + +// Helps drawing theme elements like buttons and scroll bars. This will handle +// translations and scalings that Windows might not, by either making Windows +// draw the appropriate sized control, or by rendering it into an off-screen +// context and transforming it ourselves. +class ThemeHelperWin { + enum Type { + // Use the original canvas with no changes. This is the normal mode. + ORIGINAL, + + // Use the original canvas but scale the rectangle of the control so + // that it will be the correct size, undoing any scale already on the + // canvas. This will have the effect of just drawing the control bigger + // or smaller and not actually expanding or contracting the pixels in + // it. This usually looks better. + SCALE, + + // Make a copy of the control and then transform it ourselves after + // Windows draws it. This allows us to get complex effects. + COPY, + }; + +public: + // Prepares drawing a control with the given rect to the given context. + ThemeHelperWin(GraphicsContext* context, const IntRect& rect); + ~ThemeHelperWin(); + + // Returns the context to draw the control into, which may be the original + // or the copy, depending on the mode. + GraphicsContext* context() + { + return m_newBuffer.get() ? m_newBuffer->context() : m_orgContext; + } + + // Returns the rectangle in which to draw into the canvas() by Windows. + const RECT& rect() { return m_rect; } + + RECT transformRect(const RECT& r) const; + +private: + Type m_type; + + // The original canvas to wrote to. Not owned by this class. + GraphicsContext* m_orgContext; + AffineTransform m_orgMatrix; + IntRect m_orgRect; + + // When m_type == COPY, this will be a new surface owned by this class that + // represents the copy. + OwnPtr<ImageBuffer> m_newBuffer; + + // The control rectangle in the cooredinate space of canvas(). + RECT m_rect; +}; + +} // namespace WebCore + +#endif // ThemeHelperWin_h diff --git a/webkit/port/rendering/RenderThemeWin.cpp b/webkit/port/rendering/RenderThemeWin.cpp index 2bb81ab..917e5ee 100644 --- a/webkit/port/rendering/RenderThemeWin.cpp +++ b/webkit/port/rendering/RenderThemeWin.cpp @@ -33,6 +33,7 @@ #include "GraphicsContext.h" #include "ScrollbarTheme.h" #include "SkiaUtils.h" +#include "ThemeHelperWin.h" #include "base/gfx/native_theme.h" #include "base/gfx/font_utils.h" @@ -482,20 +483,19 @@ bool RenderThemeWin::paintButton(RenderObject* o, { const ThemeData& themeData = getThemeData(o); - RECT rect; - rect.left = r.x(); - rect.top = r.y(); - rect.right = r.right(); - rect.bottom = r.bottom(); + WebCore::ThemeHelperWin helper(i.context, r); + gfx::PlatformCanvas* canvas = helper.context()->platformContext()->canvas(); - HDC hdc = i.context->platformContext()->canvas()->beginPlatformPaint(); + HDC hdc = canvas->beginPlatformPaint(); int state = themeData.m_state; + RECT renderRect = helper.rect(); + gfx::NativeTheme::instance()->PaintButton(hdc, themeData.m_part, state, themeData.m_classicState, - &rect); - i.context->platformContext()->canvas()->endPlatformPaint(); + &renderRect); + canvas->endPlatformPaint(); return false; } @@ -574,23 +574,22 @@ bool RenderThemeWin::paintTextFieldInternal(RenderObject* o, const ThemeData& themeData = getThemeData(o); - RECT rect; - rect.left = r.x(); - rect.top = r.y(); - rect.right = r.right(); - rect.bottom = r.bottom(); + WebCore::ThemeHelperWin helper(i.context, r); + gfx::PlatformCanvas* canvas = helper.context()->platformContext()->canvas(); - HDC hdc = i.context->platformContext()->canvas()->beginPlatformPaint(); + HDC hdc = canvas->beginPlatformPaint(); COLORREF clr = gfx::SkColorToCOLORREF(o->style()->backgroundColor().rgb()); + RECT renderRect = helper.rect(); + gfx::NativeTheme::instance()->PaintTextField(hdc, themeData.m_part, themeData.m_state, themeData.m_classicState, - &rect, + &renderRect, clr, true, drawEdges); - i.context->platformContext()->canvas()->endPlatformPaint(); + canvas->endPlatformPaint(); return false; } @@ -662,21 +661,23 @@ bool RenderThemeWin::paintMenuList(RenderObject* o, const RenderObject::PaintInf buttonX = o->style()->direction() == LTR ? r.right() - spacingRight - buttonWidth : r.x() + spacingLeft; } - // Compute the Windows rectangle of the button. - RECT rect; - rect.left = buttonX; - rect.top = r.y() + spacingTop; - rect.right = rect.left + std::min(buttonWidth, r.right() - r.x()); - rect.bottom = rect.top + r.height() - (spacingTop + spacingBottom); + // Compute the rectangle of the button in the destination image. + IntRect rect(buttonX, + r.y() + spacingTop, + std::min(buttonWidth, r.right() - r.x()), + r.height() - (spacingTop + spacingBottom)); // Get the correct theme data for a textfield and paint the menu. - HDC hdc = i.context->platformContext()->canvas()->beginPlatformPaint(); + WebCore::ThemeHelperWin helper(i.context, rect); + gfx::PlatformCanvas* canvas = helper.context()->platformContext()->canvas(); + HDC hdc = canvas->beginPlatformPaint(); + RECT renderRect = helper.rect(); gfx::NativeTheme::instance()->PaintMenuList(hdc, CP_DROPDOWNBUTTON, determineState(o), determineClassicState(o), - &rect); - i.context->platformContext()->canvas()->endPlatformPaint(); + &renderRect); + canvas->endPlatformPaint(); return false; } |