Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Shared / MS / Internal / MatrixUtil.cs / 1305600 / MatrixUtil.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // // File: MatrixUtil.cs // // Description: This file contains the implementation of MatrixUtil, which // provides matrix multiply code. // // History: // 01/06/2004 : [....] - Created, most copied from wcp\core\system\windows\media\milutilities.cs // //--------------------------------------------------------------------------- using System; using System.Windows; using System.Windows.Media; using System.Diagnostics; using System.Security; using System.Security.Permissions; #if WINDOWS_BASE using MS.Internal.WindowsBase; #elif PRESENTATION_CORE using MS.Internal.PresentationCore; #elif PRESENTATIONFRAMEWORK using MS.Internal.PresentationFramework; #elif DRT using MS.Internal.Drt; #else #error Attempt to use FriendAccessAllowedAttribute from an unknown assembly. using MS.Internal.YourAssemblyName; #endif namespace MS.Internal { // MatrixTypes [System.Flags] internal enum MatrixTypes { TRANSFORM_IS_IDENTITY = 0, TRANSFORM_IS_TRANSLATION = 1, TRANSFORM_IS_SCALING = 2, TRANSFORM_IS_UNKNOWN = 4 } [FriendAccessAllowed] internal static class MatrixUtil { ////// TransformRect - Internal helper for perf /// /// The Rect to transform. /// The Matrix with which to transform the Rect. internal static void TransformRect(ref Rect rect, ref Matrix matrix) { if (rect.IsEmpty) { return; } MatrixTypes matrixType = matrix._type; // If the matrix is identity, don't worry. if (matrixType == MatrixTypes.TRANSFORM_IS_IDENTITY) { return; } // Scaling if (0 != (matrixType & MatrixTypes.TRANSFORM_IS_SCALING)) { rect._x *= matrix._m11; rect._y *= matrix._m22; rect._width *= matrix._m11; rect._height *= matrix._m22; // Ensure the width is always positive. For example, if there was a reflection about the // y axis followed by a translation into the visual area, the width could be negative. if (rect._width < 0.0) { rect._x += rect._width; rect._width = -rect._width; } // Ensure the height is always positive. For example, if there was a reflection about the // x axis followed by a translation into the visual area, the height could be negative. if (rect._height < 0.0) { rect._y += rect._height; rect._height = -rect._height; } } // Translation if (0 != (matrixType & MatrixTypes.TRANSFORM_IS_TRANSLATION)) { // X rect._x += matrix._offsetX; // Y rect._y += matrix._offsetY; } if (matrixType == MatrixTypes.TRANSFORM_IS_UNKNOWN) { // Al Bunny implementation. Point point0 = matrix.Transform(rect.TopLeft); Point point1 = matrix.Transform(rect.TopRight); Point point2 = matrix.Transform(rect.BottomRight); Point point3 = matrix.Transform(rect.BottomLeft); // Width and height is always positive here. rect._x = Math.Min(Math.Min(point0.X, point1.X), Math.Min(point2.X, point3.X)); rect._y = Math.Min(Math.Min(point0.Y, point1.Y), Math.Min(point2.Y, point3.Y)); rect._width = Math.Max(Math.Max(point0.X, point1.X), Math.Max(point2.X, point3.X)) - rect._x; rect._height = Math.Max(Math.Max(point0.Y, point1.Y), Math.Max(point2.Y, point3.Y)) - rect._y; } } ////// Multiplies two transformations, where the behavior is matrix1 *= matrix2. /// This code exists so that we can efficient combine matrices without copying /// the data around, since each matrix is 52 bytes. /// To reduce duplication and to ensure consistent behavior, this is the /// method which is used to implement Matrix * Matrix as well. /// internal static void MultiplyMatrix(ref Matrix matrix1, ref Matrix matrix2) { MatrixTypes type1 = matrix1._type; MatrixTypes type2 = matrix2._type; // Check for idents // If the second is ident, we can just return if (type2 == MatrixTypes.TRANSFORM_IS_IDENTITY) { return; } // If the first is ident, we can just copy the memory across. if (type1 == MatrixTypes.TRANSFORM_IS_IDENTITY) { matrix1 = matrix2; return; } // Optimize for translate case, where the second is a translate if (type2 == MatrixTypes.TRANSFORM_IS_TRANSLATION) { // 2 additions matrix1._offsetX += matrix2._offsetX; matrix1._offsetY += matrix2._offsetY; // If matrix 1 wasn't unknown we added a translation if (type1 != MatrixTypes.TRANSFORM_IS_UNKNOWN) { matrix1._type |= MatrixTypes.TRANSFORM_IS_TRANSLATION; } return; } // Check for the first value being a translate if (type1 == MatrixTypes.TRANSFORM_IS_TRANSLATION) { // Save off the old offsets double offsetX = matrix1._offsetX; double offsetY = matrix1._offsetY; // Copy the matrix matrix1 = matrix2; matrix1._offsetX = offsetX * matrix2._m11 + offsetY * matrix2._m21 + matrix2._offsetX; matrix1._offsetY = offsetX * matrix2._m12 + offsetY * matrix2._m22 + matrix2._offsetY; if (type2 == MatrixTypes.TRANSFORM_IS_UNKNOWN) { matrix1._type = MatrixTypes.TRANSFORM_IS_UNKNOWN; } else { matrix1._type = MatrixTypes.TRANSFORM_IS_SCALING | MatrixTypes.TRANSFORM_IS_TRANSLATION; } return; } // The following code combines the type of the transformations so that the high nibble // is "this"'s type, and the low nibble is mat's type. This allows for a switch rather // than nested switches. // trans1._type | trans2._type // 7 6 5 4 | 3 2 1 0 int combinedType = ((int)type1 << 4) | (int)type2; switch (combinedType) { case 34: // S * S // 2 multiplications matrix1._m11 *= matrix2._m11; matrix1._m22 *= matrix2._m22; return; case 35: // S * S|T matrix1._m11 *= matrix2._m11; matrix1._m22 *= matrix2._m22; matrix1._offsetX = matrix2._offsetX; matrix1._offsetY = matrix2._offsetY; // Transform set to Translate and Scale matrix1._type = MatrixTypes.TRANSFORM_IS_TRANSLATION | MatrixTypes.TRANSFORM_IS_SCALING; return; case 50: // S|T * S matrix1._m11 *= matrix2._m11; matrix1._m22 *= matrix2._m22; matrix1._offsetX *= matrix2._m11; matrix1._offsetY *= matrix2._m22; return; case 51: // S|T * S|T matrix1._m11 *= matrix2._m11; matrix1._m22 *= matrix2._m22; matrix1._offsetX = matrix2._m11 * matrix1._offsetX + matrix2._offsetX; matrix1._offsetY = matrix2._m22 * matrix1._offsetY + matrix2._offsetY; return; case 36: // S * U case 52: // S|T * U case 66: // U * S case 67: // U * S|T case 68: // U * U matrix1 = new Matrix( matrix1._m11 * matrix2._m11 + matrix1._m12 * matrix2._m21, matrix1._m11 * matrix2._m12 + matrix1._m12 * matrix2._m22, matrix1._m21 * matrix2._m11 + matrix1._m22 * matrix2._m21, matrix1._m21 * matrix2._m12 + matrix1._m22 * matrix2._m22, matrix1._offsetX * matrix2._m11 + matrix1._offsetY * matrix2._m21 + matrix2._offsetX, matrix1._offsetX * matrix2._m12 + matrix1._offsetY * matrix2._m22 + matrix2._offsetY); return; #if DEBUG default: Debug.Fail("Matrix multiply hit an invalid case: " + combinedType); break; #endif } } ////// Applies an offset to the specified matrix in place. /// internal static void PrependOffset( ref Matrix matrix, double offsetX, double offsetY) { if (matrix._type == MatrixTypes.TRANSFORM_IS_IDENTITY) { matrix = new Matrix(1, 0, 0, 1, offsetX, offsetY); matrix._type = MatrixTypes.TRANSFORM_IS_TRANSLATION; } else { // // / 1 0 0 \ / m11 m12 0 \ // | 0 1 0 | * | m21 m22 0 | // \ tx ty 1 / \ ox oy 1 / // // / m11 m12 0 \ // = | m21 m22 0 | // \ m11*tx+m21*ty+ox m12*tx + m22*ty + oy 1 / // matrix._offsetX += matrix._m11 * offsetX + matrix._m21 * offsetY; matrix._offsetY += matrix._m12 * offsetX + matrix._m22 * offsetY; // It just gained a translate if was a scale transform. Identity transform is handled above. Debug.Assert(matrix._type != MatrixTypes.TRANSFORM_IS_IDENTITY); if (matrix._type != MatrixTypes.TRANSFORM_IS_UNKNOWN) { matrix._type |= MatrixTypes.TRANSFORM_IS_TRANSLATION; } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ThumbButtonInfo.cs
- PenContexts.cs
- _Rfc2616CacheValidators.cs
- ExpressionPrinter.cs
- ListenerSessionConnection.cs
- ViewStateModeByIdAttribute.cs
- TextTrailingCharacterEllipsis.cs
- SqlBinder.cs
- ViewBase.cs
- DataGridViewElement.cs
- OrderingExpression.cs
- MethodExpression.cs
- ClickablePoint.cs
- HGlobalSafeHandle.cs
- TraceUtility.cs
- VScrollBar.cs
- Events.cs
- UnsettableComboBox.cs
- XmlParserContext.cs
- WebPartAddingEventArgs.cs
- DataGridViewSelectedColumnCollection.cs
- MembershipSection.cs
- ExpandCollapsePattern.cs
- SiteMapNodeCollection.cs
- IPHostEntry.cs
- ElementMarkupObject.cs
- PinnedBufferMemoryStream.cs
- RegexGroupCollection.cs
- DateTimeConverter.cs
- PrinterSettings.cs
- CanonicalizationDriver.cs
- WorkflowApplicationAbortedEventArgs.cs
- UnionExpr.cs
- ToolBarOverflowPanel.cs
- HtmlInputPassword.cs
- ButtonBase.cs
- HttpTransportElement.cs
- XmlSchemaInfo.cs
- Globals.cs
- Crypto.cs
- PeerSecurityManager.cs
- ArrayWithOffset.cs
- DrawingContextWalker.cs
- EntityReference.cs
- XmlLoader.cs
- CompletedAsyncResult.cs
- ServicePointManager.cs
- QilUnary.cs
- PropertySourceInfo.cs
- QuadraticBezierSegment.cs
- SecurityTokenTypes.cs
- SoapAttributes.cs
- CharacterBufferReference.cs
- WizardForm.cs
- Emitter.cs
- ChannelSettingsElement.cs
- ReferentialConstraint.cs
- RelativeSource.cs
- ActivityFunc.cs
- ConfigurationSectionHelper.cs
- MulticastNotSupportedException.cs
- SizeFConverter.cs
- ImpersonationContext.cs
- Positioning.cs
- SelectionItemPatternIdentifiers.cs
- CompoundFileReference.cs
- DataGridRow.cs
- DescendantQuery.cs
- ColorConvertedBitmap.cs
- BindingMemberInfo.cs
- HeaderCollection.cs
- DocumentViewerAutomationPeer.cs
- UIntPtr.cs
- DataServiceContext.cs
- BuildResult.cs
- BamlLocalizableResource.cs
- AsynchronousChannelMergeEnumerator.cs
- FormViewPageEventArgs.cs
- Message.cs
- Int32Storage.cs
- FtpWebRequest.cs
- AtlasWeb.Designer.cs
- DateTimeStorage.cs
- GeneralTransform3DTo2D.cs
- Config.cs
- MDIWindowDialog.cs
- BulletDecorator.cs
- Signature.cs
- FileNotFoundException.cs
- AssemblyName.cs
- MenuItemStyleCollection.cs
- InputMethodStateTypeInfo.cs
- TimerEventSubscription.cs
- SoapHeaderException.cs
- AttachInfo.cs
- XslCompiledTransform.cs
- ContextMenuStrip.cs
- WindowsGrip.cs
- ListenerElementsCollection.cs
- HyperLinkColumn.cs