Changeset 191658 in webkit


Ignore:
Timestamp:
Oct 27, 2015 10:20:08 PM (8 years ago)
Author:
Hunseop Jeong
Message:

[Cairo] Incorrect dashed and dotted border painting after r177686.
https://bugs.webkit.org/show_bug.cgi?id=141967

Reviewed by Gyuyoung Kim.

Fix the incorrect dashed/dotted border painting in cairo.

Source/WebCore:

  • platform/graphics/cairo/GraphicsContextCairo.cpp:

(WebCore::GraphicsContext::drawLine):
(WebCore::calculateStrokePatternOffset): Deleted.
(WebCore::drawLineOnCairoContext): Deleted.

LayoutTests:

  • platform/gtk/TestExpectations: Removed the passed test.
Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r191652 r191658  
     12015-10-27  Hunseop Jeong  <hs85.jeong@samsung.com>
     2
     3        [Cairo] Incorrect dashed and dotted border painting after r177686.
     4        https://bugs.webkit.org/show_bug.cgi?id=141967
     5
     6        Reviewed by Gyuyoung Kim.
     7
     8        Fix the incorrect dashed/dotted border painting in cairo.
     9
     10        * platform/gtk/TestExpectations: Removed the passed test.
     11
    1122015-10-27  Chris Dumez  <cdumez@apple.com>
    213
  • trunk/LayoutTests/platform/gtk/TestExpectations

    r191546 r191658  
    530530webkit.org/b/141837 fast/borders/border-painting-correctness-dashed.html [ ImageOnlyFailure ]
    531531webkit.org/b/141837 fast/borders/border-painting-correctness-dotted.html [ ImageOnlyFailure ]
    532 webkit.org/b/141838 fast/borders/0px-borders.html [ ImageOnlyFailure ]
    533532
    534533webkit.org/b/141458 imported/mozilla/svg/blend-color-burn.svg [ ImageOnlyFailure ]
  • trunk/Source/WebCore/ChangeLog

    r191652 r191658  
     12015-10-27  Hunseop Jeong  <hs85.jeong@samsung.com>
     2
     3        [Cairo] Incorrect dashed and dotted border painting after r177686.
     4        https://bugs.webkit.org/show_bug.cgi?id=141967
     5
     6        Reviewed by Gyuyoung Kim.
     7
     8        Fix the incorrect dashed/dotted border painting in cairo.
     9
     10        * platform/graphics/cairo/GraphicsContextCairo.cpp:
     11        (WebCore::GraphicsContext::drawLine):
     12        (WebCore::calculateStrokePatternOffset): Deleted.
     13        (WebCore::drawLineOnCairoContext): Deleted.
     14
    1152015-10-27  Chris Dumez  <cdumez@apple.com>
    216
  • trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp

    r191617 r191658  
    254254}
    255255
    256 static double calculateStrokePatternOffset(int distance, int patternWidth)
    257 {
    258     // Example: 80 pixels with a width of 30 pixels. Remainder is 20.
    259     // The maximum pixels of line we could paint will be 50 pixels.
    260     int remainder = distance % patternWidth;
    261     int numSegments = (distance - remainder) / patternWidth;
    262 
    263     // Special case 1px dotted borders for speed.
    264     if (patternWidth == 1)
    265         return 1;
    266 
    267     bool evenNumberOfSegments = !(numSegments % 2);
    268     if (remainder)
    269         evenNumberOfSegments = !evenNumberOfSegments;
    270 
    271     if (evenNumberOfSegments) {
    272         if (remainder)
    273             return (patternWidth - remainder) + (remainder / 2);
    274         return patternWidth / 2;
    275     }
    276 
    277     // Odd number of segments.
    278     if (remainder)
    279         return (patternWidth - remainder) / 2.f;
    280     return 0;
    281 }
    282 
    283 static void drawLineOnCairoContext(GraphicsContext* graphicsContext, cairo_t* context, const FloatPoint& point1, const FloatPoint& point2)
    284 {
    285     StrokeStyle style = graphicsContext->strokeStyle();
    286     if (style == NoStroke)
    287         return;
    288 
    289     const Color& strokeColor = graphicsContext->strokeColor();
    290     int strokeThickness = floorf(graphicsContext->strokeThickness());
    291     if (graphicsContext->strokeThickness() < 1)
    292         strokeThickness = 1;
    293 
    294     int patternWidth = 0;
    295     if (style == DottedStroke)
    296         patternWidth = strokeThickness;
    297     else if (style == DashedStroke)
    298         patternWidth = 3 * strokeThickness;
    299 
    300     bool isVerticalLine = point1.x() == point2.x();
    301     FloatPoint point1OnPixelBoundaries = point1;
    302     FloatPoint point2OnPixelBoundaries = point2;
    303     GraphicsContext::adjustLineToPixelBoundaries(point1OnPixelBoundaries, point2OnPixelBoundaries, strokeThickness, style);
    304 
    305     if (patternWidth) {
    306         // Do a rect fill of our endpoints.  This ensures we always have the
    307         // appearance of being a border.  We then draw the actual dotted/dashed line.
    308         FloatRect firstRect(point1OnPixelBoundaries, FloatSize(strokeThickness, strokeThickness));
    309         FloatRect secondRect(point2OnPixelBoundaries, FloatSize(strokeThickness, strokeThickness));
    310         if (isVerticalLine) {
    311             firstRect.move(-strokeThickness / 2, -strokeThickness);
    312             secondRect.move(-strokeThickness / 2, 0);
    313         } else {
    314             firstRect.move(-strokeThickness, -strokeThickness / 2);
    315             secondRect.move(0, -strokeThickness / 2);
    316         }
    317         fillRectWithColor(context, firstRect, strokeColor);
    318         fillRectWithColor(context, secondRect, strokeColor);
    319 
    320         int distance = (isVerticalLine ? (point2.y() - point1.y()) : (point2.x() - point1.x())) - 2 * strokeThickness;
    321         double patternOffset = calculateStrokePatternOffset(distance, patternWidth);
    322         double patternWidthAsDouble = patternWidth;
    323         cairo_set_dash(context, &patternWidthAsDouble, 1, patternOffset);
    324     }
    325 
    326     setSourceRGBAFromColor(context, strokeColor);
    327     cairo_set_line_width(context, strokeThickness);
    328     cairo_move_to(context, point1OnPixelBoundaries.x(), point1OnPixelBoundaries.y());
    329     cairo_line_to(context, point2OnPixelBoundaries.x(), point2OnPixelBoundaries.y());
    330     cairo_stroke(context);
    331 }
    332 
    333256// This is only used to draw borders, so we should not draw shadows.
    334257void GraphicsContext::drawLine(const FloatPoint& point1, const FloatPoint& point2)
     
    337260        return;
    338261
     262    if (strokeStyle() == NoStroke)
     263        return;
     264
     265    const Color& strokeColor = this->strokeColor();
     266    float thickness = strokeThickness();
     267    bool isVerticalLine = (point1.x() + thickness == point2.x());
     268    float strokeWidth = isVerticalLine ? point2.y() - point1.y() : point2.x() - point1.x();
     269    if (!thickness || !strokeWidth)
     270        return;
     271
    339272    cairo_t* cairoContext = platformContext()->cr();
    340     cairo_save(cairoContext);
    341     drawLineOnCairoContext(this, cairoContext, point1, point2);
    342     cairo_restore(cairoContext);
     273    StrokeStyle strokeStyle = this->strokeStyle();
     274    float cornerWidth = 0;
     275    bool drawsDashedLine = strokeStyle == DottedStroke || strokeStyle == DashedStroke;
     276
     277    if (drawsDashedLine) {
     278        cairo_save(cairoContext);
     279        // Figure out end points to ensure we always paint corners.
     280        cornerWidth = strokeStyle == DottedStroke ? thickness : std::min(2 * thickness, std::max(thickness, strokeWidth / 3));
     281        if (isVerticalLine) {
     282            fillRectWithColor(cairoContext, FloatRect(point1.x(), point1.y(), thickness, cornerWidth), strokeColor);
     283            fillRectWithColor(cairoContext, FloatRect(point1.x(), point2.y() - cornerWidth, thickness, cornerWidth), strokeColor);
     284        } else {
     285            fillRectWithColor(cairoContext, FloatRect(point1.x(), point1.y(), cornerWidth, thickness), strokeColor);
     286            fillRectWithColor(cairoContext, FloatRect(point2.x() - cornerWidth, point1.y(), cornerWidth, thickness), strokeColor);
     287        }
     288        strokeWidth -= 2 * cornerWidth;
     289        float patternWidth = strokeStyle == DottedStroke ? thickness : std::min(3 * thickness, std::max(thickness, strokeWidth / 3));
     290        // Check if corner drawing sufficiently covers the line.
     291        if (strokeWidth <= patternWidth + 1) {
     292            cairo_restore(cairoContext);
     293            return;
     294        }
     295
     296        // Pattern starts with full fill and ends with the empty fill.
     297        // 1. Let's start with the empty phase after the corner.
     298        // 2. Check if we've got odd or even number of patterns and whether they fully cover the line.
     299        // 3. In case of even number of patterns and/or remainder, move the pattern start position
     300        // so that the pattern is balanced between the corners.
     301        float patternOffset = patternWidth;
     302        int numberOfSegments = std::floor(strokeWidth / patternWidth);
     303        bool oddNumberOfSegments = numberOfSegments % 2;
     304        float remainder = strokeWidth - (numberOfSegments * patternWidth);
     305        if (oddNumberOfSegments && remainder)
     306            patternOffset -= remainder / 2.f;
     307        else if (!oddNumberOfSegments) {
     308            if (remainder)
     309                patternOffset += patternOffset - (patternWidth + remainder) / 2.f;
     310            else
     311                patternOffset += patternWidth / 2.f;
     312        }
     313        const double dashedLine[2] = { static_cast<double>(patternWidth), static_cast<double>(patternWidth) };
     314        cairo_set_dash(cairoContext, dashedLine, 2, patternOffset);
     315    }
     316
     317    FloatPoint p1 = point1;
     318    FloatPoint p2 = point2;
     319    // Center line and cut off corners for pattern patining.
     320    if (isVerticalLine) {
     321        float centerOffset = (p2.x() - p1.x()) / 2;
     322        p1.move(centerOffset, cornerWidth);
     323        p2.move(-centerOffset, -cornerWidth);
     324    } else {
     325        float centerOffset = (p2.y() - p1.y()) / 2;
     326        p1.move(cornerWidth, centerOffset);
     327        p2.move(-cornerWidth, -centerOffset);
     328    }
     329
     330    if (shouldAntialias())
     331        cairo_set_antialias(cairoContext, CAIRO_ANTIALIAS_NONE);
     332
     333    cairo_new_path(cairoContext);
     334    cairo_move_to(cairoContext, p1.x(), p1.y());
     335    cairo_line_to(cairoContext, p2.x(), p2.y());
     336    cairo_stroke(cairoContext);
     337    if (drawsDashedLine)
     338        cairo_restore(cairoContext);
     339    if (shouldAntialias())
     340        cairo_set_antialias(cairoContext, CAIRO_ANTIALIAS_DEFAULT);
    343341}
    344342
Note: See TracChangeset for help on using the changeset viewer.