Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Print / Reach / AlphaFlattener / Optimizer.cs / 1 / Optimizer.cs
//------------------------------------------------------------------------------ // Microsoft Printing // Copyright (c) Microsoft Corporation, 2005 // // File: Optimizer.cs // // History: // [....]: 06/24/2005 Created //----------------------------------------------------------------------------- using System; using System.Diagnostics; using System.Collections; // for ArrayList using System.Windows; // for Rect WindowsBase.dll using System.Windows.Media; // for Geometry, Brush, ImageData. PresentationCore.dll using System.Windows.Media.Imaging; using System.Collections.Generic; using System.Windows.Xps.Serialization; namespace Microsoft.Internal.AlphaFlattener { internal class Cluster { #region Private Fields private Listm_primitives; private Rect m_bounds; #if DEBUG private bool m_debugRasterize; #endif private int m_lowestPrimitive; // lowest index in m_primitives #endregion #region Constructors public Cluster() { m_primitives = new List (); m_bounds = Rect.Empty; m_lowestPrimitive = int.MaxValue; } #endregion #region Public Methods public void Render(List commands, IProxyDrawingContext dc) { Toolbox.StartEvent(Toolbox.DRXRASTERGUID); int width = (int)Math.Round(m_bounds.Width * Configuration.RasterizationDPI / 96); int height = (int)Math.Round(m_bounds.Height * Configuration.RasterizationDPI / 96); if ((width >= 1) && (height >= 1)) // Skip shape which is too small { Matrix mat = Utility.CreateMappingTransform(m_bounds, width, height); RenderTargetBitmap brushImage = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32); DrawingVisual visual = new DrawingVisual(); // clip image to the primitives it contains Geometry clip = null; using (DrawingContext ctx = visual.RenderOpen()) { ctx.PushTransform(new MatrixTransform(mat)); m_primitives.Sort(); foreach (int i in m_primitives) { Primitive primitive = commands[i].primitive; // Fix bug 1396393: Can't use AddToCluster without fixing that bug. // We need to clip cluster to primitives in case primitives have clipping. Debug.Assert(GetPrimitiveIntersectAction() == PrimitiveIntersectAction.ClipToCluster); bool empty; Geometry geometry = Utility.Intersect(primitive.GetShapeGeometry(), primitive.Clip, Matrix.Identity, out empty); if (!empty) { primitive.OnRender(ctx); // clip cluster to this clipped primitive. we must have geometry information, // otherwise the primitive will be clipped away. Debug.Assert(geometry != null, "No geometry available for primitive"); if (clip == null) { clip = geometry; } else { CombinedGeometry cg = new CombinedGeometry(); // Opt-out of inheritance through the new Freezable. cg.CanBeInheritanceContext = false; cg.GeometryCombineMode = GeometryCombineMode.Union; cg.Geometry1 = clip; cg.Geometry2 = geometry; clip = cg; } } commands[i] = null; // Command can be deleted after cluster is rendered } ctx.Pop(); } brushImage.Render(visual); Toolbox.EndEvent(Toolbox.DRXRASTERGUID); dc.DrawImage(new ImageProxy(brushImage), m_bounds, clip, Matrix.Identity); } } #endregion #region Public Static Methods public static void CheckForRasterization(List clusters, List commands) { foreach (Cluster c in clusters) { if (c.BetterRasterize(commands)) { #if DEBUG c.m_debugRasterize = true; #endif foreach (int i in c.m_primitives) { commands[i].m_cluster = c; } } } } public static List CalculateCluster(List commands, int count, bool disjoint, List [] oldUnderlay) { List transparentCluster = new List (); // indicates which primitives have been added to any cluster bool[] addedPrimitives = new bool[commands.Count]; // calculate clusters until cluster bounds stabilize while (true) { bool clusterBoundsChanged = CalculateClusterCore( commands, count, disjoint, oldUnderlay, transparentCluster, addedPrimitives ); if (!clusterBoundsChanged || GetPrimitiveIntersectAction() != PrimitiveIntersectAction.AddToCluster) break; // // Cluster bounds have changed somewhere, need to examine all primitives that haven't // been added to a cluster and test for intersection with cluster. We add primitives // that intersect and rendered before the cluster. // // Note that here we check even opaque primitives, since they might get covered // by a transparent cluster, and thus need to be rasterized with a cluster if intersection // exists. // for (int primIndex = 0; primIndex < addedPrimitives.Length; primIndex++) { if (!addedPrimitives[primIndex] && commands[primIndex] != null) { PrimitiveInfo primitive = commands[primIndex]; for (int clusterIndex = 0; clusterIndex < transparentCluster.Count; clusterIndex++) { Cluster cluster = transparentCluster[clusterIndex]; if (primitive.GetClippedBounds().IntersectsWith(cluster.m_bounds) && primIndex < cluster.m_lowestPrimitive) { // primitive intersects this cluster, add to cluster cluster.Add( primIndex, oldUnderlay, commands, addedPrimitives ); } } } } } return transparentCluster; } #endregion #region Private Methods /// /// What action to take to handle cases where primitives intersect a cluster's bounding box, /// but does not touch any of the cluster's primitives. /// private enum PrimitiveIntersectAction { ////// Don't do anything, behavior corresponds to /// bug 1267200: MGC - ToolBarTray element does not print in some cases. /// None, ////// Adds the primitive to the cluster for rasterization. /// AddToCluster, ////// Clips the cluster rasterized image to the primitives it contains. /// ClipToCluster, } private static PrimitiveIntersectAction GetPrimitiveIntersectAction() { // // Fix bug 1396393: Printing: Background pictures are only partially printed for an xCal calendar // // The bug involves printing a calendar. What happens is the January ImagePrimitive is clipped // to the rectangle for January, but it's rasterized as part of a cluster with a color fill of // that same rectangle. Cluster rasterization loses the clipping on the picture, which effectively // makes the cluster grow to overlap April below January. This causes April to appear clipped. // // Fixing involves clipping clusters to its clipped primitives. As such, AddToCluster cannot // be used without further fixes. // return PrimitiveIntersectAction.ClipToCluster; } ////// Adds primitive to this cluster. /// /// primitive index /// underlay information /// list of primitives /// indicates which primitives have been added to any cluster private void Add( int i, List[] underlay, List commands, bool[] addedPrimitives ) { // clip bounds to avoid generating excessively large cluster Rect bounds = commands[i].GetClippedBounds(); m_bounds.Union(bounds); m_primitives.Add(i); addedPrimitives[i] = true; if (i < m_lowestPrimitive) { m_lowestPrimitive = i; } // Add all primitives covered by i recursively if ((underlay != null) && (underlay[i] != null)) { foreach (int j in underlay[i]) { if ((commands[j] != null) && m_primitives.IndexOf(j) < 0) { Add(j, underlay, commands, addedPrimitives); } } } } private void MergeWith(Cluster c) { m_bounds.Union(c.m_bounds); for (int i = 0; i < c.m_primitives.Count; i++) { if (m_primitives.IndexOf(c.m_primitives[i]) < 0) { m_primitives.Add(c.m_primitives[i]); } } } /// /// Check if the whole cluster is complex enough such that rasterizing the whole thing is better than flattening it /// /// ///private bool BetterRasterize(List commands) { double clustersize = m_bounds.Width * m_bounds.Height; double diff = - Configuration.RasterizationCost(m_bounds.Width, m_bounds.Height); // Estimate cost of geometry operations (intersecting) double pathComplexity = 1; foreach (int i in m_primitives) { PrimitiveInfo pi = commands[i]; Primitive p = pi.primitive; GeometryPrimitive gp = p as GeometryPrimitive; Rect bounds = pi.GetClippedBounds(); bool rasterize = true; if (gp != null) { double complexity = 1; Geometry geo = gp.Geometry; if (geo != null) { complexity = Utility.GetGeometryPointCount(geo); // weight down the complexity of small region complexity *= bounds.Width * bounds.Height / clustersize; } BrushProxy bp = gp.Brush; if (bp == null) { bp = gp.Pen.StrokeBrush; // Widen path would at least double the points complexity *= 3; } if (complexity > 1) { pathComplexity *= complexity; if (pathComplexity > 100000) // 333 x 333 { return true; } } if (bp != null) { Brush b = bp.Brush; if ((b != null) && ((b is SolidColorBrush) || (b is LinearGradientBrush))) { // SolidColorBrush does not need full rasterization // Vertical/Horizontal linear gradient brush does not need full rasterization rasterize = false; } } } if (rasterize) { diff += Configuration.RasterizationCost(bounds.Width, bounds.Height); if (diff > 0) { break; } } } return diff > 0; } /// /// Calculates list of transparent clusters, returning true if clusters added or bounding rectangles changed. /// private static bool CalculateClusterCore( Listcommands, int count, bool disjoint, List [] oldUnderlay, List transparentCluster, bool[] addedPrimitives // primitives added to clusters ) { bool clusterBoundsChanged = false; // Build clusters of transparent primitives for (int i = 0; i < count; i++) { PrimitiveInfo pi = commands[i]; // When disjoint is true (flattening a subtree), add all primitives to a single cluster if ((pi != null) && (disjoint || !pi.primitive.IsOpaque) && !addedPrimitives[i]) { Rect bounds = pi.GetClippedBounds(); Cluster home = null; for (int j = 0; j < transparentCluster.Count; j++) { Cluster c = transparentCluster[j]; if (disjoint || bounds.IntersectsWith(c.m_bounds)) { home = c; break; } } if (home == null) { home = new Cluster(); transparentCluster.Add(home); } Rect oldClusterBounds = home.m_bounds; home.Add(i, oldUnderlay, commands, addedPrimitives); if (!clusterBoundsChanged && oldClusterBounds != home.m_bounds) { // cluster bounds have changed clusterBoundsChanged = true; } } } // Merges clusters which touch each other bool changed; do { changed = false; for (int i = 0; i < transparentCluster.Count; i++) for (int j = i + 1; j < transparentCluster.Count; j++) { if (transparentCluster[i].m_bounds.IntersectsWith(transparentCluster[j].m_bounds)) { transparentCluster[i].MergeWith(transparentCluster[j]); // cluster bounds have changed since merging two clusters clusterBoundsChanged = true; transparentCluster.RemoveAt(j); changed = true; break; } } } while (changed); return clusterBoundsChanged; } #endregion #if DEBUG internal List DebugPrimitives { get { return m_primitives; } } internal Rect DebugBounds { get { return m_bounds; } } internal bool DebugRasterize { get { return m_debugRasterize; } } #endif } } // end of namespace // 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
- LaxModeSecurityHeaderElementInferenceEngine.cs
- smtppermission.cs
- PageCatalogPart.cs
- Timeline.cs
- ExternalException.cs
- MenuItemBindingCollection.cs
- FamilyCollection.cs
- UnmanagedMemoryStreamWrapper.cs
- IndexerNameAttribute.cs
- TextTreeText.cs
- arc.cs
- DSASignatureDeformatter.cs
- DependencyObjectPropertyDescriptor.cs
- BulletChrome.cs
- DebugView.cs
- BufferedReadStream.cs
- TextBoxBase.cs
- TraceHandlerErrorFormatter.cs
- ColorConvertedBitmap.cs
- CatalogPart.cs
- VisualStyleTypesAndProperties.cs
- SubMenuStyle.cs
- Internal.cs
- SendDesigner.xaml.cs
- QilReference.cs
- SelfIssuedAuthRSAPKCS1SignatureFormatter.cs
- Publisher.cs
- InvalidOperationException.cs
- SafeFileMappingHandle.cs
- DetailsViewInsertEventArgs.cs
- CodeCommentStatementCollection.cs
- IntegerFacetDescriptionElement.cs
- Typography.cs
- DesignerAttributeInfo.cs
- CodeTypeOfExpression.cs
- DescendentsWalker.cs
- AttachmentCollection.cs
- WebPartTransformerAttribute.cs
- ApplicationDirectoryMembershipCondition.cs
- FormViewDesigner.cs
- ToolStripPanelSelectionGlyph.cs
- MetadataSource.cs
- CookielessHelper.cs
- GestureRecognizer.cs
- NetworkCredential.cs
- DeflateInput.cs
- RemoteX509AsymmetricSecurityKey.cs
- Exceptions.cs
- Effect.cs
- PolyLineSegment.cs
- ResourceExpressionEditor.cs
- SqlBulkCopyColumnMapping.cs
- AnimationException.cs
- DataGridHelper.cs
- CopyCodeAction.cs
- WS2007FederationHttpBinding.cs
- OneOfScalarConst.cs
- NeutralResourcesLanguageAttribute.cs
- CustomValidator.cs
- DefaultWorkflowTransactionService.cs
- baseaxisquery.cs
- ObjectListCommandCollection.cs
- JpegBitmapDecoder.cs
- ThreadAbortException.cs
- ExternalException.cs
- DbConnectionPool.cs
- DialogResultConverter.cs
- VerbConverter.cs
- SystemThemeKey.cs
- CurrentTimeZone.cs
- ModelVisual3D.cs
- RegionInfo.cs
- GACIdentityPermission.cs
- XhtmlTextWriter.cs
- ExtensionSurface.cs
- UriParserTemplates.cs
- BlockCollection.cs
- Action.cs
- Mapping.cs
- ScrollBar.cs
- HttpStreamXmlDictionaryWriter.cs
- FormatStringEditor.cs
- ObjectViewEntityCollectionData.cs
- CssTextWriter.cs
- LocationUpdates.cs
- PingReply.cs
- ToolStripGripRenderEventArgs.cs
- GenericWebPart.cs
- Comparer.cs
- LocatorPartList.cs
- SafeReadContext.cs
- BamlResourceDeserializer.cs
- SingleSelectRootGridEntry.cs
- Animatable.cs
- Storyboard.cs
- XpsDigitalSignature.cs
- MessageSmuggler.cs
- CompositeKey.cs
- FunctionGenerator.cs
- ProvidePropertyAttribute.cs