/// <summary> /// Builds a PdfShading from the specified brush. If a gradient contains transparency, a soft mask is created an added to the /// specified graphic state. /// </summary> PdfShading BuildShading(LinearGradientBrush brush) { // Setup shading PdfShading shading = new PdfShading(Context.PdfDocument); #if DEBUG if (DevHelper.RenderComments) shading.Elements.SetString("/@comment", "This is the shading of a LinearGradientBrush"); #endif PdfColorMode colorMode = PdfColorMode.Rgb; //this.document.Options.ColorMode; PdfDictionary function = BuildShadingFunction(brush.GradientStops, false, colorMode); #if DEBUG if (DevHelper.RenderComments) function.Elements.SetString("/@comment", "This is the shading function of a LinearGradientBrush"); #endif shading.Elements.SetBoolean(PdfShading.Keys.AntiAlias, false); shading.Elements[PdfShading.Keys.Function] = function; shading.Elements.SetInteger(PdfShading.Keys.ShadingType, 2); // Axial shading shading.Elements.SetName(PdfShading.Keys.ColorSpace, "/DeviceRGB"); // TODO: respect ColorMode double x1 = brush.StartPoint.X; double y1 = brush.StartPoint.Y; double x2 = brush.EndPoint.X; double y2 = brush.EndPoint.Y; shading.Elements[PdfShading.Keys.Coords] = new PdfLiteral("[{0:0.####} {1:0.####} {2:0.####} {3:0.####}]", x1, y1, x2, y2); shading.Elements[PdfShading.Keys.Domain] = new PdfLiteral("[0 1]"); if (brush.SpreadMethod == SpreadMethod.Pad) shading.Elements[PdfShading.Keys.Extend] = new PdfLiteral("[true true]"); else { DevHelper.NotImplemented("SpreadMethod." + brush.SpreadMethod.ToString() + " Background painted in green."); #if DEBUG // Note from PDF reference: The background color is applied only when the shading is used as part of // a shading pattern, not when it is painted directly with the sh operator. shading.Elements[PdfShading.Keys.Background] = new PdfLiteral("[0 1 0]"); // TODO: respect ColorMode #else // Best we can currently do shading.Elements[PdfShading.Keys.Extend] = new PdfLiteral("[true true]"); #endif } return shading; }
protected XPLinearGradientBrush(LinearGradientBrush brush) : base(brush) { }
/// <summary> /// Parses a LinearGradientBrush element. /// </summary> LinearGradientBrush ParseLinearGradientBrush() { Debug.Assert(this.reader.Name == "LinearGradientBrush"); bool isEmptyElement = this.reader.IsEmptyElement; LinearGradientBrush brush = new LinearGradientBrush(); while (MoveToNextAttribute()) { switch (this.reader.Name) { case "Opacity": brush.Opacity = ParseDouble(this.reader.Value); break; case "Transform": brush.Transform = ParseMatrixTransform(this.reader.Value); break; case "ColorInterpolationMode": brush.ColorInterpolationMode = ParseEnum<ClrIntMode>(this.reader.Value); break; case "SpreadMethod": brush.SpreadMethod = ParseEnum<SpreadMethod>(this.reader.Value); break; case "MappingMode": brush.MappingMode = ParseEnum<MappingMode>(this.reader.Value); break; case "StartPoint": brush.StartPoint = Point.Parse(this.reader.Value); break; case "EndPoint": brush.EndPoint = Point.Parse(this.reader.Value); break; case "x:Key": brush.Key = this.reader.Value; break; default: Debugger.Break(); break; } } if (!isEmptyElement) { MoveToNextElement(); while (this.reader.IsStartElement()) { switch (this.reader.Name) { case "LinearGradientBrush.Transform": MoveToNextElement(); brush.Transform = ParseMatrixTransform(); MoveToNextElement(); break; case "LinearGradientBrush.GradientStops": // do not MoveToNextElement(); brush.GradientStops = ParseGradientStops(); break; default: Debugger.Break(); break; } } } MoveToNextElement(); return brush; }
void RealizeLinearGradientBrush(LinearGradientBrush brush, XForm xform) { XMatrix matrix = this.currentTransform; PdfShadingPattern pattern = new PdfShadingPattern(this.writer.Owner); pattern.Elements[PdfShadingPattern.Keys.PatternType] = new PdfInteger(2); // shading pattern // Setup shading PdfShading shading = new PdfShading(this.writer.Owner); PdfColorMode colorMode = PdfColorMode.Rgb; //this.document.Options.ColorMode; PdfDictionary function = BuildShadingFunction(brush.GradientStops, colorMode); function.Elements.SetString("/@", "This is the shading function of a LinearGradientBrush"); shading.Elements[PdfShading.Keys.Function] = function; shading.Elements[PdfShading.Keys.ShadingType] = new PdfInteger(2); // Axial shading //if (colorMode != PdfColorMode.Cmyk) shading.Elements[PdfShading.Keys.ColorSpace] = new PdfName("/DeviceRGB"); //else //shading.Elements[Keys.ColorSpace] = new PdfName("/DeviceCMYK"); //double x1 = 0, y1 = 0, x2 = 0, y2 = 0; double x1 = brush.StartPoint.X; double y1 = brush.StartPoint.Y; double x2 = brush.EndPoint.X; double y2 = brush.EndPoint.Y; shading.Elements[PdfShading.Keys.Coords] = new PdfLiteral("[{0:0.###} {1:0.###} {2:0.###} {3:0.###}]", x1, y1, x2, y2); // old: Elements[Keys.Background] = new PdfRawItem("[0 1 1]"); // old: Elements[Keys.Domain] = shading.Elements[PdfShading.Keys.Extend] = new PdfLiteral("[true true]"); // Setup pattern pattern.Elements[PdfShadingPattern.Keys.Shading] = shading; pattern.Elements[PdfShadingPattern.Keys.Matrix] = PdfLiteral.FromMatrix(matrix); // new PdfLiteral("[" + PdfEncoders.ToString(matrix) + "]"); string name = this.writer.Resources.AddPattern(pattern); this.writer.WriteLiteral("/Pattern cs\n", name); this.writer.WriteLiteral("{0} scn\n", name); double alpha = brush.Opacity * brush.GradientStops.GetAverageAlpha(); if (alpha < 1 && this.writer.renderMode == RenderMode.Default) { #if true PdfExtGState extGState = this.writer.Owner.ExtGStateTable.GetExtGStateNonStroke(alpha); string gs = this.writer.Resources.AddExtGState(extGState); this.writer.WriteLiteral("{0} gs\n", gs); #else #if true if (xform == null) { PdfExtGState extGState = this.writer.Owner.ExtGStateTable.GetExtGStateNonStroke(alpha); string gs = this.writer.Resources.AddExtGState(extGState); this.writer.WriteGraphicState(extGState); } else { //PdfFormXObject pdfForm = this.writer.Owner.FormTable.GetForm(form); PdfFormXObject pdfForm = xform.pdfForm; pdfForm.Elements.SetString("/@", "This is the Form XObject of the soft mask"); string formName = this.writer.Resources.AddForm(pdfForm); PdfTransparencyGroupAttributes tgAttributes = new PdfTransparencyGroupAttributes(this.writer.Owner); //this.writer.Owner.Internals.AddObject(tgAttributes); tgAttributes.Elements.SetName(PdfTransparencyGroupAttributes.Keys.CS, "/DeviceRGB"); // Set reference to transparency group attributes pdfForm.Elements.SetObject(PdfFormXObject.Keys.Group, tgAttributes); pdfForm.Elements[PdfFormXObject.Keys.Matrix] = new PdfLiteral("[1.001 0 0 1.001 0.001 0.001]"); PdfSoftMask softmask = new PdfSoftMask(this.writer.Owner); this.writer.Owner.Internals.AddObject(softmask); softmask.Elements.SetString("/@", "This is the soft mask"); softmask.Elements.SetName(PdfSoftMask.Keys.S, "/Luminosity"); softmask.Elements.SetReference(PdfSoftMask.Keys.G, pdfForm); //pdfForm.Elements.SetName(PdfFormXObject.Keys.Type, "Group"); //pdfForm.Elements.SetName(PdfFormXObject.Keys.ss.Ss.Type, "Group"); PdfExtGState extGState = new PdfExtGState(this.writer.Owner); this.writer.Owner.Internals.AddObject(extGState); extGState.Elements.SetReference(PdfExtGState.Keys.SMask, softmask); this.writer.WriteGraphicState(extGState); } #else XForm form = new XForm(this.writer.Owner, 220, 140); XGraphics formGfx = XGraphics.FromForm(form); // draw something //XSolidBrush xbrush = new XSolidBrush(XColor.FromArgb(128, 128, 128)); XLinearGradientBrush xbrush = new XLinearGradientBrush(new XPoint(0, 0), new XPoint(220,0), XColors.White, XColors.Black); formGfx.DrawRectangle(xbrush, -10000, -10000, 20000, 20000); //formGfx.DrawString("Text, Graphics, Images, and Forms", new XFont("Verdana", 10, XFontStyle.Regular), XBrushes.Navy, 3, 0, XStringFormat.TopLeft); formGfx.Dispose(); // Close form form.Finish(); PdfFormXObject pdfForm = this.writer.Owner.FormTable.GetForm(form); string formName = this.writer.Resources.AddForm(pdfForm); //double x = 20, y = 20; //double cx = 1; //double cy = 1; //this.writer.AppendFormat("q {2:0.###} 0 0 -{3:0.###} {0:0.###} {4:0.###} cm 100 Tz {5} Do Q\n", // x, y, cx, cy, y + 0, formName); //this.writer.AppendFormat("q {2:0.###} 0 0 -{3:0.###} {0:0.###} {4:0.###} cm 100 Tz {5} Do Q\n", // x, y, cx, cy, y + 220/1.5, formName); PdfTransparencyGroupAttributes tgAttributes = new PdfTransparencyGroupAttributes(this.writer.Owner); this.writer.Owner.Internals.AddObject(tgAttributes); tgAttributes.Elements.SetName(PdfTransparencyGroupAttributes.Keys.CS, "/DeviceRGB"); // Set reference to transparency group attributes pdfForm.Elements.SetReference(PdfFormXObject.Keys.Group, tgAttributes); PdfSoftMask softmask = new PdfSoftMask(this.writer.Owner); this.writer.Owner.Internals.AddObject(softmask); softmask.Elements.SetName(PdfSoftMask.Keys.S, "/Luminosity"); softmask.Elements.SetReference(PdfSoftMask.Keys.G, pdfForm); //pdfForm.Elements.SetName(PdfFormXObject.Keys.Type, "Group"); //pdfForm.Elements.SetName(PdfFormXObject.Keys.ss.Ss.Type, "Group"); PdfExtGState extGState = new PdfExtGState(this.writer.Owner); this.writer.Owner.Internals.AddObject(extGState); extGState.Elements.SetReference(PdfExtGState.Keys.SMask, softmask); this.writer.WriteGraphicState(extGState); #endif #endif } }
/// <summary> /// Builds a monochrome shading for a form XObject of a soft mask. /// </summary> PdfShading BuildShadingForSoftMask(LinearGradientBrush brush) { // Setup shading //<< // /ShadingType 2 // /AntiAlias false // /BBox [0 0 510.236 680.315] // /ColorSpace /DeviceGray // /Coords [5 5 153.492 -86.924] // /Domain [0 1] // /Extend [true true] // /Function 18 0 R //>> PdfShading shading = Context.PdfDocument.Internals.CreateIndirectObject<PdfShading>(); #if DEBUG if (DevHelper.RenderComments) shading.Elements.SetString("/@comment", "This is the shading function of a soft mask"); #endif shading.Elements.SetInteger(PdfShading.Keys.ShadingType, 2); // Axial shading shading.Elements.SetBoolean(PdfShading.Keys.AntiAlias, false); // TODO: BBox full page //shading.Elements.SetValue(PdfShading.Keys.BBox, new PdfLiteral("[0 0 480 640]")); shading.Elements.SetName(PdfShading.Keys.ColorSpace, "/DeviceGray"); double x1 = brush.StartPoint.X; double y1 = brush.StartPoint.Y; double x2 = brush.EndPoint.X; double y2 = brush.EndPoint.Y; shading.Elements.SetValue(PdfShading.Keys.Coords, new PdfLiteral("[{0:0.####} {1:0.####} {2:0.####} {3:0.####}]", x1, y1, x2, y2)); shading.Elements.SetValue(PdfShading.Keys.Domain, new PdfLiteral("[0 1]")); shading.Elements.SetValue(PdfShading.Keys.Extend, new PdfLiteral("[true true]")); PdfColorMode colorMode = PdfColorMode.Rgb; //this.document.Options.ColorMode; PdfDictionary function = BuildShadingFunction(brush.GradientStops, true, colorMode); #if true shading.Elements.SetValue(PdfShading.Keys.Function, function); #else Context.PdfDocument.Internals.AddObject(function); shading.Elements.SetReference(PdfShading.Keys.Function, function); #endif return shading; }
/// <summary> /// Builds a form XObject from a linear gradient brush that uses transparency. /// </summary> public static PdfFormXObject BuildFormFromLinearGradientBrush(DocumentRenderingContext context, LinearGradientBrush brush, PathGeometry geometry) { LinearShadingBuilder builder = new LinearShadingBuilder(context); PdfFormXObject pdfForm = builder.BuildForm(brush, geometry); return pdfForm; }
/// <summary> /// Builds a pattern from a linear gradient brush. /// </summary> public static PdfShadingPattern BuildPatternFromLinearGradientBrush(DocumentRenderingContext context, LinearGradientBrush brush, XMatrix transform) { LinearShadingBuilder builder = new LinearShadingBuilder(context); PdfShadingPattern pattern = builder.BuildShadingPattern(brush, transform); return pattern; }
/// <summary> /// Builds a shading from a linear gradient brush. /// </summary> public static PdfShading BuildShadingFromLinearGradientBrush(DocumentRenderingContext context, LinearGradientBrush brush) { LinearShadingBuilder builder = new LinearShadingBuilder(context); PdfShading shading = builder.BuildShading(brush); return shading; }
/// <summary> /// Builds the soft mask. /// </summary> PdfSoftMask BuildSoftMask(LinearGradientBrush brush) { Debug.Assert(brush.GradientStops.HasTransparency); XRect viewBox = new XRect(0, 0, 360, 480); // HACK //XForm xform = new XForm(Context.PdfDocument, viewBox); PdfFormXObject form = Context.PdfDocument.Internals.CreateIndirectObject<PdfFormXObject>(); #if DEBUG if (DevHelper.RenderComments) form.Elements.SetString("/@comment", "This is the Form XObject of the soft mask"); #endif form.Elements.SetRectangle(PdfFormXObject.Keys.BBox, new PdfRectangle(viewBox)); // Transparency group of mask form //<< // /CS /DeviceGray // /I false // /K false // /S /Transparency // /Type /Group //>> PdfTransparencyGroupAttributes tgAttributes = Context.PdfDocument.Internals.CreateIndirectObject<PdfTransparencyGroupAttributes>(); tgAttributes.Elements.SetName(PdfTransparencyGroupAttributes.Keys.CS, "/DeviceGray"); tgAttributes.Elements.SetBoolean(PdfTransparencyGroupAttributes.Keys.I, false); tgAttributes.Elements.SetBoolean(PdfTransparencyGroupAttributes.Keys.K, false); // ExtGState of mask form //<< // /AIS false // /BM /Normal // /ca 1 // /CA 1 // /op false // /OP false // /OPM 1 // /SA true // /SMask /None // /Type /ExtGState //>> PdfExtGState pdfStateMaskFrom = Context.PdfDocument.Internals.CreateIndirectObject<PdfExtGState>(); pdfStateMaskFrom.SetDefault1(); // Shading of mask form PdfShading shadingFrom = BuildShadingForSoftMask(brush); ////// Set reference to transparency group attributes ////pdfForm.Elements.SetObject(PdfFormXObject.Keys.Group, tgAttributes); ////pdfForm.Elements[PdfFormXObject.Keys.Matrix] = new PdfLiteral("[1.001 0 0 1.001 0.001 0.001]"); // Soft mask //<< // /G 21 0 R % form // /S /Luminosity // /Type /Mask //>> PdfSoftMask softmask = Context.PdfDocument.Internals.CreateIndirectObject<PdfSoftMask>(); // new PdfSoftMask(this.writer.Owner); //extGState.Elements.SetReference(PdfExtGState.Keys.SMask, softmask); //this.writer.Owner.Internals.AddObject(softmask); #if DEBUG if (DevHelper.RenderComments) softmask.Elements.SetString("/@comment", "This is the soft mask"); #endif softmask.Elements.SetName(PdfSoftMask.Keys.S, "/Luminosity"); softmask.Elements.SetReference(PdfSoftMask.Keys.G, form); // Create content of mask form //<< // /BBox [200.118 369.142 582.795 -141.094] // /Group 16 0 R // /Length 121 // /Matrix [1 0 0 1 0 0] // /Resources // << // /ExtGState // << // /GS0 20 0 R // >> // /Shading // << // /Sh0 19 0 R // >> // >> // /Subtype /Form //>> //stream // q // 200.118 369.142 382.677 -510.236 re // W n // q // 0 g // 1 i // GS0 gs // 0.75 0 0 -0.75 200.1181183 369.1417236 cm // BX /Sh0 sh EX Q // Q //endstream form.Elements.SetReference(PdfFormXObject.Keys.Group, tgAttributes); PdfContentWriter writer = new PdfContentWriter(Context, form); writer.BeginContentRaw(); // Acrobat 8 clips to bounding box, so we should do // why 0 480 360 -480 re ?? //writer.WriteClip(bbox); //writer.WriteGraphicsState(extGState); writer.WriteLiteral("1 i 0 g\n"); writer.WriteLiteral(writer.Resources.AddExtGState(pdfStateMaskFrom) + " gs\n"); XMatrix transform = new XMatrix(); //(brush.Viewport.Width / viewBoxForm.width, 0, 0, brush.Viewport.Height / viewBoxForm.height, 0, 0); writer.WriteMatrix(transform); writer.WriteLiteral("BX " + writer.Resources.AddShading(shadingFrom) + " sh EX\n"); writer.EndContent(); return softmask; }
/// <summary> /// Builds a PdfFormXObject from the specified brush. /// // If a gradient contains transparency, a soft mask is created an added to the specified graphic state. /// </summary> PdfFormXObject BuildForm(LinearGradientBrush brush, PathGeometry geometry) { PdfFormXObject pdfForm = Context.PdfDocument.Internals.CreateIndirectObject<PdfFormXObject>(); // HACK pdfForm.Elements.SetRectangle(PdfFormXObject.Keys.BBox, new PdfRectangle(0, 640, 480, 0)); // Transparency group of the form //<< // /I true // /K false // /S /Transparency // /Type /Group //>> PdfTransparencyGroupAttributes tgPrimaryForm = Context.PdfDocument.Internals.CreateIndirectObject<PdfTransparencyGroupAttributes>(); // not set by Acrobat: tgAttributes.Elements.SetName(PdfTransparencyGroupAttributes.Keys.CS, "/DeviceRGB"); tgPrimaryForm.Elements.SetBoolean(PdfTransparencyGroupAttributes.Keys.I, true); tgPrimaryForm.Elements.SetBoolean(PdfTransparencyGroupAttributes.Keys.K, false); pdfForm.Elements.SetReference(PdfFormXObject.Keys.Group, tgPrimaryForm); // Shading PdfShading shading = BuildShading(brush); // ExtGState //<< // /AIS false // /BM /Normal // /ca 1 // /CA 1 // /op false // /OP false // /OPM 1 // /SA true // /SMask 22 0 R // /Type /ExtGState //>> PdfExtGState pdfExtGState = Context.PdfDocument.Internals.CreateIndirectObject<PdfExtGState>(); pdfExtGState.SetDefault1(); // Soft mask PdfSoftMask softmask = BuildSoftMask(brush); pdfExtGState.Elements.SetReference(PdfExtGState.Keys.SMask, softmask); // PdfFormXObject //<< // /BBox [200.118 369.142 582.795 -141.094] // /Group 11 0 R // /Length 117 // /Matrix [1 0 0 1 0 0] // /Resources // << // /ColorSpace // << // /CS0 8 0 R // >> // /ExtGState // << // /GS0 23 0 R // >> // /Shading // << // /Sh0 14 0 R // >> // >> // /Subtype /Form //>> //stream //q //203.868 365.392 157.5 -97.5 re //W* n //q //0 g //1 i ///GS0 gs //0.75 0 0 -0.75 200.1181183 369.1417236 cm //BX /Sh0 sh EX Q //Q //endstream PdfContentWriter writer = new PdfContentWriter(Context, pdfForm); writer.BeginContentRaw(); // Acrobat 8 clips to bounding box, so we should do writer.WriteClip(geometry); //writer.WriteGraphicsState(extGState); //writer.WriteLiteral("0 g\n"); writer.WriteLiteral(writer.Resources.AddExtGState(pdfExtGState) + " gs\n"); XMatrix transform = new XMatrix(); //(brush.Viewport.Width / viewBoxForm.width, 0, 0, brush.Viewport.Height / viewBoxForm.height, 0, 0); writer.WriteMatrix(transform); writer.WriteLiteral("BX " + writer.Resources.AddShading(shading) + " sh EX\n"); writer.EndContent(); return pdfForm; }
/// <summary> /// Builds a PdfShadingPattern from the specified brush. /// </summary> PdfShadingPattern BuildShadingPattern(LinearGradientBrush brush, XMatrix transform) { //<< // /Matrix [0.75 0 0 -0.75 8 470.4] // /PatternType 2 // /Shading 22 0 R // /Type /Pattern //>> XMatrix matrix = transform; PdfShadingPattern pattern = Context.PdfDocument.Internals.CreateIndirectObject<PdfShadingPattern>(); pattern.Elements.SetInteger(PdfShadingPattern.Keys.PatternType, 2); // Shading pattern.Elements.SetMatrix(PdfShadingPattern.Keys.Matrix, matrix); PdfShading shading = BuildShading(brush); Context.PdfDocument.Internals.AddObject(shading); pattern.Elements.SetReference(PdfShadingPattern.Keys.Shading, shading); return pattern; }