summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authorbrettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-06 17:03:15 +0000
committerbrettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-06 17:03:15 +0000
commita8f643b401ec655adbe20d98dc862f168b25b17a (patch)
treea9a8d414ea876a71f8f5b5a9f8d72ee9b812f75a /webkit
parente32306c541215cf71e9464abc2f786f064dfff9a (diff)
downloadchromium_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.vcproj8
-rw-r--r--webkit/port/platform/graphics/ThemeHelperWin.cpp133
-rw-r--r--webkit/port/platform/graphics/ThemeHelperWin.h97
-rw-r--r--webkit/port/rendering/RenderThemeWin.cpp51
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;
}