void wxSVGCanvasCairo::DrawPath(cairo_t* cr, wxSVGCanvasPathCairo& canvasPath, const wxSVGMatrix& matrix, const wxCSSStyleDeclaration& style, wxSVGSVGElement& svgElem) { SetMatrix(cr, matrix); // Filling if (canvasPath.GetFill() && style.GetFill().Ok() && style.GetFill().GetPaintType() != wxSVG_PAINTTYPE_NONE) { cairo_path_t* path = canvasPath.GetPath(); cairo_append_path(cr, path); SetPaint(cr, style.GetFill(), style.GetOpacity()*style.GetFillOpacity(), canvasPath, svgElem, matrix); cairo_fill(cr); cairo_path_destroy(path); } // Stroking if (style.GetStroke().Ok() && style.GetStrokeWidth() > 0 && style.GetStroke().GetPaintType() != wxSVG_PAINTTYPE_NONE) { cairo_path_t* path = canvasPath.GetPath(); cairo_append_path(cr, path); SetPaint(cr, style.GetStroke(), style.GetOpacity()*style.GetStrokeOpacity(), canvasPath, svgElem, matrix); wxSVGCanvasPathCairo::ApplyStrokeStyle(cr, style); cairo_stroke(cr); cairo_path_destroy(path); } // marker if (style.HasMarkerStart()) { DrawMarker(style.GetMarkerStart().GetStringValue(), wxSVGMark::START, canvasPath, matrix, style, svgElem); } if (style.HasMarkerMid()) { DrawMarker(style.GetMarkerMid().GetStringValue(), wxSVGMark::MID, canvasPath, matrix, style, svgElem); } if (style.HasMarkerEnd()) { DrawMarker(style.GetMarkerEnd().GetStringValue(), wxSVGMark::END, canvasPath, matrix, style, svgElem); } }
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 wxSVGCanvasPathCairo::ApplyStrokeStyle(cairo_t* cr, const wxCSSStyleDeclaration& style) { cairo_set_line_width(cr, style.GetStrokeWidth()); switch (style.GetStrokeLinecap()) { case wxCSS_VALUE_ROUND: cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); break; case wxCSS_VALUE_SQUARE: cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); break; case wxCSS_VALUE_BUTT: default: cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT); break; } switch (style.GetStrokeLinejoin()) { case wxCSS_VALUE_BEVEL: cairo_set_line_join(cr, CAIRO_LINE_JOIN_BEVEL); break; case wxCSS_VALUE_ROUND: cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); break; case wxCSS_VALUE_MITER: default: cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER); break; } if (style.GetStrokeDasharray().GetLength() > 0) { double* dashed = new double[style.GetStrokeDasharray().GetLength()]; for (int i = 0; i < style.GetStrokeDasharray().GetLength(); i++) { dashed[i] = style.GetStrokeDasharray().Item(i).GetFloatValue(); } cairo_set_dash(cr, dashed, style.GetStrokeDasharray().GetLength(), 0.0); delete dashed; } else cairo_set_dash(cr, NULL, 0, 0); }