AffineTransform SVGSVGElement::getScreenCTM() const { // FIXME: This assumes that any <svg> element not immediately descending from another SVGElement // has *no* svg ancestors document()->updateLayoutIgnorePendingStylesheets(); float rootX = 0.0f; float rootY = 0.0f; if (RenderObject* renderer = this->renderer()) { renderer = renderer->parent(); if (renderer && !(renderer->element() && renderer->element()->isSVGElement())) { int tx = 0; int ty = 0; renderer->absolutePosition(tx, ty, true); rootX += tx; rootY += ty; } else { rootX += x().value(); rootY += y().value(); } } AffineTransform mat = SVGStyledLocatableElement::getScreenCTM(); mat.translate(rootX, rootY); if (attributes()->getNamedItem(SVGNames::viewBoxAttr)) { AffineTransform viewBox = viewBoxToViewTransform(width().value(), height().value()); mat = viewBox * mat; } return mat; }
TransformationMatrix SVGSVGElement::getScreenCTM() const { document()->updateLayoutIgnorePendingStylesheets(); FloatPoint rootLocation; if (RenderObject* renderer = this->renderer()) { if (isOutermostSVG()) { // FIXME: This doesn't work correctly with CSS transforms. FloatPoint point; if (renderer->parent()) point = renderer->localToAbsolute(point, true); rootLocation.move(point.x(), point.y()); } else rootLocation.move(x().value(this), y().value(this)); } TransformationMatrix mat = SVGStyledLocatableElement::getScreenCTM(); mat.translate(rootLocation.x(), rootLocation.y()); if (attributes()->getAttributeItem(SVGNames::viewBoxAttr)) { TransformationMatrix viewBox = viewBoxToViewTransform(width().value(this), height().value(this)); mat = viewBox * mat; } return mat; }
AffineTransform SVGSVGElement::localCoordinateSpaceTransform(SVGLocatable::CTMScope mode) const { AffineTransform viewBoxTransform; if (attributes()->getAttributeItem(SVGNames::viewBoxAttr)) viewBoxTransform = viewBoxToViewTransform(width().value(this), height().value(this)); AffineTransform transform; if (!isOutermostSVG()) transform.translate(x().value(this), y().value(this)); else if (mode == SVGLocatable::ScreenScope) { if (RenderObject* renderer = this->renderer()) { // Translate in our CSS parent coordinate space // FIXME: This doesn't work correctly with CSS transforms. FloatPoint location = renderer->localToAbsolute(FloatPoint(), false, true); // Be careful here! localToAbsolute() includes the x/y offset coming from the viewBoxToViewTransform(), because // RenderSVGRoot::localToBorderBoxTransform() (called through mapLocalToContainer(), called from localToAbsolute()) // also takes the viewBoxToViewTransform() into account, so we have to subtract it here (original cause of bug #27183) transform.translate(location.x() - viewBoxTransform.e(), location.y() - viewBoxTransform.f()); // Respect scroll offset. if (FrameView* view = document()->view()) { IntSize scrollOffset = view->scrollOffset(); transform.translate(-scrollOffset.width(), -scrollOffset.height()); } } } return transform.multLeft(viewBoxTransform); }
KCanvasMarker *SVGMarkerElement::canvasResource() { if(!m_marker) m_marker = static_cast<KCanvasMarker *>(renderingDevice()->createResource(RS_MARKER)); m_marker->setMarker(renderer()); // Spec: If the attribute is not specified, the effect is as if a // value of "0" were specified. if(!m_orientType) { SVGAngle *angle = SVGSVGElement::createSVGAngle(); angle->setValueAsString(String("0").impl()); setOrientToAngle(angle); } if(orientType()->baseVal() == SVG_MARKER_ORIENT_ANGLE) m_marker->setAngle(orientAngle()->baseVal()->value()); else m_marker->setAutoAngle(); m_marker->setRef(refX()->baseVal()->value(), refY()->baseVal()->value()); m_marker->setUseStrokeWidth(markerUnits()->baseVal() == SVG_MARKERUNITS_STROKEWIDTH); double w = markerWidth()->baseVal()->value(); double h = markerHeight()->baseVal()->value(); RefPtr<SVGMatrix> viewBox = viewBoxToViewTransform(w, h); m_marker->setScale(viewBox->matrix().m11(), viewBox->matrix().m22()); return m_marker; }
FloatRect SVGSVGElement::viewport() const { FloatRect viewRectangle; if (!isOutermostSVG()) viewRectangle.setLocation(FloatPoint(x().value(this), y().value(this))); viewRectangle.setSize(FloatSize(width().value(this), height().value(this))); return viewBoxToViewTransform(viewRectangle.width(), viewRectangle.height()).mapRect(viewRectangle); }
FloatRect SVGSVGElement::viewport() const { // FIXME: This method doesn't follow the spec and is basically untested. Parent documents are not considered here. SVGLengthContext lengthContext(this); FloatRect viewRectangle; if (!isOutermostSVG()) viewRectangle.setLocation(FloatPoint(x().value(lengthContext), y().value(lengthContext))); viewRectangle.setSize(FloatSize(width().value(lengthContext), height().value(lengthContext))); return viewBoxToViewTransform(viewRectangle.width(), viewRectangle.height()).mapRect(viewRectangle); }
AffineTransform SVGSVGElement::localCoordinateSpaceTransform( SVGElement::CTMScope mode) const { AffineTransform viewBoxTransform; if (!hasEmptyViewBox()) { FloatSize size = currentViewportSize(); viewBoxTransform = viewBoxToViewTransform(size.width(), size.height()); } AffineTransform transform; if (!isOutermostSVGSVGElement()) { SVGLengthContext lengthContext(this); transform.translate(m_x->currentValue()->value(lengthContext), m_y->currentValue()->value(lengthContext)); } else if (mode == SVGElement::ScreenScope) { if (LayoutObject* layoutObject = this->layoutObject()) { FloatPoint location; float zoomFactor = 1; // At the SVG/HTML boundary (aka LayoutSVGRoot), we apply the // localToBorderBoxTransform to map an element from SVG viewport // coordinates to CSS box coordinates. LayoutSVGRoot's localToAbsolute // method expects CSS box coordinates. We also need to adjust for the // zoom level factored into CSS coordinates (bug #96361). if (layoutObject->isSVGRoot()) { location = toLayoutSVGRoot(layoutObject) ->localToBorderBoxTransform() .mapPoint(location); zoomFactor = 1 / layoutObject->style()->effectiveZoom(); } // Translate in our CSS parent coordinate space // FIXME: This doesn't work correctly with CSS transforms. location = layoutObject->localToAbsolute(location, UseTransforms); location.scale(zoomFactor, zoomFactor); // Be careful here! localToBorderBoxTransform() included the x/y offset // coming from the viewBoxToViewTransform(), so we have to subtract it // here (original cause of bug #27183) transform.translate(location.x() - viewBoxTransform.e(), location.y() - viewBoxTransform.f()); // Respect scroll offset. if (FrameView* view = document().view()) { LayoutSize scrollOffset(view->getScrollOffset()); scrollOffset.scale(zoomFactor); transform.translate(-scrollOffset.width(), -scrollOffset.height()); } } } return transform.multiply(viewBoxTransform); }
TransformationMatrix SVGSVGElement::getCTM() const { TransformationMatrix mat; if (!isOutermostSVG()) mat.translate(x().value(this), y().value(this)); if (attributes()->getAttributeItem(SVGNames::viewBoxAttr)) { TransformationMatrix viewBox = viewBoxToViewTransform(width().value(this), height().value(this)); mat = viewBox * mat; } return mat; }
SVGMatrix *SVGPatternElement::getCTM() const { SVGMatrix *mat = SVGSVGElement::createSVGMatrix(); if (mat) { RefPtr<SVGMatrix> viewBox = viewBoxToViewTransform(width()->baseVal()->value(), height()->baseVal()->value()); mat->multiply(viewBox.get()); } return mat; }
AffineTransform SVGSVGElement::getCTM() const { AffineTransform mat; if (renderer() && renderer()->parent() && !renderer()->parent()->isSVGContainer()) mat.translate(x().value(), y().value()); if (attributes()->getNamedItem(SVGNames::viewBoxAttr)) { AffineTransform viewBox = viewBoxToViewTransform(width().value(), height().value()); mat = viewBox * mat; } return mat; }
FloatRect SVGSVGElement::viewport() const { double _x = 0.0; double _y = 0.0; if (!isOutermostSVG()) { _x = x().value(this); _y = y().value(this); } float w = width().value(this); float h = height().value(this); AffineTransform viewBox = viewBoxToViewTransform(w, h); double wDouble = w; double hDouble = h; viewBox.map(_x, _y, _x, _y); viewBox.map(w, h, wDouble, hDouble); return FloatRect::narrowPrecision(_x, _y, wDouble, hDouble); }
AffineTransform SVGSVGElement::localCoordinateSpaceTransform(SVGLocatable::CTMScope mode) const { AffineTransform viewBoxTransform; if (!hasEmptyViewBox()) { FloatSize size = currentViewportSize(); viewBoxTransform = viewBoxToViewTransform(size.width(), size.height()); } AffineTransform transform; if (!isOutermostSVGSVGElement()) { SVGLengthContext lengthContext(this); transform.translate(x().value(lengthContext), y().value(lengthContext)); } else if (mode == SVGLocatable::ScreenScope) { if (auto* renderer = this->renderer()) { FloatPoint location; float zoomFactor = 1; // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform // to map an element from SVG viewport coordinates to CSS box coordinates. // RenderSVGRoot's localToAbsolute method expects CSS box coordinates. // We also need to adjust for the zoom level factored into CSS coordinates (bug #96361). if (is<RenderSVGRoot>(*renderer)) { location = downcast<RenderSVGRoot>(*renderer).localToBorderBoxTransform().mapPoint(location); zoomFactor = 1 / renderer->style().effectiveZoom(); } // Translate in our CSS parent coordinate space // FIXME: This doesn't work correctly with CSS transforms. location = renderer->localToAbsolute(location, UseTransforms); location.scale(zoomFactor); // Be careful here! localToBorderBoxTransform() included the x/y offset coming from the viewBoxToViewTransform(), // so we have to subtract it here (original cause of bug #27183) transform.translate(location.x() - viewBoxTransform.e(), location.y() - viewBoxTransform.f()); // Respect scroll offset. if (FrameView* view = document().view()) { LayoutPoint scrollPosition = view->scrollPosition(); scrollPosition.scale(zoomFactor); transform.translate(-scrollPosition.x(), -scrollPosition.y()); } } } return transform.multiply(viewBoxTransform); }
FloatRect SVGSVGElement::viewport() const { double _x = 0.0; double _y = 0.0; if (renderer() && renderer()->parent() && !renderer()->parent()->isSVGContainer()) { _x = x().value(); _y = y().value(); } float w = width().value(); float h = height().value(); AffineTransform viewBox = viewBoxToViewTransform(w, h); double wDouble = w; double hDouble = h; viewBox.map(_x, _y, &_x, &_y); viewBox.map(w, h, &wDouble, &hDouble); return FloatRect::narrowPrecision(_x, _y, wDouble, hDouble); }
AffineTransform SVGSVGElement::localCoordinateSpaceTransform(SVGLocatable::CTMScope mode) const { AffineTransform viewBoxTransform; if (hasAttribute(SVGNames::viewBoxAttr)) { FloatSize size = currentViewportSize(); viewBoxTransform = viewBoxToViewTransform(size.width(), size.height()); } AffineTransform transform; if (!isOutermostSVGSVGElement()) { SVGLengthContext lengthContext(this); transform.translate(x().value(lengthContext), y().value(lengthContext)); } else if (mode == SVGLocatable::ScreenScope) { if (RenderObject* renderer = this->renderer()) { FloatPoint location; // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform // to map an element from SVG viewport coordinates to CSS box coordinates. // RenderSVGRoot's localToAbsolute method expects CSS box coordinates. if (renderer->isSVGRoot()) location = toRenderSVGRoot(renderer)->localToBorderBoxTransform().mapPoint(location); // Translate in our CSS parent coordinate space // FIXME: This doesn't work correctly with CSS transforms. location = renderer->localToAbsolute(location, false, true); // Be careful here! localToBorderBoxTransform() included the x/y offset coming from the viewBoxToViewTransform(), // so we have to subtract it here (original cause of bug #27183) transform.translate(location.x() - viewBoxTransform.e(), location.y() - viewBoxTransform.f()); // Respect scroll offset. if (FrameView* view = document()->view()) { LayoutSize scrollOffset = view->scrollOffset(); transform.translate(-scrollOffset.width(), -scrollOffset.height()); } } } return transform.multiply(viewBoxTransform); }