Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Shared / MS / Internal / MatrixUtil.cs / 1 / 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 : adsmith - 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. //---------------------------------------------------------------------------- // // 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 : adsmith - 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
- ServicePerformanceCounters.cs
- HTTP_SERVICE_CONFIG_URLACL_KEY.cs
- JavaScriptSerializer.cs
- PathSegmentCollection.cs
- AssociationType.cs
- CqlParserHelpers.cs
- ZipIOBlockManager.cs
- WindowsAuthenticationEventArgs.cs
- CreateSequenceResponse.cs
- TextServicesLoader.cs
- Int32AnimationUsingKeyFrames.cs
- StandardOleMarshalObject.cs
- ParallelDesigner.xaml.cs
- ComboBoxItem.cs
- XmlValidatingReader.cs
- OutputCacheProfile.cs
- DataGridViewSelectedRowCollection.cs
- SqlInternalConnection.cs
- ChtmlTextWriter.cs
- RightsManagementInformation.cs
- ChildrenQuery.cs
- JulianCalendar.cs
- CodePropertyReferenceExpression.cs
- PersonalizationAdministration.cs
- TextRangeBase.cs
- DesignerHelpers.cs
- FeatureManager.cs
- BufferedReadStream.cs
- ProxyHelper.cs
- PictureBoxDesigner.cs
- ResourceDescriptionAttribute.cs
- CodePrimitiveExpression.cs
- ToolboxItemAttribute.cs
- TimeSpanValidator.cs
- ZoneMembershipCondition.cs
- ConnectionStringsExpressionBuilder.cs
- TextViewDesigner.cs
- PluralizationServiceUtil.cs
- ObjectTypeMapping.cs
- TextSelectionProcessor.cs
- WindowShowOrOpenTracker.cs
- DataControlFieldHeaderCell.cs
- Memoizer.cs
- LayoutInformation.cs
- ContainerControl.cs
- DecoratedNameAttribute.cs
- ScrollEventArgs.cs
- CompiledQueryCacheEntry.cs
- SqlDataAdapter.cs
- BaseParser.cs
- ListViewPagedDataSource.cs
- SpeechSeg.cs
- HttpCookieCollection.cs
- OverrideMode.cs
- ActionFrame.cs
- AvTraceFormat.cs
- CellCreator.cs
- TextEndOfParagraph.cs
- OraclePermission.cs
- LogicalCallContext.cs
- VectorCollectionValueSerializer.cs
- DataListItem.cs
- FilterQuery.cs
- ClassDataContract.cs
- AttributeParameterInfo.cs
- ReadingWritingEntityEventArgs.cs
- PassportPrincipal.cs
- BindingContext.cs
- EmbeddedMailObjectsCollection.cs
- ImportOptions.cs
- ColorTranslator.cs
- AccessedThroughPropertyAttribute.cs
- DbParameterHelper.cs
- TextParaLineResult.cs
- ClientConfigurationSystem.cs
- NTAccount.cs
- AppDomainAttributes.cs
- FileDialog.cs
- ObjectStateFormatter.cs
- Operand.cs
- RangeContentEnumerator.cs
- TextureBrush.cs
- SecurityTokenTypes.cs
- DES.cs
- ReferenceEqualityComparer.cs
- Encoder.cs
- BStrWrapper.cs
- TableCellCollection.cs
- ConnectionStringsExpressionBuilder.cs
- COM2ExtendedBrowsingHandler.cs
- Matrix3DConverter.cs
- DotAtomReader.cs
- cryptoapiTransform.cs
- InvokeWebService.cs
- Table.cs
- TdsParserHelperClasses.cs
- DynamicDataResources.Designer.cs
- TextRunCacheImp.cs
- KeyPullup.cs
- XmlSchemaSimpleTypeList.cs