| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012, Google Inc. All rights reserved. | 2 * Copyright (c) 2012, Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "config.h" | 31 #include "config.h" |
| 32 | 32 |
| 33 #include "platform/graphics/skia/OpaqueRegionSkia.h" | 33 #include "platform/graphics/RegionTracker.h" |
| 34 | 34 |
| 35 #include "platform/graphics/GraphicsContext.h" | 35 #include "platform/graphics/GraphicsContext.h" |
| 36 | 36 #include "third_party/skia/include/core/SkColorFilter.h" |
| 37 #include "SkColorFilter.h" | 37 #include "third_party/skia/include/core/SkShader.h" |
| 38 #include "SkShader.h" | |
| 39 | 38 |
| 40 namespace blink { | 39 namespace blink { |
| 41 | 40 |
| 42 OpaqueRegionSkia::OpaqueRegionSkia() | 41 RegionTracker::RegionTracker() |
| 43 : m_opaqueRect(SkRect::MakeEmpty()) | 42 : m_opaqueRect(SkRect::MakeEmpty()) |
| 43 , m_trackedRegionType(Opaque) |
| 44 { | 44 { |
| 45 } | 45 } |
| 46 | 46 |
| 47 void OpaqueRegionSkia::reset() | 47 void RegionTracker::reset() |
| 48 { | 48 { |
| 49 ASSERT(m_canvasLayerStack.isEmpty()); | 49 ASSERT(m_canvasLayerStack.isEmpty()); |
| 50 m_opaqueRect = SkRect::MakeEmpty(); | 50 m_opaqueRect = SkRect::MakeEmpty(); |
| 51 } | 51 } |
| 52 | 52 |
| 53 IntRect OpaqueRegionSkia::asRect() const | 53 IntRect RegionTracker::asRect() const |
| 54 { | 54 { |
| 55 // Returns the largest enclosed rect. | 55 // Returns the largest enclosed rect. |
| 56 // TODO: actually, this logic looks like its returning the smallest. | 56 // TODO: actually, this logic looks like its returning the smallest. |
| 57 // to return largest, shouldn't we take floor of left/top | 57 // to return largest, shouldn't we take floor of left/top |
| 58 // and the ceil of right/bottom? | 58 // and the ceil of right/bottom? |
| 59 int left = SkScalarCeilToInt(m_opaqueRect.fLeft); | 59 int left = SkScalarCeilToInt(m_opaqueRect.fLeft); |
| 60 int top = SkScalarCeilToInt(m_opaqueRect.fTop); | 60 int top = SkScalarCeilToInt(m_opaqueRect.fTop); |
| 61 int right = SkScalarFloorToInt(m_opaqueRect.fRight); | 61 int right = SkScalarFloorToInt(m_opaqueRect.fRight); |
| 62 int bottom = SkScalarFloorToInt(m_opaqueRect.fBottom); | 62 int bottom = SkScalarFloorToInt(m_opaqueRect.fBottom); |
| 63 return IntRect(left, top, right-left, bottom-top); | 63 return IntRect(left, top, right-left, bottom-top); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 89 case SkXfermode::kSrcIn_Mode: // source * dest | 89 case SkXfermode::kSrcIn_Mode: // source * dest |
| 90 case SkXfermode::kDstIn_Mode: // dest * source | 90 case SkXfermode::kDstIn_Mode: // dest * source |
| 91 case SkXfermode::kSrcOut_Mode: // source * (1-dest) | 91 case SkXfermode::kSrcOut_Mode: // source * (1-dest) |
| 92 case SkXfermode::kDstOut_Mode: // dest * (1-source) | 92 case SkXfermode::kDstOut_Mode: // dest * (1-source) |
| 93 case SkXfermode::kSrcATop_Mode: // dest | 93 case SkXfermode::kSrcATop_Mode: // dest |
| 94 case SkXfermode::kXor_Mode: // source + dest - 2*(source*dest) | 94 case SkXfermode::kXor_Mode: // source + dest - 2*(source*dest) |
| 95 return false; | 95 return false; |
| 96 } | 96 } |
| 97 } | 97 } |
| 98 | 98 |
| 99 static inline bool xfermodeIsOverwrite(const SkPaint& paint) |
| 100 { |
| 101 SkXfermode* xfermode = paint.getXfermode(); |
| 102 if (!xfermode) |
| 103 return false; // default to kSrcOver_Mode |
| 104 SkXfermode::Mode mode; |
| 105 if (!xfermode->asMode(&mode)) |
| 106 return false; |
| 107 switch (mode) { |
| 108 case SkXfermode::kSrc_Mode: |
| 109 case SkXfermode::kClear_Mode: |
| 110 return true; |
| 111 default: |
| 112 return false; |
| 113 } |
| 114 } |
| 115 |
| 99 // Returns true if the xfermode will keep the dst opaque, assuming the dst is al
ready opaque. | 116 // Returns true if the xfermode will keep the dst opaque, assuming the dst is al
ready opaque. |
| 100 static inline bool xfermodePreservesOpaque(const SkPaint& paint, bool srcIsOpaqu
e) | 117 static inline bool xfermodePreservesOpaque(const SkPaint& paint, bool srcIsOpaqu
e) |
| 101 { | 118 { |
| 102 SkXfermode* xfermode = paint.getXfermode(); | 119 SkXfermode* xfermode = paint.getXfermode(); |
| 103 if (!xfermode) | 120 if (!xfermode) |
| 104 return true; // default to kSrcOver_Mode | 121 return true; // default to kSrcOver_Mode |
| 105 SkXfermode::Mode mode; | 122 SkXfermode::Mode mode; |
| 106 if (!xfermode->asMode(&mode)) | 123 if (!xfermode->asMode(&mode)) |
| 107 return false; | 124 return false; |
| 108 | 125 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 121 return false; | 138 return false; |
| 122 case SkXfermode::kSrc_Mode: // source | 139 case SkXfermode::kSrc_Mode: // source |
| 123 case SkXfermode::kSrcIn_Mode: // source * dest | 140 case SkXfermode::kSrcIn_Mode: // source * dest |
| 124 case SkXfermode::kDstIn_Mode: // dest * source | 141 case SkXfermode::kDstIn_Mode: // dest * source |
| 125 case SkXfermode::kDstATop_Mode: // source | 142 case SkXfermode::kDstATop_Mode: // source |
| 126 return srcIsOpaque; | 143 return srcIsOpaque; |
| 127 } | 144 } |
| 128 } | 145 } |
| 129 | 146 |
| 130 // Returns true if all pixels painted will be opaque. | 147 // Returns true if all pixels painted will be opaque. |
| 131 static inline bool paintIsOpaque(const SkPaint& paint, OpaqueRegionSkia::DrawTyp
e drawType, const SkBitmap* bitmap) | 148 static inline bool paintIsOpaque(const SkPaint& paint, RegionTracker::DrawType d
rawType, const SkBitmap* bitmap) |
| 132 { | 149 { |
| 133 if (paint.getAlpha() < 0xFF) | 150 if (paint.getAlpha() < 0xFF) |
| 134 return false; | 151 return false; |
| 135 bool checkFillOnly = drawType != OpaqueRegionSkia::FillOrStroke; | 152 bool checkFillOnly = drawType != RegionTracker::FillOrStroke; |
| 136 if (!checkFillOnly && paint.getStyle() != SkPaint::kFill_Style && paint.isAn
tiAlias()) | 153 if (!checkFillOnly && paint.getStyle() != SkPaint::kFill_Style && paint.isAn
tiAlias()) |
| 137 return false; | 154 return false; |
| 138 SkShader* shader = paint.getShader(); | 155 SkShader* shader = paint.getShader(); |
| 139 if (shader && !shader->isOpaque()) | 156 if (shader && !shader->isOpaque()) |
| 140 return false; | 157 return false; |
| 141 if (bitmap && !bitmap->isOpaque()) | 158 if (bitmap && !bitmap->isOpaque()) |
| 142 return false; | 159 return false; |
| 143 if (paint.getLooper()) | 160 if (paint.getLooper()) |
| 144 return false; | 161 return false; |
| 145 if (paint.getImageFilter()) | 162 if (paint.getImageFilter()) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 161 | 178 |
| 162 SkIRect deviceClipIRect; | 179 SkIRect deviceClipIRect; |
| 163 if (context->canvas()->getClipDeviceBounds(&deviceClipIRect)) | 180 if (context->canvas()->getClipDeviceBounds(&deviceClipIRect)) |
| 164 deviceClipRect.set(deviceClipIRect); | 181 deviceClipRect.set(deviceClipIRect); |
| 165 else | 182 else |
| 166 deviceClipRect.setEmpty(); | 183 deviceClipRect.setEmpty(); |
| 167 | 184 |
| 168 return true; | 185 return true; |
| 169 } | 186 } |
| 170 | 187 |
| 171 void OpaqueRegionSkia::pushCanvasLayer(const SkPaint* paint) | 188 void RegionTracker::pushCanvasLayer(const SkPaint* paint) |
| 172 { | 189 { |
| 173 CanvasLayerState state; | 190 CanvasLayerState state; |
| 174 if (paint) | 191 if (paint) |
| 175 state.paint = *paint; | 192 state.paint = *paint; |
| 176 m_canvasLayerStack.append(state); | 193 m_canvasLayerStack.append(state); |
| 177 } | 194 } |
| 178 | 195 |
| 179 void OpaqueRegionSkia::popCanvasLayer(const GraphicsContext* context) | 196 void RegionTracker::popCanvasLayer(const GraphicsContext* context) |
| 180 { | 197 { |
| 181 ASSERT(!context->paintingDisabled()); | 198 ASSERT(!context->paintingDisabled()); |
| 182 ASSERT(!m_canvasLayerStack.isEmpty()); | 199 ASSERT(!m_canvasLayerStack.isEmpty()); |
| 183 if (m_canvasLayerStack.isEmpty()) | 200 if (m_canvasLayerStack.isEmpty()) |
| 184 return; | 201 return; |
| 185 | 202 |
| 186 const CanvasLayerState& canvasLayer = m_canvasLayerStack.last(); | 203 const CanvasLayerState& canvasLayer = m_canvasLayerStack.last(); |
| 187 SkRect layerOpaqueRect = canvasLayer.opaqueRect; | 204 SkRect layerOpaqueRect = canvasLayer.opaqueRect; |
| 188 SkPaint layerPaint = canvasLayer.paint; | 205 SkPaint layerPaint = canvasLayer.paint; |
| 189 | 206 |
| 190 // Apply the image mask. | 207 // Apply the image mask. |
| 191 if (canvasLayer.hasImageMask && !layerOpaqueRect.intersect(canvasLayer.image
OpaqueRect)) | 208 if (canvasLayer.hasImageMask && !layerOpaqueRect.intersect(canvasLayer.image
OpaqueRect)) |
| 192 layerOpaqueRect.setEmpty(); | 209 layerOpaqueRect.setEmpty(); |
| 193 | 210 |
| 194 m_canvasLayerStack.removeLast(); | 211 m_canvasLayerStack.removeLast(); |
| 195 | 212 |
| 196 applyOpaqueRegionFromLayer(context, layerOpaqueRect, layerPaint); | 213 applyOpaqueRegionFromLayer(context, layerOpaqueRect, layerPaint); |
| 197 } | 214 } |
| 198 | 215 |
| 199 void OpaqueRegionSkia::setImageMask(const SkRect& imageOpaqueRect) | 216 void RegionTracker::setImageMask(const SkRect& imageOpaqueRect) |
| 200 { | 217 { |
| 201 ASSERT(!m_canvasLayerStack.isEmpty()); | 218 ASSERT(!m_canvasLayerStack.isEmpty()); |
| 202 m_canvasLayerStack.last().hasImageMask = true; | 219 m_canvasLayerStack.last().hasImageMask = true; |
| 203 m_canvasLayerStack.last().imageOpaqueRect = imageOpaqueRect; | 220 m_canvasLayerStack.last().imageOpaqueRect = imageOpaqueRect; |
| 204 } | 221 } |
| 205 | 222 |
| 206 void OpaqueRegionSkia::didDrawRect(const GraphicsContext* context, const SkRect&
fillRect, const SkPaint& paint, const SkBitmap* sourceBitmap) | 223 void RegionTracker::didDrawRect(const GraphicsContext* context, const SkRect& fi
llRect, const SkPaint& paint, const SkBitmap* sourceBitmap) |
| 207 { | 224 { |
| 208 ASSERT(!context->paintingDisabled()); | 225 ASSERT(!context->paintingDisabled()); |
| 209 // Any stroking may put alpha in pixels even if the filling part does not. | 226 // Any stroking may put alpha in pixels even if the filling part does not. |
| 210 if (paint.getStyle() != SkPaint::kFill_Style) { | 227 if (paint.getStyle() != SkPaint::kFill_Style) { |
| 211 bool fillsBounds = false; | 228 bool fillsBounds = false; |
| 212 | 229 |
| 213 if (!paint.canComputeFastBounds()) | 230 if (!paint.canComputeFastBounds()) { |
| 214 didDrawUnbounded(context, paint, FillOrStroke); | 231 didDrawUnbounded(context, paint, FillOrStroke); |
| 215 else { | 232 } else { |
| 216 SkRect strokeRect; | 233 SkRect strokeRect; |
| 217 strokeRect = paint.computeFastBounds(fillRect, &strokeRect); | 234 strokeRect = paint.computeFastBounds(fillRect, &strokeRect); |
| 218 didDraw(context, strokeRect, paint, sourceBitmap, fillsBounds, FillO
rStroke); | 235 didDraw(context, strokeRect, paint, sourceBitmap, fillsBounds, FillO
rStroke); |
| 219 } | 236 } |
| 220 } | 237 } |
| 221 | 238 |
| 222 bool fillsBounds = paint.getStyle() != SkPaint::kStroke_Style; | 239 bool fillsBounds = paint.getStyle() != SkPaint::kStroke_Style; |
| 223 didDraw(context, fillRect, paint, sourceBitmap, fillsBounds, FillOnly); | 240 didDraw(context, fillRect, paint, sourceBitmap, fillsBounds, FillOnly); |
| 224 } | 241 } |
| 225 | 242 |
| 226 void OpaqueRegionSkia::didDrawPath(const GraphicsContext* context, const SkPath&
path, const SkPaint& paint) | 243 void RegionTracker::didDrawPath(const GraphicsContext* context, const SkPath& pa
th, const SkPaint& paint) |
| 227 { | 244 { |
| 228 ASSERT(!context->paintingDisabled()); | 245 ASSERT(!context->paintingDisabled()); |
| 229 SkRect rect; | 246 SkRect rect; |
| 230 if (path.isRect(&rect)) { | 247 if (path.isRect(&rect)) { |
| 231 didDrawRect(context, rect, paint, 0); | 248 didDrawRect(context, rect, paint, 0); |
| 232 return; | 249 return; |
| 233 } | 250 } |
| 234 | 251 |
| 235 bool fillsBounds = false; | 252 bool fillsBounds = false; |
| 236 | 253 |
| 237 if (!paint.canComputeFastBounds()) | 254 if (!paint.canComputeFastBounds()) { |
| 238 didDrawUnbounded(context, paint, FillOrStroke); | 255 didDrawUnbounded(context, paint, FillOrStroke); |
| 239 else { | 256 } else { |
| 240 rect = paint.computeFastBounds(path.getBounds(), &rect); | 257 rect = paint.computeFastBounds(path.getBounds(), &rect); |
| 241 didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke); | 258 didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke); |
| 242 } | 259 } |
| 243 } | 260 } |
| 244 | 261 |
| 245 void OpaqueRegionSkia::didDrawPoints(const GraphicsContext* context, SkCanvas::P
ointMode mode, int numPoints, const SkPoint points[], const SkPaint& paint) | 262 void RegionTracker::didDrawPoints(const GraphicsContext* context, SkCanvas::Poin
tMode mode, int numPoints, const SkPoint points[], const SkPaint& paint) |
| 246 { | 263 { |
| 247 ASSERT(!context->paintingDisabled()); | 264 ASSERT(!context->paintingDisabled()); |
| 248 if (!numPoints) | 265 if (!numPoints) |
| 249 return; | 266 return; |
| 250 | 267 |
| 251 SkRect rect; | 268 SkRect rect; |
| 252 rect.fLeft = points[0].fX; | 269 rect.fLeft = points[0].fX; |
| 253 rect.fRight = points[0].fX + 1; | 270 rect.fRight = points[0].fX + 1; |
| 254 rect.fTop = points[0].fY; | 271 rect.fTop = points[0].fY; |
| 255 rect.fBottom = points[0].fY + 1; | 272 rect.fBottom = points[0].fY + 1; |
| 256 | 273 |
| 257 for (int i = 1; i < numPoints; ++i) { | 274 for (int i = 1; i < numPoints; ++i) { |
| 258 rect.fLeft = std::min(rect.fLeft, points[i].fX); | 275 rect.fLeft = std::min(rect.fLeft, points[i].fX); |
| 259 rect.fRight = std::max(rect.fRight, points[i].fX + 1); | 276 rect.fRight = std::max(rect.fRight, points[i].fX + 1); |
| 260 rect.fTop = std::min(rect.fTop, points[i].fY); | 277 rect.fTop = std::min(rect.fTop, points[i].fY); |
| 261 rect.fBottom = std::max(rect.fBottom, points[i].fY + 1); | 278 rect.fBottom = std::max(rect.fBottom, points[i].fY + 1); |
| 262 } | 279 } |
| 263 | 280 |
| 264 bool fillsBounds = false; | 281 bool fillsBounds = false; |
| 265 | 282 |
| 266 if (!paint.canComputeFastBounds()) | 283 if (!paint.canComputeFastBounds()) { |
| 267 didDrawUnbounded(context, paint, FillOrStroke); | 284 didDrawUnbounded(context, paint, FillOrStroke); |
| 268 else { | 285 } else { |
| 269 rect = paint.computeFastBounds(rect, &rect); | 286 rect = paint.computeFastBounds(rect, &rect); |
| 270 didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke); | 287 didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke); |
| 271 } | 288 } |
| 272 } | 289 } |
| 273 | 290 |
| 274 void OpaqueRegionSkia::didDrawBounded(const GraphicsContext* context, const SkRe
ct& bounds, const SkPaint& paint) | 291 void RegionTracker::didDrawBounded(const GraphicsContext* context, const SkRect&
bounds, const SkPaint& paint) |
| 275 { | 292 { |
| 276 ASSERT(!context->paintingDisabled()); | 293 ASSERT(!context->paintingDisabled()); |
| 277 bool fillsBounds = false; | 294 bool fillsBounds = false; |
| 278 | 295 |
| 279 if (!paint.canComputeFastBounds()) | 296 if (!paint.canComputeFastBounds()) { |
| 280 didDrawUnbounded(context, paint, FillOrStroke); | 297 didDrawUnbounded(context, paint, FillOrStroke); |
| 281 else { | 298 } else { |
| 282 SkRect rect; | 299 SkRect rect; |
| 283 rect = paint.computeFastBounds(bounds, &rect); | 300 rect = paint.computeFastBounds(bounds, &rect); |
| 284 didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke); | 301 didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke); |
| 285 } | 302 } |
| 286 } | 303 } |
| 287 | 304 |
| 288 void OpaqueRegionSkia::didDraw(const GraphicsContext* context, const SkRect& rec
t, const SkPaint& paint, const SkBitmap* sourceBitmap, bool fillsBounds, DrawTyp
e drawType) | 305 void RegionTracker::didDraw(const GraphicsContext* context, const SkRect& rect,
const SkPaint& paint, const SkBitmap* sourceBitmap, bool fillsBounds, DrawType d
rawType) |
| 289 { | 306 { |
| 290 ASSERT(!context->paintingDisabled()); | 307 ASSERT(!context->paintingDisabled()); |
| 291 SkRect targetRect = rect; | 308 SkRect targetRect = rect; |
| 292 | 309 |
| 293 // Apply the transform to device coordinate space. | 310 // Apply the transform to device coordinate space. |
| 294 SkMatrix canvasTransform = context->canvas()->getTotalMatrix(); | 311 SkMatrix canvasTransform = context->canvas()->getTotalMatrix(); |
| 295 if (!canvasTransform.mapRect(&targetRect)) | 312 if (!canvasTransform.mapRect(&targetRect)) |
| 296 fillsBounds = false; | 313 fillsBounds = false; |
| 297 | 314 |
| 298 // Apply the current clip. | 315 // Apply the current clip. |
| 299 SkRect deviceClipRect; | 316 SkRect deviceClipRect; |
| 300 if (!getDeviceClipAsRect(context, deviceClipRect)) | 317 if (!getDeviceClipAsRect(context, deviceClipRect)) |
| 301 fillsBounds = false; | 318 fillsBounds = false; |
| 302 else if (!targetRect.intersect(deviceClipRect)) | 319 else if (!targetRect.intersect(deviceClipRect)) |
| 303 return; | 320 return; |
| 304 | 321 |
| 322 if (m_trackedRegionType == Overwrite && fillsBounds && xfermodeIsOverwrite(p
aint)) { |
| 323 markRectAsOpaque(targetRect); |
| 324 return; |
| 325 } |
| 326 |
| 305 bool drawsOpaque = paintIsOpaque(paint, drawType, sourceBitmap); | 327 bool drawsOpaque = paintIsOpaque(paint, drawType, sourceBitmap); |
| 306 bool xfersOpaque = xfermodeIsOpaque(paint, drawsOpaque); | 328 bool xfersOpaque = xfermodeIsOpaque(paint, drawsOpaque); |
| 307 bool preservesOpaque = xfermodePreservesOpaque(paint, drawsOpaque); | |
| 308 | 329 |
| 309 if (fillsBounds && xfersOpaque) | 330 if (fillsBounds && xfersOpaque) { |
| 310 markRectAsOpaque(targetRect); | 331 markRectAsOpaque(targetRect); |
| 311 else if (!preservesOpaque) | 332 } else if (m_trackedRegionType == Opaque && !xfermodePreservesOpaque(paint,
drawsOpaque)) { |
| 312 markRectAsNonOpaque(targetRect); | 333 markRectAsNonOpaque(targetRect); |
| 334 } |
| 313 } | 335 } |
| 314 | 336 |
| 315 void OpaqueRegionSkia::didDrawUnbounded(const GraphicsContext* context, const Sk
Paint& paint, DrawType drawType) | 337 void RegionTracker::didDrawUnbounded(const GraphicsContext* context, const SkPai
nt& paint, DrawType drawType) |
| 316 { | 338 { |
| 317 ASSERT(!context->paintingDisabled()); | 339 ASSERT(!context->paintingDisabled()); |
| 318 bool drawsOpaque = paintIsOpaque(paint, drawType, 0); | 340 bool drawsOpaque = paintIsOpaque(paint, drawType, 0); |
| 319 bool preservesOpaque = xfermodePreservesOpaque(paint, drawsOpaque); | 341 bool preservesOpaque = xfermodePreservesOpaque(paint, drawsOpaque); |
| 320 | 342 |
| 321 if (preservesOpaque) | 343 if (preservesOpaque) |
| 322 return; | 344 return; |
| 323 | 345 |
| 324 SkRect deviceClipRect; | 346 SkRect deviceClipRect; |
| 325 getDeviceClipAsRect(context, deviceClipRect); | 347 getDeviceClipAsRect(context, deviceClipRect); |
| 326 markRectAsNonOpaque(deviceClipRect); | 348 markRectAsNonOpaque(deviceClipRect); |
| 327 } | 349 } |
| 328 | 350 |
| 329 void OpaqueRegionSkia::applyOpaqueRegionFromLayer(const GraphicsContext* context
, const SkRect& layerOpaqueRect, const SkPaint& paint) | 351 void RegionTracker::applyOpaqueRegionFromLayer(const GraphicsContext* context, c
onst SkRect& layerOpaqueRect, const SkPaint& paint) |
| 330 { | 352 { |
| 331 SkRect deviceClipRect; | 353 SkRect deviceClipRect; |
| 332 bool deviceClipIsARect = getDeviceClipAsRect(context, deviceClipRect); | 354 bool deviceClipIsARect = getDeviceClipAsRect(context, deviceClipRect); |
| 333 | 355 |
| 334 if (deviceClipRect.isEmpty()) | 356 if (deviceClipRect.isEmpty()) |
| 335 return; | 357 return; |
| 336 | 358 |
| 337 SkRect sourceOpaqueRect = layerOpaqueRect; | 359 SkRect sourceOpaqueRect = layerOpaqueRect; |
| 338 // Save the opaque area in the destination, so we can preserve the parts of
it under the source opaque area if possible. | 360 // Save the opaque area in the destination, so we can preserve the parts of
it under the source opaque area if possible. |
| 339 SkRect destinationOpaqueRect = currentTrackingOpaqueRect(); | 361 SkRect destinationOpaqueRect = currentTrackingOpaqueRect(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 352 bool sourceOpaqueRectPreservesOpaque = xfermodePreservesOpaque(paint, source
OpaqueRectDrawsOpaque); | 374 bool sourceOpaqueRectPreservesOpaque = xfermodePreservesOpaque(paint, source
OpaqueRectDrawsOpaque); |
| 353 | 375 |
| 354 // If the layer's opaque area is being drawn opaque in the layer below, then
mark it opaque. Otherwise, | 376 // If the layer's opaque area is being drawn opaque in the layer below, then
mark it opaque. Otherwise, |
| 355 // if it preserves opaque then keep the intersection of the two. | 377 // if it preserves opaque then keep the intersection of the two. |
| 356 if (sourceOpaqueRectXfersOpaque) | 378 if (sourceOpaqueRectXfersOpaque) |
| 357 markRectAsOpaque(sourceOpaqueRect); | 379 markRectAsOpaque(sourceOpaqueRect); |
| 358 else if (sourceOpaqueRectPreservesOpaque && sourceOpaqueRect.intersect(desti
nationOpaqueRect)) | 380 else if (sourceOpaqueRectPreservesOpaque && sourceOpaqueRect.intersect(desti
nationOpaqueRect)) |
| 359 markRectAsOpaque(sourceOpaqueRect); | 381 markRectAsOpaque(sourceOpaqueRect); |
| 360 } | 382 } |
| 361 | 383 |
| 362 void OpaqueRegionSkia::markRectAsOpaque(const SkRect& rect) | 384 void RegionTracker::markRectAsOpaque(const SkRect& rect) |
| 363 { | 385 { |
| 364 // We want to keep track of an opaque region but bound its complexity at a c
onstant size. | 386 // We want to keep track of an opaque region but bound its complexity at a c
onstant size. |
| 365 // We keep track of the largest rectangle seen by area. If we can add the ne
w rect to this | 387 // We keep track of the largest rectangle seen by area. If we can add the ne
w rect to this |
| 366 // rectangle then we do that, as that is the cheapest way to increase the ar
ea returned | 388 // rectangle then we do that, as that is the cheapest way to increase the ar
ea returned |
| 367 // without increasing the complexity. | 389 // without increasing the complexity. |
| 368 | 390 |
| 369 SkRect& opaqueRect = currentTrackingOpaqueRect(); | 391 SkRect& opaqueRect = currentTrackingOpaqueRect(); |
| 370 | 392 |
| 371 if (rect.isEmpty()) | 393 if (rect.isEmpty()) |
| 372 return; | 394 return; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 388 if (rect.fBottom > opaqueRect.fBottom && rect.fTop <= opaqueRect.fBottom
) | 410 if (rect.fBottom > opaqueRect.fBottom && rect.fTop <= opaqueRect.fBottom
) |
| 389 opaqueRect.fBottom = rect.fBottom; | 411 opaqueRect.fBottom = rect.fBottom; |
| 390 } | 412 } |
| 391 | 413 |
| 392 long opaqueArea = (long)opaqueRect.width() * (long)opaqueRect.height(); | 414 long opaqueArea = (long)opaqueRect.width() * (long)opaqueRect.height(); |
| 393 long area = (long)rect.width() * (long)rect.height(); | 415 long area = (long)rect.width() * (long)rect.height(); |
| 394 if (area > opaqueArea) | 416 if (area > opaqueArea) |
| 395 opaqueRect = rect; | 417 opaqueRect = rect; |
| 396 } | 418 } |
| 397 | 419 |
| 398 void OpaqueRegionSkia::markRectAsNonOpaque(const SkRect& rect) | 420 void RegionTracker::markRectAsNonOpaque(const SkRect& rect) |
| 399 { | 421 { |
| 400 // We want to keep as much of the current opaque rectangle as we can, so fin
d the one largest | 422 // We want to keep as much of the current opaque rectangle as we can, so fin
d the one largest |
| 401 // rectangle inside m_opaqueRect that does not intersect with |rect|. | 423 // rectangle inside m_opaqueRect that does not intersect with |rect|. |
| 402 | 424 |
| 403 SkRect& opaqueRect = currentTrackingOpaqueRect(); | 425 SkRect& opaqueRect = currentTrackingOpaqueRect(); |
| 404 | 426 |
| 405 if (!SkRect::Intersects(rect, opaqueRect)) | 427 if (!SkRect::Intersects(rect, opaqueRect)) |
| 406 return; | 428 return; |
| 407 if (rect.contains(opaqueRect)) { | 429 if (rect.contains(opaqueRect)) { |
| 408 markAllAsNonOpaque(); | 430 markAllAsNonOpaque(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 426 vertical.fRight = rect.fLeft; | 448 vertical.fRight = rect.fLeft; |
| 427 else | 449 else |
| 428 vertical.fLeft = rect.fRight; | 450 vertical.fLeft = rect.fRight; |
| 429 | 451 |
| 430 if ((long)horizontal.width() * (long)horizontal.height() > (long)vertical.wi
dth() * (long)vertical.height()) | 452 if ((long)horizontal.width() * (long)horizontal.height() > (long)vertical.wi
dth() * (long)vertical.height()) |
| 431 opaqueRect = horizontal; | 453 opaqueRect = horizontal; |
| 432 else | 454 else |
| 433 opaqueRect = vertical; | 455 opaqueRect = vertical; |
| 434 } | 456 } |
| 435 | 457 |
| 436 void OpaqueRegionSkia::markAllAsNonOpaque() | 458 void RegionTracker::markAllAsNonOpaque() |
| 437 { | 459 { |
| 438 SkRect& opaqueRect = currentTrackingOpaqueRect(); | 460 SkRect& opaqueRect = currentTrackingOpaqueRect(); |
| 439 opaqueRect.setEmpty(); | 461 opaqueRect.setEmpty(); |
| 440 } | 462 } |
| 441 | 463 |
| 442 SkRect& OpaqueRegionSkia::currentTrackingOpaqueRect() | 464 SkRect& RegionTracker::currentTrackingOpaqueRect() |
| 443 { | 465 { |
| 444 // If we are drawing into a canvas layer, then track the opaque rect in that
layer. | 466 // If we are drawing into a canvas layer, then track the opaque rect in that
layer. |
| 445 return m_canvasLayerStack.isEmpty() ? m_opaqueRect : m_canvasLayerStack.last
().opaqueRect; | 467 return m_canvasLayerStack.isEmpty() ? m_opaqueRect : m_canvasLayerStack.last
().opaqueRect; |
| 446 } | 468 } |
| 447 | 469 |
| 448 } // namespace blink | 470 } // namespace blink |
| OLD | NEW |