Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / 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
- DataService.cs
- CultureInfoConverter.cs
- FontInfo.cs
- IgnoreSectionHandler.cs
- ToolStripRenderer.cs
- OdbcParameter.cs
- BindStream.cs
- DbDeleteCommandTree.cs
- RadioButtonList.cs
- NumberSubstitution.cs
- CommonEndpointBehaviorElement.cs
- InlineObject.cs
- ParameterDataSourceExpression.cs
- HierarchicalDataBoundControlAdapter.cs
- ConfigXmlWhitespace.cs
- WorkflowTransactionService.cs
- SmiMetaData.cs
- LicenseProviderAttribute.cs
- DateTimeOffsetStorage.cs
- XmlSchemaFacet.cs
- PlatformNotSupportedException.cs
- CompilerErrorCollection.cs
- TextDocumentView.cs
- ListControlConvertEventArgs.cs
- AbsoluteQuery.cs
- TimeSpanStorage.cs
- SinglePhaseEnlistment.cs
- ControlTemplate.cs
- _ConnectStream.cs
- PropertyMap.cs
- WebPartEditorCancelVerb.cs
- WasAdminWrapper.cs
- X509SubjectKeyIdentifierClause.cs
- HScrollBar.cs
- PackagingUtilities.cs
- Asn1Utilities.cs
- WindowsUpDown.cs
- TraceSection.cs
- MetadataArtifactLoaderCompositeFile.cs
- ConfigurationSettings.cs
- PinProtectionHelper.cs
- ExtenderProvidedPropertyAttribute.cs
- FixedSOMPage.cs
- FacetChecker.cs
- Transform.cs
- IdnElement.cs
- KoreanLunisolarCalendar.cs
- PreviewPageInfo.cs
- TableLayoutPanelResizeGlyph.cs
- StorageAssociationTypeMapping.cs
- HttpResponseInternalBase.cs
- ComEventsMethod.cs
- BrushMappingModeValidation.cs
- SubMenuStyle.cs
- _LocalDataStore.cs
- SessionIDManager.cs
- XmlSchemaFacet.cs
- DataServiceHostFactory.cs
- PartitionedStream.cs
- ZipIOEndOfCentralDirectoryBlock.cs
- StylusButtonEventArgs.cs
- Calendar.cs
- UriExt.cs
- InitializingNewItemEventArgs.cs
- Point3DCollectionConverter.cs
- CustomErrorsSection.cs
- TextSelectionHelper.cs
- EasingFunctionBase.cs
- TerminatorSinks.cs
- HttpListener.cs
- ResourcePermissionBase.cs
- PointLightBase.cs
- GcHandle.cs
- SqlWriter.cs
- KeyEvent.cs
- ErrorRuntimeConfig.cs
- COMException.cs
- EnterpriseServicesHelper.cs
- assertwrapper.cs
- DispatcherSynchronizationContext.cs
- SourceElementsCollection.cs
- PointIndependentAnimationStorage.cs
- TimeSpanMinutesOrInfiniteConverter.cs
- MultipleViewPattern.cs
- IConvertible.cs
- StreamingContext.cs
- HiddenFieldPageStatePersister.cs
- SendAgentStatusRequest.cs
- TypeRestriction.cs
- DataGridViewToolTip.cs
- SqlWebEventProvider.cs
- CodeCatchClause.cs
- TabPage.cs
- Parallel.cs
- UInt64Converter.cs
- MessageEncoderFactory.cs
- MenuItemBindingCollection.cs
- XPathAxisIterator.cs
- Typography.cs
- ValueUnavailableException.cs