void wxSVGAnimateTransformElement::ApplyAnimation() { wxSVGElement* targetElement = GetTargetElement(); if (targetElement == NULL || GetDur() <= 0 || (GetTo().GetPropertyType() != wxSVG_ANIMATED_LENGTH && GetTo().GetPropertyType() != wxSVG_ANIMATED_LENGTH_LIST)) return; wxSVGLengthList values; if (GetCurrentTime() >= GetStartTime() + GetDur()) { if (GetTo().GetPropertyType() == wxSVG_ANIMATED_LENGTH) { values.push_back(GetTo().GetLength()); } else { values = GetTo().GetLengthList(); } } else if (GetCurrentTime() >= GetStartTime() && GetFrom().GetPropertyType() == GetTo().GetPropertyType() && GetFrom().GetLengthList().size() == GetTo().GetLengthList().size()) { if (GetTo().GetPropertyType() == wxSVG_ANIMATED_LENGTH) { values.Add(wxSVGLength(GetTo().GetLength().GetUnitType(), GetFrom().GetLength().GetValue() + (GetTo().GetLength().GetValue() - GetFrom().GetLength().GetValue())* (GetCurrentTime() - GetStartTime())/GetDur())); } else { for (unsigned int i = 0; i < GetFrom().GetLengthList().size(); i++) { const wxSVGLength& from = GetFrom().GetLengthList()[i]; const wxSVGLength& to = GetTo().GetLengthList()[i]; values.Add(wxSVGLength(to.GetUnitType(), from.GetValue() + (to.GetValue() - from.GetValue())*(GetCurrentTime() - GetStartTime())/GetDur())); } } } else { return; } wxSVGTransformable* transformable = wxSVGTransformable::GetSVGTransformable(*targetElement); if (transformable != NULL) { if (m_transformIdx == -1 || m_transformIdx >= (int) transformable->GetTransformList().GetAnimVal().size()) { wxSVGTransformList& transforms = transformable->GetTransformList().GetAnimVal(); if (GetAdditive() != wxSVG_ANIMATION_ADDITIVE_SUM) { transforms.Clear(); } wxSVGTransform* transform = new wxSVGTransform(); UpdateTransform(*transform, GetType(), values); transforms.Add(transform); m_transformIdx = transforms.size() - 1; } else { UpdateTransform(transformable->GetTransformList().GetAnimVal()[m_transformIdx], GetType(), values); } } else { wxSVGTransformList transforms; wxSVGTransform* transform = new wxSVGTransform(); UpdateTransform(*transform, GetType(), values); transforms.Add(transform); targetElement->SetAnimatedValue(GetAttributeName(), wxSVGAnimatedType(transforms)); } }
/** Renders SVG to bitmap image */ wxImage wxSVGDocument::Render(int width, int height, const wxSVGRect* rect, bool preserveAspectRatio, bool alpha, wxProgressDialog* progressDlg) { if (!GetRootElement()) return wxImage(); m_screenCTM = wxSVGMatrix(); if (GetRootElement()->GetWidth().GetBaseVal().GetUnitType() == wxSVG_LENGTHTYPE_UNKNOWN) GetRootElement()->SetWidth(wxSVGLength(wxSVG_LENGTHTYPE_PERCENTAGE, 100)); if (GetRootElement()->GetHeight().GetBaseVal().GetUnitType() == wxSVG_LENGTHTYPE_UNKNOWN) GetRootElement()->SetHeight(wxSVGLength(wxSVG_LENGTHTYPE_PERCENTAGE, 100)); if (width == -1 || height == -1) { width = (int) GetRootElement()->GetWidth().GetAnimVal(); height = (int) GetRootElement()->GetHeight().GetAnimVal(); if (width <= 0 || height <= 0) { width = (int) GetRootElement()->GetViewBox().GetAnimVal().GetWidth(); height = (int) GetRootElement()->GetViewBox().GetAnimVal().GetHeight(); } } if (GetRootElement()->GetWidth().GetAnimVal().GetUnitType() == wxSVG_LENGTHTYPE_PERCENTAGE) { wxSVGAnimatedLength l = GetRootElement()->GetWidth(); l.GetBaseVal().ToViewportWidth(width); if (l.GetBaseVal() != ((const wxSVGAnimatedLength&) l).GetAnimVal()) l.GetAnimVal().ToViewportWidth(width); GetRootElement()->SetWidth(l); } if (GetRootElement()->GetHeight().GetAnimVal().GetUnitType() == wxSVG_LENGTHTYPE_PERCENTAGE) { wxSVGAnimatedLength l = GetRootElement()->GetHeight(); l.GetBaseVal().ToViewportHeight(height); if (l.GetBaseVal() != ((const wxSVGAnimatedLength&) l).GetAnimVal()) l.GetAnimVal().ToViewportHeight(height); GetRootElement()->SetHeight(l); } // scale it to fit in m_scale = 1; m_scaleY = -1; // == m_scale if (GetRootElement()->GetWidth().GetAnimVal() > 0 && GetRootElement()->GetHeight().GetAnimVal() > 0) { if (preserveAspectRatio) { m_scale = width / GetRootElement()->GetWidth().GetAnimVal(); if (m_scale > height / GetRootElement()->GetHeight().GetAnimVal()) m_scale = height / GetRootElement()->GetHeight().GetAnimVal(); m_screenCTM = m_screenCTM.Scale(m_scale); width = (int) (m_scale * GetRootElement()->GetWidth().GetAnimVal()); height = (int) (m_scale * GetRootElement()->GetHeight().GetAnimVal()); } else { m_scale = width / GetRootElement()->GetWidth().GetAnimVal(); m_scaleY = height / GetRootElement()->GetHeight().GetAnimVal(); m_screenCTM = m_screenCTM.ScaleNonUniform(m_scale, m_scaleY); } } // render only rect if specified if (rect && !rect->IsEmpty()) { m_screenCTM = m_screenCTM.Translate(-rect->GetX(), -rect->GetY()); if (rect->GetWidth() * GetScaleX() < width) width = (int) (rect->GetWidth() * GetScaleX()); if (rect->GetHeight() * GetScaleY() < height) height = (int) (rect->GetHeight() * GetScaleY()); } // render m_canvas->Init(width, height, alpha); if (!alpha) m_canvas->Clear(*wxWHITE); GetCanvas()->RenderElement(GetRootElement(), rect, &m_screenCTM, &GetRootElement()->GetStyle(), NULL, NULL, progressDlg); return m_canvas->GetImage(); }
wxSVGLength wxSVGSVGElement::CreateSVGLength() const { return wxSVGLength(); }
void wxSVGCanvas::RenderElement(wxSVGElement* elem, const wxSVGRect* rect, const wxSVGMatrix* parentMatrix, const wxCSSStyleDeclaration* parentStyle, wxSVGSVGElement* ownerSVGElement, wxSVGElement* viewportElement, wxProgressDialog* progressDlg) { wxSVGMatrix matrix(*parentMatrix); wxCSSStyleRef style(*parentStyle); elem->SetOwnerSVGElement(ownerSVGElement); elem->SetViewportElement(viewportElement); switch (elem->GetDtd()) { case wxSVG_SVG_ELEMENT: { wxSVGSVGElement* element = (wxSVGSVGElement*) elem; if (element->GetVisibility() == wxCSS_VALUE_HIDDEN) break; if (element->GetWidth().GetAnimVal().GetUnitType() == wxSVG_LENGTHTYPE_UNKNOWN) ((wxSVGAnimatedLength&) element->GetWidth()).SetAnimVal( wxSVGLength(wxSVG_LENGTHTYPE_PERCENTAGE, 100)); if (element->GetHeight().GetAnimVal().GetUnitType() == wxSVG_LENGTHTYPE_UNKNOWN) ((wxSVGAnimatedLength&) element->GetHeight()).SetAnimVal( wxSVGLength(wxSVG_LENGTHTYPE_PERCENTAGE, 100)); element->UpdateMatrix(matrix); style.Add(element->GetStyle()); style.Add(element->GetAnimStyle()); if (rect && element->GetParent()) { wxSVGRect rect2 = *rect; wxSVGElement* parent = (wxSVGElement*) element->GetParent(); wxSVGTransformable* transformable = wxSVGTransformable::GetSVGTransformable(*parent); if (transformable) rect2 = rect2.MatrixTransform(transformable->GetCTM().Inverse()); RenderChilds(elem, &rect2, &matrix, &style, element, element, progressDlg); } else RenderChilds(elem, rect, &matrix, &style, element, element, progressDlg); break; } case wxSVG_G_ELEMENT: { wxSVGGElement* element = (wxSVGGElement*) elem; if (element->GetVisibility() == wxCSS_VALUE_HIDDEN) break; element->UpdateMatrix(matrix); style.Add(element->GetStyle()); style.Add(element->GetAnimStyle()); RenderChilds(elem, rect, &matrix, &style, ownerSVGElement, viewportElement, progressDlg); break; } case wxSVG_LINE_ELEMENT: { wxSVGLineElement* element = (wxSVGLineElement*) elem; if (element->GetVisibility() == wxCSS_VALUE_HIDDEN) break; element->UpdateMatrix(matrix); style.Add(element->GetStyle()); style.Add(element->GetAnimStyle()); DrawLine(element, &matrix, &style); break; } case wxSVG_POLYLINE_ELEMENT: { wxSVGPolylineElement* element = (wxSVGPolylineElement*) elem; if (element->GetVisibility() == wxCSS_VALUE_HIDDEN) break; element->UpdateMatrix(matrix); style.Add(element->GetStyle()); style.Add(element->GetAnimStyle()); DrawPolyline(element, &matrix, &style); break; } case wxSVG_POLYGON_ELEMENT: { wxSVGPolygonElement* element = (wxSVGPolygonElement*) elem; if (element->GetVisibility() == wxCSS_VALUE_HIDDEN) break; element->UpdateMatrix(matrix); style.Add(element->GetStyle()); style.Add(element->GetAnimStyle()); DrawPolygon(element, &matrix, &style); break; } case wxSVG_RECT_ELEMENT: { wxSVGRectElement* element = (wxSVGRectElement*) elem; if (element->GetVisibility() == wxCSS_VALUE_HIDDEN) break; element->UpdateMatrix(matrix); style.Add(element->GetStyle()); style.Add(element->GetAnimStyle()); DrawRect(element, &matrix, &style); break; } case wxSVG_CIRCLE_ELEMENT: { wxSVGCircleElement* element = (wxSVGCircleElement*) elem; if (element->GetVisibility() == wxCSS_VALUE_HIDDEN) break; element->UpdateMatrix(matrix); style.Add(element->GetStyle()); style.Add(element->GetAnimStyle()); DrawCircle(element, &matrix, &style); break; } case wxSVG_ELLIPSE_ELEMENT: { wxSVGEllipseElement* element = (wxSVGEllipseElement*) elem; if (element->GetVisibility() == wxCSS_VALUE_HIDDEN) break; element->UpdateMatrix(matrix); style.Add(element->GetStyle()); style.Add(element->GetAnimStyle()); DrawEllipse(element, &matrix, &style); break; } case wxSVG_PATH_ELEMENT: { wxSVGPathElement* element = (wxSVGPathElement*) elem; if (element->GetVisibility() == wxCSS_VALUE_HIDDEN) break; element->UpdateMatrix(matrix); style.Add(element->GetStyle()); style.Add(element->GetAnimStyle()); DrawPath(element, &matrix, &style); break; } case wxSVG_TSPAN_ELEMENT: break; case wxSVG_TEXT_ELEMENT: { wxSVGTextElement* element = (wxSVGTextElement*) elem; if (element->GetVisibility() == wxCSS_VALUE_HIDDEN) break; element->UpdateMatrix(matrix); style.Add(element->GetStyle()); style.Add(element->GetAnimStyle()); DrawText(element, &matrix, &style); break; } case wxSVG_IMAGE_ELEMENT: { wxSVGImageElement* element = (wxSVGImageElement*) elem; if (element->GetVisibility() == wxCSS_VALUE_HIDDEN || element->GetOpacity() == 0) break; element->UpdateMatrix(matrix); style.Add(element->GetStyle()); style.Add(element->GetAnimStyle()); DrawImage(element, &matrix, &style, rect, progressDlg); break; } case wxSVG_VIDEO_ELEMENT: { wxSVGVideoElement* element = (wxSVGVideoElement*) elem; if (element->GetVisibility() == wxCSS_VALUE_HIDDEN || element->GetOpacity() == 0) break; element->UpdateMatrix(matrix); style.Add(element->GetStyle()); style.Add(element->GetAnimStyle()); #ifdef USE_LIBAV DrawVideo(element, &matrix, &style); #else wxSVGGElement* gElem = new wxSVGGElement(); gElem->SetOwnerSVGElement(ownerSVGElement); gElem->SetViewportElement(viewportElement); gElem->SetStyle(element->GetStyle()); wxSVGRectElement* rectElem = new wxSVGRectElement(); rectElem->SetX(element->GetX().GetAnimVal()); rectElem->SetY(element->GetY().GetAnimVal()); rectElem->SetWidth(element->GetWidth().GetAnimVal()); rectElem->SetHeight(element->GetHeight().GetAnimVal()); rectElem->SetFill(wxSVGPaint(0,0,0)); gElem->AppendChild(rectElem); wxSVGTextElement* textElem = new wxSVGTextElement; textElem->SetX((double)element->GetX().GetAnimVal()); textElem->SetY(element->GetY().GetAnimVal()+(double)element->GetHeight().GetAnimVal()/10); textElem->SetFontSize((double)element->GetHeight().GetAnimVal()/15); textElem->SetFill(wxSVGPaint(255,255,255)); textElem->SetStroke(wxSVGPaint(255,255,255)); textElem->AddChild(new wxSvgXmlNode(wxSVGXML_TEXT_NODE, wxT(""), wxT(" [") + element->GetHref() + wxT("]"))); gElem->AppendChild(textElem); // render RenderElement(gElem, rect, &matrix, &style, ownerSVGElement, viewportElement, progressDlg); // delete shadow tree delete gElem; #endif break; } case wxSVG_USE_ELEMENT: { wxSVGUseElement* element = (wxSVGUseElement*) elem; if (element->GetVisibility() == wxCSS_VALUE_HIDDEN) break; element->UpdateMatrix(matrix); style.Add(element->GetStyle()); style.Add(element->GetAnimStyle()); // test if visible if (element->GetWidth().GetAnimVal().GetUnitType() != wxSVG_LENGTHTYPE_UNKNOWN && element->GetHeight().GetAnimVal().GetUnitType() != wxSVG_LENGTHTYPE_UNKNOWN) { if (rect && !ownerSVGElement->CheckIntersection(*elem, *rect)) break; wxSVGPoint point(element->GetX().GetAnimVal() + element->GetWidth().GetAnimVal(), element->GetY().GetAnimVal() + element->GetHeight().GetAnimVal()); point = point.MatrixTransform(matrix); if (point.GetX() < 0 || point.GetY() < 0) break; } // get ref element wxString href = element->GetHref(); if (href.length() == 0 || href.GetChar(0) != wxT('#')) break; href.Remove(0, 1); wxSVGElement* refElem = (wxSVGElement*) ownerSVGElement->GetElementById(href); if (!refElem) break; // create shadow tree wxSVGGElement* gElem = new wxSVGGElement(); gElem->SetOwnerDocument(elem->GetOwnerDocument()); gElem->SetOwnerSVGElement(ownerSVGElement); gElem->SetViewportElement(viewportElement); gElem->SetStyle(element->GetStyle()); if (element->GetX().GetAnimVal().GetUnitType() != wxSVG_LENGTHTYPE_UNKNOWN) gElem->Translate(element->GetX().GetAnimVal(), element->GetY().GetAnimVal()); if (refElem->GetDtd() == wxSVG_SYMBOL_ELEMENT || refElem->GetDtd() == wxSVG_SVG_ELEMENT) { wxSVGSVGElement* svgElem; if (refElem->GetDtd() == wxSVG_SVG_ELEMENT) svgElem = (wxSVGSVGElement*) refElem->CloneNode(); else { svgElem = new wxSVGSVGElement(); wxSvgXmlElement* child = refElem->GetChildren(); while (child) { svgElem->AddChild(child->CloneNode()); child = child->GetNext(); } svgElem->SetViewBox(((wxSVGSymbolElement*) refElem)->GetViewBox()); svgElem->SetPreserveAspectRatio(((wxSVGSymbolElement*) refElem)->GetPreserveAspectRatio()); } if (element->GetWidth().GetAnimVal().GetUnitType() != wxSVG_LENGTHTYPE_UNKNOWN) svgElem->SetWidth(element->GetWidth().GetAnimVal()); if (element->GetHeight().GetAnimVal().GetUnitType() != wxSVG_LENGTHTYPE_UNKNOWN) svgElem->SetHeight(element->GetHeight().GetAnimVal()); gElem->AddChild(svgElem); LoadImages(refElem, svgElem, progressDlg); } else gElem->AddChild(refElem->CloneNode()); // render RenderElement(gElem, rect, &matrix, &style, ownerSVGElement, viewportElement, progressDlg); // delete shadow tree delete gElem; break; } default: break; } }