Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Print / Reach / AlphaFlattener / PrimitiveRenderer.cs / 1 / PrimitiveRenderer.cs
//------------------------------------------------------------------------------ // Microsoft Printing // Copyright (c) Microsoft Corporation, 2004 // // File: PrimitveRenderer.cs // // History: // [....]: 04/20/2004 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; // for BitmapSource using System.Windows.Shapes; // for Glyphs PresentationFramework.dll using System.Collections.Generic; namespace Microsoft.Internal.AlphaFlattener { ////// Render a primitive to IProxyDrawingContext /// internal class PrimitiveRenderer { #region Public Methods // External API public void RenderImage(ImageProxy image, Rect dest, Geometry clip, Matrix trans, string desp) { if (image == null) { return; } Geometry bounds; bool clipToBounds; if (clip == null) { // no clipping needed, draw everything bounds = Utility.TransformGeometry(new RectangleGeometry(dest), trans); clipToBounds = false; } else { // clip to provided geometry. it's already in world space bounds = clip; clipToBounds = true; } RenderImage(image, dest, bounds, clipToBounds, 0, trans, desp); } // External API public void DrawGeometry(Geometry cur, string desp, GeometryPrimitive gp) { if (cur == null) { return; } int start = 0; PrimitiveInfo topPI; Geometry topBounds; Geometry inter; if (_pen != null) { Debug.Assert(_brush == null, "no brush"); if ((_overlapping != null) && FindIntersection(gp.WidenGeometry, ref start, out topPI, out topBounds, out inter)) { cur = gp.WidenGeometry; _brush = _pen.StrokeBrush; _pen = null; // Draw the stroking as filling widened path #if DEBUG FillGeometry(topPI, cur, desp + "_widen", null, null, start, inter, topBounds); #else FillGeometry(topPI, cur, null, null, null, start, inter, topBounds); #endif } else { // Render to dc if nothing on top _dc.Comment(desp); _dc.DrawGeometry(_brush, _pen, cur, _clip, Matrix.Identity, ProxyDrawingFlags.None); } } else { if (FindIntersection(cur, ref start, out topPI, out topBounds, out inter)) { FillGeometry(topPI, cur, desp, null, null, start, inter, topBounds); } else { // Render to dc if nothing on top _dc.Comment(desp); _dc.DrawGeometry(_brush, _pen, cur, _clip, Matrix.Identity, ProxyDrawingFlags.None); } } } // External API public bool DrawGlyphs(GlyphRun glyphrun, Rect bounds, Matrix trans, string desp) { if (glyphrun == null) { return true; } int start = 0; PrimitiveInfo topPI; Geometry topBounds; Geometry inter; // If glyph has intersection with something on the top, change to geometry fill // Use bounding rectangle to test for overlapping first, avoinding expensive BuildGeometry call if ((_overlapping != null) && FindIntersection(new RectangleGeometry(bounds), ref start, out topPI, out topBounds, out inter)) { start = 0; Geometry cur = glyphrun.BuildGeometry(); cur = Utility.TransformGeometry(cur, trans); if (FindIntersection(cur, ref start, out topPI, out topBounds, out inter)) { // FillGeometry expects brush in world space. Apply trans to brush. if (_brush != null) { _brush = _brush.ApplyTransformCopy(trans); } FillGeometry(topPI, cur, desp, null, null, start, inter, topBounds); return true; } } _dc.Comment(desp); return _dc.DrawGlyphs(glyphrun, _clip, trans, _brush); } #endregion #region Public Properties public Geometry Clip { set { _clip = value; } } public BrushProxy Brush { get { return _brush; } set { _brush = value; } } public PenProxy Pen { get { return _pen; } set { _pen = value; } } public ListOverlapping { set { _overlapping = value; } } public List Commands { set { _commands = value; } } public IProxyDrawingContext DC { set { _dc = value; } } public bool Disjoint { set { _disjoint = value; } } #endregion #region Private Static Methods private static Matrix ReverseMap(Matrix trans, Rect dest, double width, double height) { // Render the intersection using blended image Matrix mat = Matrix.Identity; // Transformation from source rect to destination mat.Scale(dest.Width / width, dest.Height / height); mat.Translate(dest.Left, dest.Top); // Transformation from source rect to canvas coordinate space mat.Append(trans); // from canvas to source rect mat.Invert(); return mat; } #if DEBUG private static string Oper(string t1, char op, string t2) { char[] opers = new char[2]; opers[0] = '-'; opers[1] = '*'; if ((op != '-') && t1.IndexOfAny(opers) >= 0) { t1 = "(" + t1 + ")"; } if (t2.IndexOfAny(opers) >= 0) { t2 = "(" + t2 + ")"; } return t1 + op + t2; } #endif #endregion #region Private Methods private void RenderImage( ImageProxy image, Rect dest, Geometry bounds, bool clipToBounds, int start, Matrix trans, string desp ) { PrimitiveInfo topPI; Geometry topBounds; Geometry inter; if (FindIntersection(bounds, ref start, out topPI, out topBounds, out inter)) { Primitive p = topPI.primitive; Geometry diff = Utility.Exclude(bounds, topBounds, trans); // DrawImage may modify image ImageProxy imageBlend = new ImageProxy(image.GetImage()); if (diff != null) { // Render cur - top #if DEBUG RenderImage(image, dest, diff, true, start + 1, trans, Oper(desp, '-', topPI.id)); #else RenderImage(image, dest, diff, true, start + 1, trans, null); #endif } if (!p.IsTransparent) { #if DEBUG topPI.id = Oper(topPI.id, '-', Oper(desp, '.', "bounds")); #endif // Render the intersection using blended image p.BlendOverImage(imageBlend, ReverseMap(trans, dest, imageBlend.PixelWidth, imageBlend.PixelHeight)); #if DEBUG RenderImage(imageBlend, dest, inter, true, start + 1, trans, Oper(desp, '*', topPI.id)); #else RenderImage(imageBlend, dest, inter, true, start + 1, trans, null); #endif } p.Exclude(bounds); } else { Geometry clip = _clip; bool empty = false; if (clipToBounds) { clip = Utility.Intersect(clip, bounds, Matrix.Identity, out empty); } if (!empty) { _dc.Comment(desp); _dc.DrawImage(image, dest, clip, trans); } } } // Find the next Primitive having intersection with cur in overlapping list private bool FindIntersection(Geometry cur, ref int start, out PrimitiveInfo topPI, out Geometry topBounds, out Geometry inter) { topPI = null; topBounds = null; inter = null; if (_overlapping == null) { return false; } // If not in a subtree which needs composition, igore overlapping list if all are opaque if (!_disjoint) { bool allopaque = true; for (int s = start; s < _overlapping.Count; s++) { PrimitiveInfo pi = _commands[_overlapping[s]] as PrimitiveInfo; if ((pi != null) && !pi.primitive.IsTransparent && !pi.primitive.IsOpaque) { allopaque = false; break; } } if (allopaque) { return false; } } // Search for all possible intersections while (start < _overlapping.Count) { topPI = _commands[_overlapping[start]] as PrimitiveInfo; if (!topPI.primitive.IsTransparent) // Skip primitives with nothing to draw { topBounds = topPI.primitive.GetClippedShapeGeometry(); if (topBounds != null) { bool empty; inter = Utility.Intersect(cur, topBounds, Matrix.Identity, out empty); if (inter != null) { return true; } } } start++; } return false; } // Recursive // _brush must be in world space private void FillGeometry(Geometry cur, string desp, Geometry curAlt, string despAlt, int start) { PrimitiveInfo pi; Geometry top; Geometry inter; if (FindIntersection(cur, ref start, out pi, out top, out inter)) { FillGeometry(pi, cur, desp, curAlt, despAlt, start, inter, top); } else { if (curAlt != null) { cur = curAlt; desp = despAlt; } // Render to dc if nothing on top _dc.Comment(desp); _dc.DrawGeometry(_brush, _pen, cur, _clip, Matrix.Identity, ProxyDrawingFlags.None); } } // Recursive // _brush must be in world space private void FillGeometry( PrimitiveInfo topPI, Geometry cur, string desp, Geometry curAlt, string despAlt, int start, Geometry inter, Geometry topBounds ) { Primitive p = topPI.primitive; Geometry diff = Utility.Exclude(cur, topBounds, Matrix.Identity); if (diff != null) { // Render cur [- topBounds] using original brush if (_disjoint) { #if DEBUG FillGeometry(diff, Oper(desp, '-', topPI.id), null, null, start + 1); #else FillGeometry(diff, null, null, null, start + 1); #endif } else { // Only diff = cur - topBounds need to be rendered. But it may generate more // complicated path and gaps between objects if (curAlt != null) { #if DEBUG FillGeometry(diff, Oper(desp, '-', topPI.id), curAlt, despAlt, start + 1); #else FillGeometry(diff, null, curAlt, despAlt, start + 1); #endif } else { #if DEBUG FillGeometry(diff, Oper(desp, '-', topPI.id), cur, desp, start + 1); #else FillGeometry(diff, null, cur, desp, start + 1); #endif } } } //if (_disjoint || ! p.IsOpaque) { if (topPI.primitive is ImagePrimitive) { // If primitve on the top is ImagePrimitive, change it to DrawImage with blended image. // An alternative will be generating an image brush ImagePrimitive ip = topPI.primitive as ImagePrimitive; bool empty; double imageWidth = ip.Image.Image.Width; double imageHeight = ip.Image.Image.Height; // Get clip in world space. Geometry clip = Utility.Intersect(inter, Utility.TransformGeometry(new RectangleGeometry(ip.DstRect), ip.Transform), ip.Transform, out empty); if (!empty) { // Get clip bounds in image space. Geometry clipImageSpace = Utility.TransformGeometry(clip, ReverseMap(ip.Transform, ip.DstRect, imageWidth, imageHeight)); Rect drawBounds = clipImageSpace.Bounds; // Clip image data to the intersection. Resulting draw bounds are in image space. BitmapSource clippedImage = ip.Image.GetClippedImage(drawBounds, out drawBounds); if (clippedImage != null) { // Transform draw bounds back to world space. drawBounds.Scale(ip.DstRect.Width / imageWidth, ip.DstRect.Height / imageHeight); drawBounds.Offset(ip.DstRect.Left, ip.DstRect.Top); ImageProxy image = new ImageProxy(clippedImage); // Blend image with other brush, then render composited image. image.BlendOverBrush(false, _brush, ReverseMap(ip.Transform, drawBounds, image.PixelWidth, image.PixelHeight)); #if DEBUG RenderImage(image, drawBounds, clip, true, start + 1, ip.Transform, Oper(desp, '*', topPI.id)); #else RenderImage(image, drawBounds, clip, true, start + 1, ip.Transform, null); #endif } } } else { // -- If top primitive opaque, skip the intersection // -- If current primitive is completely covered by an opaque object, skip the intersection if (p.IsOpaque) // && Utility.Covers(topBounds, cur)) { cur = null; } else { // Render the intersection using blended brush BrushProxy oldbrush = _brush; _brush = p.BlendBrush(_brush); #if DEBUG FillGeometry(inter, Oper(desp, '*', topPI.id), null, null, start + 1); #else FillGeometry(inter, null, null, null, start + 1); #endif _brush = oldbrush; } } if (cur != null) { bool empty; Geometry geo = Utility.Intersect(cur, _clip, Matrix.Identity, out empty); if (geo != null) { topPI.primitive.Exclude(geo); // exclude cur & _clip #if DEBUG topPI.id = Oper(topPI.id, '-', Oper(desp, '*', Oper(desp, '.', "c"))); #endif } } } } #endregion #region Private Fields private Geometry _clip; private BrushProxy _brush; // primitive brush, possibly in world space private PenProxy _pen; private List _overlapping; private List _commands; private IProxyDrawingContext _dc; private bool _disjoint; #endregion } // end of class PrimitiveRenderer } // 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
- TimeStampChecker.cs
- EntityDataSourceWizardForm.cs
- Propagator.Evaluator.cs
- DesignerActionService.cs
- FacetChecker.cs
- EmptyCollection.cs
- CqlLexerHelpers.cs
- HtmlAnchor.cs
- XmlQueryType.cs
- Expression.cs
- DataColumnPropertyDescriptor.cs
- RowCache.cs
- PassportAuthenticationModule.cs
- FloaterBaseParagraph.cs
- CounterCreationData.cs
- XmlCodeExporter.cs
- ComboBox.cs
- ComponentRenameEvent.cs
- DesignerForm.cs
- TextRunTypographyProperties.cs
- ComplusTypeValidator.cs
- PrivilegeNotHeldException.cs
- ProgressPage.cs
- ButtonPopupAdapter.cs
- ZipPackage.cs
- Trustee.cs
- SecurityHelper.cs
- TableAutomationPeer.cs
- StrongNameUtility.cs
- DefaultTextStoreTextComposition.cs
- SynchronizingStream.cs
- XmlNodeChangedEventArgs.cs
- SqlClientPermission.cs
- UnsafeNativeMethodsCLR.cs
- Drawing.cs
- MethodRental.cs
- XmlLoader.cs
- activationcontext.cs
- EntityModelSchemaGenerator.cs
- AssemblyInfo.cs
- _ProxyChain.cs
- NonParentingControl.cs
- CompilerResults.cs
- GeneralTransform3D.cs
- TextAdaptor.cs
- DetailsView.cs
- ConfigXmlSignificantWhitespace.cs
- ToolStripOverflowButton.cs
- Visual.cs
- ToolboxDataAttribute.cs
- XmlParserContext.cs
- ValidationErrorCollection.cs
- ProcessModelSection.cs
- BamlResourceContent.cs
- VisualStyleInformation.cs
- DataGridViewButtonCell.cs
- CaretElement.cs
- SortedList.cs
- ProfilePropertyMetadata.cs
- LinkConverter.cs
- TabPanel.cs
- GroupQuery.cs
- DefaultHttpHandler.cs
- NullableDecimalAverageAggregationOperator.cs
- StringConverter.cs
- loginstatus.cs
- OleDbConnection.cs
- InternalDispatchObject.cs
- XmlSerializableWriter.cs
- ToolBar.cs
- StaticExtensionConverter.cs
- BufferedGraphics.cs
- BaseProcessor.cs
- RectangleGeometry.cs
- PaintValueEventArgs.cs
- WebResourceAttribute.cs
- SoapSchemaMember.cs
- fixedPageContentExtractor.cs
- ImportCatalogPart.cs
- FileBasedResourceGroveler.cs
- RegexCode.cs
- Duration.cs
- DataTable.cs
- ResourceReferenceKeyNotFoundException.cs
- ObjectIDGenerator.cs
- PeerNameRecord.cs
- RequestCacheManager.cs
- CanonicalizationDriver.cs
- DataMemberAttribute.cs
- AutomationEvent.cs
- XmlILConstructAnalyzer.cs
- WinOEToolBoxItem.cs
- PathFigureCollection.cs
- SaveFileDialog.cs
- AttributeCollection.cs
- PointConverter.cs
- RawStylusInputReport.cs
- MatrixKeyFrameCollection.cs
- TransformCollection.cs
- PropertyValueEditor.cs