void GLUtils::convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix) { transformMatrix.setMatrix( matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5], matrix[6], matrix[7], matrix[8], matrix[9], matrix[10], matrix[11], matrix[12], matrix[13], matrix[14], matrix[15]); }
void TextureMapperLayer::paintRecursive(const TextureMapperPaintOptions& options) { if (!isVisible()) return; float opacity = options.opacity * m_opacity; RefPtr<BitmapTexture> maskTexture = m_state.maskLayer ? m_state.maskLayer->texture() : 0; TextureMapperPaintOptions paintOptions(options); paintOptions.mask = maskTexture.get(); if (!shouldPaintToIntermediateSurface()) { paintOptions.opacity = opacity; paintSelfAndChildrenWithReplica(paintOptions); return; } // Prepare a surface to paint into. // We paint into the surface ignoring the opacity/transform of the current layer. IntRect surfaceRect = intermediateSurfaceRect(); RefPtr<BitmapTexture> surface = options.textureMapper->acquireTextureFromPool(surfaceRect.size()); paintOptions.surface = surface; options.textureMapper->bindSurface(surface.get()); paintOptions.opacity = 1; paintOptions.transform = m_transform.combined().inverse(); paintOptions.offset = -IntSize(surfaceRect.x(), surfaceRect.y()); paintSelfAndChildrenWithReplica(paintOptions); // If we painted the replica, the mask is already applied so we don't need to paint it again. if (m_state.replicaLayer) maskTexture = 0; #if ENABLE(CSS_FILTERS) surface = applyFilters(m_filters, options.textureMapper, surface.get(), surfaceRect); #endif options.textureMapper->bindSurface(options.surface.get()); TransformationMatrix targetTransform; targetTransform.translate(options.offset.width(), options.offset.height()); targetTransform.multiply(options.transform); targetTransform.multiply(m_transform.combined()); options.textureMapper->drawTexture(*surface.get(), surfaceRect, targetTransform, opacity, maskTexture.get()); }
bool AnimationBase::computeTransformedExtentViaMatrix(const FloatRect& rendererBox, const RenderStyle& style, LayoutRect& bounds) const { TransformationMatrix transform; style.applyTransform(transform, rendererBox, RenderStyle::IncludeTransformOrigin); if (!transform.isAffine()) return false; TransformationMatrix::Decomposed2Type fromDecomp; transform.decompose2(fromDecomp); // Any rotation prevents us from using a simple start/end rect union. if (fromDecomp.angle) return false; bounds = LayoutRect(transform.mapRect(bounds)); return true; }
FloatRect SVGSVGElement::viewport() const { double _x = 0.0; double _y = 0.0; if (!isOutermostSVG()) { _x = x().value(this); _y = y().value(this); } float w = width().value(this); float h = height().value(this); TransformationMatrix viewBox = viewBoxToViewTransform(w, h); double wDouble = w; double hDouble = h; viewBox.map(_x, _y, _x, _y); viewBox.map(w, h, wDouble, hDouble); return FloatRect::narrowPrecision(_x, _y, wDouble, hDouble); }
static inline TransformationMatrix contentToScreenSpaceTransform(const LayerType* layer) { ASSERT(layerTransformsToScreenKnown(layer)); IntSize boundsInLayerSpace = layer->bounds(); IntSize boundsInContentSpace = layer->contentBounds(); TransformationMatrix transform = layer->screenSpaceTransform(); if (boundsInContentSpace.isEmpty()) return transform; // Scale from content space to layer space transform.scaleNonUniform(boundsInLayerSpace.width() / static_cast<double>(boundsInContentSpace.width()), boundsInLayerSpace.height() / static_cast<double>(boundsInContentSpace.height())); return transform; }
IntRect LayerWebKitThread::mapFromTransformed(const IntRect& contentsRect, double scale) { IntRect untransformedContentsRect = contentsRect; if (scale != 1.0) { TransformationMatrix matrix; matrix.scale(1.0 / scale); untransformedContentsRect = matrix.mapRect(contentsRect); // We extract from the contentsRect but draw a slightly larger region than // we were told to, in order to avoid pixels being rendered only partially. const int atLeastOneDevicePixel = static_cast<int>(ceilf(1.0 / scale)); untransformedContentsRect.inflate(atLeastOneDevicePixel); } return untransformedContentsRect; }
void CustomFilterRenderer::bindProgramTransformParameter(int uniformLocation, CustomFilterTransformParameter* transformParameter) { TransformationMatrix matrix; if (m_contextSize.width() && m_contextSize.height()) { // The viewport is a box with the size of 1 unit, so we are scaling up here to make sure that translations happen using real pixel // units. At the end we scale back down in order to map it back to the original box. Note that transforms come in reverse order, because it is // supposed to multiply to the left of the coordinates of the vertices. // Note that the origin (0, 0) of the viewport is in the middle of the context, so there's no need to change the origin of the transform // in order to rotate around the middle of mesh. matrix.scale3d(1.0 / m_contextSize.width(), 1.0 / m_contextSize.height(), 1); transformParameter->applyTransform(matrix, m_contextSize); matrix.scale3d(m_contextSize.width(), m_contextSize.height(), 1); } float glMatrix[16]; matrix.toColumnMajorFloatArray(glMatrix); m_context->uniformMatrix4fv(uniformLocation, 1, false, &glMatrix[0]); }
void TextureMapperLayer::paintSelf(const TextureMapperPaintOptions& options) { if (!m_state.visible || !m_state.contentsVisible) return; // We apply the following transform to compensate for painting into a surface, and then apply the offset so that the painting fits in the target rect. TransformationMatrix transform; transform.translate(options.offset.width(), options.offset.height()); transform.multiply(options.transform); transform.multiply(m_currentTransform.combined()); if (m_state.solidColor.isValid() && !m_state.contentsRect.isEmpty() && m_state.solidColor.alpha()) { options.textureMapper->drawSolidColor(m_state.contentsRect, transform, blendWithOpacity(m_state.solidColor, options.opacity)); if (m_state.showDebugBorders) options.textureMapper->drawBorder(m_state.debugBorderColor, m_state.debugBorderWidth, layerRect(), transform); return; } options.textureMapper->setWrapMode(TextureMapper::StretchWrap); options.textureMapper->setPatternTransform(TransformationMatrix()); if (m_backingStore) { FloatRect targetRect = layerRect(); ASSERT(!targetRect.isEmpty()); m_backingStore->paintToTextureMapper(options.textureMapper, targetRect, transform, options.opacity); if (m_state.showDebugBorders) m_backingStore->drawBorder(options.textureMapper, m_state.debugBorderColor, m_state.debugBorderWidth, targetRect, transform); // Only draw repaint count for the main backing store. if (m_state.showRepaintCounter) m_backingStore->drawRepaintCounter(options.textureMapper, m_state.repaintCount, m_state.debugBorderColor, targetRect, transform); } if (!m_contentsLayer) return; if (!m_state.contentsTileSize.isEmpty()) { computePatternTransformIfNeeded(); options.textureMapper->setWrapMode(TextureMapper::RepeatWrap); options.textureMapper->setPatternTransform(m_patternTransform); } ASSERT(!layerRect().isEmpty()); m_contentsLayer->paintToTextureMapper(options.textureMapper, m_state.contentsRect, transform, options.opacity); if (m_state.showDebugBorders) m_contentsLayer->drawBorder(options.textureMapper, m_state.debugBorderColor, m_state.debugBorderWidth, m_state.contentsRect, transform); }
TransformationMatrix TiledLayerChromium::tilingTransform() const { TransformationMatrix transform = drawTransform(); if (contentBounds().isEmpty()) return transform; transform.scaleNonUniform(bounds().width() / static_cast<double>(contentBounds().width()), bounds().height() / static_cast<double>(contentBounds().height())); // Tiler draws with a different origin from other layers. transform.translate(-contentBounds().width() / 2.0, -contentBounds().height() / 2.0); transform.translate(-scrollPosition().x(), -scrollPosition().y()); return transform; }
TransformOperations TransformOperations::blendByUsingMatrixInterpolation(const TransformOperations& from, double progress, const LayoutSize& size) const { TransformOperations result; // Convert the TransformOperations into matrices TransformationMatrix fromTransform; TransformationMatrix toTransform; from.apply(size, fromTransform); apply(size, toTransform); toTransform.blend(fromTransform, progress); // Append the result result.operations().append(Matrix3DTransformOperation::create(toTransform)); return result; }
void TextureMapperLayer::paintSelf(const TextureMapperPaintOptions& options) { // We apply the following transform to compensate for painting into a surface, and then apply the offset so that the painting fits in the target rect. TransformationMatrix transform; transform.translate(options.offset.width(), options.offset.height()); transform.multiply(options.transform); transform.multiply(m_transform.combined()); float opacity = options.opacity; RefPtr<BitmapTexture> mask = options.mask; if (m_backingStore) m_backingStore->paintToTextureMapper(options.textureMapper, layerRect(), transform, opacity, mask.get()); if (m_contentsLayer) m_contentsLayer->paintToTextureMapper(options.textureMapper, m_state.contentsRect, transform, opacity, mask.get()); }
bool AnimationBase::computeTransformedExtentViaTransformList(const FloatRect& rendererBox, const RenderStyle& style, LayoutRect& bounds) const { FloatRect floatBounds = bounds; FloatPoint transformOrigin; bool applyTransformOrigin = containsRotation(style.transform().operations()) || style.transform().affectedByTransformOrigin(); if (applyTransformOrigin) { float offsetX = style.transformOriginX().isPercent() ? rendererBox.x() : 0; float offsetY = style.transformOriginY().isPercent() ? rendererBox.y() : 0; transformOrigin.setX(floatValueForLength(style.transformOriginX(), rendererBox.width()) + offsetX); transformOrigin.setY(floatValueForLength(style.transformOriginY(), rendererBox.height()) + offsetY); // Ignore transformOriginZ because we'll bail if we encounter any 3D transforms. floatBounds.moveBy(-transformOrigin); } for (const auto& operation : style.transform().operations()) { if (operation->type() == TransformOperation::ROTATE) { // For now, just treat this as a full rotation. This could take angle into account to reduce inflation. floatBounds = boundsOfRotatingRect(floatBounds); } else { TransformationMatrix transform; operation->apply(transform, rendererBox.size()); if (!transform.isAffine()) return false; if (operation->type() == TransformOperation::MATRIX || operation->type() == TransformOperation::MATRIX_3D) { TransformationMatrix::Decomposed2Type toDecomp; transform.decompose2(toDecomp); // Any rotation prevents us from using a simple start/end rect union. if (toDecomp.angle) return false; } floatBounds = transform.mapRect(floatBounds); } } if (applyTransformOrigin) floatBounds.moveBy(transformOrigin); bounds = LayoutRect(floatBounds); return true; }
bool GLUtils::has3dTransform(const TransformationMatrix& matrix) { return matrix.m13() != 0 || matrix.m23() != 0 || matrix.m31() != 0 || matrix.m32() != 0 || matrix.m33() != 1 || matrix.m34() != 0 || matrix.m43() != 0; }
static inline TransformationMatrix clipToTextMask(GraphicsContext* context, OwnPtr<ImageBuffer>& imageBuffer, const RenderObject* object, const SVGPaintServerGradient* gradientServer) { FloatRect maskBBox = const_cast<RenderObject*>(findTextRootObject(object))->objectBoundingBox(); // Fixup transformations to be able to clip to mask TransformationMatrix transform = object->absoluteTransform(); FloatRect textBoundary = transform.mapRect(maskBBox); IntSize maskSize(lroundf(textBoundary.width()), lroundf(textBoundary.height())); clampImageBufferSizeToViewport(object->view()->frameView(), maskSize); textBoundary.setSize(textBoundary.size().shrunkTo(maskSize)); // Clip current context to mask image (gradient) context->concatCTM(transform.inverse()); context->clipToImageBuffer(textBoundary, imageBuffer.get()); context->concatCTM(transform); TransformationMatrix matrix; if (gradientServer->boundingBoxMode()) { matrix.translate(maskBBox.x(), maskBBox.y()); matrix.scaleNonUniform(maskBBox.width(), maskBBox.height()); } matrix.multiply(gradientServer->gradientTransform()); return matrix; }
void ContentLayerChromium::calculateClippedUpdateRect(IntRect& dirtyRect, IntRect& drawRect) const { // For the given layer size and content rect, calculate: // 1) The minimal texture space rectangle to be uploaded, returned in dirtyRect. // 2) The rectangle to draw this texture in relative to the target render surface, returned in drawRect. ASSERT(m_targetRenderSurface); const IntRect clipRect = m_targetRenderSurface->contentRect(); TransformationMatrix layerOriginTransform = drawTransform(); layerOriginTransform.translate3d(-0.5 * m_bounds.width(), -0.5 * m_bounds.height(), 0); // For now we apply the large layer treatment only for layers that are either untransformed // or are purely translated. Their matrix is expected to be invertible. ASSERT(layerOriginTransform.isInvertible()); TransformationMatrix targetToLayerMatrix = layerOriginTransform.inverse(); IntRect clipRectInLayerCoords = targetToLayerMatrix.mapRect(clipRect); clipRectInLayerCoords.intersect(IntRect(0, 0, m_bounds.width(), m_bounds.height())); dirtyRect = clipRectInLayerCoords; // Map back to the target surface coordinate system. drawRect = layerOriginTransform.mapRect(dirtyRect); }
void LayoutGeometryMap::push(const LayoutObject* layoutObject, const TransformationMatrix& t, GeometryInfoFlags flags, LayoutSize offsetForFixedPosition) { ASSERT(m_insertionPosition != kNotFound); ASSERT(!layoutObject->isLayoutView() || !m_insertionPosition || m_mapCoordinatesFlags & TraverseDocumentBoundaries); ASSERT(offsetForFixedPosition.isZero() || layoutObject->isLayoutView()); m_mapping.insert(m_insertionPosition, LayoutGeometryMapStep(layoutObject, flags)); LayoutGeometryMapStep& step = m_mapping[m_insertionPosition]; step.m_offsetForFixedPosition = offsetForFixedPosition; if (!t.isIntegerTranslation()) step.m_transform = TransformationMatrix::create(t); else step.m_offset = LayoutSize(LayoutUnit(t.e()), LayoutUnit(t.f())); stepInserted(step); }
void RenderGeometryMap::push(const RenderObject* renderer, const TransformationMatrix& t, bool accumulatingTransform, bool isNonUniform, bool isFixedPosition, bool hasTransform, LayoutSize offsetForFixedPosition) { ASSERT(m_insertionPosition != kNotFound); ASSERT(!renderer->isRenderView() || !m_insertionPosition || m_mapCoordinatesFlags & TraverseDocumentBoundaries); ASSERT(offsetForFixedPosition.isZero() || renderer->isRenderView()); m_mapping.insert(m_insertionPosition, RenderGeometryMapStep(renderer, accumulatingTransform, isNonUniform, isFixedPosition, hasTransform)); RenderGeometryMapStep& step = m_mapping[m_insertionPosition]; step.m_offsetForFixedPosition = offsetForFixedPosition; if (!t.isIntegerTranslation()) step.m_transform = adoptPtr(new TransformationMatrix(t)); else step.m_offset = LayoutSize(t.e(), t.f()); stepInserted(step); }
void ShaderProgram::setProjectionMatrix(SkRect& geometry, GLint projectionMatrixHandle) { TransformationMatrix translate; translate.translate3d(geometry.fLeft, geometry.fTop, 0.0); TransformationMatrix scale; scale.scale3d(geometry.width(), geometry.height(), 1.0); TransformationMatrix total; if (!m_alphaLayer) total = m_projectionMatrix * m_repositionMatrix * m_webViewMatrix * translate * scale; else total = m_projectionMatrix * translate * scale; GLfloat projectionMatrix[16]; GLUtils::toGLMatrix(projectionMatrix, total); glUniformMatrix4fv(projectionMatrixHandle, 1, GL_FALSE, projectionMatrix); }
void BoundingBox::getMax(float &x, float &y, float &z) const { // Maximum, relative to the origin if (_absolute) { x = _max[0]; y = _max[1]; z = _max[2]; return; } TransformationMatrix min = _origin; min.translate(_min[0], _min[1], _min[2]); TransformationMatrix max = _origin; max.translate(_max[0], _max[1], _max[2]); x = MAX(min.getX(), max.getX()); y = MAX(min.getY(), max.getY()); z = MAX(min.getZ(), max.getZ()); }
virtual void render(const RenderState& state) { TransformationMatrix renderMatrix; if (pageNode()->devicePixelRatio() != 1.0) { renderMatrix.scale(pageNode()->devicePixelRatio()); if (matrix()) renderMatrix.multiply(*matrix()); } else if (matrix()) renderMatrix = *matrix(); // When rendering to an intermediate surface, Qt will // mirror the projection matrix to fit on the destination coordinate system. const QMatrix4x4* projection = state.projectionMatrix; bool mirrored = projection && (*projection)(0, 0) * (*projection)(1, 1) - (*projection)(0, 1) * (*projection)(1, 0) > 0; // FIXME: Support non-rectangular clippings. coordinatedGraphicsScene()->paintToCurrentGLContext(renderMatrix, inheritedOpacity(), clipRect(), mirrored ? TextureMapper::PaintingMirrored : 0); }
void ShaderProgram::drawQuadInternal(SkRect& geometry, GLint textureId, float opacity, GLint program, GLint projectionMatrixHandle, GLint texSampler, GLenum textureTarget, GLint position, GLint alpha, GLint texFilter, GLint contrast) { glUseProgram(program); if (!geometry.isEmpty()) setProjectionMatrix(geometry, projectionMatrixHandle); else { TransformationMatrix matrix; // Map x,y from (0,1) to (-1, 1) matrix.scale3d(2, 2, 1); matrix.translate3d(-0.5, -0.5, 0); GLfloat projectionMatrix[16]; GLUtils::toGLMatrix(projectionMatrix, matrix); glUniformMatrix4fv(projectionMatrixHandle, 1, GL_FALSE, projectionMatrix); } glActiveTexture(GL_TEXTURE0); glUniform1i(texSampler, 0); glBindTexture(textureTarget, textureId); glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, texFilter); glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, texFilter); glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]); glEnableVertexAttribArray(position); glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0); glUniform1f(alpha, opacity); if (contrast != -1) glUniform1f(contrast, m_contrast); setBlendingState(opacity < 1.0); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); }
AffineTransform SVGGraphicsElement::calculateAnimatedLocalTransform() const { AffineTransform matrix; const ComputedStyle* style = layoutObject() ? layoutObject()->style() : nullptr; // If CSS property was set, use that, otherwise fallback to attribute (if set). if (style && style->hasTransform()) { TransformationMatrix transform; float zoom = style->effectiveZoom(); // SVGTextElements need special handling for the text positioning code. if (isSVGTextElement(this)) { // Do not take into account SVG's zoom rules, transform-origin, or percentage values. style->applyTransform(transform, LayoutSize(0, 0), ComputedStyle::ExcludeTransformOrigin, ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTransformProperties); } else { // CSS transforms operate with pre-scaled lengths. To make this work with SVG // (which applies the zoom factor globally, at the root level) we // // * pre-scale the bounding box (to bring it into the same space as the other CSS values) // * invert the zoom factor (to effectively compute the CSS transform under a 1.0 zoom) // // 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/ if (zoom != 1) { FloatRect scaledBBox = layoutObject()->objectBoundingBox(); scaledBBox.scale(zoom); transform.scale(1 / zoom); style->applyTransform(transform, scaledBBox, ComputedStyle::IncludeTransformOrigin, ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTransformProperties); transform.scale(zoom); } else { style->applyTransform(transform, layoutObject()->objectBoundingBox(), ComputedStyle::IncludeTransformOrigin, ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTransformProperties); } } // Flatten any 3D transform. matrix = transform.toAffineTransform(); } else { m_transform->currentValue()->concatenate(matrix); } if (hasSVGRareData()) return *svgRareData()->animateMotionTransform() * matrix; return matrix; }
static FloatRect damageInSurfaceSpace(CCLayerImpl* renderSurfaceLayer, const FloatRect& rootDamageRect) { FloatRect surfaceDamageRect; // For now, we conservatively use the root damage as the damage for // all surfaces, except perspective transforms. TransformationMatrix screenSpaceTransform = computeScreenSpaceTransformForSurface(renderSurfaceLayer); if (screenSpaceTransform.hasPerspective()) { // Perspective projections do not play nice with mapRect of // inverse transforms. In this uncommon case, its simpler to // just redraw the entire surface. // FIXME: use calculateVisibleRect to handle projections. CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); surfaceDamageRect = renderSurface->contentRect(); } else { TransformationMatrix inverseScreenSpaceTransform = screenSpaceTransform.inverse(); surfaceDamageRect = inverseScreenSpaceTransform.mapRect(rootDamageRect); } return surfaceDamageRect; }
void ThreadedCompositor::renderLayerTree() { if (!m_scene) return; if (!ensureGLContext()) return; FloatRect clipRect(0, 0, m_viewportSize.width(), m_viewportSize.height()); TransformationMatrix viewportTransform; FloatPoint scrollPostion = viewportController()->visibleContentsRect().location(); viewportTransform.scale(viewportController()->pageScaleFactor() * m_deviceScaleFactor); viewportTransform.translate(-scrollPostion.x(), -scrollPostion.y()); m_scene->paintToCurrentGLContext(viewportTransform, 1, clipRect, Color::white, false, scrollPostion); glContext()->swapBuffers(); }
static inline TransformationMatrix contentToTargetSurfaceTransform(const LayerType* layer) { IntSize boundsInLayerSpace = layer->bounds(); IntSize boundsInContentSpace = layer->contentBounds(); TransformationMatrix transform = layer->drawTransform(); if (boundsInContentSpace.isEmpty()) return transform; // Scale from content space to layer space transform.scaleNonUniform(boundsInLayerSpace.width() / static_cast<double>(boundsInContentSpace.width()), boundsInLayerSpace.height() / static_cast<double>(boundsInContentSpace.height())); // The draw transform expects the origin to be in the middle of the layer. transform.translate(-boundsInContentSpace.width() / 2.0, -boundsInContentSpace.height() / 2.0); return transform; }
void TransformState::applyTransform( const TransformationMatrix& transformFromContainer, TransformAccumulation accumulate, bool* wasClamped) { if (wasClamped) *wasClamped = false; if (transformFromContainer.isIntegerTranslation()) { move(LayoutSize(LayoutUnit(transformFromContainer.e()), LayoutUnit(transformFromContainer.f())), accumulate); return; } applyAccumulatedOffset(); // If we have an accumulated transform from last time, multiply in this // transform if (m_accumulatedTransform) { if (m_direction == ApplyTransformDirection) m_accumulatedTransform = TransformationMatrix::create( transformFromContainer * *m_accumulatedTransform); else m_accumulatedTransform->multiply(transformFromContainer); } else if (accumulate == AccumulateTransform) { // Make one if we started to accumulate m_accumulatedTransform = TransformationMatrix::create(transformFromContainer); } if (accumulate == FlattenTransform) { if (m_forceAccumulatingTransform) { m_accumulatedTransform->flattenTo2d(); } else { const TransformationMatrix* finalTransform = m_accumulatedTransform ? m_accumulatedTransform.get() : &transformFromContainer; flattenWithTransform(*finalTransform, wasClamped); } } m_accumulatingTransform = accumulate == AccumulateTransform || m_forceAccumulatingTransform; }
FloatRect ShaderProgram::debugMatrixTransform(const TransformationMatrix& matrix, const char* matrixName) { FloatRect rect(0.0, 0.0, 1.0, 1.0); rect = matrix.mapRect(rect); ALOGV("After %s matrix:\n %f, %f rect.width() %f rect.height() %f", matrixName, rect.x(), rect.y(), rect.width(), rect.height()); return rect; }
TEST_F(PaintPropertyTreeBuilderTest, TransformNodesInSVG) { setBodyInnerHTML( "<style>" " body {" " margin: 0px;" " }" " svg {" " margin-left: 50px;" " transform: translate3d(1px, 2px, 3px);" " position: absolute;" " left: 20px;" " top: 25px;" " }" " rect {" " transform: translate(100px, 100px) rotate(45deg);" " transform-origin: 50px 25px;" " }" "</style>" "<svg id='svgRootWith3dTransform' width='100px' height='100px'>" " <rect id='rectWith2dTransform' width='100px' height='100px' />" "</svg>"); LayoutObject& svgRootWith3dTransform = *document().getElementById("svgRootWith3dTransform")->layoutObject(); ObjectPaintProperties* svgRootWith3dTransformProperties = svgRootWith3dTransform.objectPaintProperties(); EXPECT_EQ(TransformationMatrix().translate3d(1, 2, 3), svgRootWith3dTransformProperties->transform()->matrix()); EXPECT_EQ(FloatPoint3D(50, 50, 0), svgRootWith3dTransformProperties->transform()->origin()); EXPECT_EQ(svgRootWith3dTransformProperties->paintOffsetTranslation(), svgRootWith3dTransformProperties->transform()->parent()); EXPECT_EQ(TransformationMatrix().translate(70, 25), svgRootWith3dTransformProperties->paintOffsetTranslation()->matrix()); EXPECT_EQ(document().view()->scrollTranslation(), svgRootWith3dTransformProperties->paintOffsetTranslation()->parent()); LayoutObject& rectWith2dTransform = *document().getElementById("rectWith2dTransform")->layoutObject(); ObjectPaintProperties* rectWith2dTransformProperties = rectWith2dTransform.objectPaintProperties(); TransformationMatrix matrix; matrix.translate(100, 100); matrix.rotate(45); // SVG's transform origin is baked into the transform. matrix.applyTransformOrigin(50, 25, 0); EXPECT_EQ(matrix, rectWith2dTransformProperties->transform()->matrix()); EXPECT_EQ(FloatPoint3D(0, 0, 0), rectWith2dTransformProperties->transform()->origin()); // SVG does not use paint offset. EXPECT_EQ(nullptr, rectWith2dTransformProperties->paintOffsetTranslation()); }
void LayerCompositingThread::setDrawTransform(double scale, const TransformationMatrix& matrix) { m_drawTransform = matrix; float bx = m_bounds.width() / 2.0; float by = m_bounds.height() / 2.0; if (sizeIsScaleInvariant()) { bx /= scale; by /= scale; } m_transformedBounds.setP1(matrix.mapPoint(FloatPoint(-bx, -by))); m_transformedBounds.setP2(matrix.mapPoint(FloatPoint(-bx, by))); m_transformedBounds.setP3(matrix.mapPoint(FloatPoint(bx, by))); m_transformedBounds.setP4(matrix.mapPoint(FloatPoint(bx, -by))); m_drawRect = m_transformedBounds.boundingBox(); }
/** This method draws the desired target that is to be tracked. */ void ControllerEditor::drawDesiredTarget(){ Character* ch = conF->getCharacter(); //we need to get the desired pose, and set it to the character DynamicArray<double> pose; conF->getController()->updateTrackingPose(pose, Globals::targetPosePhase); glPushMatrix(); Point3d p = ch->getRoot()->getCMPosition(); //this is where we will be drawing the target pose p.x += 2; p.y = 1.35; p.z += 0; worldState.clear(); conF->getWorld()->getState(&worldState); pose[0] = 0; pose[1] = 0; pose[2] = 0; ch->setState(&pose); glTranslated(p.x, p.y, p.z); TransformationMatrix tmp; double val[16]; conF->getCharacterFrame().getRotationMatrix(&tmp); tmp.getOGLValues(val); glMultMatrixd(val); float tempColor[] = {0.5, 0.5, 0.5, 1.0}; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, tempColor); conF->getWorld()->drawRBs(SHOW_MESH); p = ch->getRoot()->getCMPosition(); glDisable(GL_LIGHTING); glTranslated(p.x,p.y,p.z); GLUtils::drawAxes(0.2); glPopMatrix(); glEnable(GL_LIGHTING); //set the state back to the original... conF->getWorld()->setState(&worldState); }