bool SVGPaintServerGradient::setup(QPainter* painter, QPainterPath* painterPath, const RenderObject* object, SVGPaintTargetType type, bool isPaintingText) const { Q_UNUSED(isPaintingText); kDebug() << "!!!!!!!" << endl; m_ownerElement->buildGradient(); /*QPainter* painter(context ? context->platformContext() : 0); Q_ASSERT(painter);*/ /*QPainterPath* path(context ? context->currentPath() : 0); Q_ASSERT(path);*/ RenderStyle* renderStyle = object->style(); QGradient gradient = setupGradient(painter, painterPath, object); painter->setPen(Qt::NoPen); painter->setBrush(Qt::NoBrush); if (spreadMethod() == SPREADMETHOD_REPEAT) gradient.setSpread(QGradient::RepeatSpread); else if (spreadMethod() == SPREADMETHOD_REFLECT) gradient.setSpread(QGradient::ReflectSpread); else gradient.setSpread(QGradient::PadSpread); double opacity = 1.0; kDebug() << "type: " << type << (type & ApplyToFillTargetType) << endl; if ((type & ApplyToFillTargetType) && renderStyle->svgStyle()->hasFill()) { fillColorArray(gradient, gradientStops(), opacity); QBrush brush(gradient); brush.setMatrix(gradientTransform()); painter->setBrush(brush); /* FIXME khtml context->setFillRule(renderStyle->svgStyle()->fillRule());*/ } if ((type & ApplyToStrokeTargetType) && renderStyle->svgStyle()->hasStroke()) { fillColorArray(gradient, gradientStops(), opacity); QPen pen; QBrush brush(gradient); brush.setMatrix(gradientTransform()); setPenProperties(object, renderStyle, pen); pen.setBrush(brush); painter->setPen(pen); } return true; }
bool SVGPaintServerGradient::setup(GraphicsContext*& context, const RenderObject* object, SVGPaintTargetType type, bool isPaintingText) const { m_ownerElement->buildGradient(); QPainter* painter(context ? context->platformContext() : 0); Q_ASSERT(painter); QPainterPath* path(context ? context->currentPath() : 0); Q_ASSERT(path); const SVGRenderStyle* svgStyle = object->style()->svgStyle(); RenderStyle* style = object->style(); QGradient gradient = setupGradient(context, object); painter->setPen(Qt::NoPen); painter->setBrush(Qt::NoBrush); if (spreadMethod() == SpreadMethodRepeat) gradient.setSpread(QGradient::RepeatSpread); else if (spreadMethod() == SpreadMethodReflect) gradient.setSpread(QGradient::ReflectSpread); else gradient.setSpread(QGradient::PadSpread); double opacity = 1.0; if ((type & ApplyToFillTargetType) && svgStyle->hasFill()) { fillColorArray(gradient, gradientStops(), opacity); QBrush brush(gradient); brush.setMatrix(gradientTransform()); painter->setBrush(brush); context->setFillRule(svgStyle->fillRule()); } if ((type & ApplyToStrokeTargetType) && svgStyle->hasStroke()) { fillColorArray(gradient, gradientStops(), opacity); QPen pen; QBrush brush(gradient); brush.setMatrix(gradientTransform()); pen.setBrush(brush); painter->setPen(pen); applyStrokeStyleToContext(context, style, object); } return true; }
TextStream& SVGPaintServerGradient::externalRepresentation(TextStream& ts) const { // Gradients/patterns aren't setup, until they are used for painting. Work around that fact. m_ownerElement->buildGradient(); // abstract, don't stream type ts << "[stops=" << gradientStops() << "]"; if (spreadMethod() != SpreadMethodPad) ts << "[method=" << spreadMethod() << "]"; if (!boundingBoxMode()) ts << " [bounding box mode=" << boundingBoxMode() << "]"; if (!gradientTransform().isIdentity()) ts << " [transform=" << gradientTransform() << "]"; return ts; }
bool SVGPaintServerGradient::setup(GraphicsContext*& context, const RenderObject* object, SVGPaintTargetType type, bool isPaintingText) const { m_ownerElement->buildGradient(); const SVGRenderStyle* style = object->style()->svgStyle(); bool isFilled = (type & ApplyToFillTargetType) && style->hasFill(); bool isStroked = (type & ApplyToStrokeTargetType) && style->hasStroke(); ASSERT(isFilled && !isStroked || !isFilled && isStroked); context->save(); if (isPaintingText) { #if PLATFORM(CG) if (!createMaskAndSwapContextForTextGradient(context, m_savedContext, m_imageBuffer, object)) { context->restore(); return false; } #endif context->setTextDrawingMode(isFilled ? cTextFill : cTextStroke); } if (isFilled) { context->setAlpha(style->fillOpacity()); context->setFillGradient(m_gradient); context->setFillRule(style->fillRule()); } if (isStroked) { context->setAlpha(style->strokeOpacity()); context->setStrokeGradient(m_gradient); applyStrokeStyleToContext(context, object->style(), object); } if (boundingBoxMode() && !isPaintingText) { FloatRect bbox = object->relativeBBox(false); // Don't use gradientes for 1d objects like horizontal/vertical // lines or rectangles without width or height. if (bbox.width() == 0 || bbox.height() == 0) { Color color(0, 0, 0); context->setStrokeColor(color); return true; } context->translate(bbox.x(), bbox.y()); context->scale(FloatSize(bbox.width(), bbox.height())); // With scaling the context, the strokeThickness is scaled too. We have to // undo this. float strokeThickness = std::max((context->strokeThickness() / ((bbox.width() + bbox.height()) / 2) - 0.001f), 0.f); context->setStrokeThickness(strokeThickness); } context->concatCTM(gradientTransform()); context->setSpreadMethod(spreadMethod()); return true; }
void SVGPaintServerGradient::handleBoundingBoxModeAndGradientTransformation(GraphicsContext* context, const FloatRect& targetRect) const { CGContextRef contextRef = context->platformContext(); if (boundingBoxMode()) { // Choose default gradient bounding box CGRect gradientBBox = CGRectMake(0.0, 0.0, 1.0, 1.0); // Generate a transform to map between both bounding boxes CGAffineTransform gradientIntoObjectBBox = CGAffineTransformMakeMapBetweenRects(gradientBBox, CGRect(targetRect)); CGContextConcatCTM(contextRef, gradientIntoObjectBBox); } // Apply the gradient's own transform CGAffineTransform transform = gradientTransform(); CGContextConcatCTM(contextRef, transform); }
bool SVGPaintServerGradient::setup(GraphicsContext*& context, const RenderObject* object, SVGPaintTargetType type, bool isPaintingText) const { m_ownerElement->buildGradient(); cairo_t* cr = context->platformContext(); cairo_pattern_t* pattern; cairo_matrix_t matrix; cairo_matrix_init_identity (&matrix); const cairo_matrix_t gradient_matrix = gradientTransform(); if (this->type() == LinearGradientPaintServer) { const SVGPaintServerLinearGradient* linear = static_cast<const SVGPaintServerLinearGradient*>(this); if (boundingBoxMode()) { FloatRect bbox = object->relativeBBox(false); cairo_matrix_translate(&matrix, bbox.x(), bbox.y()); cairo_matrix_scale(&matrix, bbox.width(), bbox.height()); } double x0 = linear->gradientStart().x(); double y0 = linear->gradientStart().y(); double x1 = linear->gradientEnd().x(); double y1 = linear->gradientEnd().y(); pattern = cairo_pattern_create_linear(x0, y0, x1, y1); } else if (this->type() == RadialGradientPaintServer) { const SVGPaintServerRadialGradient* radial = static_cast<const SVGPaintServerRadialGradient*>(this); if (boundingBoxMode()) { FloatRect bbox = object->relativeBBox(false); cairo_matrix_translate(&matrix, bbox.x(), bbox.y()); cairo_matrix_scale(&matrix, bbox.width(), bbox.height()); } double cx = radial->gradientCenter().x(); double cy = radial->gradientCenter().y(); double radius = radial->gradientRadius(); double fx = radial->gradientFocal().x(); double fy = radial->gradientFocal().y(); fx -= cx; fy -= cy; double fradius = 0.0; if (sqrt(fx * fx + fy * fy) > radius) { double angle = atan2(fy, fx); if ((fx + cx) < cx) fx = int(cos(angle) * radius) + 1; else fx = int(cos(angle) * radius) - 1; if ((fy + cy) < cy) fy = int(sin(angle) * radius) + 1; else fy = int(sin(angle) * radius) - 1; } pattern = cairo_pattern_create_radial(fx + cx, fy + cy, fradius, cx, cy, radius); } else { return false; } cairo_pattern_set_filter(pattern, CAIRO_FILTER_BILINEAR); switch (spreadMethod()) { case SPREADMETHOD_PAD: cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD); break; case SPREADMETHOD_REFLECT: cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REFLECT); break; case SPREADMETHOD_REPEAT: cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); break; default: cairo_pattern_set_extend(pattern, CAIRO_EXTEND_NONE); break; } cairo_matrix_multiply(&matrix, &matrix, &gradient_matrix); cairo_matrix_invert(&matrix); cairo_pattern_set_matrix(pattern, &matrix); const Vector<SVGGradientStop>& stops = gradientStops(); for (unsigned i = 0; i < stops.size(); ++i) { float offset = stops[i].first; Color color = stops[i].second; cairo_pattern_add_color_stop_rgba(pattern, offset, color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0, color.alpha() / 255.0); } cairo_set_source(cr, pattern); cairo_pattern_destroy(pattern); return true; }
bool SVGPaintServerGradient::setup(GraphicsContext*& context, const RenderObject* object, SVGPaintTargetType type, bool isPaintingText) const { m_ownerElement->buildGradient(); RenderStyle* style = object->style(); bool isFilled = (type & ApplyToFillTargetType) && style->svgStyle()->hasFill(); bool isStroked = (type & ApplyToStrokeTargetType) && style->svgStyle()->hasStroke(); if(!gradientStops().size()) return false; if(gradientStops().size()==1) { context->setFillColor(gradientStops()[0].second); return true; } // Create a gradient builder helper to generate the data // we'll need to provide Skia SkiaGradientBuilder builder(gradientStops(), isFilled ? style->svgStyle()->fillOpacity() : style->svgStyle()->strokeOpacity()); SkShader::TileMode tile_mode; // Convert SVG spread modes to Skia tile modes switch(spreadMethod()) { default: case SPREADMETHOD_PAD: tile_mode = SkShader::kClamp_TileMode; break; case SPREADMETHOD_REFLECT: tile_mode = SkShader::kMirror_TileMode; break; case SPREADMETHOD_REPEAT: tile_mode = SkShader::kRepeat_TileMode; break; } SkShader* shader = NULL; SkMatrix matrix; // Calculate a matrix to transform a gradient to fit the bounding box if (boundingBoxMode()) { matrix.reset(); SkRect rc = context->getBoundingBoxForCurrentPath(true); matrix.preTranslate(rc.fLeft, rc.fTop); matrix.preScale(rc.width(), rc.height()); matrix.preConcat(gradientTransform()); } else matrix = gradientTransform(); if (this->type() == LinearGradientPaintServer) { const SVGPaintServerLinearGradient* linear = static_cast<const SVGPaintServerLinearGradient*>(this); SkPoint pts[2]; pts[0].fX = linear->gradientStart().x(); pts[0].fY = linear->gradientStart().y(); pts[1].fX = linear->gradientEnd().x(); pts[1].fY = linear->gradientEnd().y(); shader = SkGradientShader::CreateLinear(pts, builder.colors(), builder.pos(), builder.count(), tile_mode); } else if (this->type() == RadialGradientPaintServer) { const SVGPaintServerRadialGradient* radial = static_cast<const SVGPaintServerRadialGradient*>(this); SkPoint center; SkScalar radius; center.fX = radial->gradientCenter().x(); center.fY = radial->gradientCenter().y(); radius = radial->gradientRadius(); shader = SkGradientShader::CreateRadial( center, radius, builder.colors(), builder.pos(), builder.count(), tile_mode); } else { return false; } if (isPaintingText) { if (isFilled) { context->setTextDrawingMode(cTextFill); } if (isStroked) { context->setTextDrawingMode(cTextStroke); } } if (isStroked) { applyStrokeStyleToContext(context, style, object); } if (shader) { shader->setLocalMatrix(matrix); context->platformContext()->setGradient(shader); return true; } return false; }