void ofCairoRenderer::drawPath(const ofShape & path,bool is_subpath){
	if(!surface || !cr) return;
	const vector<ofShape::Command> & commands = path.getCommands();
	if(is_subpath)
		cairo_new_sub_path(cr);
	else
		cairo_new_path(cr);
	for(int i=0; i<(int)commands.size(); i++){
		switch(commands[i].type){
		case ofShape::Command::lineTo:
			curvePoints.clear();
			cairo_line_to(cr,commands[i].to.x,commands[i].to.y);
			break;


		case ofShape::Command::curveTo:
			curvePoints.push_back(commands[i].to);

			//code adapted from ofxVectorGraphics to convert catmull rom to bezier
			if(curvePoints.size()==4){
				ofPoint p1=curvePoints[0];
				ofPoint p2=curvePoints[1];
				ofPoint p3=curvePoints[2];
				ofPoint p4=curvePoints[3];

				//SUPER WEIRD MAGIC CONSTANT = 1/6 (this works 100% can someone explain it?)
				ofPoint cp1 = p2 + ( p3 - p1 ) * (1.0/6);
				ofPoint cp2 = p3 + ( p2 - p4 ) * (1.0/6);

				cairo_curve_to( cr, cp1.x, cp1.y, cp2.x, cp2.y, p3.x, p3.y );
				curvePoints.pop_front();
			}
			break;


		case ofShape::Command::bezierTo:
			curvePoints.clear();
			cairo_curve_to(cr,commands[i].cp1.x,commands[i].cp1.y,commands[i].cp2.x,commands[i].cp2.y,commands[i].to.x,commands[i].to.y);
			break;

		case ofShape::Command::quadBezierTo:
			curvePoints.clear();
			cairo_curve_to(cr,commands[i].cp1.x,commands[i].cp1.y,commands[i].cp2.x,commands[i].cp2.y,commands[i].to.x,commands[i].to.y);
			break;


		case ofShape::Command::arc:
			curvePoints.clear();
			// elliptic arcs not directly supported in cairo, lets scale y
			if(commands[i].radiusX!=commands[i].radiusY){
				float ellipse_ratio = commands[i].radiusY/commands[i].radiusX;
				pushMatrix();
				translate(0,-commands[i].to.y*ellipse_ratio);
				scale(1,ellipse_ratio);
				translate(0,commands[i].to.y*1/ellipse_ratio);
				cairo_arc(cr,commands[i].to.x,commands[i].to.y,commands[i].radiusX,commands[i].angleBegin,commands[i].angleEnd);
				//cairo_set_matrix(cr,&stored_matrix);
				popMatrix();
			}else{
				cairo_arc(cr,commands[i].to.x,commands[i].to.y,commands[i].radiusX,commands[i].angleBegin,commands[i].angleEnd);
			}
			break;
		}
	}

	if(path.isClosed()){
		cairo_close_path(cr);
	}

	const vector<ofShape> &subpaths = path.getSubShapes();
	for(int i=0;i<(int)subpaths.size();i++){
		drawPath(subpaths[i],true);
	}

	cairo_fill_rule_t cairo_poly_mode;
	if(path.getWindingMode()==OF_POLY_WINDING_ODD) cairo_poly_mode=CAIRO_FILL_RULE_EVEN_ODD;
	else cairo_poly_mode=CAIRO_FILL_RULE_WINDING;

	cairo_set_fill_rule(cr,cairo_poly_mode);


	if(path.getStrokeWidth()>0){
		ofColor c = path.getStrokeColor() * ofGetStyle().color;
		c.a = path.getStrokeColor().a/255. * ofGetStyle().color.a;
		cairo_set_source_rgba(cr, (float)c.r/255.0, (float)c.g/255.0, (float)c.b/255.0, (float)c.a/255.0);
		cairo_set_line_width( cr, path.getStrokeWidth() );
		if(path.isFilled())
			cairo_stroke_preserve( cr );
		else
			cairo_stroke( cr );
	}
	if(path.isFilled()){
		ofColor c = path.getFillColor() * ofGetStyle().color;
		c.a = path.getFillColor().a/255. * ofGetStyle().color.a;
		cairo_set_source_rgba(cr, (float)c.r/255.0, (float)c.g/255.0, (float)c.b/255.0, (float)c.a/255.0);
		cairo_fill( cr );
	}
}
void ofCairoRenderer::draw(ofShape & shape){
	cairo_new_path(cr);
	vector<ofSubPath> & paths = shape.getSubPaths();
	for(int i=0;i<(int)paths.size();i++){
		draw(paths[i]);
	}

	cairo_fill_rule_t cairo_poly_mode;
	if(shape.getWindingMode()==OF_POLY_WINDING_ODD) cairo_poly_mode=CAIRO_FILL_RULE_EVEN_ODD;
	else cairo_poly_mode=CAIRO_FILL_RULE_WINDING;

	cairo_set_fill_rule(cr,cairo_poly_mode);


	ofColor prevColor;
	if(shape.getUseShapeColor()){
		prevColor = ofGetStyle().color;
	}

	if(shape.isFilled()){
		if(shape.getUseShapeColor()){
			ofColor c = shape.getFillColor() * ofGetStyle().color;
			c.a = shape.getFillColor().a/255. * ofGetStyle().color.a;
			cairo_set_source_rgba(cr, (float)c.r/255.0, (float)c.g/255.0, (float)c.b/255.0, (float)c.a/255.0);
		}

		if(shape.hasOutline()){
			cairo_fill_preserve( cr );
		}else{
			cairo_fill(cr);
		}
	}
	if(shape.hasOutline()){
		float lineWidth = ofGetStyle().lineWidth;
		if(shape.getUseShapeColor()){
			ofColor c = shape.getFillColor() * ofGetStyle().color;
			c.a = shape.getFillColor().a/255. * ofGetStyle().color.a;
			cairo_set_source_rgba(cr, (float)c.r/255.0, (float)c.g/255.0, (float)c.b/255.0, (float)c.a/255.0);
		}
		cairo_set_line_width( cr, shape.getStrokeWidth() );
		cairo_stroke( cr );
		cairo_set_line_width( cr, lineWidth );
	}

	if(shape.getUseShapeColor()){
		setColor(prevColor);
	}
	ofPopStyle();
}
void ofGLRenderer::draw(ofShape & path){
	ofShapeTessellation & shape = path.getTessellation();
	draw(shape);
}