void SVGStylable::pickTraverse(svgl::Context * svglContext, svgl::GLInfo* glinfo) { const css::CSSStyleDeclaration& style = getStyle().getValue(); const css::Color * fill = style.getFill(); const css::Color * stroke = style.getStroke(); svg::SVGLength strokeWidth = style.getStrokeWidth(); float sw = svglContext->computeWidthLength(strokeWidth); SVGElement * e = dynamic_cast<SVGElement*>(this); if(!e) { std::cerr << "SVGStylable must be an SVGElement in pickTraverse" __FL__; return; } //FIXME if(fill==css::Color::getNoneColor()) fill = 0; // as if it wasn't there... if(stroke==css::Color::getNoneColor()) stroke = 0; // as if it wasn't there... computeGeometryForDrawing(svglContext,glinfo); dom::Document * currentDoc = e->getOwnerDocument(); svg::SVGClipPathElement *clippath_element=0; clippath_element = getSVGClipPathElement(svglContext->externalEntityManager, currentDoc); if(clippath_element) clippath_element->pickTraverse(svglContext, glinfo); glinfo->pushPickInfo(e); if(fill) { glTraverseFill(svglContext, glinfo); } if(stroke) { glTraverseStroke(svglContext, glinfo, sw); } glinfo->popPickInfo(); }
void SVGStylable::glTraverse(svgl::Context * svglContext, svgl::GLInfo* glinfo, bool stencilStrokeHint, bool traverseEvenIfNonVisible) { const css::CSSStyleDeclaration& style = GET_SIMPLE_VAL(Style); const css::Color * fill = style.getFill(); const css::Color * stroke = style.getStroke(); float fillOpacity = style.getFillOpacity(); float strokeOpacity = style.getStrokeOpacity(); float opacity = style.getOpacity(); svg::SVGLength strokeWidth = style.getStrokeWidth(); float sw = svglContext->computeWidthLength(strokeWidth); css::CSSStyle::DisplayType display = style.getDisplay(); //FIXME if(fill==css::Color::getNoneColor()) fill = 0; // as if it wasn't there... if(stroke==css::Color::getNoneColor()) stroke = 0; // as if it wasn't there... if(!display) { return; } computeGeometryForDrawing(svglContext,glinfo); SVGElement * meAsElement = dynamic_cast<SVGElement*>(this); dom::Document * currentDoc = meAsElement->getOwnerDocument(); svg::SVGClipPathElement *clippath_element=0; clippath_element = getSVGClipPathElement(svglContext->externalEntityManager, currentDoc); if(clippath_element) { clippath_element->glPreTraverse(svglContext, glinfo); } SVGFilterElement* filter_element = 0; #if 1 filter_element = getSVGFilterElement(svglContext->externalEntityManager, currentDoc); if(filter_element) filter_element->glPreTraverse(svglContext, glinfo, dynamic_cast<SVGElement*>(this)); #endif if(fill && stroke && opacity<1) { glTraverseOpacity(svglContext, glinfo, fill, stroke, fillOpacity, strokeOpacity, opacity, sw, stencilStrokeHint //, //bbx,bby,bbwidth,bbheight ); } else { float alpha_save = glinfo->alpha; glinfo->alpha *= opacity; #define AA 1 #if AA //#define AA_PRIMITIVE GL_POLYGON_SMOOTH //#define AA_PRIMITIVE GL_MULTISAMPLE_ARB #define AA_PRIMITIVE glinfo->aa_primitive #define AA_PRIMITIVE_HINT GL_POLYGON_SMOOTH_HINT #endif if(fill) { float alpha_save = glinfo->alpha; glinfo->alpha *= fillOpacity; fill->glPreTraverse(svglContext, glinfo, this); if(!stroke && glinfo->doAntiAliasing()) { bool opaque = false; if(glinfo->alpha==1) opaque = true; glinfo->enableAntiAliasing(opaque); } glTraverseFill(svglContext, glinfo); fill->glPostTraverse(svglContext, glinfo, this); if(!stroke && glinfo->doAntiAliasing()) { glinfo->disableAntiAliasing(); } glinfo->alpha = alpha_save; } if(stroke && sw > 0) { float alpha_save = glinfo->alpha; float swon2 = sw/2.; float bbx,bby,bbwidth,bbheight; stencilStrokeHint=1; if(stencilStrokeHint && strokeOpacity<1) { // since stroke pathes may recover themselves (think "8") , we must use stencil #if 1 glinfo->stencilEnableTopAndPush(); #else glinfo->stencilEnableTest(); int& stencil = glinfo->stencil; glStencilFunc(GL_EQUAL, stencil, static_cast<GLuint>(-1)); glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); ++stencil; #endif } glinfo->alpha *= strokeOpacity; stroke->glPreTraverse(svglContext, glinfo, this, sw); if(glinfo->doAntiAliasing()) { bool opaque = false; if(glinfo->alpha==1) opaque = true; glinfo->enableAntiAliasing(opaque); } glTraverseStroke(svglContext, glinfo, sw); if(glinfo->doAntiAliasing()) { glinfo->disableAntiAliasing(); } // remove stencil if(stencilStrokeHint && strokeOpacity<1) { // FIXME, not necessary if stroke is a gradient... // not sure though... getBoundingBox(svglContext, glinfo, &bbx, &bby, &bbwidth, &bbheight); glinfo->stencilPop(); glBegin(GL_QUAD_STRIP); glVertex2f(bbx-swon2,bby-swon2); glVertex2f(bbx-swon2, bby+bbheight+sw); glVertex2f(bbx+bbwidth+sw, bby-swon2); glVertex2f(bbx+bbwidth+sw, bby+bbheight+sw); glEnd(); glinfo->stencilEnableTop(); } stroke->glPostTraverse(svglContext, glinfo, this, sw); glinfo->alpha = alpha_save; #if AA #undef AA_PRIMITIVE #undef AA_PRIMITIVE_HINT #undef AA #endif } glinfo->alpha = alpha_save; } SVGStylable::glTraverseMarker(svglContext, glinfo, sw); if(filter_element) { filter_element->glPostTraverse(svglContext, glinfo, dynamic_cast<SVGElement*>(this)); } if(clippath_element) { clippath_element->glPostTraverse(svglContext, glinfo); } #if 0 // draw bbox //if(glinfo->_has_GL_ARB_imaging) { if(1) { float swon2 = sw/2.; float bbx,bby,bbwidth,bbheight; getBoundingBox(svglContext, glinfo, &bbx, &bby, &bbwidth, &bbheight); glinfo->stencilDisableTest(); glColor4d(0,0,0,1); glBegin(GL_LINE_LOOP); glVertex2f(bbx-swon2,bby-swon2); glVertex2f(bbx-swon2, bby+bbheight+swon2); glVertex2f(bbx+bbwidth+swon2, bby+bbheight+swon2); glVertex2f(bbx+bbwidth+swon2, bby-swon2); glEnd(); glinfo->stencilEnableTest(); } // -- #endif }
void SVGStylable::glTraverseMarker(svgl::Context* svglContext, svgl::GLInfo* glinfo, float shapeStrokeWidth) { SVGElement * meAsElement = dynamic_cast<SVGElement*>(this); dom::Document * currentDoc = meAsElement->getOwnerDocument(); SVGMarkerElement* marker = getSVGMarkerElement(svglContext->externalEntityManager, currentDoc); SVGMarkerElement *marker_start=marker, *marker_end=marker, *marker_mid=marker; marker_start = getSVGMarkerStartElement(svglContext->externalEntityManager, currentDoc); marker_end = getSVGMarkerEndElement(svglContext->externalEntityManager, currentDoc); marker_mid = getSVGMarkerMidElement(svglContext->externalEntityManager, currentDoc); if( !(marker || marker_start || marker_end || marker_mid) ) return; BezierPath bezierpath; asBezier(svglContext, glinfo, &bezierpath); #if 0 SVGStylable* stylable = dynamic_cast<SVGStylable*>(shape); if(!stylable) { std::cerr << "unstylable referring shape for marker " __FL__; return; } #endif SVGStylable* stylable = this; if(!marker_start) { marker_start=marker; } else { css::CSSStyleDeclaration& style = marker_start->getStyle().getValue(); style.setParent(stylable->getStyle().getValue().getParent()); } if(!marker_end) { marker_end=marker; } else { css::CSSStyleDeclaration& style = marker_end->getStyle().getValue(); style.setParent(stylable->getStyle().getValue().getParent()); } if(!marker_mid) { marker_mid=marker; } else { css::CSSStyleDeclaration& style = marker_mid->getStyle().getValue(); style.setParent(stylable->getStyle().getValue().getParent()); } if(marker) { css::CSSStyleDeclaration& style = marker->getStyle().getValue(); style.setParent(stylable->getStyle().getValue().getParent()); } marker=0; glPushMatrix(); for (BezierPath::const_iterator i = bezierpath.begin(); i!=bezierpath.end(); ++i) { if(marker) marker->glTraverseFromUse(svglContext, glinfo, shapeStrokeWidth, 0); switch ( (*i).type() ) { case BezierPath::move: { const BezierPath::Point& p0 = (*i)[0]; glTranslatef(p0.x(), p0.y(), 0); marker = marker_start; } break; case BezierPath::line: { const BezierPath::Point& p0 = (*i)[0]; const BezierPath::Point& p1 = (*i)[1]; BezierPath::Coord dx = p1.x()-p0.x(); BezierPath::Coord dy = p1.y()-p0.y(); glTranslatef(dx, dy, 0); marker = marker_mid; } break; case BezierPath::close: { const BezierPath::Point& p0 = (*i)[0]; const BezierPath::Point& p1 = (*i)[1]; BezierPath::Coord dx = p1.x()-p0.x(); BezierPath::Coord dy = p1.y()-p0.y(); glTranslatef(dx, dy, 0); marker = marker_end; } break; default: STDDBG; break; } } marker=marker_end; if(marker) marker->glTraverseFromUse(svglContext, glinfo, shapeStrokeWidth, 0); glPopMatrix(); }