void GutUserControl_RotateObject(Matrix4x4 object_matrix, float time_advance) { // 讀取滑鼠 GutMouseInfo mouse; if ( GutReadMouse(&mouse) ) { float rotation_speed = 1.0 * time_advance; // 如果按下滑鼠左鍵,就旋轉鏡頭 if ( mouse.button[0] ) { Matrix4x4 rotate_matrix; rotate_matrix.RotateY_Replace(mouse.x * rotation_speed); rotate_matrix.RotateX(mouse.y * rotation_speed); object_matrix = object_matrix * rotate_matrix; } // 用滾輪來縮放物件 if ( mouse.z ) { float scale = 1.0f + mouse.z / 1000.0f; object_matrix.Scale(scale, scale, scale); } } }
/* ============= Uniform Scale ============= */ void PS2Sprite::Scale( const float s ) { Matrix4x4 rotationMatrix; rotationMatrix.Scale( s ); // apply required scaling to matrix for( int i = 0; i < mNumOfVerts; i++ ) { // apply to Vertex Vectors pVerts[ i ] = rotationMatrix * pVerts[ i ]; } }
const Matrix4x4 Layer::GetTransform() const { Matrix4x4 transform = mTransform; if (const ContainerLayer* c = AsContainerLayer()) { transform.Scale(c->GetPreXScale(), c->GetPreYScale(), 1.0f); } transform = transform * Matrix4x4().Scale(mPostXScale, mPostYScale, 1.0f); return transform; }
const Matrix4x4 Layer::GetLocalTransform() { Matrix4x4 transform; if (LayerComposite* shadow = AsLayerComposite()) transform = shadow->GetShadowTransform(); else transform = mTransform; if (ContainerLayer* c = AsContainerLayer()) { transform.Scale(c->GetPreXScale(), c->GetPreYScale(), 1.0f); } transform = transform * Matrix4x4().Scale(mPostXScale, mPostYScale, 1.0f); return transform; }
void AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer) { LayerComposite* layerComposite = aLayer->AsLayerComposite(); const FrameMetrics& metrics = aLayer->GetFrameMetrics(); // We must apply the resolution scale before a pan/zoom transform, so we call // GetTransform here. Matrix4x4 oldTransform = aLayer->GetTransform(); CSSToLayerScale geckoZoom = metrics.LayersPixelsPerCSSPixel(); LayerIntPoint scrollOffsetLayerPixels = RoundedToInt(metrics.GetScrollOffset() * geckoZoom); if (mIsFirstPaint) { mContentRect = metrics.mScrollableRect; SetFirstPaintViewport(scrollOffsetLayerPixels, geckoZoom, mContentRect); mIsFirstPaint = false; } else if (!metrics.mScrollableRect.IsEqualEdges(mContentRect)) { mContentRect = metrics.mScrollableRect; SetPageRect(mContentRect); } // We synchronise the viewport information with Java after sending the above // notifications, so that Java can take these into account in its response. // Calculate the absolute display port to send to Java LayerIntRect displayPort = RoundedToInt( (metrics.mCriticalDisplayPort.IsEmpty() ? metrics.mDisplayPort : metrics.mCriticalDisplayPort ) * geckoZoom); displayPort += scrollOffsetLayerPixels; LayerMargin fixedLayerMargins(0, 0, 0, 0); ScreenPoint offset(0, 0); // Ideally we would initialize userZoom to AsyncPanZoomController::CalculateResolution(metrics) // but this causes a reftest-ipc test to fail (see bug 883646 comment 27). The reason for this // appears to be that metrics.mZoom is poorly initialized in some scenarios. In these scenarios, // however, we can assume there is no async zooming in progress and so the following statement // works fine. CSSToScreenScale userZoom(metrics.mDevPixelsPerCSSPixel * metrics.mCumulativeResolution * LayerToScreenScale(1)); ScreenPoint userScroll = metrics.GetScrollOffset() * userZoom; SyncViewportInfo(displayPort, geckoZoom, mLayersUpdated, userScroll, userZoom, fixedLayerMargins, offset); mLayersUpdated = false; // Apply the render offset mLayerManager->GetCompositor()->SetScreenRenderOffset(offset); // Handle transformations for asynchronous panning and zooming. We determine the // zoom used by Gecko from the transformation set on the root layer, and we // determine the scroll offset used by Gecko from the frame metrics of the // primary scrollable layer. We compare this to the user zoom and scroll // offset in the view transform we obtained from Java in order to compute the // transformation we need to apply. ScreenPoint geckoScroll(0, 0); if (metrics.IsScrollable()) { geckoScroll = metrics.GetScrollOffset() * userZoom; } ParentLayerToScreenScale scale = userZoom / metrics.mDevPixelsPerCSSPixel / metrics.GetParentResolution(); ScreenPoint translation = userScroll - geckoScroll; Matrix4x4 treeTransform = ViewTransform(scale, -translation); // The transform already takes the resolution scale into account. Since we // will apply the resolution scale again when computing the effective // transform, we must apply the inverse resolution scale here. Matrix4x4 computedTransform = oldTransform * treeTransform; if (ContainerLayer* container = aLayer->AsContainerLayer()) { computedTransform.Scale(1.0f/container->GetPreXScale(), 1.0f/container->GetPreYScale(), 1); } computedTransform.ScalePost(1.0f/aLayer->GetPostXScale(), 1.0f/aLayer->GetPostYScale(), 1); layerComposite->SetShadowTransform(computedTransform); NS_ASSERTION(!layerComposite->GetShadowTransformSetByAnimation(), "overwriting animated transform!"); // Apply resolution scaling to the old transform - the layer tree as it is // doesn't have the necessary transform to display correctly. oldTransform.Scale(metrics.mResolution.scale, metrics.mResolution.scale, 1); // Make sure that overscroll and under-zoom are represented in the old // transform so that fixed position content moves and scales accordingly. // These calculations will effectively scale and offset fixed position layers // in screen space when the compensatory transform is performed in // AlignFixedAndStickyLayers. ScreenRect contentScreenRect = mContentRect * userZoom; gfxPoint3D overscrollTranslation; if (userScroll.x < contentScreenRect.x) { overscrollTranslation.x = contentScreenRect.x - userScroll.x; } else if (userScroll.x + metrics.mCompositionBounds.width > contentScreenRect.XMost()) { overscrollTranslation.x = contentScreenRect.XMost() - (userScroll.x + metrics.mCompositionBounds.width); } if (userScroll.y < contentScreenRect.y) { overscrollTranslation.y = contentScreenRect.y - userScroll.y; } else if (userScroll.y + metrics.mCompositionBounds.height > contentScreenRect.YMost()) { overscrollTranslation.y = contentScreenRect.YMost() - (userScroll.y + metrics.mCompositionBounds.height); } oldTransform.Translate(overscrollTranslation.x, overscrollTranslation.y, overscrollTranslation.z); gfx::Size underZoomScale(1.0f, 1.0f); if (mContentRect.width * userZoom.scale < metrics.mCompositionBounds.width) { underZoomScale.width = (mContentRect.width * userZoom.scale) / metrics.mCompositionBounds.width; } if (mContentRect.height * userZoom.scale < metrics.mCompositionBounds.height) { underZoomScale.height = (mContentRect.height * userZoom.scale) / metrics.mCompositionBounds.height; } oldTransform.Scale(underZoomScale.width, underZoomScale.height, 1); // Make sure fixed position layers don't move away from their anchor points // when we're asynchronously panning or zooming AlignFixedAndStickyLayers(aLayer, aLayer, oldTransform, aLayer->GetLocalTransform(), fixedLayerMargins); }
static void ApplyAsyncTransformToScrollbarForContent(ContainerLayer* aScrollbar, Layer* aContent, bool aScrollbarIsChild) { // We only apply the transform if the scroll-target layer has non-container // children (i.e. when it has some possibly-visible content). This is to // avoid moving scroll-bars in the situation that only a scroll information // layer has been built for a scroll frame, as this would result in a // disparity between scrollbars and visible content. if (aContent->AsContainerLayer() && !LayerHasNonContainerDescendants(aContent->AsContainerLayer())) { return; } const FrameMetrics& metrics = aContent->GetFrameMetrics(); AsyncPanZoomController* apzc = aContent->GetAsyncPanZoomController(); Matrix4x4 asyncTransform = apzc->GetCurrentAsyncTransform(); Matrix4x4 nontransientTransform = apzc->GetNontransientAsyncTransform(); Matrix4x4 nontransientUntransform = nontransientTransform; nontransientUntransform.Invert(); Matrix4x4 transientTransform = asyncTransform * nontransientUntransform; // |transientTransform| represents the amount by which we have scrolled and // zoomed since the last paint. Because the scrollbar was sized and positioned based // on the painted content, we need to adjust it based on transientTransform so that // it reflects what the user is actually seeing now. // - The scroll thumb needs to be scaled in the direction of scrolling by the inverse // of the transientTransform scale (representing the zoom). This is because zooming // in decreases the fraction of the whole scrollable rect that is in view. // - It needs to be translated in opposite direction of the transientTransform // translation (representing the scroll). This is because scrolling down, which // translates the layer content up, should result in moving the scroll thumb down. // The amount of the translation to the scroll thumb should be such that the ratio // of the translation to the size of the scroll port is the same as the ratio // of the scroll amount to the size of the scrollable rect. Matrix4x4 scrollbarTransform; if (aScrollbar->GetScrollbarDirection() == Layer::VERTICAL) { float scale = metrics.CalculateCompositedSizeInCssPixels().height / metrics.mScrollableRect.height; scrollbarTransform = scrollbarTransform * Matrix4x4().Scale(1.f, 1.f / transientTransform._22, 1.f); scrollbarTransform = scrollbarTransform * Matrix4x4().Translate(0, -transientTransform._42 * scale, 0); } if (aScrollbar->GetScrollbarDirection() == Layer::HORIZONTAL) { float scale = metrics.CalculateCompositedSizeInCssPixels().width / metrics.mScrollableRect.width; scrollbarTransform = scrollbarTransform * Matrix4x4().Scale(1.f / transientTransform._11, 1.f, 1.f); scrollbarTransform = scrollbarTransform * Matrix4x4().Translate(-transientTransform._41 * scale, 0, 0); } Matrix4x4 transform = scrollbarTransform * aScrollbar->GetTransform(); if (aScrollbarIsChild) { // If the scrollbar layer is a child of the content it is a scrollbar for, then we // need to do an extra untransform to cancel out the transient async transform on // the content. This is needed because otherwise that transient async transform is // part of the effective transform of this scrollbar, and the scrollbar will jitter // as the content scrolls. transientTransform.Invert(); transform = transform * transientTransform; } // GetTransform already takes the pre- and post-scale into account. Since we // will apply the pre- and post-scale again when computing the effective // transform, we must apply the inverses here. transform.Scale(1.0f/aScrollbar->GetPreXScale(), 1.0f/aScrollbar->GetPreYScale(), 1); transform = transform * Matrix4x4().Scale(1.0f/aScrollbar->GetPostXScale(), 1.0f/aScrollbar->GetPostYScale(), 1); aScrollbar->AsLayerComposite()->SetShadowTransform(transform); }
bool AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer) { bool appliedTransform = false; for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) { appliedTransform |= ApplyAsyncContentTransformToTree(child); } if (AsyncPanZoomController* controller = aLayer->GetAsyncPanZoomController()) { LayerComposite* layerComposite = aLayer->AsLayerComposite(); Matrix4x4 oldTransform = aLayer->GetTransform(); ViewTransform asyncTransformWithoutOverscroll, overscrollTransform; ScreenPoint scrollOffset; controller->SampleContentTransformForFrame(&asyncTransformWithoutOverscroll, scrollOffset, &overscrollTransform); const FrameMetrics& metrics = aLayer->GetFrameMetrics(); CSSToLayerScale paintScale = metrics.LayersPixelsPerCSSPixel(); CSSRect displayPort(metrics.mCriticalDisplayPort.IsEmpty() ? metrics.mDisplayPort : metrics.mCriticalDisplayPort); LayerMargin fixedLayerMargins(0, 0, 0, 0); ScreenPoint offset(0, 0); SyncFrameMetrics(scrollOffset, asyncTransformWithoutOverscroll.mScale.scale, metrics.mScrollableRect, mLayersUpdated, displayPort, paintScale, mIsFirstPaint, fixedLayerMargins, offset); mIsFirstPaint = false; mLayersUpdated = false; // Apply the render offset mLayerManager->GetCompositor()->SetScreenRenderOffset(offset); Matrix4x4 transform = AdjustAndCombineWithCSSTransform( asyncTransformWithoutOverscroll * overscrollTransform, aLayer); // GetTransform already takes the pre- and post-scale into account. Since we // will apply the pre- and post-scale again when computing the effective // transform, we must apply the inverses here. if (ContainerLayer* container = aLayer->AsContainerLayer()) { transform.Scale(1.0f/container->GetPreXScale(), 1.0f/container->GetPreYScale(), 1); } transform = transform * Matrix4x4().Scale(1.0f/aLayer->GetPostXScale(), 1.0f/aLayer->GetPostYScale(), 1); layerComposite->SetShadowTransform(transform); NS_ASSERTION(!layerComposite->GetShadowTransformSetByAnimation(), "overwriting animated transform!"); // Apply resolution scaling to the old transform - the layer tree as it is // doesn't have the necessary transform to display correctly. LayoutDeviceToLayerScale resolution = metrics.mCumulativeResolution; oldTransform.Scale(resolution.scale, resolution.scale, 1); // For the purpose of aligning fixed and sticky layers, we disregard // the overscroll transform when computing the 'aCurrentTransformForRoot' // parameter. This ensures that the overscroll transform is not unapplied, // and therefore that the visual effect applies to fixed and sticky layers. Matrix4x4 transformWithoutOverscroll = AdjustAndCombineWithCSSTransform( asyncTransformWithoutOverscroll, aLayer); AlignFixedAndStickyLayers(aLayer, aLayer, oldTransform, transformWithoutOverscroll, fixedLayerMargins); appliedTransform = true; } if (aLayer->AsContainerLayer() && aLayer->GetScrollbarDirection() != Layer::NONE) { ApplyAsyncTransformToScrollbar(aLayer->AsContainerLayer()); } return appliedTransform; }