1 //////////////////////////////////////////////////////////////////////////////
2 // Name:        SVGCanvasPathCairo.cpp
3 // Purpose:     Cairo canvas path
4 // Author:      Alex Thuering
5 // Created:     2005/05/12
6 // RCS-ID:      $Id: SVGCanvasPathCairo.cpp,v 1.15 2016/07/27 08:54:21 ntalex Exp $
7 // Copyright:   (c) 2005 Alex Thuering
8 // Licence:     wxWindows licence
9 //////////////////////////////////////////////////////////////////////////////
10 
11 #include "SVGCanvasPathCairo.h"
12 #include <wx/log.h>
13 
wxSVGCanvasPathCairo(cairo_surface_t * surface,wxSVGMatrix * matrix)14 wxSVGCanvasPathCairo::wxSVGCanvasPathCairo(cairo_surface_t* surface, wxSVGMatrix* matrix) {
15 	m_cr = cairo_create(surface);
16 #if 0 //!defined(__WXMAC__) && !defined(__WXMSW__)
17 	if (matrix) {
18 		 // for correct checking of surface size when text is rendered using PangaCairo
19 		cairo_matrix_t m;
20 		cairo_matrix_init(&m, matrix->GetA(), matrix->GetB(), matrix->GetC(), matrix->GetD(), matrix->GetE(), matrix->GetF());
21 		cairo_set_matrix(m_cr, &m);
22 	};
23 #endif
24 	m_curx = m_cury = m_cubicx = m_cubicy = m_quadx = m_quady = 0;
25 }
26 
~wxSVGCanvasPathCairo()27 wxSVGCanvasPathCairo::~wxSVGCanvasPathCairo() {
28 	cairo_destroy(m_cr);
29 }
30 
End()31 void wxSVGCanvasPathCairo::End() {
32 }
33 
GetPath()34 cairo_path_t* wxSVGCanvasPathCairo::GetPath() {
35 	return cairo_copy_path(m_cr);
36 }
37 
GetBBox(const wxSVGMatrix * matrix)38 wxSVGRect wxSVGCanvasPathCairo::GetBBox(const wxSVGMatrix* matrix) {
39 	if (matrix) {
40 		cairo_matrix_t m;
41 		cairo_matrix_init(&m, matrix->GetA(), matrix->GetB(), matrix->GetC(), matrix->GetD(),
42 				matrix->GetE(), matrix->GetF());
43 		cairo_matrix_invert(&m);
44 		cairo_set_matrix(m_cr, &m);
45 	}
46 	double x1, y1, x2, y2;
47 	cairo_fill_extents(m_cr, &x1, &y1, &x2, &y2);
48 	if (matrix) {
49 		cairo_matrix_t mat;
50 		cairo_matrix_init(&mat, 1, 0, 0, 1, 0, 0);
51 		cairo_set_matrix(m_cr, &mat);
52 	}
53 	return wxSVGRect(x1, y1, x2 - x1, y2 - y1);
54 }
55 
GetResultBBox(const wxCSSStyleDeclaration & style,const wxSVGMatrix * matrix)56 wxSVGRect wxSVGCanvasPathCairo::GetResultBBox(const wxCSSStyleDeclaration& style, const wxSVGMatrix* matrix) {
57 	if (matrix) {
58 		cairo_matrix_t m;
59 		cairo_matrix_init(&m, matrix->GetA(), matrix->GetB(), matrix->GetC(), matrix->GetD(),
60 				matrix->GetE(), matrix->GetF());
61 		cairo_matrix_invert(&m);
62 		cairo_set_matrix(m_cr, &m);
63 	}
64 	ApplyStrokeStyle(m_cr, style);
65 	double x1, y1, x2, y2;
66 	if (style.GetStrokeWidth() > 0)
67 		cairo_stroke_extents(m_cr, &x1, &y1, &x2, &y2);
68 	else
69 		cairo_fill_extents(m_cr, &x1, &y1, &x2, &y2);
70 	if (matrix) {
71 		cairo_matrix_t mat;
72 		cairo_matrix_init(&mat, 1, 0, 0, 1, 0, 0);
73 		cairo_set_matrix(m_cr, &mat);
74 	}
75 	return wxSVGRect(x1, y1, x2 - x1, y2 - y1);
76 }
77 
MoveToImpl(double x,double y)78 void wxSVGCanvasPathCairo::MoveToImpl(double x, double y) {
79 	cairo_move_to(m_cr, x, y);
80 }
81 
LineToImpl(double x,double y)82 void wxSVGCanvasPathCairo::LineToImpl(double x, double y) {
83 	cairo_line_to(m_cr, x, y);
84 }
85 
CurveToCubicImpl(double x1,double y1,double x2,double y2,double x,double y)86 void wxSVGCanvasPathCairo::CurveToCubicImpl(double x1, double y1, double x2,
87 		double y2, double x, double y) {
88 	cairo_curve_to(m_cr, x1, y1, x2, y2, x, y);
89 }
90 
ClosePathImpl()91 bool wxSVGCanvasPathCairo::ClosePathImpl() {
92 	cairo_close_path(m_cr);
93 	return true;
94 }
95 
ApplyStrokeStyle(cairo_t * cr,const wxCSSStyleDeclaration & style)96 void wxSVGCanvasPathCairo::ApplyStrokeStyle(cairo_t* cr, const wxCSSStyleDeclaration& style) {
97 	cairo_set_line_width(cr, style.GetStrokeWidth());
98 	switch (style.GetStrokeLinecap()) {
99 	case wxCSS_VALUE_ROUND:
100 		cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
101 		break;
102 	case wxCSS_VALUE_SQUARE:
103 		cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
104 		break;
105 	case wxCSS_VALUE_BUTT:
106 	default:
107 		cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
108 		break;
109 	}
110 	switch (style.GetStrokeLinejoin()) {
111 	case wxCSS_VALUE_BEVEL:
112 		cairo_set_line_join(cr, CAIRO_LINE_JOIN_BEVEL);
113 		break;
114 	case wxCSS_VALUE_ROUND:
115 		cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
116 		break;
117 	case wxCSS_VALUE_MITER:
118 	default:
119 		cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
120 		break;
121 	}
122 	if (style.GetStrokeDasharray().GetLength() > 0) {
123 		double* dashed = new double[style.GetStrokeDasharray().GetLength()];
124 		for (int i = 0; i < style.GetStrokeDasharray().GetLength(); i++) {
125 			dashed[i] = style.GetStrokeDasharray().Item(i).GetFloatValue();
126 		}
127 		cairo_set_dash(cr, dashed, style.GetStrokeDasharray().GetLength(), style.GetStrokeDashoffset());
128 		delete dashed;
129 	} else
130 		cairo_set_dash(cr, NULL, 0, 0);
131 }
132