#include "svgrenderstate.h" namespace lunasvg { SVGBlendInfo::SVGBlendInfo(const SVGElement* element) : m_clipper(element->clipper()) , m_masker(element->masker()) , m_opacity(element->opacity()) { } bool SVGBlendInfo::requiresCompositing(SVGRenderMode mode) const { return (m_clipper && m_clipper->requiresMasking()) || (mode == SVGRenderMode::Painting && (m_masker || m_opacity < 1.f)); } bool SVGRenderState::hasCycleReference(const SVGElement* element) const { auto current = this; do { if(element == current->element()) return true; current = current->parent(); } while(current); return false; } void SVGRenderState::beginGroup(const SVGBlendInfo& blendInfo) { auto requiresCompositing = blendInfo.requiresCompositing(m_mode); if(requiresCompositing) { auto boundingBox = m_currentTransform.mapRect(m_element->paintBoundingBox()); boundingBox.intersect(m_canvas->extents()); m_canvas = Canvas::create(boundingBox); } else { m_canvas->save(); } if(!requiresCompositing && blendInfo.clipper()) { blendInfo.clipper()->applyClipPath(*this); } } void SVGRenderState::endGroup(const SVGBlendInfo& blendInfo) { if(m_canvas == m_parent->canvas()) { m_canvas->restore(); return; } auto opacity = m_mode == SVGRenderMode::Clipping ? 1.f : blendInfo.opacity(); if(blendInfo.clipper()) blendInfo.clipper()->applyClipMask(*this); if(m_mode == SVGRenderMode::Painting && blendInfo.masker()) { blendInfo.masker()->applyMask(*this); } m_parent->m_canvas->blendCanvas(*m_canvas, BlendMode::Src_Over, opacity); } } // namespace lunasvg