1 /* 2 * Copyright (C) 2009 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifndef TransparencyWin_h 32 #define TransparencyWin_h 33 34 #include <windows.h> 35 36 #include "AffineTransform.h" 37 #include "ImageBuffer.h" 38 #include "Noncopyable.h" 39 #include "wtf/OwnPtr.h" 40 41 class SkBitmap; 42 class SkCanvas; 43 44 namespace WebCore { 45 46 class GraphicsContext; 47 class TransparencyWin_NoLayer_Test; 48 class TransparencyWin_WhiteLayer_Test; 49 class TransparencyWin_TextComposite_Test; 50 class TransparencyWin_OpaqueCompositeLayer_Test; 51 52 // Helper class that abstracts away drawing ClearType text and Windows form 53 // controls either to the original context directly, or to an offscreen context 54 // that is composited later manually. This is to get around Windows' inability 55 // to handle the alpha channel, semitransparent text, and transformed form 56 // controls. 57 class TransparencyWin { 58 WTF_MAKE_NONCOPYABLE(TransparencyWin); 59 public: 60 enum LayerMode { 61 // No extra layer is created. Drawing will happen to the source. 62 // Valid only with KeepTransform and ScaleTransform. The region being 63 // drawn onto must be opaque, since the modified region will be forced 64 // to opaque when drawing is complete. 65 NoLayer, 66 67 // Makes a temporary layer consisting of the composited layers below 68 // it. This result must be opaque. When complete, the result will be 69 // compared to the original, and the difference will be added to a thee 70 // destination layer. 71 // 72 // This mode only works if the lower layers are opque (normally the 73 // case for a web page) and layers are only drawn in the stack order, 74 // meaning you can never draw underneath a layer. 75 // 76 // This doesn't technically produce the correct answer in all cases. If 77 // you have an opaque base, a transparency layer, than a semitransparent 78 // drawing on top, the result will actually be blended in twice. But 79 // this isn't a very important case. This mode is used for form 80 // controls which are always opaque except for occationally some 81 // antialiasing. It means form control antialiasing will be too light in 82 // some cases, but only if you have extra layers. 83 OpaqueCompositeLayer, 84 85 // Allows semitransparent text to be drawn on any background (even if it 86 // is itself semitransparent), but disables ClearType. 87 // 88 // It makes a trmporary layer filled with white. This is composited with 89 // the lower layer with a custom color applied to produce the result. 90 // The caller must draw the text in black, and set the desired final 91 // text color by calling setTextCompositeColor(). 92 // 93 // Only valid with KeepTransform, which is the only mode where drawing 94 // text in this fashion makes sense. 95 TextComposite, 96 97 // Makes a temporary layer filled with white. When complete, the layer 98 // will be forced to be opqaue (since Windows may have messed up the 99 // alpha channel) and composited down. Any areas not drawn into will 100 // remain white. 101 // 102 // This is the mode of last resort. If the opacity of the final image 103 // is unknown and we can't do the text trick (since we know its color), 104 // then we have to live with potential white halos. This is used for 105 // form control drawing, for example. 106 WhiteLayer, 107 }; 108 109 enum TransformMode { 110 // There are no changes to the transform. Use this when drawing 111 // horizontal text. The current transform must not have rotation. 112 KeepTransform, 113 114 // Drawing happens in an Untransformed space, and then that bitmap is 115 // transformed according to the current context when it is copied down. 116 // Requires that a layer be created (layer mode is not NoLayer). 117 Untransform, 118 119 // When the current transform only has a scaling factor applied and 120 // you're drawing form elements, use this parameter. This will unscale 121 // the coordinate space, so the OS will just draw the form controls 122 // larger or smaller depending on the destination size. 123 ScaleTransform, 124 }; 125 126 // You MUST call init() below. 127 // |region| is expressed relative to the current transformation. 128 TransparencyWin(); 129 ~TransparencyWin(); 130 131 // Initializes the members if you use the 0-argument constructor. Don't call 132 // this if you use the multiple-argument constructor. 133 void init(GraphicsContext* dest, 134 LayerMode layerMode, 135 TransformMode transformMode, 136 const IntRect& region); 137 138 // Combines the source and destination bitmaps using the given mode. 139 // Calling this function before the destructor runs is mandatory in most 140 // cases, and harmless otherwise. The mandatory cases are: 141 // (m_layerMode != NoLayer) || (m_transformMode == ScaleTransform) 142 void composite(); 143 144 // Returns the context for drawing into, which may be the destination 145 // context, or a temporary one. 146 GraphicsContext* context() const { return m_drawContext; } 147 148 PlatformGraphicsContext* platformContext() const { return m_drawContext ? m_drawContext->platformContext() : 0; } 149 150 // When the mode is TextComposite, this sets the color that the text will 151 // get. See the enum above for more. 152 void setTextCompositeColor(Color color); 153 154 // Returns the input bounds translated into the destination space. This is 155 // not necessary for KeepTransform since the rectangle will be unchanged. 156 const IntRect& drawRect() { return m_drawRect; } 157 158 private: 159 friend TransparencyWin_NoLayer_Test; 160 friend TransparencyWin_WhiteLayer_Test; 161 friend TransparencyWin_TextComposite_Test; 162 friend TransparencyWin_OpaqueCompositeLayer_Test; 163 164 class OwnedBuffers; 165 166 void computeLayerSize(); 167 168 // Sets up a new layer, if any. setupLayer() will call the appopriate layer- 169 // specific helper. Must be called after computeLayerSize(); 170 void setupLayer(); 171 void setupLayerForNoLayer(); 172 void setupLayerForOpaqueCompositeLayer(); 173 void setupLayerForTextComposite(); 174 void setupLayerForWhiteLayer(); 175 176 // Sets up the transformation on the newly created layer. setupTransform() 177 // will call the appropriate transform-specific helper. Must be called after 178 // setupLayer(). 179 void setupTransform(const IntRect& region); 180 void setupTransformForKeepTransform(const IntRect& region); 181 void setupTransformForUntransform(); 182 void setupTransformForScaleTransform(); 183 184 void initializeNewContext(); 185 186 void compositeOpaqueComposite(); 187 void compositeTextComposite(); 188 189 // Fixes the alpha channel to make the region inside m_transformedRect 190 // opaque. 191 void makeLayerOpaque(); 192 193 // The context our drawing will eventually end up in. 194 GraphicsContext* m_destContext; 195 196 // The original transform from the destination context. 197 AffineTransform m_orgTransform; 198 199 LayerMode m_layerMode; 200 TransformMode m_transformMode; 201 202 // The rectangle we're drawing in the destination's coordinate space 203 IntRect m_sourceRect; 204 205 // The source rectangle transformed into pixels in the final image. For 206 // Untransform this has no meaning, since the destination might not be a 207 // rectangle. 208 IntRect m_transformedSourceRect; 209 210 // The size of the layer we created. If there's no layer, this is the size 211 // of the region we're using in the source. 212 IntSize m_layerSize; 213 214 // The rectangle we're drawing to in the draw context's coordinate space. 215 // This will be the same as the source rectangle except for ScaleTransform 216 // where we create a new virtual coordinate space for the layer. 217 IntRect m_drawRect; 218 219 // Points to the graphics context to draw text to, which will either be 220 // the original context or the copy, depending on our mode. 221 GraphicsContext* m_drawContext; 222 223 // This flag is set when we call save() on the draw context during 224 // initialization. It allows us to avoid doing an extra save()/restore() 225 // when one is unnecessary. 226 bool m_savedOnDrawContext; 227 228 // Used only when m_mode = TextComposite, this is the color that the text 229 // will end up being once we figure out the transparency. 230 Color m_textCompositeColor; 231 232 // Layer we're drawing to. 233 ImageBuffer* m_layerBuffer; 234 235 // When the layer type is OpaqueCompositeLayer, this will contain a copy 236 // of the original contents of the m_layerBuffer before Windows drew on it. 237 // It allows us to re-create what Windows did to the layer. It is an 238 // SkBitmap instead of an ImageBuffer because an SkBitmap is lighter-weight 239 // (ImageBuffers are also GDI surfaces, which we don't need here). 240 SkBitmap* m_referenceBitmap; 241 242 // If the given size of bitmap can be cached, they will be stored here. Both 243 // the bitmap and the reference are guaranteed to be allocated if this 244 // member is non-null. 245 static OwnedBuffers* m_cachedBuffers; 246 247 // If a buffer was too big to be cached, it will be created temporarily, and 248 // this member tracks its scope to make sure it gets deleted. Always use 249 // m_layerBuffer, which will either point to this object, or the statically 250 // cached one. Don't access directly. 251 OwnPtr<OwnedBuffers> m_ownedBuffers; 252 253 // Sometimes we're asked to create layers that have negative dimensions. 254 // This API is not designed to fail to initialize, so we hide the fact 255 // that they are illegal and can't be rendered (failing silently, drawing 256 // nothing). 257 bool m_validLayer; 258 }; 259 260 } // namespace WebCore 261 262 #endif // TransaprencyWin_h 263