static void drawLineOnCairoContext(GraphicsContext* graphicsContext, cairo_t* context, const FloatPoint& point1, const FloatPoint& point2)
{
    StrokeStyle style = graphicsContext->strokeStyle();
    if (style == NoStroke)
        return;

    const Color& strokeColor = graphicsContext->strokeColor();
    int strokeThickness = floorf(graphicsContext->strokeThickness());
    if (graphicsContext->strokeThickness() < 1)
        strokeThickness = 1;

    int patternWidth = 0;
    if (style == DottedStroke)
        patternWidth = strokeThickness;
    else if (style == DashedStroke)
        patternWidth = 3 * strokeThickness;

    bool isVerticalLine = point1.x() == point2.x();
    FloatPoint point1OnPixelBoundaries = point1;
    FloatPoint point2OnPixelBoundaries = point2;
    GraphicsContext::adjustLineToPixelBoundaries(point1OnPixelBoundaries, point2OnPixelBoundaries, strokeThickness, style);

    cairo_set_antialias(context, CAIRO_ANTIALIAS_NONE);
    if (patternWidth) {
        // Do a rect fill of our endpoints.  This ensures we always have the
        // appearance of being a border.  We then draw the actual dotted/dashed line.
        FloatRect firstRect(point1OnPixelBoundaries, FloatSize(strokeThickness, strokeThickness));
        FloatRect secondRect(point2OnPixelBoundaries, FloatSize(strokeThickness, strokeThickness));
        if (isVerticalLine) {
            firstRect.move(-strokeThickness / 2, -strokeThickness);
            secondRect.move(-strokeThickness / 2, 0);
        } else {
            firstRect.move(-strokeThickness, -strokeThickness / 2);
            secondRect.move(0, -strokeThickness / 2);
        }
        fillRectWithColor(context, firstRect, strokeColor);
        fillRectWithColor(context, secondRect, strokeColor);

        int distance = (isVerticalLine ? (point2.y() - point1.y()) : (point2.x() - point1.x())) - 2 * strokeThickness;
        double patternOffset = calculateStrokePatternOffset(distance, patternWidth);
        double patternWidthAsDouble = patternWidth;
        cairo_set_dash(context, &patternWidthAsDouble, 1, patternOffset);
    }

    setSourceRGBAFromColor(context, strokeColor);
    cairo_set_line_width(context, strokeThickness);
    cairo_move_to(context, point1OnPixelBoundaries.x(), point1OnPixelBoundaries.y());
    cairo_line_to(context, point2OnPixelBoundaries.x(), point2OnPixelBoundaries.y());
    cairo_stroke(context);
}
示例#2
0
void GraphicsContext::drawLinesForText(const FloatPoint& point, const DashArray& widths, bool printing, bool doubleUnderlines)
{
    if (paintingDisabled())
        return;

    if (widths.size() <= 0)
        return;

    Color localStrokeColor(strokeColor());

    bool shouldAntialiasLine;
    FloatRect bounds = computeLineBoundsAndAntialiasingModeForText(point, widths.last(), printing, shouldAntialiasLine, localStrokeColor);

    Vector<FloatRect, 4> dashBounds;
    ASSERT(!(widths.size() % 2));
    dashBounds.reserveInitialCapacity(dashBounds.size() / 2);
    for (size_t i = 0; i < widths.size(); i += 2)
        dashBounds.append(FloatRect(FloatPoint(bounds.x() + widths[i], bounds.y()), FloatSize(widths[i+1] - widths[i], bounds.height())));

    if (doubleUnderlines) {
        // The space between double underlines is equal to the height of the underline
        for (size_t i = 0; i < widths.size(); i += 2)
            dashBounds.append(FloatRect(FloatPoint(bounds.x() + widths[i], bounds.y() + 2 * bounds.height()), FloatSize(widths[i+1] - widths[i], bounds.height())));
    }

    cairo_t* cr = platformContext()->cr();
    cairo_save(cr);

    for (auto& dash : dashBounds)
        fillRectWithColor(cr, dash, localStrokeColor);

    cairo_restore(cr);
}
void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace)
{
    if (paintingDisabled())
        return;

    if (hasShadow())
        platformContext()->shadowBlur().drawRectShadow(this, rect, RoundedRect::Radii());

    fillRectWithColor(platformContext()->cr(), rect, color);
}
// Draws a filled rectangle with a stroked border.
void GraphicsContext::drawRect(const IntRect& rect)
{
    if (paintingDisabled())
        return;

    cairo_t* cr = platformContext()->cr();
    cairo_save(cr);

    fillRectWithColor(cr, rect, fillColor());

    if (strokeStyle() != NoStroke) {
        setSourceRGBAFromColor(cr, strokeColor());
        FloatRect r(rect);
        r.inflate(-.5f);
        cairo_rectangle(cr, r.x(), r.y(), r.width(), r.height());
        cairo_set_line_width(cr, 1.0);
        cairo_stroke(cr);
    }

    cairo_restore(cr);
}