SVGRect SVGTextQuery::extentOfCharacter(unsigned position) const
{
    if (m_textBoxes.isEmpty())
        return SVGRect();

    ExtentOfCharacterData data(position);
    executeQuery(&data, &SVGTextQuery::extentOfCharacterCallback);
    return data.extent;
}
SVGRect SVGTextContentElement::getExtentOfChar(unsigned charnum, ExceptionState& es)
{
    document().updateLayoutIgnorePendingStylesheets();

    if (charnum > getNumberOfChars()) {
        es.throwUninformativeAndGenericDOMException(IndexSizeError);
        return SVGRect();
    }

    return SVGTextQuery(renderer()).extentOfCharacter(charnum);
}
Exemple #3
0
/* static */
OP_STATUS SVGFilter::FetchValues(SVGFilter* filter, HTML_Element* filter_elm,
                                 SVGElementResolver* resolver, SVGDocumentContext* doc_ctx,
                                 HTML_Element* filter_target_elm,
                                 const SVGValueContext& vcxt, SVGBoundingBox* override_targetbbox)
{
    // Handle filter attributes
    // filterUnits, primitiveUnits, x, y, width, height,
    // filterRes, xlink:href<to other filter>
    // this means we should inherit from the referenced element

    HTML_Element* parent_filter_elm = SVGUtils::FindHrefReferredNode(resolver, doc_ctx, filter_elm);
    if (parent_filter_elm && !parent_filter_elm->IsMatchingType(Markup::SVGE_FILTER, NS_SVG))
        parent_filter_elm = NULL;

    if (parent_filter_elm)
    {
        doc_ctx->RegisterDependency(filter_elm, parent_filter_elm);

        SVGElementResolverStack resolver_mark(resolver);
        RETURN_IF_ERROR(resolver_mark.Push(parent_filter_elm));
        RETURN_IF_ERROR(FetchValues(filter, parent_filter_elm, resolver, doc_ctx, filter_target_elm,
                                    vcxt, override_targetbbox));
    }

    // If this element has no relevant children, and the referenced
    // element does (possibly due to its own href attribute), then
    // this element inherits the children from the referenced element.
    if (parent_filter_elm && !SVGUtils::HasChildren(filter_elm))
    {
        filter->SetChildRoot(filter->GetChildRoot());
    }
    else
    {
        filter->SetChildRoot(filter_elm);
    }

    if (AttrValueStore::HasObject(filter_elm, Markup::SVGA_FILTERUNITS, NS_IDX_SVG))
    {
        SVGUnitsType units;
        OP_STATUS status = AttrValueStore::GetUnits(filter_elm, Markup::SVGA_FILTERUNITS, units, SVGUNITS_OBJECTBBOX);
        if (OpStatus::IsSuccess(status))
            filter->SetFilterUnits(units);
    }

    if (AttrValueStore::HasObject(filter_elm, Markup::SVGA_PRIMITIVEUNITS, NS_IDX_SVG))
    {
        SVGUnitsType units;
        OP_STATUS status = AttrValueStore::GetUnits(filter_elm, Markup::SVGA_PRIMITIVEUNITS, units, SVGUNITS_USERSPACEONUSE);
        if (OpStatus::IsSuccess(status))
            filter->SetPrimitiveUnits(units);
    }

    // Need target bounding box
    SVGBoundingBox bbox;

    if (override_targetbbox)
    {
        bbox = *override_targetbbox;
    }
    else
    {
        SVGNumberPair vp(vcxt.viewport_width, vcxt.viewport_height);
        RETURN_IF_ERROR(GetElementBBox(doc_ctx, filter_target_elm, vp, bbox));
    }

    filter->SetSourceElementBBox(bbox);

    SVGRect filter_region = filter->GetRegionInUnits();
    if (!parent_filter_elm)
    {
        // Set defaults
        filter_region = SVGRect(-0.1, -0.1, 1.2, 1.2);
        if (filter->GetFilterUnits() == SVGUNITS_USERSPACEONUSE)
        {
            filter_region.x *= vcxt.viewport_width;
            filter_region.width *= vcxt.viewport_width;
            filter_region.y *= vcxt.viewport_height;
            filter_region.height *= vcxt.viewport_height;
        }
    }

    SVGUtils::GetResolvedLengthWithUnits(filter_elm, Markup::SVGA_X, SVGLength::SVGLENGTH_X,
                                         filter->GetFilterUnits(), vcxt, filter_region.x);
    SVGUtils::GetResolvedLengthWithUnits(filter_elm, Markup::SVGA_Y, SVGLength::SVGLENGTH_Y,
                                         filter->GetFilterUnits(), vcxt, filter_region.y);
    SVGUtils::GetResolvedLengthWithUnits(filter_elm, Markup::SVGA_WIDTH, SVGLength::SVGLENGTH_X,
                                         filter->GetFilterUnits(), vcxt, filter_region.width);
    SVGUtils::GetResolvedLengthWithUnits(filter_elm, Markup::SVGA_HEIGHT, SVGLength::SVGLENGTH_Y,
                                         filter->GetFilterUnits(), vcxt, filter_region.height);

    // "Negative values for width or height are an error"
    if (filter_region.width < 0 || filter_region.height < 0)
        return OpSVGStatus::INVALID_ARGUMENT;

    // "Zero values disable rendering of the element which referenced the filter."
    if (filter_region.width.Equal(0) || filter_region.height.Equal(0))
        return OpSVGStatus::ELEMENT_IS_INVISIBLE;

    filter->SetRegionInUnits(filter_region);
    if (filter->GetFilterUnits() == SVGUNITS_OBJECTBBOX)
    {
        SVGMatrix bbox_xfrm;

        /* bbox set earlier */
        bbox_xfrm.SetValues(bbox.maxx - bbox.minx, 0, 0,
                            bbox.maxy - bbox.miny,
                            bbox.minx, bbox.miny);

        filter_region = bbox_xfrm.ApplyToRect(filter_region);
    }
    filter->SetFilterRegion(filter_region);

    if (AttrValueStore::HasObject(filter_elm, Markup::SVGA_FILTERRES, NS_IDX_SVG))
    {
        SVGNumberPair filt_res;

        OP_STATUS status = SVGUtils::GetNumberOptionalNumber(filter_elm, Markup::SVGA_FILTERRES, filt_res);
        if (OpStatus::IsSuccess(status))
        {
            // "Negative or zero values disable rendering of the element which referenced the filter."
            if (filt_res.x <= 0 || filt_res.y <= 0)
                return OpSVGStatus::ELEMENT_IS_INVISIBLE;

            filter->SetFilterResolution(filt_res.x, filt_res.y);
        }
    }
    return OpStatus::OK;
}