DRAW_TEST_P(CGContextFillMode, OverlappedEllipses) {
    CGContextRef context = GetDrawingContext();
    CGRect bounds = GetDrawingBounds();
    bounds = CGRectInset(bounds, 16.f, 16.f);
    CGFloat width = bounds.size.width;
    CGFloat height = bounds.size.height;
    CGFloat xstart = bounds.origin.x;
    CGFloat ystart = bounds.origin.y;

    CGPathDrawingMode fillMode = GetParam();

    CGMutablePathRef leftCircles = CGPathCreateMutable();

    CGPathMoveToPoint(leftCircles, NULL, xstart + .25 * width + .4 * height, ystart + .5 * height);
    CGPathAddArc(leftCircles, NULL, xstart + .25 * width, ystart + .5 * height, .4 * height, 0, M_PI, true);
    CGPathAddArc(leftCircles, NULL, xstart + .25 * width, ystart + .5 * height, .4 * height, M_PI, 0, true);

    CGPathMoveToPoint(leftCircles, NULL, xstart + .25 * width + .3 * height, ystart + .5 * height);
    CGPathAddArc(leftCircles, NULL, xstart + .25 * width, ystart + .5 * height, .3 * height, 0, M_PI, true);
    CGPathAddArc(leftCircles, NULL, xstart + .25 * width, ystart + .5 * height, .3 * height, M_PI, 0, true);

    CGPathMoveToPoint(leftCircles, NULL, xstart + .25 * width + .2 * height, ystart + .5 * height);
    CGPathAddArc(leftCircles, NULL, xstart + .25 * width, ystart + .5 * height, .2 * height, 0, M_PI, true);
    CGPathAddArc(leftCircles, NULL, xstart + .25 * width, ystart + .5 * height, .2 * height, M_PI, 0, true);

    CGPathMoveToPoint(leftCircles, NULL, xstart + .25 * width + .1 * height, ystart + .5 * height);
    CGPathAddArc(leftCircles, NULL, xstart + .25 * width, ystart + .5 * height, .1 * height, 0, M_PI, true);
    CGPathAddArc(leftCircles, NULL, xstart + .25 * width, ystart + .5 * height, .1 * height, M_PI, 0, true);

    CGPathCloseSubpath(leftCircles);

    CGMutablePathRef rightCircles = CGPathCreateMutable();

    CGPathMoveToPoint(rightCircles, NULL, xstart + .75 * width + .4 * height, ystart + .5 * height);
    CGPathAddArc(rightCircles, NULL, xstart + .75 * width, ystart + .5 * height, .4 * height, 0, M_PI, false);
    CGPathAddArc(rightCircles, NULL, xstart + .75 * width, ystart + .5 * height, .4 * height, M_PI, 0, false);

    CGPathMoveToPoint(rightCircles, NULL, xstart + .75 * width + .3 * height, ystart + .5 * height);
    CGPathAddArc(rightCircles, NULL, xstart + .75 * width, ystart + .5 * height, .3 * height, 0, M_PI, true);
    CGPathAddArc(rightCircles, NULL, xstart + .75 * width, ystart + .5 * height, .3 * height, M_PI, 0, true);

    CGPathMoveToPoint(rightCircles, NULL, xstart + .75 * width + .2 * height, ystart + .5 * height);
    CGPathAddArc(rightCircles, NULL, xstart + .75 * width, ystart + .5 * height, .2 * height, 0, M_PI, false);
    CGPathAddArc(rightCircles, NULL, xstart + .75 * width, ystart + .5 * height, .2 * height, M_PI, 0, false);

    CGPathMoveToPoint(rightCircles, NULL, xstart + .75 * width + .1 * height, ystart + .5 * height);
    CGPathAddArc(rightCircles, NULL, xstart + .75 * width, ystart + .5 * height, .1 * height, 0, M_PI, true);
    CGPathAddArc(rightCircles, NULL, xstart + .75 * width, ystart + .5 * height, .1 * height, M_PI, 0, true);

    CGPathCloseSubpath(rightCircles);

    CGContextAddPath(context, leftCircles);
    CGContextAddPath(context, rightCircles);
    CGContextSetRGBFillColor(context, 0, 0, 1, 1);
    CGContextSetRGBStrokeColor(context, 1, 0, 0, 1);
    CGContextDrawPath(context, fillMode);

    CGPathRelease(leftCircles);
    CGPathRelease(rightCircles);
}
void JBGStrokePathByLines(CGContextRef ctx, CGPathRef path, CGColorRef color_1, CGFloat width_1, CGColorRef color_2, CGFloat width_2, CGColorRef color_3, CGFloat width_3)
{
    if (width_1 > 0.0f)
    {
        CGContextSetLineWidth(ctx, width_1);
        CGContextAddPath(ctx, path);
        CGContextSetStrokeColorWithColor(ctx, color_1);
        CGContextStrokePath(ctx);
    }

    if (width_2 > 0.0f)
    {
        CGContextAddPath(ctx, path);
        CGContextSetStrokeColorWithColor(ctx, color_2);
        CGContextSetLineWidth(ctx, width_2);
        CGContextStrokePath(ctx);
    }
    
    if (width_3 > 0.0f)
    {
        CGContextAddPath(ctx, path);
        CGContextSetStrokeColorWithColor(ctx, color_3);
        CGContextSetLineWidth(ctx, width_3);
        CGContextStrokePath(ctx);
    }
}
Beispiel #3
0
//-----------------------------------------------------------------------------
void CGDrawContext::fillLinearGradient (CGraphicsPath* _path, const CGradient& gradient, const CPoint& startPoint, const CPoint& endPoint, bool evenOdd, CGraphicsTransform* t)
{
	QuartzGraphicsPath* path = dynamic_cast<QuartzGraphicsPath*> (_path);
	if (path == 0)
		return;

	const QuartzGradient* cgGradient = dynamic_cast<const QuartzGradient*> (&gradient);
	if (cgGradient == 0)
		return;

	CGContextRef cgContext = beginCGContext (true, currentState.drawMode.integralMode ());
	if (cgContext)
	{
		if (t)
		{
			CGContextSaveGState (cgContext);
			CGAffineTransform transform = QuartzGraphicsPath::createCGAfflineTransform (*t);
			CGContextConcatCTM (cgContext, transform);
			CGContextAddPath (cgContext, path->getCGPathRef ());
			CGContextRestoreGState (cgContext);
		}
		else
			CGContextAddPath (cgContext, path->getCGPathRef ());

		if (evenOdd)
			CGContextEOClip (cgContext);
		else
			CGContextClip (cgContext);

		CGContextDrawLinearGradient (cgContext, *cgGradient, CGPointMake (startPoint.x, startPoint.y), CGPointMake (endPoint.x, endPoint.y), kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
		
		releaseCGContext (cgContext);
	}
}
Beispiel #4
0
//-----------------------------------------------------------------------------
void CGDrawContext::drawGraphicsPath (CGraphicsPath* _path, PathDrawMode mode, CGraphicsTransform* t)
{
    QuartzGraphicsPath* path = dynamic_cast<QuartzGraphicsPath*> (_path);
    if (path == 0)
        return;

    CGContextRef context = beginCGContext (true, getDrawMode ().integralMode ());
    if (context)
    {
        CGPathDrawingMode cgMode;
        switch (mode)
        {
        case kPathFilledEvenOdd:
        {
            cgMode = kCGPathEOFill;
            break;
        }
        case kPathStroked:
        {
            cgMode = kCGPathStroke;
            applyLineStyle (context);
            break;
        }
        default:
        {
            cgMode = kCGPathFill;
            break;
        }
        }

        if (getDrawMode ().integralMode ())
        {
            applyLineWidthCTM (context);
            path->pixelAlign (this, t);
            CGContextAddPath (context, path->getCGPathRef ());
        }
        else if (t)
        {
            CGContextSaveGState (context);
            CGAffineTransform transform = QuartzGraphicsPath::createCGAffineTransform (*t);
            CGContextConcatCTM (context, transform);
            CGContextAddPath (context, path->getCGPathRef ());
            CGContextRestoreGState (context);
        }
        else
            CGContextAddPath (context, path->getCGPathRef ());

        CGContextDrawPath (context, cgMode);

        releaseCGContext (context);
    }
}
Beispiel #5
0
bool
PathCG::StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
                            const Point &aPoint,
                            const Matrix &aTransform) const
{
  Matrix inverse = aTransform;
  inverse.Invert();
  Point transformedPoint = inverse*aPoint;
  // We could probably drop the input transform and just transform the point at the caller?
  CGPoint point = {transformedPoint.x, transformedPoint.y};

  CGContextRef cg = ScratchContext();

  CGContextSaveGState(cg);

  CGContextBeginPath(cg);
  CGContextAddPath(cg, mPath);

  SetStrokeOptions(cg, aStrokeOptions);

  CGContextReplacePathWithStrokedPath(cg);
  CGContextRestoreGState(cg);

  CGPathRef sPath = CGContextCopyPath(cg);
  bool inStroke = CGPathContainsPoint(sPath, nullptr, point, false);
  CGPathRelease(sPath);

  return inStroke;
}
Beispiel #6
0
Rect
PathCG::GetStrokedBounds(const StrokeOptions &aStrokeOptions,
                         const Matrix &aTransform) const
{
  // 10.7 has CGPathCreateCopyByStrokingPath which we could use
  // instead of this scratch context business
  CGContextRef cg = ScratchContext();

  CGContextSaveGState(cg);

  CGContextBeginPath(cg);
  CGContextAddPath(cg, mPath);

  SetStrokeOptions(cg, aStrokeOptions);

  CGContextReplacePathWithStrokedPath(cg);
  Rect bounds = CGRectToRect(CGContextGetPathBoundingBox(cg));

  CGContextRestoreGState(cg);

  if (!bounds.IsFinite()) {
    return Rect();
  }

  return aTransform.TransformBounds(bounds);
}
void GraphicsContext::drawFocusRing(const Color& color)
{
    if (paintingDisabled())
        return;

    float radius = (focusRingWidth() - 1) / 2.0f;
    int offset = radius + focusRingOffset();
    CGColorRef colorRef = color.isValid() ? cgColor(color) : 0;

    CGMutablePathRef focusRingPath = CGPathCreateMutable();
    const Vector<IntRect>& rects = focusRingRects();
    unsigned rectCount = rects.size();
    for (unsigned i = 0; i < rectCount; i++)
        CGPathAddRect(focusRingPath, 0, CGRectInset(rects[i], -offset, -offset));

    CGContextRef context = platformContext();
    CGContextSaveGState(context);

    CGContextBeginPath(context);
    CGContextAddPath(context, focusRingPath);

    wkDrawFocusRing(context, colorRef, radius);

    CGColorRelease(colorRef);

    CGPathRelease(focusRingPath);

    CGContextRestoreGState(context);
}
Beispiel #8
0
void GraphicsContext::drawPath(const Path& path)
{
    if (paintingDisabled())
        return;

    CGContextRef context = platformContext();
    const GraphicsContextState& state = m_state;

    if (state.fillGradient || state.strokeGradient) {
        // We don't have any optimized way to fill & stroke a path using gradients
        // FIXME: Be smarter about this.
        fillPath(path);
        strokePath(path);
        return;
    }

    CGContextBeginPath(context);
    CGContextAddPath(context, path.platformPath());

    if (state.fillPattern)
        applyFillPattern();
    if (state.strokePattern)
        applyStrokePattern();

    CGPathDrawingMode drawingMode;
    if (calculateDrawingMode(state, drawingMode))
        CGContextDrawPath(context, drawingMode);
}
Beispiel #9
0
void GraphicsContext::fillPath(const Path& path)
{
    if (paintingDisabled())
        return;

    CGContextRef context = platformContext();

    CGContextBeginPath(context);
    CGContextAddPath(context, path.platformPath());

    if (m_state.fillGradient) {
        CGContextSaveGState(context);
        if (fillRule() == RULE_EVENODD)
            CGContextEOClip(context);
        else
            CGContextClip(context);
        CGContextConcatCTM(context, m_state.fillGradient->gradientSpaceTransform());
        m_state.fillGradient->paint(this);
        CGContextRestoreGState(context);
        return;
    }

    if (m_state.fillPattern)
        applyFillPattern();
    fillPathWithFillRule(context, fillRule());
}
Beispiel #10
0
FloatRect strokeBoundingBox(const Path& path, RenderStyle* style, const RenderObject* object)
{
    // the bbox might grow if the path is stroked.
    // and CGPathGetBoundingBox doesn't support that, so we'll have
    // to make an alternative call...

    // FIXME: since this is mainly used to decide what to repaint,
    // perhaps it would be sufficient to just outset the fill bbox by
    // the stroke width - that should be way cheaper and simpler than
    // what we do here.

    CGPathRef cgPath = path.platformPath();

    CGContextRef context = scratchContext();
    CGContextSaveGState(context);

    CGContextBeginPath(context);
    CGContextAddPath(context, cgPath);

    GraphicsContext gc(context);
    applyStrokeStyleToContext(&gc, style, object);

    CGContextReplacePathWithStrokedPath(context);
    if (CGContextIsPathEmpty(context)) {
        // CGContextReplacePathWithStrokedPath seems to fail to create a path sometimes, this is not well understood.
        // returning here prevents CG from logging to the console from CGContextGetPathBoundingBox
        CGContextRestoreGState(context);
        return FloatRect();
    }

    CGRect box = CGContextGetPathBoundingBox(context);
    CGContextRestoreGState(context);

    return FloatRect(box);
}
Beispiel #11
0
//-----------------------------------------------------------------------------
void CGDrawContext::fillLinearGradient (CGraphicsPath* _path, const CGradient& gradient, const CPoint& startPoint, const CPoint& endPoint, bool evenOdd, CGraphicsTransform* t)
{
    QuartzGraphicsPath* path = dynamic_cast<QuartzGraphicsPath*> (_path);
    if (path == 0)
        return;

    const QuartzGradient* cgGradient = dynamic_cast<const QuartzGradient*> (&gradient);
    if (cgGradient == 0)
        return;

    CGContextRef context = beginCGContext (true, getDrawMode ().integralMode ());
    if (context)
    {
        CGPoint start = CGPointFromCPoint (startPoint);
        CGPoint end = CGPointFromCPoint (endPoint);
        if (getDrawMode ().integralMode ())
        {
            path->pixelAlign (this, t);
            applyLineWidthCTM (context);
            CGContextAddPath (context, path->getCGPathRef ());
            start = pixelAlligned (start);
            end = pixelAlligned (end);
        }
        else if (t)
        {
            CGContextSaveGState (context);
            CGAffineTransform transform = QuartzGraphicsPath::createCGAffineTransform (*t);
            CGContextConcatCTM (context, transform);
            CGContextAddPath (context, path->getCGPathRef ());
            CGContextRestoreGState (context);
        }
        else
            CGContextAddPath (context, path->getCGPathRef ());

        if (evenOdd)
            CGContextEOClip (context);
        else
            CGContextClip (context);

        CGContextDrawLinearGradient (context, *cgGradient, start, end, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);

        releaseCGContext (context);
    }
}
Beispiel #12
0
void GraphicsContext::clipOut(const Path& path)
{
    if (paintingDisabled())
        return;

    CGContextBeginPath(platformContext());
    CGContextAddRect(platformContext(), CGContextGetClipBoundingBox(platformContext()));
    CGContextAddPath(platformContext(), path.platformPath());
    CGContextEOClip(platformContext());
}
void GraphicsContext::clip(const Path& path)
{
    if (paintingDisabled())
        return;
    CGContextRef context = platformContext();
    CGContextBeginPath(context);
    CGContextAddPath(context, path.platformPath());
    CGContextClip(context);
    m_data->clip(path);
}
void CanvasRenderingContext2D::fill()
{
    GraphicsContext* c = drawingContext();
    if (!c)
        return;
    // FIXME: Do this through platform-independent GraphicsContext API.
#if PLATFORM(CG)
    CGContextBeginPath(c->platformContext());
    CGContextAddPath(c->platformContext(), state().m_path.platformPath());

    if (!state().m_path.isEmpty())
        willDraw(CGContextGetPathBoundingBox(c->platformContext()));

    if (state().m_fillStyle->gradient()) {
        // Shading works on the entire clip region, so convert the current path to a clip.
        c->save();
        CGContextClip(c->platformContext());
        CGContextDrawShading(c->platformContext(), state().m_fillStyle->gradient()->platformShading());        
        c->restore();
    } else {
        if (state().m_fillStyle->pattern())
            applyFillPattern();
        CGContextFillPath(c->platformContext());
    }
#elif PLATFORM(QT)
    QPainterPath* path = state().m_path.platformPath();
    QPainter* p = static_cast<QPainter*>(c->platformContext());
    willDraw(path->controlPointRect());
    if (state().m_fillStyle->gradient()) {
        p->fillPath(*path, QBrush(*(state().m_fillStyle->gradient()->platformShading())));
    } else {
        if (state().m_fillStyle->pattern())
            applyFillPattern();
        p->fillPath(*path, p->brush());
    }
#elif PLATFORM(CAIRO)
    cairo_t* pathCr = state().m_path.platformPath()->m_cr;
    cairo_t* cr = c->platformContext();
    cairo_save(cr);
    willDraw(state().m_path.boundingRect());
    if (state().m_fillStyle->gradient()) {
        cairo_set_source(cr, state().m_fillStyle->gradient()->platformShading());
        c->addPath(state().m_path);
        cairo_fill(cr);
    } else {
        if (state().m_fillStyle->pattern())
            applyFillPattern();
        c->addPath(state().m_path);
        cairo_fill(cr);
    }
    cairo_restore(cr);
#endif

    clearPathForDashboardBackwardCompatibilityMode();
}
DRAW_TEST_F(CGContextFlush, FillFlush, WhiteBackgroundTest<>) {
    CGContextRef context = GetDrawingContext();
    CGRect bounds = GetDrawingBounds();
    _CGContextPushBeginDraw(context);

    CGContextSetRGBFillColor(context, 1, 0, 0, 1);
    CGContextFillRect(context, bounds);

    // Flush the red fill rect
    CGContextFlush(context);

    CGContextSetRGBFillColor(context, 0, 0, 1, 1);
    CGContextFillRect(context, CGRectMake(0, 0, 300, 300));

    // We should still have red & blue rectangle should not show up.
    unsigned char* dataPtr = static_cast<unsigned char*>(CGBitmapContextGetData(context));
    ASSERT_NE(dataPtr, nullptr);

    // Validate only the red fill rect is executed.
    EXPECT_EQ(dataPtr[0], 0x00);
    EXPECT_EQ(dataPtr[1], 0x00);
    EXPECT_EQ(dataPtr[2], 0xff);
    EXPECT_EQ(dataPtr[3], 0xff);

    CGContextFlush(context);

    // We should now see the blue fill rect
    EXPECT_EQ(dataPtr[0], 0xff);
    EXPECT_EQ(dataPtr[1], 0x00);
    EXPECT_EQ(dataPtr[2], 0x00);
    EXPECT_EQ(dataPtr[3], 0xff);

    // Add some extra drawings
    CGContextClearRect(context, CGRectMake(100, 100, 200, 300));

    CGPoint center = _CGRectGetCenter(bounds);

    CGMutablePathRef concentricCirclesPath = CGPathCreateMutable();

    CGPathAddEllipseInRect(concentricCirclesPath, nullptr, _CGRectCenteredOnPoint({ 50, 50 }, center));
    CGPathAddEllipseInRect(concentricCirclesPath, nullptr, _CGRectCenteredOnPoint({ 100, 100 }, center));
    CGPathAddEllipseInRect(concentricCirclesPath, nullptr, _CGRectCenteredOnPoint({ 150, 150 }, center));
    CGPathAddEllipseInRect(concentricCirclesPath, nullptr, _CGRectCenteredOnPoint({ 200, 200 }, center));

    CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 0.5);
    CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);

    CGContextAddPath(context, concentricCirclesPath);
    CGContextDrawPath(context, kCGPathFillStroke);

    CGPathRelease(concentricCirclesPath);

    _CGContextPopEndDraw(context);
}
Beispiel #16
0
//-----------------------------------------------------------------------------
void CGDrawContext::fillRadialGradient (CGraphicsPath* _path, const CGradient& gradient, const CPoint& center, CCoord radius, const CPoint& originOffset, bool evenOdd, CGraphicsTransform* t)
{
    QuartzGraphicsPath* path = dynamic_cast<QuartzGraphicsPath*> (_path);
    if (path == 0)
        return;

    const QuartzGradient* cgGradient = dynamic_cast<const QuartzGradient*> (&gradient);
    if (cgGradient == 0)
        return;

    CGContextRef context = beginCGContext (true, getDrawMode ().integralMode ());
    if (context)
    {
        if (getDrawMode ().integralMode ())
        {
            path->pixelAlign (this, t);
            CGContextAddPath (context, path->getCGPathRef ());
        }
        else if (t)
        {
            CGContextSaveGState (context);
            CGAffineTransform transform = QuartzGraphicsPath::createCGAffineTransform (*t);
            CGContextConcatCTM (context, transform);
            CGContextAddPath (context, path->getCGPathRef ());
            CGContextRestoreGState (context);
        }
        else
            CGContextAddPath (context, path->getCGPathRef ());

        if (evenOdd)
            CGContextEOClip (context);
        else
            CGContextClip (context);

        CPoint startCenter = center + originOffset;
        CGContextDrawRadialGradient (context, *cgGradient, CGPointFromCPoint (startCenter), 0, CGPointFromCPoint (center), static_cast<CGFloat> (radius), kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);

        releaseCGContext (context);
    }
}
Beispiel #17
0
void PlatformCALayer::drawRepaintIndicator(CGContextRef context, PlatformCALayer* platformCALayer, int repaintCount, CGColorRef customBackgroundColor)
{
    char text[16]; // that's a lot of repaints
    snprintf(text, sizeof(text), "%d", repaintCount);
    
    FloatRect indicatorBox = platformCALayer->bounds();\
    indicatorBox.setLocation( { 1, 1 } );
    indicatorBox.setSize(FloatSize(12 + 10 * strlen(text), 27));

    CGContextStateSaver stateSaver(context);
    
    CGContextSetAlpha(context, 0.5f);
    CGContextBeginTransparencyLayerWithRect(context, indicatorBox, 0);
    
    if (customBackgroundColor)
        CGContextSetFillColorWithColor(context, customBackgroundColor);
    else
        CGContextSetRGBFillColor(context, 0, 0.5f, 0.25f, 1);
    
    if (platformCALayer->isOpaque())
        CGContextFillRect(context, indicatorBox);
    else {
        Path boundsPath;
        boundsPath.moveTo(indicatorBox.maxXMinYCorner());
        boundsPath.addLineTo(indicatorBox.maxXMaxYCorner());
        boundsPath.addLineTo(indicatorBox.minXMaxYCorner());

        const float cornerChunk = 8;
        boundsPath.addLineTo(FloatPoint(indicatorBox.x(), indicatorBox.y() + cornerChunk));
        boundsPath.addLineTo(FloatPoint(indicatorBox.x() + cornerChunk, indicatorBox.y()));
        boundsPath.closeSubpath();

        CGContextAddPath(context, boundsPath.platformPath());
        CGContextFillPath(context);
    }

    if (platformCALayer->owner()->isUsingDisplayListDrawing(platformCALayer)) {
        CGContextSetRGBStrokeColor(context, 0, 0, 0, 0.65);
        CGContextSetLineWidth(context, 2);
        CGContextStrokeRect(context, indicatorBox);
    }

    if (platformCALayer->acceleratesDrawing())
        CGContextSetRGBFillColor(context, 1, 0, 0, 1);
    else
        CGContextSetRGBFillColor(context, 1, 1, 1, 1);
    
    platformCALayer->drawTextAtPoint(context, indicatorBox.x() + 5, indicatorBox.y() + 22, CGSizeMake(1, -1), 22, text, strlen(text));
    
    CGContextEndTransparencyLayer(context);
}
void CanvasRenderingContext2D::stroke()
{
    GraphicsContext* c = drawingContext();
    if (!c)
        return;
    // FIXME: Do this through platform-independent GraphicsContext API.
#if PLATFORM(CG)
    CGContextBeginPath(c->platformContext());
    CGContextAddPath(c->platformContext(), state().m_path.platformPath());

    if (!state().m_path.isEmpty()) {
        float lineWidth = state().m_lineWidth;
        float inset = -lineWidth / 2;
        CGRect boundingRect = CGRectInset(CGContextGetPathBoundingBox(c->platformContext()), inset, inset);
        willDraw(boundingRect);
    }

    if (state().m_strokeStyle->gradient()) {
        // Shading works on the entire clip region, so convert the current path to a clip.
        c->save();
        CGContextReplacePathWithStrokedPath(c->platformContext());
        CGContextClip(c->platformContext());
        CGContextDrawShading(c->platformContext(), state().m_strokeStyle->gradient()->platformShading());        
        c->restore();
    } else {
        if (state().m_strokeStyle->pattern())
            applyStrokePattern();
        CGContextStrokePath(c->platformContext());
    }
#elif PLATFORM(QT)
    QPainterPath* path = state().m_path.platformPath();
    QPainter* p = static_cast<QPainter*>(c->platformContext());
    willDraw(path->controlPointRect());
    if (state().m_strokeStyle->gradient()) {
        p->save();
        p->setBrush(*(state().m_strokeStyle->gradient()->platformShading()));
        p->strokePath(*path, p->pen());
        p->restore();
    } else {
        if (state().m_strokeStyle->pattern())
            applyStrokePattern();
        p->strokePath(*path, p->pen());
    }
#endif

    clearPathForDashboardBackwardCompatibilityMode();
}
Beispiel #19
0
bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) const
{
    ASSERT(applier);

    CGContextRef context = scratchContext();

    CGContextSaveGState(context);
    CGContextBeginPath(context);
    CGContextAddPath(context, platformPath());

    GraphicsContext gc(context);
    applier->strokeStyle(&gc);

    bool hitSuccess = CGContextPathContainsPoint(context, point, kCGPathStroke);
    CGContextRestoreGState(context);
    
    return hitSuccess;
}
Beispiel #20
0
void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
{
    if (paintingDisabled())
        return;

    if (path.isEmpty())
        return;

    CGContextRef context = platformContext();

    CGContextBeginPath(platformContext());
    CGContextAddPath(platformContext(), path.platformPath());

    if (clipRule == RULE_EVENODD)
        CGContextEOClip(context);
    else
        CGContextClip(context);
}
Beispiel #21
0
void GraphicsContext::clip(const Path& path)
{
    if (paintingDisabled())
        return;
    CGContextRef context = platformContext();

    // CGContextClip does nothing if the path is empty, so in this case, we
    // instead clip against a zero rect to reduce the clipping region to
    // nothing - which is the intended behavior of clip() if the path is empty.    
    if (path.isEmpty())
        CGContextClipToRect(context, CGRectZero);
    else {
        CGContextBeginPath(context);
        CGContextAddPath(context, path.platformPath());
        CGContextClip(context);
    }
    m_data->clip(path);
}
Beispiel #22
0
FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const
{
    CGContextRef context = scratchContext();

    CGContextSaveGState(context);
    CGContextBeginPath(context);
    CGContextAddPath(context, platformPath());

    if (applier) {
        GraphicsContext graphicsContext(context);
        applier->strokeStyle(&graphicsContext);
    }

    CGContextReplacePathWithStrokedPath(context);
    CGRect box = CGContextIsPathEmpty(context) ? CGRectZero : CGContextGetPathBoundingBox(context);
    CGContextRestoreGState(context);

    return box;
}
Beispiel #23
0
void TIPGradientAxialFillPath( CGContextRef theContext, TIPGradientRef theGradient, CGPathRef thePath, float angle)
{
    CGRect boundingRect = CGPathGetBoundingBox(thePath);
    CGPoint startPoint;
    CGPoint endPoint;

    TIPGradientFindEndpointsForRotation(boundingRect,angle,&startPoint,&endPoint);

    // CoreGraphics Calls
    CGContextSaveGState(theContext);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
    CGShadingRef myCGShading = CGShadingCreateAxial(colorSpace,startPoint,endPoint,theGradient->gradientFunction,FALSE,FALSE);

    CGContextAddPath(theContext,thePath);
    CGContextClip(theContext);
    CGContextDrawShading(theContext,myCGShading);

    CGShadingRelease(myCGShading);
    CGColorSpaceRelease(colorSpace);
    CGContextRestoreGState(theContext);
}
void doRotatedEllipsesWithCGPath(CGContextRef context)
{
	int i, totreps = 144.;
	CGMutablePathRef path = NULL;
	float  tint = 1., tintIncrement = 1./totreps;
	// Create a new transform consisting of a 45 degree rotation.
	CGAffineTransform theTransform = CGAffineTransformMakeRotation(M_PI/4);
	// Apply a scaling transformation to the transform just created.
	theTransform = CGAffineTransformScale(theTransform, 1, 2);
	// Create a mutable CGPath object.
	path = CGPathCreateMutable();
	if(!path){
		fprintf(stderr, "Couldn't create path!\n");
		return;
	}
	// Add a circular arc to the CGPath object, transformed
	// by an affine transform.
	CGPathAddArc(path, &theTransform, 0., 0., 45., 0., 2*M_PI, false); 
	// Close the CGPath object.
	CGPathCloseSubpath(path);
	
	// Place the first ellipse at a good location.	
	CGContextTranslateCTM(context, 100., 100.);
	for (i = 0 ; i < totreps ; i++){
		CGContextBeginPath(context);
		// Add the CGPath object to the current path in the context.
		CGContextAddPath(context, path);
		
		// Set the fill color for this instance of the ellipse.
		CGContextSetRGBFillColor(context, tint, 0., 0., 1.);
		// Filling the path implicitly closes it.
		CGContextFillPath(context);
		// Compute the next tint color.
		tint -= tintIncrement;
		// Move over for the next ellipse.
		CGContextTranslateCTM(context, 1, 0.);
	}
	// Release the path when done with it.
	CGPathRelease(path);
}
Beispiel #25
0
void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
{
    if (paintingDisabled())
        return;

    // FIXME: Why does this method ignore empty paths?
    if (path.isEmpty())
        return; 

    wxGraphicsContext* gc = m_data->context->GetGraphicsContext();

#if wxUSE_CAIRO
    cairo_t* cr = (cairo_t*)gc->GetNativeContext();
    cairo_path_t* nativePath = (cairo_path_t*)path.platformPath()->GetNativePath();

    cairo_new_path(cr);
    cairo_append_path(cr, nativePath);

    cairo_set_fill_rule(cr, clipRule == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
    cairo_clip(cr);
#elif __WXMAC__
    CGContextRef context = (CGContextRef)gc->GetNativeContext();   
    CGPathRef nativePath = (CGPathRef)path.platformPath()->GetNativePath(); 
    
    CGContextBeginPath(context);
    CGContextAddPath(context, nativePath);
    if (clipRule == RULE_EVENODD)
        CGContextEOClip(context);
    else
        CGContextClip(context);
#elif __WXMSW__
    Gdiplus::Graphics* g = (Gdiplus::Graphics*)gc->GetNativeContext();
    Gdiplus::GraphicsPath* nativePath = (Gdiplus::GraphicsPath*)path.platformPath()->GetNativePath();
    if (clipRule == RULE_EVENODD)
        nativePath->SetFillMode(Gdiplus::FillModeAlternate);
    else
        nativePath->SetFillMode(Gdiplus::FillModeWinding);
    g->SetClip(nativePath);
#endif
}
Beispiel #26
0
CGContextRef BitLockerSkia::cgContext()
{
    SkDevice* device = m_canvas->getDevice();
    ASSERT(device);
    if (!device)
        return 0;
    releaseIfNeeded();
    const SkBitmap& bitmap = device->accessBitmap(true);
    bitmap.lockPixels();
    void* pixels = bitmap.getPixels();
    m_cgContext = CGBitmapContextCreate(pixels, device->width(),
        device->height(), 8, bitmap.rowBytes(), CGColorSpaceCreateDeviceRGB(), 
        kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst);

    // Apply device matrix.
    CGAffineTransform contentsTransform = CGAffineTransformMakeScale(1, -1);
    contentsTransform = CGAffineTransformTranslate(contentsTransform, 0, -device->height());
    CGContextConcatCTM(m_cgContext, contentsTransform);

    // Apply clip in device coordinates.
    CGMutablePathRef clipPath = CGPathCreateMutable();
    SkRegion::Iterator iter(m_canvas->getTotalClip());
    for (; !iter.done(); iter.next()) {
        IntRect rect = iter.rect();
        CGPathAddRect(clipPath, 0, rect);
    }
    CGContextAddPath(m_cgContext, clipPath);
    CGContextClip(m_cgContext);
    CGPathRelease(clipPath);

    // Apply content matrix.
    const SkMatrix& skMatrix = m_canvas->getTotalMatrix();
    CGAffineTransform affine = SkMatrixToCGAffineTransform(skMatrix);
    CGContextConcatCTM(m_cgContext, affine);

    return m_cgContext;
}
Beispiel #27
0
bool RenderPath::strokeContains(const FloatPoint& point, bool requiresStroke) const
{
    if (path().isEmpty())
        return false;

    if (requiresStroke && !SVGPaintServer::strokePaintServer(style(), this))
        return false;

    CGMutablePathRef cgPath = path().platformPath();
    
    CGContextRef context = scratchContext();
    CGContextSaveGState(context);
    
    CGContextBeginPath(context);
    CGContextAddPath(context, cgPath);

    GraphicsContext gc(context);
    applyStrokeStyleToContext(&gc, style(), this);

    bool hitSuccess = CGContextPathContainsPoint(context, point, kCGPathStroke);
    CGContextRestoreGState(context);
    
    return hitSuccess;
}
Beispiel #28
0
void GraphicsContext::strokePath(const Path& path)
{
    if (paintingDisabled())
        return;

    CGContextRef context = platformContext();

    CGContextBeginPath(context);
    CGContextAddPath(context, path.platformPath());

    if (m_state.strokeGradient) {
        CGContextSaveGState(context);
        CGContextReplacePathWithStrokedPath(context);
        CGContextClip(context);
        CGContextConcatCTM(context, m_state.strokeGradient->gradientSpaceTransform());
        m_state.strokeGradient->paint(this);
        CGContextRestoreGState(context);
        return;
    }

    if (m_state.strokePattern)
        applyStrokePattern();
    CGContextStrokePath(context);
}
Beispiel #29
0
static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
                          int from, int numGlyphs, const FloatPoint& point)
{
    Color fillColor = graphicsContext->fillColor();

    bool drawIntoBitmap = false;
    TextDrawingModeFlags drawingMode = graphicsContext->textDrawingMode();
    if (drawingMode == TextModeFill) {
        if (!fillColor.alpha())
            return;

        drawIntoBitmap = fillColor.alpha() != 255 || graphicsContext->inTransparencyLayer();
        if (!drawIntoBitmap) {
            FloatSize offset;
            float blur;
            Color color;
            ColorSpace shadowColorSpace;

            graphicsContext->getShadow(offset, blur, color, shadowColorSpace);
            drawIntoBitmap = offset.width() || offset.height() || blur;
        }
    }

    // We have to convert CG's two-dimensional floating point advances to just horizontal integer advances.
    Vector<int, 2048> gdiAdvances;
    int totalWidth = 0;
    for (int i = 0; i < numGlyphs; i++) {
        gdiAdvances.append(lroundf(glyphBuffer.advanceAt(from + i)));
        totalWidth += gdiAdvances[i];
    }

    HDC hdc = 0;
    OwnPtr<GraphicsContext::WindowsBitmap> bitmap;
    IntRect textRect;
    if (!drawIntoBitmap)
        hdc = graphicsContext->getWindowsContext(textRect, true, false);
    if (!hdc) {
        drawIntoBitmap = true;
        // We put slop into this rect, since glyphs can overflow the ascent/descent bounds and the left/right edges.
        // FIXME: Can get glyphs' optical bounds (even from CG) to get this right.
        const FontMetrics& fontMetrics = font->fontMetrics();
        int lineGap = fontMetrics.lineGap();
        textRect = IntRect(point.x() - (fontMetrics.ascent() + fontMetrics.descent()) / 2,
                           point.y() - fontMetrics.ascent() - lineGap,
                           totalWidth + fontMetrics.ascent() + fontMetrics.descent(),
                           fontMetrics.lineSpacing());
        bitmap = graphicsContext->createWindowsBitmap(textRect.size());
        memset(bitmap->buffer(), 255, bitmap->bufferLength());
        hdc = bitmap->hdc();

        XFORM xform;
        xform.eM11 = 1.0f;
        xform.eM12 = 0.0f;
        xform.eM21 = 0.0f;
        xform.eM22 = 1.0f;
        xform.eDx = -textRect.x();
        xform.eDy = -textRect.y();
        SetWorldTransform(hdc, &xform);
    }

    SelectObject(hdc, font->platformData().hfont());

    // Set the correct color.
    if (drawIntoBitmap)
        SetTextColor(hdc, RGB(0, 0, 0));
    else
        SetTextColor(hdc, RGB(fillColor.red(), fillColor.green(), fillColor.blue()));

    SetBkMode(hdc, TRANSPARENT);
    SetTextAlign(hdc, TA_LEFT | TA_BASELINE);

    // Uniscribe gives us offsets to help refine the positioning of combining glyphs.
    FloatSize translation = glyphBuffer.offsetAt(from);
    if (translation.width() || translation.height()) {
        XFORM xform;
        xform.eM11 = 1.0;
        xform.eM12 = 0;
        xform.eM21 = 0;
        xform.eM22 = 1.0;
        xform.eDx = translation.width();
        xform.eDy = translation.height();
        ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
    }

    if (drawingMode == TextModeFill) {
        XFORM xform;
        xform.eM11 = 1.0;
        xform.eM12 = 0;
        xform.eM21 = font->platformData().syntheticOblique() ? -tanf(syntheticObliqueAngle * piFloat / 180.0f) : 0;
        xform.eM22 = 1.0;
        xform.eDx = point.x();
        xform.eDy = point.y();
        ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
        ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, reinterpret_cast<const WCHAR*>(glyphBuffer.glyphs(from)), numGlyphs, gdiAdvances.data());
        if (font->syntheticBoldOffset()) {
            xform.eM21 = 0;
            xform.eDx = font->syntheticBoldOffset();
            xform.eDy = 0;
            ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
            ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, reinterpret_cast<const WCHAR*>(glyphBuffer.glyphs(from)), numGlyphs, gdiAdvances.data());
        }
    } else {
        XFORM xform;
        GetWorldTransform(hdc, &xform);
        AffineTransform hdcTransform(xform.eM11, xform.eM21, xform.eM12, xform.eM22, xform.eDx, xform.eDy);
        CGAffineTransform initialGlyphTransform = hdcTransform.isInvertible() ? hdcTransform.inverse() : CGAffineTransformIdentity;
        if (font->platformData().syntheticOblique())
            initialGlyphTransform = CGAffineTransformConcat(initialGlyphTransform, CGAffineTransformMake(1, 0, tanf(syntheticObliqueAngle * piFloat / 180.0f), 1, 0, 0));
        initialGlyphTransform.tx = 0;
        initialGlyphTransform.ty = 0;
        CGContextRef cgContext = graphicsContext->platformContext();

        CGContextSaveGState(cgContext);

        BOOL fontSmoothingEnabled = false;
        SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fontSmoothingEnabled, 0);
        CGContextSetShouldAntialias(cgContext, fontSmoothingEnabled);

        CGContextScaleCTM(cgContext, 1.0, -1.0);
        CGContextTranslateCTM(cgContext, point.x() + glyphBuffer.offsetAt(from).width(), -(point.y() + glyphBuffer.offsetAt(from).height()));

        for (unsigned i = 0; i < numGlyphs; ++i) {
            RetainPtr<CGPathRef> glyphPath(AdoptCF, createPathForGlyph(hdc, glyphBuffer.glyphAt(from + i)));
            CGContextSaveGState(cgContext);
            CGContextConcatCTM(cgContext, initialGlyphTransform);

            if (drawingMode & TextModeFill) {
                CGContextAddPath(cgContext, glyphPath.get());
                CGContextFillPath(cgContext);
                if (font->syntheticBoldOffset()) {
                    CGContextTranslateCTM(cgContext, font->syntheticBoldOffset(), 0);
                    CGContextAddPath(cgContext, glyphPath.get());
                    CGContextFillPath(cgContext);
                    CGContextTranslateCTM(cgContext, -font->syntheticBoldOffset(), 0);
                }
            }
            if (drawingMode & TextModeStroke) {
                CGContextAddPath(cgContext, glyphPath.get());
                CGContextStrokePath(cgContext);
                if (font->syntheticBoldOffset()) {
                    CGContextTranslateCTM(cgContext, font->syntheticBoldOffset(), 0);
                    CGContextAddPath(cgContext, glyphPath.get());
                    CGContextStrokePath(cgContext);
                    CGContextTranslateCTM(cgContext, -font->syntheticBoldOffset(), 0);
                }
            }

            CGContextRestoreGState(cgContext);
            CGContextTranslateCTM(cgContext, gdiAdvances[i], 0);
        }

        CGContextRestoreGState(cgContext);
    }

    if (drawIntoBitmap) {
        UInt8* buffer = bitmap->buffer();
        unsigned bufferLength = bitmap->bufferLength();
        for (unsigned i = 0; i < bufferLength; i += 4) {
            // Use green, which is always in the middle.
            UInt8 alpha = (255 - buffer[i + 1]) * fillColor.alpha() / 255;
            buffer[i] = fillColor.blue();
            buffer[i + 1] = fillColor.green();
            buffer[i + 2] = fillColor.red();
            buffer[i + 3] = alpha;
        }
        graphicsContext->drawWindowsBitmap(bitmap.get(), textRect.location());
    } else
        graphicsContext->releaseWindowsContext(hdc, textRect, true, false);
}
void GraphicsContext::addPath(const Path& path)
{
    CGContextAddPath(platformContext(), path.platformPath());
}