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
- InvalidOperationException.cs
- ActionItem.cs
- Rect3DValueSerializer.cs
- WhereaboutsReader.cs
- PermissionListSet.cs
- AdornerPresentationContext.cs
- VarRemapper.cs
- DataControlPagerLinkButton.cs
- Array.cs
- SqlBuffer.cs
- ServicesExceptionNotHandledEventArgs.cs
- Parser.cs
- KeyPressEvent.cs
- WindowsTitleBar.cs
- InstanceDataCollectionCollection.cs
- DrawingAttributeSerializer.cs
- DeferredReference.cs
- RuntimeHandles.cs
- URLAttribute.cs
- SplayTreeNode.cs
- WebSysDefaultValueAttribute.cs
- ObjectDataSourceFilteringEventArgs.cs
- ThreadAttributes.cs
- BuildProviderCollection.cs
- SoapFault.cs
- CompoundFileDeflateTransform.cs
- AnnotationComponentManager.cs
- ExternalFile.cs
- SystemIcmpV6Statistics.cs
- BatchServiceHost.cs
- DefaultParameterValueAttribute.cs
- HtmlInputSubmit.cs
- TouchesCapturedWithinProperty.cs
- XmlComplianceUtil.cs
- EntityStoreSchemaGenerator.cs
- XmlEncoding.cs
- EDesignUtil.cs
- EntityCommandCompilationException.cs
- StrokeRenderer.cs
- BitmapFrameDecode.cs
- JsonServiceDocumentSerializer.cs
- SHA1.cs
- XmlArrayAttribute.cs
- CatalogZone.cs
- DropTarget.cs
- PolyLineSegment.cs
- FixedSOMTextRun.cs
- Helpers.cs
- TextLine.cs
- MethodSet.cs
- SoapTypeAttribute.cs
- util.cs
- CellIdBoolean.cs
- Attachment.cs
- HierarchicalDataSourceConverter.cs
- SafeLibraryHandle.cs
- PackageStore.cs
- SizeAnimationBase.cs
- RowsCopiedEventArgs.cs
- _PooledStream.cs
- DataTemplate.cs
- DynamicQueryStringParameter.cs
- EventMappingSettings.cs
- EdmComplexTypeAttribute.cs
- MobileComponentEditorPage.cs
- WindowsAuthenticationEventArgs.cs
- InternalSafeNativeMethods.cs
- FormatterServices.cs
- MdiWindowListStrip.cs
- Transform3DGroup.cs
- DeliveryStrategy.cs
- BitmapEffectDrawingContextWalker.cs
- DataGridTablesFactory.cs
- mediapermission.cs
- XmlILIndex.cs
- ConfigurationElementProperty.cs
- MsmqDecodeHelper.cs
- BufferedGraphicsManager.cs
- WindowsGraphicsWrapper.cs
- JsonWriter.cs
- DropSource.cs
- ParameterCollection.cs
- Pen.cs
- ContentIterators.cs
- TextElementEditingBehaviorAttribute.cs
- AssemblyCollection.cs
- UserInitiatedRoutedEventPermission.cs
- InvalidComObjectException.cs
- EarlyBoundInfo.cs
- UidPropertyAttribute.cs
- MessageSmuggler.cs
- GorillaCodec.cs
- Rotation3D.cs
- TableCell.cs
- entitydatasourceentitysetnameconverter.cs
- SSmlParser.cs
- HwndKeyboardInputProvider.cs
- WebBrowserPermission.cs
- DataException.cs
- Attributes.cs