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
- NativeBuffer.cs
- ScrollData.cs
- ApplicationContext.cs
- TextOptions.cs
- ServiceParser.cs
- SoapClientMessage.cs
- XmlWellformedWriter.cs
- ScriptServiceAttribute.cs
- SchemaTableColumn.cs
- NumericUpDown.cs
- TraceData.cs
- DataGridTemplateColumn.cs
- SecurityCriticalDataForSet.cs
- PointUtil.cs
- RequestSecurityTokenResponseCollection.cs
- GridEntry.cs
- Ops.cs
- XmlSchemaIdentityConstraint.cs
- DiagnosticTrace.cs
- TextCompositionEventArgs.cs
- HttpBufferlessInputStream.cs
- WindowsSolidBrush.cs
- ObjectSecurity.cs
- OutputScopeManager.cs
- OleDbParameter.cs
- ServiceDocumentFormatter.cs
- StylusCollection.cs
- HandlerWithFactory.cs
- ContextBase.cs
- DataGridViewCellValidatingEventArgs.cs
- WindowsScrollBarBits.cs
- DiscoveryClientElement.cs
- RoleGroup.cs
- PrincipalPermission.cs
- _AuthenticationState.cs
- DefaultPerformanceCounters.cs
- CommandManager.cs
- VBIdentifierDesigner.xaml.cs
- CorrelationManager.cs
- ClockGroup.cs
- EraserBehavior.cs
- AssemblyInfo.cs
- VersionPair.cs
- NodeFunctions.cs
- TemplateBindingExtension.cs
- NamespaceInfo.cs
- BooleanFunctions.cs
- GroupByExpressionRewriter.cs
- GridViewSelectEventArgs.cs
- SafeRegistryKey.cs
- PocoEntityKeyStrategy.cs
- OneWayElement.cs
- SpanIndex.cs
- ProfileInfo.cs
- TypefaceMetricsCache.cs
- WebZone.cs
- WebBrowserProgressChangedEventHandler.cs
- ApplicationFileCodeDomTreeGenerator.cs
- UriExt.cs
- XmlObjectSerializer.cs
- ColorBlend.cs
- GraphicsState.cs
- TimeSpanStorage.cs
- BasePattern.cs
- PropertyTabChangedEvent.cs
- DataControlFieldCollection.cs
- QilTargetType.cs
- QilVisitor.cs
- _Semaphore.cs
- DisplayToken.cs
- ComAdminWrapper.cs
- FormatterServices.cs
- AuthenticationSection.cs
- SimpleWebHandlerParser.cs
- HttpModulesSection.cs
- CultureInfoConverter.cs
- GridItem.cs
- TdsParserStateObject.cs
- DrawingBrush.cs
- Switch.cs
- FixedPageStructure.cs
- MemoryFailPoint.cs
- configsystem.cs
- System.Data_BID.cs
- InfocardChannelParameter.cs
- DescendantOverDescendantQuery.cs
- MessagePropertyVariants.cs
- QueryResponse.cs
- DropSource.cs
- CompiledRegexRunner.cs
- UnsafeNetInfoNativeMethods.cs
- InfoCardTraceRecord.cs
- cryptoapiTransform.cs
- Light.cs
- DbConnectionStringBuilder.cs
- EnumBuilder.cs
- ProgressPage.cs
- IdentityValidationException.cs
- SelfIssuedAuthAsymmetricKey.cs
- XmlObjectSerializerWriteContextComplex.cs