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; }
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 fAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.SVGMatrix.f._set"); V8SVGPODTypeWrapper<AffineTransform>* wrapper = V8SVGPODTypeWrapper<AffineTransform>::toNative(info.Holder()); AffineTransform impInstance = *wrapper; AffineTransform* imp = &impInstance; double v = static_cast<double>(value->NumberValue()); imp->setF(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(); }