From c809af5a3092ca13ff96ae50adf25d7308f7b0a2 Mon Sep 17 00:00:00 2001 From: Devdatta Deshpande Date: Fri, 16 Aug 2013 11:11:33 +0530 Subject: [PATCH] [cherrypick] Prevent sampling outside source boundaries, by creating subsurfaces from source surfaces. [Title] White line appears in Sensor ball app [Issue#] P130806-1683 [Problem] A white line appears at specific locations in Sensor ball app when the ball is moved slowly at some particular locations in the app [Cause] The view port is divided into several tiles by Backing store. When the ball is on the edge of any tile the paint rect is divided between two tiles. Due to this division and various other parameters like scale factor etc. the height is converted into a float. Since cairo does not handle floats properly a white line appears. [Solution] In latest opensource code this scenario is already taken care of by expanding the float rect to an int rect. Cherry-picked the change from http://trac.webkit.org/changeset/148681 Change-Id: Ibcd73ffaae360042b209ed92929673d560537376 --- .../graphics/cairo/PlatformContextCairo.cpp | 42 ++++++++++++++-------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp index bff8c29..fa33de8 100644 --- a/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp @@ -165,7 +165,7 @@ static void drawPatternToCairoContext(cairo_t* cr, cairo_pattern_t* pattern, con cairo_fill(cr); } -void PlatformContextCairo::drawSurfaceToContext(cairo_surface_t* surface, const FloatRect& destRect, const FloatRect& srcRect, GraphicsContext* context) +void PlatformContextCairo::drawSurfaceToContext(cairo_surface_t* surface, const FloatRect& destRect, const FloatRect& originalSrcRect, GraphicsContext* context) { #if ENABLE(TIZEN_USE_XPIXMAP_DECODED_IMAGESOURCE) cairo_surface_type_t surfaceType = cairo_surface_get_type(cairo_get_target (cr())); @@ -259,9 +259,21 @@ void PlatformContextCairo::drawSurfaceToContext(cairo_surface_t* surface, const } #endif - // If we're drawing a sub portion of the image or scaling then create - // a pattern transformation on the image and draw the transformed pattern. - // Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html + FloatRect srcRect = originalSrcRect; + + // We need to account for negative source dimensions by flipping the rectangle. + if (originalSrcRect.width() < 0) { + srcRect.setX(originalSrcRect.x() + originalSrcRect.width()); + srcRect.setWidth(std::fabs(originalSrcRect.width())); + } + if (originalSrcRect.height() < 0) { + srcRect.setY(originalSrcRect.y() + originalSrcRect.height()); + srcRect.setHeight(std::fabs(originalSrcRect.height())); + } + + // Cairo subsurfaces don't support floating point boundaries well, so we expand the rectangle. + IntRect expandedSrcRect(enclosingIntRect(srcRect)); + #if ENABLE(TIZEN_ATLAS_IMAGE_BUG_FIX) #if ENABLE(TIZEN_CAIROGLES_IMAGE_CACHE) RefPtr pattern; @@ -276,7 +288,7 @@ void PlatformContextCairo::drawSurfaceToContext(cairo_surface_t* surface, const && (srcRect.x() >= 0 && srcRect.x() < imageWidth && srcRect.y() >= 0 && srcRect.y() < imageHeight) && floor(srcRect.x() + srcRect.width()) - ceil(srcRect.x()) >= 1 && floor(srcRect.y() + srcRect.height()) - ceil(srcRect.y()) >= 1) { - subSurface = cairo_surface_create_for_rectangle(surface, srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height()); + subSurface = cairo_surface_create_for_rectangle(surface, expandedSrcRect.x(), expandedSrcRect.y(), expandedSrcRect.width(), expandedSrcRect.height()); pattern = adoptRef(cairo_pattern_create_for_surface(subSurface)); cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, 0, 0 }; cairo_pattern_set_matrix(pattern.get(), &matrix); @@ -309,7 +321,7 @@ void PlatformContextCairo::drawSurfaceToContext(cairo_surface_t* surface, const && (srcRect.x() >= 0 && srcRect.x() < imageWidth && srcRect.y() >= 0 && srcRect.y() < imageHeight) && floor(srcRect.x() + srcRect.width()) - ceil(srcRect.x()) >= 1 && floor(srcRect.y() + srcRect.height()) - ceil(srcRect.y()) >= 1) { - subSurface = cairo_surface_create_for_rectangle(surface, srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height()); + subSurface = cairo_surface_create_for_rectangle(surface, expandedSrcRect.x(), expandedSrcRect.y(), expandedSrcRect.width(), expandedSrcRect.height()); pattern = adoptRef(cairo_pattern_create_for_surface(subSurface)); cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, 0, 0 }; cairo_pattern_set_matrix(pattern.get(), &matrix); @@ -358,28 +370,30 @@ void PlatformContextCairo::drawSurfaceToContext(cairo_surface_t* surface, const } cairo_pattern_set_extend(pattern.get(), CAIRO_EXTEND_PAD); + float leftPadding = static_cast(expandedSrcRect.x()) - floorf(srcRect.x()); + float topPadding = static_cast(expandedSrcRect.y()) - floorf(srcRect.y()); #if !ENABLE(TIZEN_ATLAS_IMAGE_BUG_FIX) - float scaleX = srcRect.width() / destRect.width(); - float scaleY = srcRect.height() / destRect.height(); + float scaleX = std::fabs(srcRect.width() / destRect.width()); + float scaleY = std::fabs(srcRect.height() / destRect.height()); #if ENABLE(TIZEN_CAIROGLES_IMAGE_AUTOSCALE) float scaleWidth = (float)original_width/current_width; float scaleHeight = (float)original_height/current_height; - cairo_matrix_t matrix = { scaleX/scaleWidth, 0, 0, scaleY/scaleHeight, srcRect.x()/scaleWidth, srcRect.y()/scaleHeight }; + cairo_matrix_t matrix = { scaleX/scaleWidth, 0, 0, scaleY/scaleHeight, leftPadding/scaleWidth, topPadding/scaleHeight }; #else - cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, srcRect.x(), srcRect.y() }; + cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, leftPadding, topPadding }; #endif cairo_pattern_set_matrix(pattern.get(), &matrix); #else #if ENABLE(TIZEN_CAIROGLES_IMAGE_CACHE) ||ENABLE(TIZEN_USE_XPIXMAP_DECODED_IMAGESOURCE) if (surfaceType == CAIRO_SURFACE_TYPE_GL) { - float scaleX = srcRect.width() / destRect.width(); - float scaleY = srcRect.height() / destRect.height(); + float scaleX = std::fabs(srcRect.width() / destRect.width()); + float scaleY = std::fabs(srcRect.height() / destRect.height()); #if ENABLE(TIZEN_CAIROGLES_IMAGE_AUTOSCALE) float scaleWidth = (float)original_width/current_width; float scaleHeight = (float)original_height/current_height; - cairo_matrix_t matrix = { scaleX/scaleWidth, 0, 0, scaleY/scaleHeight, srcRect.x()/scaleWidth, srcRect.y()/scaleHeight }; + cairo_matrix_t matrix = { scaleX/scaleWidth, 0, 0, scaleY/scaleHeight,leftPadding/scaleWidth, topPadding/scaleHeight }; #else - cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, srcRect.x(), srcRect.y() }; + cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, leftPadding, topPadding }; #endif cairo_pattern_set_matrix(pattern.get(), &matrix); } -- 2.7.4