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); }