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 APPLE COMPUTER, INC. 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: Container(WebCore::Node * node,const WebCore::IntRect & r)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 ~Container()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 Container(const Container & src)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. canBeRemoved()79 bool canBeRemoved() 80 { 81 return m_picture->getRefCnt() == 1; 82 } 83 matches(const WebCore::Node * match)84 bool matches(const WebCore::Node* match) { return m_node == match; } 85 node()86 const WebCore::Node* node() const { return m_node; } 87 88 // Provide a pointer to our SkPicture. picture()89 SkPicture* picture() { return m_picture; } 90 rect()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. setRect(WebCore::IntRect r)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. updateFocusState(WebCore::RenderSkinAndroid::State state)109 void updateFocusState(WebCore::RenderSkinAndroid::State state) 110 { 111 if (state == m_state) 112 return; 113 // If this button is being told to draw focused, but it is already in a 114 // pressed state, leave it in the pressed state, to show that it is 115 // being followed. 116 if (m_state == WebCore::RenderSkinAndroid::kPressed && 117 state == WebCore::RenderSkinAndroid::kFocused) 118 return; 119 m_state = state; 120 SkCanvas* canvas = m_picture->beginRecording(m_rect.width(), m_rect.height()); 121 WebCore::RenderSkinButton::Draw(canvas, m_rect, state); 122 m_picture->endRecording(); 123 } 124 private: 125 // Only used for comparison, since after it is stored it will be transferred 126 // to the UI thread. 127 WebCore::Node* m_node; 128 // The rectangle representing the bounds of the button. 129 WebCore::IntRect m_rect; 130 // An SkPicture that, thanks to storeButtonInfo, is pointed to by the master 131 // picture, so that we can rerecord this button without rerecording the 132 // world. 133 SkPicture* m_picture; 134 // The state of the button - Currently kFocused or kNormal (and kDisabled 135 // as an initial value), but could be expanded to include other states. 136 WebCore::RenderSkinAndroid::State m_state; 137 }; 138 139 namespace WebCore { 140 141 class GraphicsContext; 142 143 class PlatformGraphicsContext { 144 public: 145 PlatformGraphicsContext(); 146 // Pass in a recording canvas, and an array of button information to be 147 // updated. 148 PlatformGraphicsContext(SkCanvas* canvas, WTF::Vector<Container>* buttons); 149 ~PlatformGraphicsContext(); 150 151 SkCanvas* mCanvas; 152 deleteUs()153 bool deleteUs() const { return m_deleteCanvas; } 154 // If our graphicscontext has a button list, add a new container for the 155 // nod/rect, and record a new subpicture for this node/button in the current 156 // mCanvas 157 void storeButtonInfo(Node* node, const IntRect& r); 158 private: 159 bool m_deleteCanvas; 160 WTF::Vector<Container>* m_buttons; 161 }; 162 163 } 164 #endif 165 166