18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
2f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick * Copyright (C) 2010 Sencha, Inc.
3bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * Copyright (C) 2010 Igalia S.L.
4f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick *
5f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick * All rights reserved.
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
29f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick#ifndef ContextShadow_h
30f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick#define ContextShadow_h
31f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
32bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "Color.h"
33bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "FloatRect.h"
34bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "IntRect.h"
352bde8e466a4451c7319e3a072d118917957d6554Steve Block#include <wtf/RefCounted.h>
36bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if USE(CAIRO)
38bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsentypedef struct _cairo cairo_t;
39bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsentypedef struct _cairo_surface cairo_surface_t;
40bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#elif PLATFORM(QT)
41bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include <QImage>
42cad810f21b803229eb11403f9209855525a25d57Steve BlockQT_BEGIN_NAMESPACE
43bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass QPainter;
44cad810f21b803229eb11403f9209855525a25d57Steve BlockQT_END_NAMESPACE
45bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#endif
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
47f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merricknamespace WebCore {
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
49cad810f21b803229eb11403f9209855525a25d57Steve Blockclass AffineTransform;
50cad810f21b803229eb11403f9209855525a25d57Steve Blockclass GraphicsContext;
51cad810f21b803229eb11403f9209855525a25d57Steve Block
522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if USE(CAIRO)
536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennertypedef cairo_surface_t* PlatformImage;
546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennertypedef cairo_t* PlatformContext;
556b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#elif PLATFORM(QT)
566b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennertypedef QImage PlatformImage;
576b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennertypedef QPainter* PlatformContext;
586b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#else
596b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennertypedef void* PlatformImage;
606b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennertypedef void* PlatformContext;
616b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#endif
626b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
63f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick// This is to track and keep the shadow state. We use this rather than
64f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick// using GraphicsContextState to allow possible optimizations (right now
65f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick// only to determine the shadow type, but in future it might covers things
66f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick// like cached scratch image, persistent shader, etc).
67231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
68f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick// This class should be copyable since GraphicsContextQt keeps a stack of
69f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick// the shadow state for savePlatformState and restorePlatformState.
70231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// This class is Deprecated. Platforms should migrate to ShadowBlur.
722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
73f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickclass ContextShadow {
74f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickpublic:
75f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    enum {
76f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        NoShadow,
77bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        SolidShadow,
78f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        BlurShadow
79bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    } m_type;
80231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
81bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    Color m_color;
82a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int m_blurDistance;
83bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    FloatSize m_offset;
84f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
85f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    ContextShadow();
86bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ContextShadow(const Color&, float radius, const FloatSize& offset);
87f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
88cad810f21b803229eb11403f9209855525a25d57Steve Block    bool mustUseContextShadow(GraphicsContext*);
89f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    void clear();
90f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
91e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    // The pair beginShadowLayer and endShadowLayer creates a temporary image
92bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // where the caller can draw onto, using the returned context. This context
93bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // must be used only to draw between the call to beginShadowLayer and
94bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // endShadowLayer.
95e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    //
96bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Note: multiple/nested shadow layers are NOT allowed.
97e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    //
98e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    // The current clip region will be used to optimize the size of the
99bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // temporary image. Thus, the original context should not change any
100bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // clipping until endShadowLayer. If the shadow will be completely outside
101bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // the clipping region, beginShadowLayer will return 0.
102e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    //
103bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // The returned context will have the transformation matrix and clipping
104bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // properly initialized to start doing the painting (no need to account for
105bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // the shadow offset), however it will not have the same render hints, pen,
106bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // brush, etc as the passed context. This is intentional, usually shadows
107bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // have different properties than the shapes which cast them.
108e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    //
109bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Once endShadowLayer is called, the temporary image will be drawn with the
110bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // original context. If blur radius is specified, the shadow will be
111bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // filtered first.
112bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
113cad810f21b803229eb11403f9209855525a25d57Steve Block    PlatformContext beginShadowLayer(GraphicsContext*, const FloatRect& layerArea);
114cad810f21b803229eb11403f9209855525a25d57Steve Block    void endShadowLayer(GraphicsContext*);
115bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    static void purgeScratchBuffer();
116f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
117f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    void setShadowsIgnoreTransforms(bool enable) { m_shadowsIgnoreTransforms = enable; }
118f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    bool shadowsIgnoreTransforms() const { return m_shadowsIgnoreTransforms; }
1192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if USE(CAIRO)
120a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    void drawRectShadow(GraphicsContext* context, const IntRect& rect, const IntSize& topLeftRadius = IntSize(), const IntSize& topRightRadius = IntSize(), const IntSize& bottomLeftRadius = IntSize(), const IntSize& bottomRightRadius = IntSize());
121a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif
122bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#if PLATFORM(QT)
123f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    QPointF offset() const { return QPointF(m_offset.width(), m_offset.height()); }
124bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#endif
125bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
126e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockprivate:
127f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    PlatformImage m_layerImage; // Buffer to where the temporary shadow will be drawn to.
128f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    PlatformContext m_layerContext; // Context used to paint the shadow to the layer image.
129f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    FloatRect m_sourceRect; // Sub-rect of m_layerImage that contains the shadow pixels.
130f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    FloatPoint m_layerOrigin; // Top-left corner of the (possibly clipped) bounding rect to draw the shadow to.
131f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    FloatPoint m_layerContextTranslation; // Translation to apply to m_layerContext for the shadow to be correctly clipped.
132f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    bool m_shadowsIgnoreTransforms;
133f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
134cad810f21b803229eb11403f9209855525a25d57Steve Block    void adjustBlurDistance(GraphicsContext*);
135bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    void blurLayerImage(unsigned char*, const IntSize& imageSize, int stride);
136cad810f21b803229eb11403f9209855525a25d57Steve Block    IntRect calculateLayerBoundingRect(GraphicsContext*, const FloatRect& layerArea, const IntRect& clipRect);
137f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
1382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if USE(CAIRO)
139cad810f21b803229eb11403f9209855525a25d57Steve Block    void drawRectShadowWithoutTiling(GraphicsContext*, const IntRect& shadowRect, const IntSize& topLeftRadius, const IntSize& topRightRadius, const IntSize& bottomLeftRadius, const IntSize& bottomRightRadius, float alpha);
140a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif
141f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick};
142231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
143231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} // namespace WebCore
144231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
145f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick#endif // ContextShadow_h
146