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); }
void wxSVGCanvas::DrawCanvasText(wxSVGCanvasText& canvasText, wxSVGMatrix& matrix, const wxCSSStyleDeclaration& style, wxSVGSVGElement& svgElem) { for (int i=0; i<(int)canvasText.m_chunks.Count(); i++) { wxSVGCanvasTextChunk& chunk = canvasText.m_chunks[i]; chunk.style.SetFillRule(wxCSS_VALUE_EVENODD); wxSVGMatrix pathMatrix = matrix.Multiply(chunk.matrix); for (unsigned int j=0; j<chunk.chars.Count(); j++) DrawItem(*chunk.chars[j].path, pathMatrix, chunk.style, svgElem); } }
void wxSVGCanvas::GetRadialGradientTransform(wxSVGPoint& focus, wxSVGMatrix& matrix, const wxSVGRadialGradientElement& gradElem, wxSVGCanvasPath& path, bool scale) { double r, cx, cy, fx, fy; r = gradElem.GetR().GetAnimVal(); cx = gradElem.GetCx().GetAnimVal(); cy = gradElem.GetCy().GetAnimVal(); fx = gradElem.GetFx().GetAnimVal(); fy = gradElem.GetFy().GetAnimVal(); if (gradElem.GetGradientUnits().GetAnimVal() == wxSVG_UNIT_TYPE_UNKNOWN || gradElem.GetGradientUnits().GetAnimVal() == wxSVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { wxSVGRect bbox = path.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(); } // Compute gradient transformation matrix const wxSVGTransformList& transforms = gradElem.GetGradientTransform().GetAnimVal(); for (int i=0; i<(int)transforms.Count(); i++) matrix = matrix.Multiply(transforms[i].GetMatrix()); // Apply Gradient parameters to transformation matrix = matrix.Translate(cx, cy); //.Scale(r); if (scale) matrix = matrix.Scale(r); // Change Focus reference to gradient reference focus.SetX((fx - cx) / r); focus.SetY((fy - cy) / r); }
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; }
void wxSVGCanvasCairo::DrawCanvasPath(wxSVGCanvasPathCairo& canvasPath, wxSVGMatrix& matrix, const wxCSSStyleDeclaration& style, wxSVGSVGElement& svgElem) { // check Filter if (style.GetFilter().GetCSSPrimitiveType() == wxCSS_URI && style.GetFilter().GetStringValue().length() > 1) { wxString filterId = style.GetFilter().GetStringValue().substr(1); wxSVGElement* filterElem = (wxSVGElement*) svgElem.GetElementById(filterId); // feGaussianBlur if (filterElem && filterElem->GetDtd() == wxSVG_FILTER_ELEMENT && filterElem->GetFirstChild() != NULL && ((wxSVGSVGElement*) filterElem->GetFirstChild())->GetDtd() == wxSVG_FEGAUSSIANBLUR_ELEMENT) { float stdX = ((wxSVGFEGaussianBlurElement*) filterElem->GetFirstChild())->GetStdDeviationX().GetAnimVal(); float stdY = ((wxSVGFEGaussianBlurElement*) filterElem->GetFirstChild())->GetStdDeviationY().GetAnimVal(); if (stdX <= 0 || stdY <= 0) return; int dx = int(floor(stdX * 3 * sqrt(2 * M_PI) / 4 + 0.5)); int dy = int(floor(stdY * 3 * sqrt(2 * M_PI) / 4 + 0.5)); wxSVGRect rect = canvasPath.GetResultBBox(style, matrix.Inverse()); rect.SetX(rect.GetX() - 2*dx); rect.SetY(rect.GetY() - 2*dy); rect.SetWidth(rect.GetWidth() + 4*dx); rect.SetHeight(rect.GetHeight() + 4*dy); int width = (int) rect.GetWidth(); int height = (int) rect.GetHeight(); cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t* cr = cairo_create(surface); wxSVGMatrix matrix2 = wxSVGMatrix(1, 0, 0, 1, - rect.GetX(), - rect.GetY()).Multiply(matrix); DrawPath(cr, canvasPath, matrix2, style, svgElem); gaussianBlur(surface, dx, dy); // draw surface cairo_save(m_cr); SetMatrix(m_cr, wxSVGMatrix(1, 0, 0, 1, rect.GetX(), rect.GetY())); cairo_set_source_surface(m_cr, surface, 0, 0); cairo_rectangle(m_cr, 0, 0, width, height); cairo_paint(m_cr); // fill the rectangle using the pattern cairo_new_path(m_cr); cairo_restore(m_cr); cairo_destroy(cr); cairo_surface_destroy(surface); return; } } DrawPath(m_cr, canvasPath, matrix, style, svgElem); }
void wxSVGTransformable::UpdateMatrix(wxSVGMatrix& matrix) const { const wxSVGTransformList& transforms = GetTransform().GetAnimVal(); for (unsigned int i = 0; i < transforms.Count(); i++) matrix = matrix.Multiply(transforms[i].GetMatrix()); }
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); } }