/***** * drawfill.h * Andy Hammerlindl 2002/06/06 * * Stores a cyclic path that will outline a filled shape in a picture. *****/ #ifndef DRAWFILL_H #define DRAWFILL_H #include "drawelement.h" #include "path.h" namespace camp { class drawFill : public drawSuperPathPenBase { protected: bool stroke; public: void noncyclic() { reportError("non-cyclic path cannot be filled"); } drawFill(const vm::array& src, bool stroke, pen pentype) : drawSuperPathPenBase(src,pentype), stroke(stroke) { if(!stroke && !cyclic()) noncyclic(); } bool svg() {return true;} // dvisvgm doesn't yet support SVG patterns. bool svgpng() {return pentype.fillpattern() != "";} virtual ~drawFill() {} virtual bool draw(psfile *out); virtual void palette(psfile *out) { penSave(out); penTranslate(out); } virtual void fill(psfile *out) { out->setpen(pentype); if(stroke) out->strokepath(); out->fill(pentype); penRestore(out); }; drawElement *transformed(const transform& t); }; class drawShade : public drawFill { public: drawShade(const vm::array& src, bool stroke, pen pentype) : drawFill(src,stroke,pentype) {} void bounds(bbox& b, iopipestream& iopipe, boxvector& vbox, bboxlist& bboxstack) { if(stroke) strokebounds(b); else drawSuperPathPenBase::bounds(b,iopipe,vbox,bboxstack); } // Shading in SVG is incomplete and not supported at all by dvisvgm. bool svg() {return true;} bool svgpng() {return !settings::getSetting("svgemulation");} virtual void beginshade(psfile *out)=0; virtual void shade(psfile *out)=0; bool draw(psfile *out) { if(pentype.invisible() || empty()) return true; palette(out); beginshade(out); writeclippath(out); if(stroke) strokepath(out); shade(out); out->grestore(); return true; } }; class drawLatticeShade : public drawShade { protected: vm::array pens; const transform T; public: drawLatticeShade(const vm::array& src, bool stroke, pen pentype, const vm::array& pens, const camp::transform& T=identity) : drawShade(src,stroke,pentype), pens(pens), T(T) {} void palette(psfile *out) { out->gsave(); } void beginshade(psfile *out) { out->beginlatticeshade(pens,bpath); } void shade(psfile *out) { bbox b; for(size_t i=0; i < size; i++) b += vm::read(P,i).transformed(inverse(T)).bounds(); pair lambda=b.Max()-b.Min(); out->latticeshade(pens,T*scale(lambda.getx(),lambda.gety())); } drawElement *transformed(const transform& t); }; class drawAxialShade : public drawShade { protected: pair a; pen penb; pair b; ColorSpace colorspace; public: drawAxialShade(const vm::array& src, bool stroke, pen pentype, pair a, pen penb, pair b) : drawShade(src,stroke,pentype), a(a), penb(penb), b(b) {} bool svgpng() {return false;} void palette(psfile *out); void beginshade(psfile *out) { out->begingradientshade(true,colorspace,pentype,a,0,penb,b,0); } void shade(psfile *out) { out->gradientshade(true,colorspace,pentype,a,0,penb,b,0); } drawElement *transformed(const transform& t); }; class drawRadialShade : public drawAxialShade { protected: double ra; double rb; public: drawRadialShade(const vm::array& src, bool stroke, pen pentype, pair a, double ra, pen penb, pair b, double rb) : drawAxialShade(src,stroke,pentype,a,penb,b), ra(ra), rb(rb) {} bool svgpng() {return ra > 0.0;} void beginshade(psfile *out) { out->begingradientshade(false,colorspace,pentype,a,ra,penb,b,rb); } void shade(psfile *out) { out->gradientshade(false,colorspace,pentype,a,ra,penb,b,rb); } drawElement *transformed(const transform& t); }; class drawGouraudShade : public drawShade { protected: vm::array pens,vertices,edges; public: drawGouraudShade(const vm::array& src, bool stroke, pen pentype, const vm::array& pens, const vm::array& vertices, const vm::array& edges) : drawShade(src,stroke,pentype), pens(pens), vertices(vertices), edges(edges) {} void palette(psfile *out) { out->gsave(); } void beginshade(psfile *out) { out->begingouraudshade(pens,vertices,edges); } void shade(psfile *out) { out->gouraudshade(pentype,pens,vertices,edges); } drawElement *transformed(const transform& t); }; class drawTensorShade : public drawShade { protected: vm::array pens,boundaries,z; public: drawTensorShade(const vm::array& src, bool stroke, pen pentype, const vm::array& pens, const vm::array& boundaries, const vm::array& z) : drawShade(src,stroke,pentype), pens(pens), boundaries(boundaries), z(z) {} bool svgpng() { return pens.size() > 1 || !settings::getSetting("svgemulation"); } void palette(psfile *out) { out->gsave(); } void beginshade(psfile *out) { out->begintensorshade(pens,boundaries,z); } void shade(psfile *out) { out->tensorshade(pentype,pens,boundaries,z); } drawElement *transformed(const transform& t); }; class drawFunctionShade : public drawFill { protected: string shader; public: drawFunctionShade(const vm::array& src, bool stroke, pen pentype, const string& shader) : drawFill(src,stroke,pentype), shader(shader) { string texengine=settings::getSetting("tex"); if(!settings::pdf(texengine)) reportError("functionshade is not implemented for the '"+texengine+ "' tex engine"); } virtual ~drawFunctionShade() {} bool svgpng() {return true;} bool draw(psfile *out) {return false;} bool write(texfile *, const bbox&); bool islabel() {return true;} drawElement *transformed(const transform& t); }; } #endif