This source file includes following definitions.
- svgExtensionsFromElement
- m_isInvalidating
- layout
- willBeDestroyed
- styleDidChange
- idChanged
- markAllClientsForInvalidation
- markAllClientLayersForInvalidation
- markClientForInvalidation
- addClient
- removeClient
- addClientRenderLayer
- addClientRenderLayer
- removeClientRenderLayer
- invalidateCacheAndMarkForLayout
- registerResource
- shouldTransformOnTextPainting
- transformOnNonScalingStroke
#include "config.h"
#include "core/rendering/svg/RenderSVGResourceContainer.h"
#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/svg/SVGRenderingContext.h"
#include "core/rendering/svg/SVGResourcesCache.h"
#include "core/svg/SVGGraphicsElement.h"
#include "wtf/TemporaryChange.h"
namespace WebCore {
static inline SVGDocumentExtensions& svgExtensionsFromElement(SVGElement* element)
{
ASSERT(element);
return element->document().accessSVGExtensions();
}
RenderSVGResourceContainer::RenderSVGResourceContainer(SVGElement* node)
: RenderSVGHiddenContainer(node)
, m_isInLayout(false)
, m_id(node->getIdAttribute())
, m_invalidationMask(0)
, m_registered(false)
, m_isInvalidating(false)
{
}
RenderSVGResourceContainer::~RenderSVGResourceContainer()
{
if (m_registered)
svgExtensionsFromElement(element()).removeResource(m_id);
}
void RenderSVGResourceContainer::layout()
{
ASSERT(needsLayout());
if (m_isInLayout)
return;
LayoutRectRecorder recorder(*this);
TemporaryChange<bool> inLayoutChange(m_isInLayout, true);
RenderSVGHiddenContainer::layout();
clearInvalidationMask();
}
void RenderSVGResourceContainer::willBeDestroyed()
{
SVGResourcesCache::resourceDestroyed(this);
RenderSVGHiddenContainer::willBeDestroyed();
}
void RenderSVGResourceContainer::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderSVGHiddenContainer::styleDidChange(diff, oldStyle);
if (!m_registered) {
m_registered = true;
registerResource();
}
}
void RenderSVGResourceContainer::idChanged()
{
removeAllClientsFromCache();
SVGDocumentExtensions& extensions = svgExtensionsFromElement(element());
extensions.removeResource(m_id);
m_id = element()->getIdAttribute();
registerResource();
}
void RenderSVGResourceContainer::markAllClientsForInvalidation(InvalidationMode mode)
{
if ((m_clients.isEmpty() && m_clientLayers.isEmpty()) || m_isInvalidating)
return;
if (m_invalidationMask & mode)
return;
m_invalidationMask |= mode;
m_isInvalidating = true;
bool needsLayout = mode == LayoutAndBoundariesInvalidation;
bool markForInvalidation = mode != ParentOnlyInvalidation;
HashSet<RenderObject*>::iterator end = m_clients.end();
for (HashSet<RenderObject*>::iterator it = m_clients.begin(); it != end; ++it) {
RenderObject* client = *it;
if (client->isSVGResourceContainer()) {
toRenderSVGResourceContainer(client)->removeAllClientsFromCache(markForInvalidation);
continue;
}
if (markForInvalidation)
markClientForInvalidation(client, mode);
RenderSVGResource::markForLayoutAndParentResourceInvalidation(client, needsLayout);
}
markAllClientLayersForInvalidation();
m_isInvalidating = false;
}
void RenderSVGResourceContainer::markAllClientLayersForInvalidation()
{
HashSet<RenderLayer*>::iterator layerEnd = m_clientLayers.end();
for (HashSet<RenderLayer*>::iterator it = m_clientLayers.begin(); it != layerEnd; ++it)
(*it)->filterNeedsRepaint();
}
void RenderSVGResourceContainer::markClientForInvalidation(RenderObject* client, InvalidationMode mode)
{
ASSERT(client);
ASSERT(!m_clients.isEmpty());
switch (mode) {
case LayoutAndBoundariesInvalidation:
case BoundariesInvalidation:
client->setNeedsBoundariesUpdate();
break;
case RepaintInvalidation:
if (client->view()) {
if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && frameView()->isInPerformLayout())
client->setShouldDoFullRepaintAfterLayout(true);
else
client->repaint();
}
break;
case ParentOnlyInvalidation:
break;
}
}
void RenderSVGResourceContainer::addClient(RenderObject* client)
{
ASSERT(client);
m_clients.add(client);
clearInvalidationMask();
}
void RenderSVGResourceContainer::removeClient(RenderObject* client)
{
ASSERT(client);
removeClientFromCache(client, false);
m_clients.remove(client);
}
void RenderSVGResourceContainer::addClientRenderLayer(Node* node)
{
ASSERT(node);
if (!node->renderer() || !node->renderer()->hasLayer())
return;
m_clientLayers.add(toRenderLayerModelObject(node->renderer())->layer());
clearInvalidationMask();
}
void RenderSVGResourceContainer::addClientRenderLayer(RenderLayer* client)
{
ASSERT(client);
m_clientLayers.add(client);
clearInvalidationMask();
}
void RenderSVGResourceContainer::removeClientRenderLayer(RenderLayer* client)
{
ASSERT(client);
m_clientLayers.remove(client);
}
void RenderSVGResourceContainer::invalidateCacheAndMarkForLayout(SubtreeLayoutScope* layoutScope)
{
if (selfNeedsLayout())
return;
setNeedsLayout(MarkContainingBlockChain, layoutScope);
if (everHadLayout())
removeAllClientsFromCache();
}
void RenderSVGResourceContainer::registerResource()
{
SVGDocumentExtensions& extensions = svgExtensionsFromElement(element());
if (!extensions.hasPendingResource(m_id)) {
extensions.addResource(m_id, this);
return;
}
OwnPtr<SVGDocumentExtensions::SVGPendingElements> clients(extensions.removePendingResource(m_id));
extensions.addResource(m_id, this);
const SVGDocumentExtensions::SVGPendingElements::const_iterator end = clients->end();
for (SVGDocumentExtensions::SVGPendingElements::const_iterator it = clients->begin(); it != end; ++it) {
ASSERT((*it)->hasPendingResources());
extensions.clearHasPendingResourcesIfPossible(*it);
RenderObject* renderer = (*it)->renderer();
if (!renderer)
continue;
SVGResourcesCache::clientStyleChanged(renderer, StyleDifferenceLayout, renderer->style());
renderer->setNeedsLayout();
}
}
bool RenderSVGResourceContainer::shouldTransformOnTextPainting(RenderObject* object, AffineTransform& resourceTransform)
{
ASSERT_UNUSED(object, object);
ASSERT(object->isSVGText() || object->isSVGTextPath() || object->isSVGInline());
float scalingFactor = SVGRenderingContext::calculateScreenFontSizeScalingFactor(object);
if (scalingFactor == 1)
return false;
resourceTransform.scale(scalingFactor);
return true;
}
AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderObject* object, const AffineTransform& resourceTransform)
{
if (!object->isSVGShape())
return resourceTransform;
SVGGraphicsElement* element = toSVGGraphicsElement(object->node());
AffineTransform transform = element->getScreenCTM(SVGGraphicsElement::DisallowStyleUpdate);
transform *= resourceTransform;
return transform;
}
}