unsigned SVGPathSegList::getPathSegAtLength(float)
{
    // FIXME : to be useful this will need to support non-normalized SVGPathSegLists
    ExceptionCode ec = 0;
    int len = numberOfItems();
    // FIXME: Eventually this will likely move to a "path applier"-like model, until then PathTraversalState is less useful as we could just use locals
    PathTraversalState traversalState(PathTraversalState::TraversalSegmentAtLength);
    for (int i = 0; i < len; ++i) {
        SVGPathSeg* segment = getItem(i, ec).get();
        float segmentLength = 0;
        switch (segment->pathSegType()) {
        case SVGPathSeg::PATHSEG_MOVETO_ABS:
        {
            SVGPathSegMovetoAbs* moveTo = static_cast<SVGPathSegMovetoAbs*>(segment);
            segmentLength = traversalState.moveTo(FloatPoint(moveTo->x(), moveTo->y()));
            break;
        }
        case SVGPathSeg::PATHSEG_LINETO_ABS:
        {
            SVGPathSegLinetoAbs* lineTo = static_cast<SVGPathSegLinetoAbs*>(segment);
            segmentLength = traversalState.lineTo(FloatPoint(lineTo->x(), lineTo->y()));
            break;
        }
        case SVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
        {
            SVGPathSegCurvetoCubicAbs* curveTo = static_cast<SVGPathSegCurvetoCubicAbs*>(segment);
            segmentLength = traversalState.cubicBezierTo(FloatPoint(curveTo->x1(), curveTo->y1()),
                                      FloatPoint(curveTo->x2(), curveTo->y2()),
                                      FloatPoint(curveTo->x(), curveTo->y()));
            break;
        }
        case SVGPathSeg::PATHSEG_CLOSEPATH:
            segmentLength = traversalState.closeSubpath();
            break;
        default:
            ASSERT(false); // FIXME: This only works with normalized/processed path data.
            break;
        }
        traversalState.m_totalLength += segmentLength;
        if ((traversalState.m_action == PathTraversalState::TraversalSegmentAtLength)
            && (traversalState.m_totalLength > traversalState.m_desiredLength)) {
            return traversalState.m_segmentIndex;
        }
        traversalState.m_segmentIndex++;
    }
    
    return 0; // The SVG spec is unclear as to what to return when the distance is not on the path    
}
Path SVGPathSegList::toPathData()
{
    // FIXME : This should also support non-normalized PathSegLists
    Path pathData;
    ExceptionCode ec = 0;
    int len = numberOfItems();
    for (int i = 0; i < len; ++i) {
        SVGPathSeg* segment = getItem(i, ec).get();;
        switch (segment->pathSegType())
        {
            case SVGPathSeg::PATHSEG_MOVETO_ABS:
            {
                SVGPathSegMovetoAbs* moveTo = static_cast<SVGPathSegMovetoAbs*>(segment);
                pathData.moveTo(FloatPoint(moveTo->x(), moveTo->y()));
                break;
            }
            case SVGPathSeg::PATHSEG_LINETO_ABS:
            {
                SVGPathSegLinetoAbs* lineTo = static_cast<SVGPathSegLinetoAbs*>(segment);
                pathData.addLineTo(FloatPoint(lineTo->x(), lineTo->y()));
                break;
            }
            case SVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
            {
                SVGPathSegCurvetoCubicAbs* curveTo = static_cast<SVGPathSegCurvetoCubicAbs*>(segment);
                pathData.addBezierCurveTo(FloatPoint(curveTo->x1(), curveTo->y1()),
                                          FloatPoint(curveTo->x2(), curveTo->y2()),
                                          FloatPoint(curveTo->x(), curveTo->y()));
                break;
            }
            case SVGPathSeg::PATHSEG_CLOSEPATH:
                pathData.closeSubpath();
                break;
            default:
                ASSERT(false); // FIXME: This only works with normalized/processed path data.
                break;
        }
    }
    
    return pathData;
}
JSValue* JSSVGPathSegCurvetoCubicAbs::getValueProperty(ExecState* exec, int token) const
{
    switch (token) {
    case XAttrNum: {
        SVGPathSegCurvetoCubicAbs* imp = static_cast<SVGPathSegCurvetoCubicAbs*>(impl());

        return jsNumber(imp->x());
    }
    case YAttrNum: {
        SVGPathSegCurvetoCubicAbs* imp = static_cast<SVGPathSegCurvetoCubicAbs*>(impl());

        return jsNumber(imp->y());
    }
    case X1AttrNum: {
        SVGPathSegCurvetoCubicAbs* imp = static_cast<SVGPathSegCurvetoCubicAbs*>(impl());

        return jsNumber(imp->x1());
    }
    case Y1AttrNum: {
        SVGPathSegCurvetoCubicAbs* imp = static_cast<SVGPathSegCurvetoCubicAbs*>(impl());

        return jsNumber(imp->y1());
    }
    case X2AttrNum: {
        SVGPathSegCurvetoCubicAbs* imp = static_cast<SVGPathSegCurvetoCubicAbs*>(impl());

        return jsNumber(imp->x2());
    }
    case Y2AttrNum: {
        SVGPathSegCurvetoCubicAbs* imp = static_cast<SVGPathSegCurvetoCubicAbs*>(impl());

        return jsNumber(imp->y2());
    }
    }
    return 0;
}
void JSSVGPathSegCurvetoCubicAbs::putValueProperty(ExecState* exec, int token, JSValue* value, int /*attr*/)
{
    switch (token) {
    case XAttrNum: {
        SVGPathSegCurvetoCubicAbs* imp = static_cast<SVGPathSegCurvetoCubicAbs*>(impl());

        imp->setX(value->toFloat(exec));
        break;
    }
    case YAttrNum: {
        SVGPathSegCurvetoCubicAbs* imp = static_cast<SVGPathSegCurvetoCubicAbs*>(impl());

        imp->setY(value->toFloat(exec));
        break;
    }
    case X1AttrNum: {
        SVGPathSegCurvetoCubicAbs* imp = static_cast<SVGPathSegCurvetoCubicAbs*>(impl());

        imp->setX1(value->toFloat(exec));
        break;
    }
    case Y1AttrNum: {
        SVGPathSegCurvetoCubicAbs* imp = static_cast<SVGPathSegCurvetoCubicAbs*>(impl());

        imp->setY1(value->toFloat(exec));
        break;
    }
    case X2AttrNum: {
        SVGPathSegCurvetoCubicAbs* imp = static_cast<SVGPathSegCurvetoCubicAbs*>(impl());

        imp->setX2(value->toFloat(exec));
        break;
    }
    case Y2AttrNum: {
        SVGPathSegCurvetoCubicAbs* imp = static_cast<SVGPathSegCurvetoCubicAbs*>(impl());

        imp->setY2(value->toFloat(exec));
        break;
    }
    }
    if (context())
        context()->notifyAttributeChange();
}