public void Render(List <PrimitiveInfo> commands, IProxyDrawingContext dc) { Toolbox.EmitEvent(EventTrace.Event.WClientDRXRasterStart); 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.EmitEvent(EventTrace.Event.WClientDRXRasterEnd); dc.DrawImage(new ImageProxy(brushImage), m_bounds, clip, Matrix.Identity); } }
/// <summary> /// Resolve object overlapping in a primitive tree. /// Send broken down drawing primitives to _dc. /// </summary> /// <param name="dc"></param> /// <param name="disjoint">True if all output primitives need to be disjoint</param> public void AlphaFlatten(IProxyDrawingContext dc, bool disjoint) { List <PrimitiveInfo> commands = _dl.Commands; if (commands == null) { return; } int count = commands.Count; _dc = dc; bool needFlattening = true; if (Configuration.BlendAlphaWithWhite || Configuration.ForceAlphaOpaque) { needFlattening = false; } else if (!disjoint) { needFlattening = false; for (int i = 0; i < count; i++) { PrimitiveInfo info = commands[i]; if (!info.primitive.IsOpaque) { needFlattening = true; break; } } } if (needFlattening) { #if DEBUG Console.WriteLine(); Console.WriteLine("Stage 2: Calculating intersections using bounding boxes"); Console.WriteLine(); #endif // Still need all the primitive, for removal by opaque covering and white primitive removal _dl.CalculateIntersections(count); } #if DEBUG if (Configuration.Verbose >= 2) { Console.WriteLine(); Console.WriteLine("Original display list"); Console.WriteLine(); DisplayList.PrintPrimitive(null, -1, true); for (int i = 0; i < count; i++) { DisplayList.PrintPrimitive(commands[i], i, true); } Console.WriteLine(); Console.WriteLine("Primitives in display list: {0}", count); Console.WriteLine(); } #endif if (needFlattening) { DisplayListOptimization(commands, count, disjoint); } #if DEBUG for (int i = 0; i < count; i++) { if (commands[i] != null) { commands[i].SetID(i); } } Console.WriteLine(); Console.WriteLine("Stage 4: Alpha flattening"); Console.WriteLine(); #endif for (int i = 0; i < count; i++) { PrimitiveInfo info = commands[i]; if (info == null) { continue; } String desp = null; #if DEBUG if (Configuration.Verbose >= 2) { Console.Write(i); Console.Write(": "); } desp = info.id; #endif if (info.m_cluster != null) { info.m_cluster.Render(commands, dc); } else { AlphaRender(info.primitive, info.overlap, info.overlapHasTransparency, disjoint, desp); } #if DEBUG if (Configuration.Verbose >= 2) { Console.WriteLine(""); } #endif } _dc = null; }