wxSVGMatrix wxSVGMatrix::Multiply(const wxSVGMatrix& secondMatrix) const { wxSVGMatrix res; res.SetA(GetA() * secondMatrix.GetA() + GetC() * secondMatrix.GetB()); res.SetB(GetB() * secondMatrix.GetA() + GetD() * secondMatrix.GetB()); res.SetC(GetA() * secondMatrix.GetC() + GetC() * secondMatrix.GetD()); res.SetD(GetB() * secondMatrix.GetC() + GetD() * secondMatrix.GetD()); res.SetE(GetA() * secondMatrix.GetE() + GetC() * secondMatrix.GetF() + GetE()); res.SetF(GetB() * secondMatrix.GetE() + GetD() * secondMatrix.GetF() + GetF()); return res; }
wxSVGRect wxSVGCanvasPathCairo::GetBBox(const wxSVGMatrix& matrix) { if (&matrix) { cairo_matrix_t m; cairo_matrix_init(&m, matrix.GetA(), matrix.GetB(), matrix.GetC(), matrix.GetD(), matrix.GetE(), matrix.GetF()); cairo_set_matrix(m_cr, &m); } double x1, y1, x2, y2; cairo_fill_extents(m_cr, &x1, &y1, &x2, &y2); if (&matrix) { cairo_matrix_t mat; cairo_matrix_init(&mat, 1, 0, 0, 1, 0, 0); cairo_set_matrix(m_cr, &mat); } return wxSVGRect(x1, y1, x2 - x1, y2 - y1); }
void wxSVGCanvasCairo::DrawMarker(const wxString& uri, wxSVGMark::Type type, wxSVGCanvasPathCairo& canvasPath, const wxSVGMatrix& matrix, const wxCSSStyleDeclaration& style, wxSVGSVGElement& svgElem) { wxSVGMarkerElement* markerElem = GetMarkerElement(svgElem, uri); if (markerElem == NULL || markerElem->GetMarkerWidth().GetAnimVal() <= 0 || markerElem->GetMarkerHeight().GetAnimVal() <= 0) return; vector<wxSVGMark> markPoints = canvasPath.GetMarkPoints(); for (vector<wxSVGMark>::iterator it = markPoints.begin(); it != markPoints.end(); it++) { if (it->type != type) continue; wxSVGMark& markPoint = *it; double scaleX = matrix.GetA() * style.GetStrokeWidth(); double scaleY = matrix.GetD() * style.GetStrokeWidth(); markerElem->SetOwnerSVGElement(&svgElem); markerElem->SetViewportElement(&svgElem); cairo_surface_t* surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, lround(markerElem->GetMarkerWidth().GetAnimVal() * scaleX), lround(markerElem->GetMarkerHeight().GetAnimVal() * scaleY)); cairo_t* cr = cairo_create(surface); wxSVGMatrix markerMatrix; markerMatrix = markerMatrix.ScaleNonUniform(scaleX, scaleY); wxCSSStyleDeclaration style; DrawMask(cr, markerElem, markerMatrix, style, svgElem); // draw surface cairo_save(m_cr); double refX = markerElem->GetRefX().GetAnimVal() * style.GetStrokeWidth(); double refY = markerElem->GetRefY().GetAnimVal() * style.GetStrokeWidth(); wxSVGPoint point(markPoint.x - refX, markPoint.y - refY); point = point.MatrixTransform(matrix); wxSVGMatrix m; m = m.Translate(point.GetX(), point.GetY()); if (markPoint.angle != 0) { refX = markerElem->GetRefX().GetAnimVal() * scaleX; refY = markerElem->GetRefY().GetAnimVal() * scaleY; m = m.Translate(refX, refY).Rotate(markPoint.angle / M_PI * 180).Translate(-refX, -refY); } SetMatrix(m_cr, m); cairo_set_source_surface(m_cr, surface, 0, 0); cairo_paint(m_cr); cairo_restore(m_cr); cairo_destroy(cr); cairo_surface_destroy(surface); } }
wxSVGRect wxSVGCanvasPathCairo::GetResultBBox(const wxCSSStyleDeclaration& style, const wxSVGMatrix& matrix) { if (&matrix) { cairo_matrix_t m; cairo_matrix_init(&m, matrix.GetA(), matrix.GetB(), matrix.GetC(), matrix.GetD(), matrix.GetE(), matrix.GetF()); cairo_set_matrix(m_cr, &m); } ApplyStrokeStyle(m_cr, style); double x1, y1, x2, y2; if (style.GetStrokeWidth() > 0) cairo_stroke_extents(m_cr, &x1, &y1, &x2, &y2); else cairo_fill_extents(m_cr, &x1, &y1, &x2, &y2); if (&matrix) { cairo_matrix_t mat; cairo_matrix_init(&mat, 1, 0, 0, 1, 0, 0); cairo_set_matrix(m_cr, &mat); } return wxSVGRect(x1, y1, x2 - x1, y2 - y1); }
wxSVGPoint wxSVGPoint::MatrixTransform(const wxSVGMatrix& matrix) const { wxSVGPoint res(m_x*matrix.GetA() + m_y*matrix.GetC() + matrix.GetE(), m_x*matrix.GetB() + m_y*matrix.GetD() + matrix.GetF()); return res; }
void wxSVGCanvasCairo::SetMatrix(cairo_t* cr, const wxSVGMatrix& matrix) { cairo_matrix_t mat; cairo_matrix_init(&mat, matrix.GetA(), matrix.GetB(), matrix.GetC(), matrix.GetD(), matrix.GetE(), matrix.GetF()); cairo_set_matrix(cr, &mat); }
void wxSVGCanvasCairo::SetPaint(cairo_t* cr, const wxSVGPaint& paint, float opacity, wxSVGCanvasPathCairo& canvasPath, wxSVGSVGElement& svgElem, const wxSVGMatrix& matrix) { if (paint.GetPaintType() >= wxSVG_PAINTTYPE_URI_NONE && paint.GetPaintType() <= wxSVG_PAINTTYPE_URI) { wxSVGGradientElement* gradElem = GetGradientElement(svgElem, paint.GetUri()); if (gradElem != NULL) { if (m_pattern != NULL) { cairo_pattern_destroy(m_pattern); m_pattern = NULL; } switch (gradElem->GetDtd()) { case wxSVG_LINEARGRADIENT_ELEMENT: { wxSVGPoint p1, p2; GetLinearGradientVector(p1, p2, (wxSVGLinearGradientElement&) *gradElem, canvasPath); m_pattern = cairo_pattern_create_linear(p1.GetX(), p1.GetY(), p2.GetX(), p2.GetY()); break; } case wxSVG_RADIALGRADIENT_ELEMENT: { wxSVGRadialGradientElement* radialGradElem = (wxSVGRadialGradientElement*) gradElem; double r = radialGradElem->GetQualifiedR(); double cx = radialGradElem->GetQualifiedCx(); double cy = radialGradElem->GetQualifiedCy(); double fx = radialGradElem->GetQualifiedFx(); double fy = radialGradElem->GetQualifiedFy(); if (gradElem->GetGradientUnits().GetAnimVal() == wxSVG_UNIT_TYPE_UNKNOWN || gradElem->GetGradientUnits().GetAnimVal() == wxSVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { wxSVGRect bbox = canvasPath.GetBBox(); r = r * sqrt(bbox.GetWidth() * bbox.GetWidth() + bbox.GetHeight() * bbox.GetHeight()); cx = bbox.GetX() + cx * bbox.GetWidth(); cy = bbox.GetY() + cy * bbox.GetHeight(); fx = bbox.GetX() + fx * bbox.GetWidth(); fy = bbox.GetY() + fy * bbox.GetHeight(); } m_pattern = cairo_pattern_create_radial(fx, fy, 0.0, cx, cy, r); const wxSVGTransformList& transforms = gradElem->GetGradientTransform().GetAnimVal(); if (transforms.GetCount() > 0) { wxSVGMatrix patMatrix; for (unsigned int i = 0; i < transforms.GetCount(); i++) patMatrix = patMatrix.Multiply(transforms[i].GetMatrix()); patMatrix = patMatrix.Inverse(); cairo_matrix_t mat; cairo_matrix_init(&mat, patMatrix.GetA(), patMatrix.GetB(), patMatrix.GetC(), patMatrix.GetD(), patMatrix.GetE(), patMatrix.GetF()); cairo_pattern_set_matrix(m_pattern, &mat); } break; } default: break; } if (m_pattern != NULL) { int nstops = GetGradientStops(svgElem, gradElem, opacity); if (nstops) { cairo_set_source(cr, m_pattern); } else { cairo_pattern_destroy(m_pattern); m_pattern = NULL; } } } wxSVGPatternElement* patternElem = GetPatternElement(svgElem, paint.GetUri()); if (patternElem != NULL && patternElem->GetWidth().GetAnimVal() > 0 && patternElem->GetHeight().GetAnimVal() > 0) { if (m_pattern != NULL) { cairo_pattern_destroy(m_pattern); m_pattern = NULL; } double scaleX = matrix.GetA(); scaleX = lround(patternElem->GetWidth().GetAnimVal()*scaleX) / patternElem->GetWidth().GetAnimVal(); double scaleY = matrix.GetD(); scaleY = lround(patternElem->GetHeight().GetAnimVal()*scaleY) / patternElem->GetHeight().GetAnimVal(); patternElem->SetOwnerSVGElement(&svgElem); patternElem->SetViewportElement(&svgElem); cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, lround(patternElem->GetWidth().GetAnimVal()*scaleX), lround(patternElem->GetHeight().GetAnimVal()*scaleY)); cairo_t* cr = cairo_create(surface); wxSVGMatrix patMatrix; patMatrix = patMatrix.ScaleNonUniform(scaleX, scaleY); wxCSSStyleDeclaration style; DrawMask(cr, patternElem, patMatrix, style, svgElem); m_pattern = cairo_pattern_create_for_surface(surface); if (patternElem->GetX().GetAnimVal() > 0 || patternElem->GetY().GetAnimVal() > 0) { patMatrix = patMatrix.Translate(patternElem->GetX().GetAnimVal(), patternElem->GetY().GetAnimVal()); } if (patternElem->GetPatternTransform().GetAnimVal().size()) { const wxSVGTransformList& transforms = patternElem->GetPatternTransform().GetAnimVal(); for (unsigned int i = 0; i < transforms.Count(); i++) { patMatrix = patMatrix.Multiply(transforms[i].GetMatrix().Inverse()); } } cairo_matrix_t mat; cairo_matrix_init(&mat, patMatrix.GetA(), patMatrix.GetB(), patMatrix.GetC(), patMatrix.GetD(), patMatrix.GetE(), patMatrix.GetF()); cairo_pattern_set_matrix(m_pattern, &mat); cairo_set_source(m_cr, m_pattern); cairo_pattern_set_extend(m_pattern, CAIRO_EXTEND_REPEAT); cairo_destroy(cr); cairo_surface_destroy(surface); } } else { wxRGBColor color = paint.GetRGBColor(); cairo_set_source_rgba(cr, color.Red() / 255.0, color.Green() / 255.0, color.Blue() / 255.0, opacity); } }