Py::Object RendererAgg::draw_rectangle(const Py::Tuple & args) { _VERBOSE("RendererAgg::draw_rectangle"); args.verify_length(6); theRasterizer->reset_clipping(); Py::Object gcEdge( args[0] ); Py::Object rgbFaceMaybeNone( args[1] ); double l = Py::Float( args[2] ); double b = Py::Float( args[3] ); double w = Py::Float( args[4] ); double h = Py::Float( args[5] ); set_clip_rectangle(gcEdge); double lw = points_to_pixels ( gcEdge.getAttr("_linewidth") ) ; agg::path_storage path; b = height - (b+h); path.move_to(l, b+h); path.line_to(l+w, b+h); path.line_to(l+w, b); path.line_to(l, b); path.close_polygon(); agg::rgba edgecolor = get_color(gcEdge); if (rgbFaceMaybeNone.ptr() != Py_None) { //fill the face Py::SeqBase<Py::Object> rgbFace = rgbFaceMaybeNone; agg::rgba facecolor = rgb_to_color(rgbFace, edgecolor.a); rendererAA->color(facecolor); theRasterizer->add_path(path); agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA); } //now fill the edge agg::conv_stroke<agg::path_storage> stroke(path); stroke.width(lw); rendererAA->color(edgecolor); //self->theRasterizer->gamma(agg::gamma_power(gamma)); theRasterizer->add_path(stroke); agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA); return Py::Object(); }
double worksheet::row_height(row_t row) const { static const auto DefaultRowHeight = 15.0; if (has_row_properties(row) && row_properties(row).height.is_set()) { return row_properties(row).height.get(); } else { return points_to_pixels(DefaultRowHeight, 96.0); } }
double worksheet::column_width(column_t column) const { static const auto DefaultColumnWidth = 51.85; if (has_column_properties(column)) { return column_properties(column).width.get(); } else { return points_to_pixels(DefaultColumnWidth, 96.0); } }
Py::Object RendererAgg::draw_ellipse(const Py::Tuple& args) { _VERBOSE("RendererAgg::draw_ellipse"); args.verify_length(6); Py::Object gcEdge = args[0]; Py::Object rgbFaceMaybeNone = args[1]; double x = Py::Float( args[2] ); double y = Py::Float( args[3] ); double w = Py::Float( args[4] ); double h = Py::Float( args[5] ); set_clip_rectangle(gcEdge); //last arg is num steps agg::ellipse path(x, height-y, w, h, 100); agg::rgba edgecolor = get_color(gcEdge); if (rgbFaceMaybeNone.ptr() != Py_None) { Py::SeqBase<Py::Object> rgbFace = rgbFaceMaybeNone; agg::rgba facecolor = rgb_to_color(rgbFace, edgecolor.a); theRenderer->color(facecolor); theRasterizer->add_path(path); theRasterizer->render(*slineP8, *theRenderer); } //now fill the edge double lw = points_to_pixels ( gcEdge.getAttr("_linewidth") ) ; agg::conv_stroke<agg::ellipse> stroke(path); stroke.width(lw); theRenderer->color(edgecolor); //self->theRasterizer->gamma(agg::gamma_power(gamma)); theRasterizer->add_path(stroke); theRasterizer->render(*slineP8, *theRenderer); return Py::Object(); }
Py::Object RendererAgg::draw_lines(const Py::Tuple& args) { theRasterizer->reset_clipping(); _VERBOSE("RendererAgg::draw_lines"); args.verify_length(3); Py::Object gc = args[0]; Py::SeqBase<Py::Object> x = args[1]; //todo: use numerix for efficiency Py::SeqBase<Py::Object> y = args[2]; //todo: use numerix for efficiency set_clip_rectangle(gc); size_t Nx = x.length(); size_t Ny = y.length(); if (Nx!=Ny) throw Py::ValueError("x and y must be equal length sequences"); if (Nx<2) throw Py::ValueError("x and y must have length >= 2"); agg::vcgen_stroke::line_cap_e cap = get_linecap(gc); agg::vcgen_stroke::line_join_e join = get_joinstyle(gc); double lw = points_to_pixels ( gc.getAttr("_linewidth") ) ; //std::cout << "agg lw " << lw << std::endl; agg::rgba color = get_color(gc); // process the dashes Py::Tuple dashes = get_dashes(gc); bool useDashes = dashes[0].ptr() != Py_None; double offset = 0; Py::SeqBase<Py::Object> dashSeq; if ( dashes[0].ptr() != Py_None ) { // use dashes //TODO: use offset offset = points_to_pixels_snapto(dashes[0]); dashSeq = dashes[1]; }; agg::path_storage path; int isaa = antialiased(gc); double heightd = double(height); if (Nx==2) { // this is a little hack - len(2) lines are probably grid and // ticks so I'm going to snap to pixel //printf("snapto %d\n", Nx); double x0 = Py::Float(x[0]); double y0 = Py::Float(y[0]); double x1 = Py::Float(x[1]); double y1 = Py::Float(y[1]); if (x0==x1) { x0 = (int)x0 + 0.5; x1 = (int)x1 + 0.5; } if (y0==y1) { y0 = (int)y0 + 0.5; y1 = (int)y1 + 0.5; } y0 = heightd-y0; y1 = heightd-y1; path.move_to(x0, y0); path.line_to(x1, y1); } else { double thisX = Py::Float( x[0] ); double thisY = Py::Float( y[0] ); thisY = heightd - thisY; //flipy path.move_to(thisX, thisY); for (size_t i=1; i<Nx; ++i) { thisX = Py::Float( x[i] ); thisY = Py::Float( y[i] ); thisY = heightd - thisY; //flipy //if ((i<10) || i>=19990) //std::cout << i << " " << Nx << " " << thisX << " " << thisY << std::endl; path.line_to(thisX, thisY); } } //std::cout << width << " " << height << std::endl; if (! useDashes ) { agg::conv_stroke<agg::path_storage> stroke(path); stroke.line_cap(cap); stroke.line_join(join); stroke.width(lw); //freeze was here std::cout << "\t adding path!" << std::endl; theRasterizer->add_path(stroke); } else { // set the dashes //TODO: scale for DPI size_t N = dashSeq.length(); if (N%2 != 0 ) throw Py::ValueError("dashes must be an even length sequence"); typedef agg::conv_dash<agg::path_storage> dash_t; dash_t dash(path); double on, off; for (size_t i=0; i<N/2; i+=1) { on = points_to_pixels_snapto(dashSeq[2*i]); off = points_to_pixels_snapto(dashSeq[2*i+1]); dash.add_dash(on, off); } agg::conv_stroke<dash_t> stroke(dash); stroke.line_cap(cap); stroke.line_join(join); stroke.width(lw); theRasterizer->add_path(stroke); } if ( isaa ) { rendererAA->color(color); agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA); } else { rendererBin->color(color); agg::render_scanlines(*theRasterizer, *slineBin, *rendererBin); } return Py::Object(); }
Py::Object RendererAgg::draw_regpoly_collection(const Py::Tuple& args) { theRasterizer->reset_clipping(); _VERBOSE("RendererAgg::draw_regpoly_collection"); args.verify_length(9); set_clip_from_bbox(args[0]); Py::SeqBase<Py::Object> offsets = args[1]; // this is throwing even though the instance is a Transformation! //if (!Transformation::check(args[2])) // throw Py::TypeError("RendererAgg::draw_regpoly_collection(clipbox, offsets, transOffset, verts, ...) expected a Transformation instance for transOffset"); Transformation* transOffset = static_cast<Transformation*>(args[2].ptr()); transOffset->eval_scalars(); Py::SeqBase<Py::Object> verts = args[3]; Py::SeqBase<Py::Object> sizes = args[4]; Py::SeqBase<Py::Object> facecolors = args[5]; Py::SeqBase<Py::Object> edgecolors = args[6]; Py::SeqBase<Py::Object> linewidths = args[7]; Py::SeqBase<Py::Object> antialiaseds = args[8]; size_t Noffsets = offsets.length(); size_t Nverts = verts.length(); size_t Nsizes = sizes.length(); size_t Nface = facecolors.length(); size_t Nedge = edgecolors.length(); size_t Nlw = linewidths.length(); size_t Naa = antialiaseds.length(); double thisx, thisy; // dump the x.y vertices into a double array for faster access double xverts[Nverts]; double yverts[Nverts]; Py::Tuple xy; for (size_t i=0; i<Nverts; ++i) { xy = Py::Tuple(verts[i]); xverts[i] = Py::Float(xy[0]); yverts[i] = Py::Float(xy[1]); } std::pair<double, double> offsetPair; for (size_t i=0; i<Noffsets; ++i) { Py::Tuple pos = Py::Tuple(offsets[i]); double xo = Py::Float(pos[0]); double yo = Py::Float(pos[1]); offsetPair = transOffset->operator()(xo, yo); double scale = Py::Float(sizes[i%Nsizes]); agg::path_storage path; for (size_t j=0; j<Nverts; ++j) { thisx = scale*xverts[j] + offsetPair.first; thisy = scale*yverts[j] + offsetPair.second; thisy = height - thisy; if (j==0) path.move_to(thisx, thisy); else path.line_to(thisx, thisy); } path.close_polygon(); int isaa = Py::Int(antialiaseds[i%Naa]); // get the facecolor and render Py::Tuple rgba = Py::Tuple(facecolors[ i%Nface]); double r = Py::Float(rgba[0]); double g = Py::Float(rgba[1]); double b = Py::Float(rgba[2]); double a = Py::Float(rgba[3]); if (a>0) { //only render if alpha>0 agg::rgba facecolor(r, g, b, a); theRasterizer->add_path(path); if (isaa) { rendererAA->color(facecolor); agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA); } else { rendererBin->color(facecolor); agg::render_scanlines(*theRasterizer, *slineBin, *rendererBin); } } //renderer face // get the edgecolor and render rgba = Py::Tuple(edgecolors[ i%Nedge]); r = Py::Float(rgba[0]); g = Py::Float(rgba[1]); b = Py::Float(rgba[2]); a = Py::Float(rgba[3]); if (a>0) { //only render if alpha>0 agg::rgba edgecolor(r, g, b, a); agg::conv_stroke<agg::path_storage> stroke(path); //stroke.line_cap(cap); //stroke.line_join(join); double lw = points_to_pixels ( Py::Float( linewidths[i%Nlw] ) ); stroke.width(lw); theRasterizer->add_path(stroke); // render antialiased or not if ( isaa ) { rendererAA->color(edgecolor); agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA); } else { rendererBin->color(edgecolor); agg::render_scanlines(*theRasterizer, *slineBin, *rendererBin); } } //rendered edge } // for every poly return Py::Object(); }
Py::Object RendererAgg::draw_poly_collection(const Py::Tuple& args) { theRasterizer->reset_clipping(); _VERBOSE("RendererAgg::draw_poly_collection"); args.verify_length(9); Py::SeqBase<Py::Object> verts = args[0]; //todo: fix transformation check Transformation* transform = static_cast<Transformation*>(args[1].ptr()); transform->eval_scalars(); set_clip_from_bbox(args[2]); Py::SeqBase<Py::Object> facecolors = args[3]; Py::SeqBase<Py::Object> edgecolors = args[4]; Py::SeqBase<Py::Object> linewidths = args[5]; Py::SeqBase<Py::Object> antialiaseds = args[6]; Py::SeqBase<Py::Object> offsets; Transformation* transOffset = NULL; bool usingOffsets = args[7].ptr() != Py_None; if (usingOffsets) { offsets = args[7]; //todo: fix transformation check transOffset = static_cast<Transformation*>(args[8].ptr()); transOffset->eval_scalars(); } size_t Noffsets = offsets.length(); size_t Nverts = verts.length(); size_t Nface = facecolors.length(); size_t Nedge = edgecolors.length(); size_t Nlw = linewidths.length(); size_t Naa = antialiaseds.length(); size_t N = (Noffsets>Nverts) ? Noffsets : Nverts; std::pair<double, double> xyo, xy; Py::Tuple thisverts; for (size_t i=0; i<N; ++i) { thisverts = verts[i % Nverts]; if (usingOffsets) { Py::Tuple pos = Py::Tuple(offsets[i]); double xo = Py::Float(pos[0]); double yo = Py::Float(pos[1]); xyo = transOffset->operator()(xo, yo); } size_t Nverts = thisverts.length(); agg::path_storage path; Py::Tuple thisvert; // dump the verts to double arrays so we can do more efficient // look aheads and behinds when doing snapto pixels double xs[Nverts], ys[Nverts]; for (size_t j=0; j<Nverts; ++j) { thisvert = Py::Tuple(thisverts[j]); double x = Py::Float(thisvert[0]); double y = Py::Float(thisvert[1]); xy = transform->operator()(x, y); if (usingOffsets) { xy.first += xyo.first; xy.second += xyo.second; } xy.second = height - xy.second; xs[j] = xy.first; ys[j] = xy.second; } for (size_t j=0; j<Nverts; ++j) { double x = xs[j]; double y = ys[j]; if (j==0) { if (xs[j] == xs[Nverts-1]) x = (int)xs[j] + 0.5; if (ys[j] == ys[Nverts-1]) y = (int)ys[j] + 0.5; } else if (j==Nverts-1) { if (xs[j] == xs[0]) x = (int)xs[j] + 0.5; if (ys[j] == ys[0]) y = (int)ys[j] + 0.5; } if (j < Nverts-1) { if (xs[j] == xs[j+1]) x = (int)xs[j] + 0.5; if (ys[j] == ys[j+1]) y = (int)ys[j] + 0.5; } if (j>0) { if (xs[j] == xs[j-1]) x = (int)xs[j] + 0.5; if (ys[j] == ys[j-1]) y = (int)ys[j] + 0.5; } if (j==0) path.move_to(x,y); else path.line_to(x,y); } path.close_polygon(); int isaa = Py::Int(antialiaseds[i%Naa]); // get the facecolor and render Py::Tuple rgba = Py::Tuple(facecolors[ i%Nface]); double r = Py::Float(rgba[0]); double g = Py::Float(rgba[1]); double b = Py::Float(rgba[2]); double a = Py::Float(rgba[3]); if (a>0) { //only render if alpha>0 agg::rgba facecolor(r, g, b, a); theRasterizer->add_path(path); if (isaa) { rendererAA->color(facecolor); agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA); } else { rendererBin->color(facecolor); agg::render_scanlines(*theRasterizer, *slineBin, *rendererBin); } } //renderer face // get the edgecolor and render rgba = Py::Tuple(edgecolors[ i%Nedge]); r = Py::Float(rgba[0]); g = Py::Float(rgba[1]); b = Py::Float(rgba[2]); a = Py::Float(rgba[3]); if (a>0) { //only render if alpha>0 agg::rgba edgecolor(r, g, b, a); agg::conv_stroke<agg::path_storage> stroke(path); //stroke.line_cap(cap); //stroke.line_join(join); double lw = points_to_pixels ( Py::Float( linewidths[i%Nlw] ) ); stroke.width(lw); theRasterizer->add_path(stroke); // render antialiased or not if ( isaa ) { rendererAA->color(edgecolor); agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA); } else { rendererBin->color(edgecolor); agg::render_scanlines(*theRasterizer, *slineBin, *rendererBin); } } //rendered edge } // for every poly return Py::Object(); }
Py::Object RendererAgg::draw_line_collection(const Py::Tuple& args) { theRasterizer->reset_clipping(); _VERBOSE("RendererAgg::draw_line_collection"); args.verify_length(8); //segments, trans, clipbox, colors, linewidths, antialiaseds Py::SeqBase<Py::Object> segments = args[0]; /* this line is broken, mysteriously if (!Transformation::check(args[1])) throw Py::TypeError("RendererAgg::draw_line_collection(segments, transform, ...) expected a Transformation instance for transform"); */ Transformation* transform = static_cast<Transformation*>(args[1].ptr()); set_clip_from_bbox(args[2]); Py::SeqBase<Py::Object> colors = args[3]; Py::SeqBase<Py::Object> linewidths = args[4]; Py::SeqBase<Py::Object> antialiaseds = args[5]; bool usingOffsets = args[6].ptr()!=Py_None; Py::SeqBase<Py::Object> offsets; Transformation* transOffset=NULL; if (usingOffsets) { offsets = Py::SeqBase<Py::Object>(args[6]); transOffset = static_cast<Transformation*>(args[7].ptr()); } size_t Nsegments = segments.length(); size_t Nc = colors.length(); size_t Nlw = linewidths.length(); size_t Naa = antialiaseds.length(); size_t Noffsets = 0; size_t N = Nsegments; if (usingOffsets) { Noffsets = offsets.length(); if (Noffsets>Nsegments) N = Noffsets; } double xo(0.0), yo(0.0), thisx(0.0), thisy(0.0); std::pair<double, double> xy; Py::Tuple xyo; Py::SeqBase<Py::Object> xys; for (size_t i=0; i<N; ++i) { if (usingOffsets) { xyo = Py::Tuple(offsets[i%Noffsets]); xo = Py::Float(xyo[0]); yo = Py::Float(xyo[1]); xy = transOffset->operator()(xo,yo); xo = xy.first; yo = xy.second; } xys = segments[i%Nsegments]; size_t numtups = xys.length(); if (numtups<2) continue; agg::path_storage path; for (size_t j=0; j<numtups; j++) { xyo = xys[j]; thisx = Py::Float(xyo[0]); thisy = Py::Float(xyo[1]); xy = transform->operator()(thisx,thisy); thisx = xy.first; thisy = xy.second; if (usingOffsets) { thisx += xo; thisy += yo; } if (j==0) path.move_to(thisx, height-thisy); else path.line_to(thisx, height-thisy); } agg::conv_stroke<agg::path_storage> stroke(path); //stroke.line_cap(cap); //stroke.line_join(join); double lw = points_to_pixels ( Py::Float( linewidths[i%Nlw] ) ); stroke.width(lw); theRasterizer->add_path(stroke); // get the color and render Py::Tuple rgba = Py::Tuple(colors[ i%Nc]); double r = Py::Float(rgba[0]); double g = Py::Float(rgba[1]); double b = Py::Float(rgba[2]); double a = Py::Float(rgba[3]); agg::rgba color(r, g, b, a); // render antialiased or not int isaa = Py::Int(antialiaseds[i%Naa]); if ( isaa ) { rendererAA->color(color); agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA); } else { rendererBin->color(color); agg::render_scanlines(*theRasterizer, *slineBin, *rendererBin); } } //for every segment return Py::Object(); }
Py::Object RendererAgg::draw_polygon(const Py::Tuple& args) { _VERBOSE("RendererAgg::draw_polygon"); theRasterizer->reset_clipping(); args.verify_length(3); Py::Object gcEdge( args[0] ); Py::Object rgbFaceMaybeNone( args[1] ); Py::SeqBase<Py::Object> points( args[2] ); set_clip_rectangle(gcEdge); agg::vcgen_stroke::line_cap_e cap = get_linecap(gcEdge); agg::vcgen_stroke::line_join_e join = get_joinstyle(gcEdge); double lw = points_to_pixels ( gcEdge.getAttr("_linewidth") ) ; size_t Npoints = points.length(); if (Npoints<=0) return Py::Object(); // dump the x.y vertices into a double array for faster look ahread // and behind access double xs[Npoints]; double ys[Npoints]; Py::Tuple xy; for (size_t i=0; i<Npoints; ++i) { xy = Py::Tuple(points[i]); xs[i] = Py::Float(xy[0]); ys[i] = Py::Float(xy[1]); ys[i] = height - ys[i]; } agg::path_storage path; for (size_t j=0; j<Npoints; ++j) { double x = xs[j]; double y = ys[j]; if (j==0) path.move_to(x,y); else path.line_to(x,y); } path.close_polygon(); agg::rgba edgecolor = get_color(gcEdge); if (rgbFaceMaybeNone.ptr() != Py_None) { //fill the face Py::SeqBase<Py::Object> rgbFace = rgbFaceMaybeNone; agg::rgba facecolor = rgb_to_color(rgbFace, edgecolor.a); rendererAA->color(facecolor); theRasterizer->add_path(path); agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA); } //now fill the edge agg::conv_stroke<agg::path_storage> stroke(path); stroke.width(lw); stroke.line_cap(cap); stroke.line_join(join); rendererAA->color(edgecolor); //self->theRasterizer->gamma(agg::gamma_power(gamma)); theRasterizer->add_path(stroke); agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA); return Py::Object(); }
Py::Object RendererAgg::draw_line_collection(const Py::Tuple& args) { _VERBOSE("RendererAgg::draw_line_collection"); args.verify_length(8); //segments, trans, clipbox, colors, linewidths, antialiaseds Py::SeqBase<Py::Object> segments = args[0]; /* this line is broken, mysteriously if (!Transformation::check(args[1])) throw Py::TypeError("RendererAgg::draw_line_collection(segments, transform, ...) expected a Transformation instance for transform"); */ Transformation* transform = static_cast<Transformation*>(args[1].ptr()); set_clip_from_bbox(args[2]); Py::SeqBase<Py::Object> colors = args[3]; Py::SeqBase<Py::Object> linewidths = args[4]; Py::SeqBase<Py::Object> antialiaseds = args[5]; bool usingOffsets = args[6].ptr()!=Py_None; Py::SeqBase<Py::Object> offsets; Transformation* transOffset=NULL; if (usingOffsets) { /* this line is broken, mysteriously if (!Transformation::check(args[7])) throw Py::TypeError("RendererAgg::draw_line_collection expected a Transformation instance for transOffset"); */ offsets = Py::SeqBase<Py::Object>(args[6]); transOffset = static_cast<Transformation*>(args[7].ptr()); } size_t Nsegments = segments.length(); size_t Nc = colors.length(); size_t Nlw = linewidths.length(); size_t Naa = antialiaseds.length(); size_t Noffsets = 0; size_t N = Nsegments; if (usingOffsets) { Noffsets = offsets.length(); if (Noffsets>Nsegments) N = Noffsets; } Py::Tuple xyo, pos; for (size_t i=0; i<N; ++i) { pos = Py::Tuple(segments[i%Nsegments]); double x0 = Py::Float(pos[0]); double y0 = Py::Float(pos[1]); double x1 = Py::Float(pos[2]); double y1 = Py::Float(pos[3]); std::pair<double, double> xy = transform->operator()(x0,y0); x0 = xy.first; y0 = xy.second; xy = transform->operator()(x1,y1); x1 = xy.first; y1 = xy.second; if (usingOffsets) { xyo = Py::Tuple(offsets[i%Noffsets]); double xo = Py::Float(xyo[0]); double yo = Py::Float(xyo[1]); std::pair<double, double> xy = transOffset->operator()(xo,yo); x0 += xy.first; y0 += xy.second; x1 += xy.first; y1 += xy.second; } //snap x to pixel for verical lines if (x0==x1) { x0 = (int)x0 + 0.5; x1 = (int)x1 + 0.5; } //snap y to pixel for horizontal lines if (y0==y1) { y0 = (int)y0 + 0.5; y1 = (int)y1 + 0.5; } agg::path_storage path; path.move_to(x0, height-y0); path.line_to(x1, height-y1); agg::conv_stroke<agg::path_storage> stroke(path); //stroke.line_cap(cap); //stroke.line_join(join); double lw = points_to_pixels ( Py::Float( linewidths[i%Nlw] ) ); stroke.width(lw); theRasterizer->add_path(stroke); // get the color and render Py::Tuple rgba = Py::Tuple(colors[ i%Nc]); double r = Py::Float(rgba[0]); double g = Py::Float(rgba[1]); double b = Py::Float(rgba[2]); double a = Py::Float(rgba[3]); agg::rgba color(r, g, b, a); // render antialiased or not int isaa = Py::Int(antialiaseds[i%Naa]); if ( isaa ) { theRenderer->color(color); theRasterizer->render(*slineP8, *theRenderer); } else { rendererBin->color(color); theRasterizer->render(*slineBin, *rendererBin); } } //for every segment return Py::Object(); }