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; }
void SVGPaintServerGradient::updateQuartzGradientCache(const SVGPaintServerGradient* server) { // cache our own copy of the stops for faster access. // this is legacy code, probably could be reworked. if (!m_stopsCache) updateQuartzGradientStopsCache(gradientStops()); CGShadingRelease(m_shadingCache); if (type() == RadialGradientPaintServer) { const SVGPaintServerRadialGradient* radial = static_cast<const SVGPaintServerRadialGradient*>(server); m_shadingCache = CGShadingRefForRadialGradient(radial); } else if (type() == LinearGradientPaintServer) { const SVGPaintServerLinearGradient* linear = static_cast<const SVGPaintServerLinearGradient*>(server); m_shadingCache = CGShadingRefForLinearGradient(linear); } }
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; }
QGradient GradientEditor::gradient() const { _gradient->setStops(gradientStops()); return *_gradient; }