KCanvasTreeDebug.cpp [plain text]
#include "config.h"
#if SVG_SUPPORT
#include "KCanvasTreeDebug.h"
#include "HTMLNames.h"
#include "RenderTreeAsText.h"
#include <kcanvas/RenderSVGContainer.h>
#include <kcanvas/device/KRenderingDevice.h>
#include <kcanvas/device/KRenderingFillPainter.h>
#include <kcanvas/device/KRenderingPaintServerGradient.h>
#include <kcanvas/device/KRenderingPaintServerPattern.h>
#include <kcanvas/device/KRenderingPaintServerSolid.h>
#include <kcanvas/device/KRenderingStrokePainter.h>
#include <ksvg2/svg/SVGStyledElement.h>
#include <math.h>
namespace WebCore {
class TextStreamSeparator
{
public:
TextStreamSeparator(const DeprecatedString &s) : m_separator(s), m_needToSeparate(false) {}
private:
friend TextStream& operator<<(TextStream &ts, TextStreamSeparator &sep);
private:
DeprecatedString m_separator;
bool m_needToSeparate;
};
TextStream& operator<<(TextStream &ts, TextStreamSeparator &sep)
{
if (sep.m_needToSeparate)
ts << sep.m_separator;
else
sep.m_needToSeparate = true;
return ts;
}
TextStream &operator<<(TextStream &ts, const IntPoint &p)
{
return ts << "(" << p.x() << "," << p.y() << ")";
}
TextStream &operator<<(TextStream &ts, const IntRect &r)
{
return ts << "at (" << r.x() << "," << r.y() << ") size " << r.width() << "x" << r.height();
}
bool hasFractions(double val)
{
double epsilon = 0.0001;
int ival = int(val);
double dval = double(ival);
return (fabs(val-dval) > epsilon);
}
TextStream &operator<<(TextStream &ts, const FloatRect &r)
{
ts << "at (";
if (hasFractions(r.x()))
ts << r.x();
else
ts << int(r.x());
ts << ",";
if (hasFractions(r.y()))
ts << r.y();
else
ts << int(r.y());
ts << ") size ";
if (hasFractions(r.width()))
ts << r.width();
else
ts << int(r.width());
ts << "x";
if (hasFractions(r.height()))
ts << r.height();
else
ts << int(r.height());
return ts;
}
TextStream &operator<<(TextStream &ts, const FloatPoint &p)
{
ts << "(";
if (hasFractions(p.x()))
ts << p.x();
else
ts << int(p.x());
ts << ",";
if (hasFractions(p.y()))
ts << p.y();
else
ts << int(p.y());
return ts << ")";
}
TextStream &operator<<(TextStream &ts, const FloatSize &s)
{
ts << "width=";
if (hasFractions(s.width()))
ts << s.width();
else
ts << int(s.width());
ts << " height=";
if (hasFractions(s.height()))
ts << s.height();
else
ts << int(s.height());
return ts;
}
TextStream &operator<<(TextStream &ts, const AffineTransform &m)
{
if (m.isIdentity())
ts << "identity";
else
{
ts << "{m=((" << m.m11() << "," << m.m12() << ")(" << m.m21() << "," << m.m22() << "))";
ts << " t=(" << m.dx() << "," << m.dy() << ")}";
}
return ts;
}
TextStream &operator<<(TextStream &ts, const Color &c)
{
return ts << c.name();
}
static void writeIndent(TextStream &ts, int indent)
{
for (int i = 0; i != indent; ++i) {
ts << " ";
}
}
static TextStream &operator<<(TextStream &ts, const KCDashArray &a)
{
ts << "{";
for (KCDashArray::ConstIterator it = a.begin(); it != a.end(); ++it) {
if (it != a.begin())
ts << ", ";
ts << *it;
}
ts << "}";
return ts;
}
static TextStream &operator<<(TextStream &ts, KCCapStyle style)
{
switch (style) {
case CAP_BUTT:
ts << "BUTT"; break;
case CAP_ROUND:
ts << "ROUND"; break;
case CAP_SQUARE:
ts << "SQUARE"; break;
}
return ts;
}
static TextStream &operator<<(TextStream &ts, KCJoinStyle style)
{
switch (style) {
case JOIN_MITER:
ts << "MITER"; break;
case JOIN_ROUND:
ts << "ROUND"; break;
case JOIN_BEVEL:
ts << "BEVEL"; break;
}
return ts;
}
#define DIFFERS_FROM_PARENT(path) (!parentStyle || (parentStyle->path != childStyle->path))
#define DIFFERS_FROM_PARENT_AVOID_TEST_IF_FALSE(pred, path) (!parentStyle || ((!parentStyle->pred) || (parentStyle->path != childStyle->path)))
static void writeStyle(TextStream &ts, const RenderObject &object)
{
const RenderStyle *style = object.style();
const SVGRenderStyle *svgStyle = style->svgStyle();
if (!object.localTransform().isIdentity())
ts << " [transform=" << object.localTransform() << "]";
if (svgStyle->imageRendering() != SVGRenderStyle::initialImageRendering())
ts << " [image rendering=" << svgStyle->imageRendering() << "]";
if (style->opacity() != RenderStyle::initialOpacity())
ts << " [opacity=" << style->opacity() << "]";
if (object.isRenderPath()) {
const RenderPath &path = static_cast<const RenderPath &>(object);
KRenderingPaintServer *strokePaintServer = KSVGPainterFactory::strokePaintServer(style, &path);
if (strokePaintServer) {
TextStreamSeparator s(" ");
ts << " [stroke={";
if (strokePaintServer) {
if (!strokePaintServer->idInRegistry().isEmpty())
ts << s << "[id=\""<< strokePaintServer->idInRegistry() << "\"]";
else
ts << s << *strokePaintServer;
}
KRenderingStrokePainter p = KSVGPainterFactory::strokePainter(style, &path);
if (p.opacity() != 1.0f)
ts << s << "[opacity=" << p.opacity() << "]";
if (p.strokeWidth() != 1.0f)
ts << s << "[stroke width=" << p.strokeWidth() << "]";
if (p.strokeMiterLimit() != 4)
ts << s << "[miter limit=" << p.strokeMiterLimit() << "]";
if (p.strokeCapStyle() != 1)
ts << s << "[line cap=" << p.strokeCapStyle() << "]";
if (p.strokeJoinStyle() != 1)
ts << s << "[line join=" << p.strokeJoinStyle() << "]";
if (p.dashOffset() != 0.0f)
ts << s << "[dash offset=" << p.dashOffset() << "]";
if (!p.dashArray().isEmpty())
ts << s << "[dash array=" << p.dashArray() << "]";
ts << "}]";
}
KRenderingPaintServer *fillPaintServer = KSVGPainterFactory::fillPaintServer(style, &path);
if (fillPaintServer) {
TextStreamSeparator s(" ");
ts << " [fill={";
if (fillPaintServer) {
if (!fillPaintServer->idInRegistry().isEmpty())
ts << s << "[id=\"" << fillPaintServer->idInRegistry() << "\"]";
else
ts << s << *fillPaintServer;
}
KRenderingFillPainter p = KSVGPainterFactory::fillPainter(style, &path);
if (p.opacity() != 1.0f)
ts << s << "[opacity=" << p.opacity() << "]";
if (p.fillRule() != RULE_NONZERO)
ts << s << "[fill rule=" << p.fillRule() << "]";
ts << "}]";
}
}
if (!svgStyle->clipPath().isEmpty())
ts << " [clip path=\"" << svgStyle->clipPath() << "\"]";
if (!svgStyle->startMarker().isEmpty())
ts << " [start marker=" << svgStyle->startMarker() << "]";
if (!svgStyle->midMarker().isEmpty())
ts << " [middle marker=" << svgStyle->midMarker() << "]";
if (!svgStyle->endMarker().isEmpty())
ts << " [end marker=" << svgStyle->endMarker() << "]";
if (!svgStyle->filter().isEmpty())
ts << " [filter=" << svgStyle->filter() << "]";
}
#undef DIFFERS_FROM_PARENT
#undef DIFFERS_FROM_PARENT_AVOID_TEST_IF_FALSE
static TextStream &operator<<(TextStream &ts, const RenderPath &o)
{
ts << " " << o.absoluteTransform().mapRect(o.relativeBBox());
writeStyle(ts, o);
ts << " [data=\"" << renderingDevice()->stringForPath(o.path()) << "\"]";
return ts;
}
static TextStream &operator<<(TextStream &ts, const RenderSVGContainer &o)
{
ts << " " << o.absoluteTransform().mapRect(o.relativeBBox());
writeStyle(ts, o);
return ts;
}
static DeprecatedString getTagName(void *node)
{
SVGStyledElement *elem = static_cast<SVGStyledElement *>(node);
if (elem)
return String(elem->nodeName()).deprecatedString();
return DeprecatedString();
}
void write(TextStream &ts, const RenderSVGContainer &container, int indent)
{
writeIndent(ts, indent);
ts << container.renderName();
if (container.element()) {
DeprecatedString tagName = getTagName(container.element());
if (!tagName.isEmpty())
ts << " {" << tagName << "}";
}
ts << container << endl;
for (RenderObject *child = container.firstChild(); child != NULL; child = child->nextSibling())
write(ts, *child, indent + 1);
}
void write(TextStream &ts, const RenderPath &path, int indent)
{
writeIndent(ts, indent);
ts << path.renderName();
if (path.element()) {
DeprecatedString tagName = getTagName(path.element());
if (!tagName.isEmpty())
ts << " {" << tagName << "}";
}
ts << path << endl;
}
void writeRenderResources(TextStream &ts, Node *parent)
{
ASSERT(parent);
Node *node = parent;
do {
if (!node->isSVGElement())
continue;
SVGElement *svgElement = static_cast<SVGElement *>(node);
if (!svgElement->isStyled())
continue;
SVGStyledElement *styled = static_cast<SVGStyledElement *>(svgElement);
KCanvasResource *resource = styled->canvasResource();
if (!resource)
continue;
DeprecatedString elementId = svgElement->getAttribute(HTMLNames::idAttr).deprecatedString();
if (resource->isPaintServer())
ts << "KRenderingPaintServer {id=\"" << elementId << "\" " << *static_cast<KRenderingPaintServer *>(resource) << "}" << endl;
else
ts << "KCanvasResource {id=\"" << elementId << "\" " << *resource << "}" << endl;
} while ((node = node->traverseNextNode(parent)));
}
TextStream &operator<<(TextStream &ts, const DeprecatedStringList &l)
{
ts << "[";
DeprecatedStringList::ConstIterator it = l.begin();
DeprecatedStringList::ConstIterator it_e = l.end();
while (it != it_e)
{
ts << *it;
++it;
if (it != it_e) ts << ", ";
}
ts << "]";
return ts;
}
}
#endif // SVG_SUPPORT