AffineTransform SVGGraphicsElement::animatedLocalTransform() const
{
    AffineTransform matrix;
    RenderStyle* style = renderer() ? &renderer()->style() : nullptr;

    // If CSS property was set, use that, otherwise fallback to attribute (if set).
    if (style && style->hasTransform()) {
        // Note: objectBoundingBox is an emptyRect for elements like pattern or clipPath.
        // See the "Object bounding box units" section of http://dev.w3.org/csswg/css3-transforms/
        TransformationMatrix transform;
        style->applyTransform(transform, renderer()->objectBoundingBox());

        // Flatten any 3D transform.
        matrix = transform.toAffineTransform();
        // CSS bakes the zoom factor into lengths, including translation components.
        // In order to align CSS & SVG transforms, we need to invert this operation.
        float zoom = style->effectiveZoom();
        if (zoom != 1) {
            matrix.setE(matrix.e() / zoom);
            matrix.setF(matrix.f() / zoom);
        }

    } else
        transform().concatenate(matrix);

    if (m_supplementalTransform)
        return *m_supplementalTransform * matrix;
    return matrix;
}
AffineTransform LayoutSVGShape::nonScalingStrokeTransform() const
{
    AffineTransform t = toSVGGraphicsElement(element())->getScreenCTM(SVGGraphicsElement::DisallowStyleUpdate);
    // Width of non-scaling stroke is independent of translation, so zero it out here.
    t.setE(0);
    t.setF(0);
    return t;
}
Beispiel #3
0
static void affineTransformCompose(AffineTransform& m, const double sr[9])
{
    m.setA(sr[3]);
    m.setB(sr[4]);
    m.setC(sr[5]);
    m.setD(sr[6]);
    m.setE(sr[7]);
    m.setF(sr[8]);
    m.rotate(rad2deg(sr[2]));
    m.scale(sr[0], sr[1]);
}
static void eAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
{
    INC_STATS("DOM.SVGMatrix.e._set");
    V8SVGPODTypeWrapper<AffineTransform>* wrapper = V8SVGPODTypeWrapper<AffineTransform>::toNative(info.Holder());
    AffineTransform impInstance = *wrapper;
    AffineTransform* imp = &impInstance;
    double v = static_cast<double>(value->NumberValue());
    imp->setE(v);
    wrapper->commitChange(*imp, V8Proxy::svgContext(wrapper));
    return;
}
static inline void normalizeTransform(AffineTransform& transform)
{
    // Obtain consistent numerical results for the AffineTransform on both 32/64bit platforms.
    // Tested with SnowLeopard on Core Duo vs. Core 2 Duo.
    static const float s_floatEpsilon = std::numeric_limits<float>::epsilon();

    if (fabs(transform.a() - 1) <= s_floatEpsilon)
        transform.setA(1);
    else if (fabs(transform.a() + 1) <= s_floatEpsilon)
        transform.setA(-1);

    if (fabs(transform.d() - 1) <= s_floatEpsilon)
        transform.setD(1);
    else if (fabs(transform.d() + 1) <= s_floatEpsilon)
        transform.setD(-1);

    if (fabs(transform.e()) <= s_floatEpsilon)
        transform.setE(0);

    if (fabs(transform.f()) <= s_floatEpsilon)
        transform.setF(0);
}
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
{
    const FontPlatformData& fontPlatformData = primaryFont()->platformData();
    const float scaleFactor = fontPlatformData.scaleFactor();
    Olympia::Platform::Text::Font* font = fontPlatformData.font(); // FIXME: use fallback fonts as well?
    Olympia::Platform::Text::DrawParam drawParam;

    String sanitized = setupTextDrawing(this, run, &drawParam);
    adjustOffsetsForTextDrawing(run, from, to);

    SurfaceOpenVG* surface = context->platformContext();
    surface->makeCurrent();

    // Before passing control to Text API, make sure we're ok ourselves.
    ASSERT_VG_NO_ERROR();

    PainterOpenVG* painter = surface->activePainter();
    painter->save();
    painter->setStateModified(PainterOpenVG::AllStateCategories);

    Olympia::Platform::Text::GraphicsContext* textContext = FontPlatformData::textGraphicsContext();

#if PLATFORM(EGL)
    textContext->setDisplay(static_cast<Olympia::Platform::Text::NativeGraphicsDisplay>(surface->eglDisplay()));
    textContext->setSurface(static_cast<Olympia::Platform::Text::NativeGraphicsSurface>(surface->eglSurface()));
    textContext->setContext(static_cast<Olympia::Platform::Text::NativeGraphicsContext>(surface->eglContext()));
    ASSERT_EGL_NO_ERROR();
#endif

    if (painter->textDrawingMode() & cTextClip)
        return; // unsupported for every port except CG at the time of writing
    if (!(painter->textDrawingMode() & cTextFill))
        painter->setFillColor(Color::transparent);
    if (!(painter->textDrawingMode() & cTextStroke))
        painter->setStrokeStyle(NoStroke);

    if (from > 0 || to < sanitized.length()) {
        // Clip to the from-to region. We need to draw the full text
        // (and clip) because characters might change appearance when
        // connected to other characters.
        double fromX;
        FontPlatformData::engine()->textPosToX(from, fromX, *font,
            sanitized.characters(), sanitized.length(), drawParam);
        ASSERT_VG_NO_ERROR();
        fromX *= scaleFactor;

        double toX;
        FontPlatformData::engine()->textPosToX(to, toX, *font,
            sanitized.characters(), sanitized.length(), drawParam);
        ASSERT_VG_NO_ERROR();
        toX *= scaleFactor;

        // FIXME: Some glyphs can be higher than primary font's height.
        // We multiply ascent and descent by 4 so the clip rect will be high
        // enough for all glyphs we know. This is safe because we only apply
        // the clip rect when drawing partial strings, and we are only interested
        // in horizontal clip range.
        const float y = point.y() - primaryFont()->ascent() * 4;
        const float height = (primaryFont()->ascent() + primaryFont()->descent()) * 4;
        FloatRect clipRect = (toX > fromX)
            ? FloatRect(point.x() + fromX, y, toX - fromX, height)
            : FloatRect(point.x() + toX, y, fromX - toX, height);

        painter->clipRect(clipRect, PainterOpenVG::IntersectClip);
    }

    AffineTransform transformation = painter->transformation();
    transformation.translate(point.x(), point.y());
    FloatPoint currentTranslation(transformation.e(), transformation.f());
    transformation.setE(0);
    transformation.setF(0);
    transformation.scale(scaleFactor);
    transformation.setE(roundf(currentTranslation.x()));
    transformation.setF(roundf(currentTranslation.y()));
    painter->setTransformation(transformation);

    if (painter->shadowEnabled()) {
        painter->beginDrawShadow();
        FontPlatformData::engine()->drawText(textContext, *font,
            sanitized.characters(), sanitized.length(), 0, 0,
            0 /* no wrap */, &drawParam, 0 /* returned metrics */);
        painter->endDrawShadow();
    }

    FontPlatformData::engine()->drawText(textContext, *font,
        sanitized.characters(), sanitized.length(), 0, 0,
        0 /* no wrap */, &drawParam, 0 /* returned metrics */);

#if PLATFORM(EGL)
    SurfaceOpenVG* sharedSurface = surface->sharedSurface();
    textContext->setDisplay(static_cast<Olympia::Platform::Text::NativeGraphicsDisplay>(sharedSurface->eglDisplay()));
    textContext->setSurface(static_cast<Olympia::Platform::Text::NativeGraphicsSurface>(sharedSurface->eglSurface()));
    textContext->setContext(static_cast<Olympia::Platform::Text::NativeGraphicsContext>(sharedSurface->eglContext()));
    ASSERT_EGL_NO_ERROR();
#endif

    // Let's make sure Text API didn't cause any troubles.
    ASSERT_VG_NO_ERROR();
    painter->restore();
}