From b9f7bcc11968053f7c2644e2f167e6dccdacf902 Mon Sep 17 00:00:00 2001 From: Sergey Tatarintsev Date: Tue, 25 Feb 2014 15:50:00 +0200 Subject: [PATCH] Correctly handle box-shadows Now box-shadows rects are calculated the same way as in Blink engine. --- lib/element-rect.js | 55 ++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/lib/element-rect.js b/lib/element-rect.js index b9dd060c8..2782ee59d 100644 --- a/lib/element-rect.js +++ b/lib/element-rect.js @@ -27,39 +27,52 @@ exports.get = function get(element) { .then(function(rect) { return element.getCssValue('box-shadow').then(function(boxShadow) { var shadows = parseBoxShadow(boxShadow); - return shadows.reduce(addBoxShadowRect, rect); + return adjustRect(rect, shadows); }); }); }; function parseBoxShadow(value) { - var regex = /.+? ((?:\d*)(?:\.\d+)?)px ((?:\d*)(?:\.\d+)?)px ((?:\d*)(?:\.\d+)?)px ((?:\d*)(?:\.\d+)?)px( inset)?/, + var regex = /.+? ([-+]?\d*\.?\d+)px ([-+]?\d*\.?\d+)px ([-+]?\d*\.?\d+)px ([-+]?\d*\.?\d+)px( inset)?/, results = [], match; while ((match = value.match(regex))) { - //ignore inset shadows - if (!match[5]) { - results.push({ - offsetX: +match[1], - offsetY: +match[2], - blurRadius: +match[3], - spreadRadius: +match[4] - }); - } - + results.push({ + offsetX: +match[1], + offsetY: +match[2], + blurRadius: +match[3], + spreadRadius: +match[4], + inset: !!match[5] + }); value = value.substring(match.index + match[0].length); } return results; } -function addBoxShadowRect(rect, shadow) { - var size = shadow.blurRadius + shadow.spreadRadius, - shadowRect = new Rect( - rect.x + shadow.offsetX - size, - rect.y + shadow.offsetY - size, - rect.width - shadow.offsetX + 2 * size, - rect.height - shadow.offsetY + 2 *size - ); - return rect.merge(shadowRect); +function adjustRect(rect, shadows) { + var extent = calculateShadowExtent(shadows); + return new Rect( + Math.max(0, rect.x + extent.left), + Math.max(0, rect.y + extent.top), + rect.width - extent.left + extent.right, + rect.height - extent.top + extent.bottom + ); +} + +function calculateShadowExtent(shadows) { + var result = {top: 0, left: 0, right: 0, bottom: 0}; + shadows.forEach(function(shadow) { + if (shadow.inset) { + //skip inset shadows + return; + } + + var blurAndSpread = shadow.spreadRadius + shadow.blurRadius; + result.left = Math.min(shadow.offsetX - blurAndSpread, result.left); + result.right = Math.max(shadow.offsetX + blurAndSpread, result.right); + result.top = Math.min(shadow.offsetY - blurAndSpread, result.top); + result.bottom = Math.max(shadow.offsetY + blurAndSpread, result.bottom); + }); + return result; }