1 /* 2 * Copyright 2006, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #ifndef platform_graphics_context_h 27 #define platform_graphics_context_h 28 29 #include "IntRect.h" 30 #include "RenderSkinAndroid.h" 31 #include "RenderSkinButton.h" 32 #include "SkCanvas.h" 33 #include "SkPicture.h" 34 #include "SkTDArray.h" 35 36 class SkCanvas; 37 38 class Container { 39 public: 40 Container(WebCore::Node* node, const WebCore::IntRect& r) 41 : m_node(node), m_rect(r), m_state(WebCore::RenderSkinAndroid::kDisabled) 42 { 43 m_picture = new SkPicture; 44 } 45 46 ~Container() 47 { 48 m_picture->unref(); 49 } 50 51 Container& operator=(const Container& src) 52 { 53 if (this != &src) { 54 m_node = src.m_node; 55 if (m_picture) 56 m_picture->unref(); 57 m_picture = src.m_picture; 58 m_picture->ref(); 59 m_rect = src.m_rect; 60 m_state = WebCore::RenderSkinAndroid::kDisabled; 61 } 62 return *this; 63 } 64 65 Container(const Container& src) 66 { 67 m_node = src.m_node; 68 m_picture = src.m_picture; 69 m_picture->ref(); 70 m_rect = src.m_rect; 71 m_state = WebCore::RenderSkinAndroid::kDisabled; 72 } 73 74 // m_picture has a ref count of 1 to begin with. It will increase each time 75 // m_picture is referenced by another picture. When the other pictures are 76 // deleted, the ref count gets decremented. If the ref count is one, then 77 // no other pictures reference this one, so the button is no longer being 78 // used, and therefore can be removed. 79 bool canBeRemoved() 80 { 81 return m_picture->getRefCnt() == 1; 82 } 83 84 bool matches(const WebCore::Node* match) { return m_node == match; } 85 86 const WebCore::Node* node() const { return m_node; } 87 88 // Provide a pointer to our SkPicture. 89 SkPicture* picture() { return m_picture; } 90 91 WebCore::IntRect rect() { return m_rect; } 92 93 // Update the rectangle with a new rectangle, as the positioning of this 94 // button may have changed due to a new layout. If it is a new rectangle, 95 // set its state to disabled, so that it will be redrawn when we cycle 96 // through the list of buttons. 97 void setRect(WebCore::IntRect r) 98 { 99 if (m_rect != r) { 100 m_rect = r; 101 m_state = WebCore::RenderSkinAndroid::kDisabled; 102 } 103 } 104 105 // Update the focus state of this button, depending on whether it 106 // corresponds to the focused node passed in. If its state has changed, 107 // re-record to the subpicture, so the master picture will reflect the 108 // change. 109 void updateFocusState(WebCore::RenderSkinAndroid::State state, 110 WebCore::RenderSkinButton* buttonSkin) 111 { 112 if (state == m_state) 113 return; 114 // If this button is being told to draw focused, but it is already in a 115 // pressed state, leave it in the pressed state, to show that it is 116 // being followed. 117 if (m_state == WebCore::RenderSkinAndroid::kPressed && 118 state == WebCore::RenderSkinAndroid::kFocused) 119 return; 120 m_state = state; 121 SkCanvas* canvas = m_picture->beginRecording(m_rect.maxX(), m_rect.maxY()); 122 buttonSkin->draw(canvas, m_rect, state); 123 m_picture->endRecording(); 124 } 125 private: 126 // Only used for comparison, since after it is stored it will be transferred 127 // to the UI thread. 128 WebCore::Node* m_node; 129 // The rectangle representing the bounds of the button. 130 WebCore::IntRect m_rect; 131 // An SkPicture that, thanks to storeButtonInfo, is pointed to by the master 132 // picture, so that we can rerecord this button without rerecording the 133 // world. 134 SkPicture* m_picture; 135 // The state of the button - Currently kFocused or kNormal (and kDisabled 136 // as an initial value), but could be expanded to include other states. 137 WebCore::RenderSkinAndroid::State m_state; 138 }; 139 140 namespace WebCore { 141 142 class GraphicsContext; 143 144 class PlatformGraphicsContext { 145 public: 146 PlatformGraphicsContext(); 147 // Pass in a recording canvas, and an array of button information to be 148 // updated. 149 PlatformGraphicsContext(SkCanvas* canvas, WTF::Vector<Container>* buttons); 150 ~PlatformGraphicsContext(); 151 152 SkCanvas* mCanvas; 153 154 bool deleteUs() const { return m_deleteCanvas; } 155 // If our graphicscontext has a button list, add a new container for the 156 // nod/rect, and record a new subpicture for this node/button in the current 157 // mCanvas 158 void storeButtonInfo(Node* node, const IntRect& r); 159 private: 160 bool m_deleteCanvas; 161 WTF::Vector<Container>* m_buttons; 162 }; 163 164 } 165 #endif 166