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
- DataChangedEventManager.cs
- JavaScriptString.cs
- _emptywebproxy.cs
- DoubleCollectionConverter.cs
- RegexCompilationInfo.cs
- MimeXmlReflector.cs
- FunctionGenerator.cs
- CommandSet.cs
- NamespaceDecl.cs
- TraceAsyncResult.cs
- SqlEnums.cs
- TransformerInfoCollection.cs
- RequestCachePolicyConverter.cs
- RangeBase.cs
- DesignerWebPartChrome.cs
- SafeRightsManagementEnvironmentHandle.cs
- UrlMappingCollection.cs
- ServiceModelEnumValidatorAttribute.cs
- ObjectPersistData.cs
- TokenBasedSetEnumerator.cs
- FragmentQuery.cs
- Ticks.cs
- AspCompat.cs
- BitmapEffectState.cs
- TableDetailsRow.cs
- Int16Animation.cs
- ToolBarTray.cs
- ResizeGrip.cs
- TableLayoutCellPaintEventArgs.cs
- RenameRuleObjectDialog.cs
- WindowsButton.cs
- XamlDesignerSerializationManager.cs
- InternalResources.cs
- XmlKeywords.cs
- MessageVersion.cs
- TimeSpanOrInfiniteConverter.cs
- bindurihelper.cs
- ContextMenuService.cs
- AutomationEventArgs.cs
- ServerProtocol.cs
- TargetInvocationException.cs
- PropertyManager.cs
- userdatakeys.cs
- HttpResponse.cs
- Serializer.cs
- TemplateEditingVerb.cs
- TabletCollection.cs
- MarkupObject.cs
- Calendar.cs
- RegexGroupCollection.cs
- RawStylusActions.cs
- ProcessModuleCollection.cs
- IsolatedStorage.cs
- TcpChannelListener.cs
- SelectionPattern.cs
- BitmapEffectDrawingContent.cs
- SignedInfo.cs
- BooleanExpr.cs
- GridProviderWrapper.cs
- ExceptionValidationRule.cs
- Config.cs
- ProxyAttribute.cs
- StyleSheet.cs
- AQNBuilder.cs
- EntityConnection.cs
- FaultBookmark.cs
- PriorityItem.cs
- AssemblyCache.cs
- BitmapInitialize.cs
- FormViewDeletedEventArgs.cs
- TextParagraphCache.cs
- Site.cs
- Console.cs
- ThreadAbortException.cs
- GetLedgerEntryForRecipientRequest.cs
- SpanIndex.cs
- ListBoxDesigner.cs
- RegexCaptureCollection.cs
- BulletedListEventArgs.cs
- XmlChildNodes.cs
- CollectionsUtil.cs
- TextRunCacheImp.cs
- SID.cs
- WizardForm.cs
- Context.cs
- TemplateField.cs
- DataControlHelper.cs
- Configuration.cs
- AudioLevelUpdatedEventArgs.cs
- BitmapCacheBrush.cs
- XmlSiteMapProvider.cs
- DocumentsTrace.cs
- DataView.cs
- TextDecorationCollection.cs
- XmlSchemaAppInfo.cs
- UIElementPropertyUndoUnit.cs
- ChildDocumentBlock.cs
- RequestCacheManager.cs
- SiteMapSection.cs
- ConnectionStringSettingsCollection.cs