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); }
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); }
oop CGContextGetPathBoundingBox_wrap(CGContextRef c) { CGRect x = CGContextGetPathBoundingBox(c); objVectorOop r = Memory->objVectorObj->cloneSize(4); r->obj_at_put(0, as_floatOop(x.origin.x), false); r->obj_at_put(1, as_floatOop(x.origin.y), false); r->obj_at_put(2, as_floatOop(x.size.width), false); r->obj_at_put(3, as_floatOop(x.size.height), false); return r; }
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(); }
JNIEXPORT void JNICALL OS_NATIVE(CGContextGetPathBoundingBox) (JNIEnv *env, jclass that, jint arg0, jobject arg1) { CGRect _arg1, *lparg1=NULL; OS_NATIVE_ENTER(env, that, CGContextGetPathBoundingBox_FUNC); if (arg1) if ((lparg1 = getCGRectFields(env, arg1, &_arg1)) == NULL) goto fail; *lparg1 = CGContextGetPathBoundingBox((CGContextRef)arg0); fail: if (arg1 && lparg1) setCGRectFields(env, arg1, lparg1); OS_NATIVE_EXIT(env, that, CGContextGetPathBoundingBox_FUNC); }
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(); }
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; }
void SVGPaintServerGradient::renderPath(GraphicsContext*& context, const RenderPath* path, SVGPaintTargetType type) const { RenderStyle* style = path->style(); CGContextRef contextRef = context->platformContext(); ASSERT(contextRef); // Compute destination object bounding box FloatRect objectBBox; if (boundingBoxMode()) objectBBox = CGContextGetPathBoundingBox(contextRef); if ((type & ApplyToFillTargetType) && style->svgStyle()->hasFill()) clipToFillPath(contextRef, path); if ((type & ApplyToStrokeTargetType) && style->svgStyle()->hasStroke()) clipToStrokePath(contextRef, path); handleBoundingBoxModeAndGradientTransformation(context, objectBBox); }
bool SVGPaintServerPattern::setup(GraphicsContext*& context, const RenderObject* object, SVGPaintTargetType type, bool isPaintingText) const { CGContextRef contextRef = context->platformContext(); // Build pattern tile, passing destination object bounding box FloatRect targetRect; if (isPaintingText) { IntRect textBoundary = const_cast<RenderObject*>(object)->absoluteBoundingBoxRect(); targetRect = object->absoluteTransform().inverse().mapRect(textBoundary); } else targetRect = CGContextGetPathBoundingBox(contextRef); m_ownerElement->buildPattern(targetRect); if (!tile()) return false; CGSize cellSize = CGSize(tile()->size()); CGFloat alpha = 1; // canvasStyle->opacity(); //which? context->save(); // Repesct local pattern transformations CGContextConcatCTM(contextRef, patternTransform()); // Pattern space seems to start in the lower-left, so we flip the Y here. CGSize phase = CGSizeMake(patternBoundaries().x(), -patternBoundaries().y()); CGContextSetPatternPhase(contextRef, phase); RenderStyle* style = object->style(); CGContextSetAlpha(contextRef, style->opacity()); // or do I set the alpha above? ASSERT(!m_pattern); CGPatternCallbacks callbacks = {0, patternCallback, NULL}; m_pattern = CGPatternCreate(tile(), CGRectMake(0, 0, cellSize.width, cellSize.height), CGContextGetCTM(contextRef), patternBoundaries().width(), patternBoundaries().height(), kCGPatternTilingConstantSpacing, // FIXME: should ask CG guys. true, // has color &callbacks); if (!m_patternSpace) m_patternSpace = CGColorSpaceCreatePattern(0); if ((type & ApplyToFillTargetType) && style->svgStyle()->hasFill()) { CGContextSetFillColorSpace(contextRef, m_patternSpace); CGContextSetFillPattern(contextRef, m_pattern, &alpha); if (isPaintingText) context->setTextDrawingMode(cTextFill); } if ((type & ApplyToStrokeTargetType) && style->svgStyle()->hasStroke()) { CGContextSetStrokeColorSpace(contextRef, m_patternSpace); CGContextSetStrokePattern(contextRef, m_pattern, &alpha); applyStrokeStyleToContext(contextRef, style, object); if (isPaintingText) context->setTextDrawingMode(cTextStroke); } return true; }