PdfDictionary BuildShadingFunction3(GradientStopCollection gradients, bool softMask, PdfColorMode colorMode) { int count = gradients.Count; Debug.Assert(count >= 2); // // Build a Type 3 function with an array of n-1 Type 2 functions PdfDictionary fn1 = new PdfDictionary(); fn1.Elements["/FunctionType"] = new PdfInteger(3); // Type 3 - Stitching Function fn1.Elements["/Domain"] = new PdfLiteral("[0 1]"); fn1.Elements["/Range"] = new PdfLiteral("[0 1 0 1 0 1]"); PdfArray fnarray = new PdfArray(); fn1.Elements["/Functions"] = fnarray; StringBuilder bounds = new StringBuilder("["); StringBuilder encode = new StringBuilder("["); for (int idx = 1; idx < count; idx++) { PdfDictionary fn2 = new PdfDictionary(); fn2.Elements["/FunctionType"] = new PdfInteger(2); Color clr0 = gradients[idx - 1].Color; Color clr1 = gradients[idx].Color; if (softMask) { fn2.Elements["/C0"] = new PdfLiteral("[" + PdfEncoders.ToString(clr0.ScA) + "]"); fn2.Elements["/C1"] = new PdfLiteral("[" + PdfEncoders.ToString(clr1.ScA) + "]"); fn2.Elements["/Range"] = new PdfLiteral("[0 1]"); } else { fn2.Elements["/C0"] = new PdfLiteral("[" + PdfEncoders.ToString(clr0, colorMode) + "]"); fn2.Elements["/C1"] = new PdfLiteral("[" + PdfEncoders.ToString(clr1, colorMode) + "]"); fn2.Elements["/Range"] = new PdfLiteral("[0 1 0 1 0 1]"); } fn2.Elements["/Domain"] = new PdfLiteral("[0 1]"); fn2.Elements["/N"] = new PdfInteger(1); fnarray.Elements.Add(fn2); if (idx > 1) { bounds.Append(' '); encode.Append(' '); } if (idx < count - 1) { bounds.Append(PdfEncoders.ToString(gradients[idx].Offset)); } encode.Append("0 1"); } bounds.Append(']'); encode.Append(']'); fn1.Elements["/Bounds"] = new PdfLiteral(bounds.ToString()); fn1.Elements["/Encode"] = new PdfLiteral(encode.ToString()); return(fn1); }
internal override void WriteObject(PdfWriter writer) { PdfPage dest = null; //pdf.AppendFormat(CultureInfo.InvariantCulture, // "{0} 0 obj\n<<\n/Type/Annot\n/Subtype/Link\n" + // "/Rect[{1} {2} {3} {4}]\n/BS<</Type/Border>>\n/Border[0 0 0]\n/C[0 0 0]\n", // ObjectID.ObjectNumber, rect.X1, rect.Y1, rect.X2, rect.Y2); // Older Adobe Reader versions uses a border width of 0 as default value if neither Border nor BS are present. // But the PDF Reference specifies: // "If neither the Border nor the BS entry is present, the border is drawn as a solid line with a width of 1 point." // After this issue was fixed in newer Reader versions older PDFsharp created documents show an ugly solid border. // The following hack fixes this by specifying a 0 width border. if (Elements[PdfAnnotation.Keys.BS] == null) { Elements[PdfAnnotation.Keys.BS] = new PdfLiteral("<</Type/Border/W 0>>"); } // May be superfluous. See comment above. if (Elements[PdfAnnotation.Keys.Border] == null) { Elements[PdfAnnotation.Keys.Border] = new PdfLiteral("[0 0 0]"); } switch (_linkType) { case LinkType.None: break; case LinkType.Document: // destIndex > Owner.PageCount can happen when rendering pages using PDFsharp directly. int destIndex = _destPage; if (destIndex > Owner.PageCount) { destIndex = Owner.PageCount; } destIndex--; dest = Owner.Pages[destIndex]; //pdf.AppendFormat("/Dest[{0} 0 R/XYZ null null 0]\n", dest.ObjectID); Elements[Keys.Dest] = new PdfLiteral("[{0} 0 R/XYZ null null 0]", dest.ObjectNumber); break; case LinkType.Web: //pdf.AppendFormat("/A<</S/URI/URI{0}>>\n", PdfEncoders.EncodeAsLiteral(url)); Elements[PdfAnnotation.Keys.A] = new PdfLiteral("<</S/URI/URI{0}>>", //PdfEncoders.EncodeAsLiteral(url)); PdfEncoders.ToStringLiteral(_url, PdfStringEncoding.WinAnsiEncoding, writer.SecurityHandler)); break; case LinkType.File: //pdf.AppendFormat("/A<</Type/Action/S/Launch/F<</Type/Filespec/F{0}>> >>\n", // PdfEncoders.EncodeAsLiteral(url)); Elements[PdfAnnotation.Keys.A] = new PdfLiteral("<</Type/Action/S/Launch/F<</Type/Filespec/F{0}>> >>", //PdfEncoders.EncodeAsLiteral(url)); PdfEncoders.ToStringLiteral(_url, PdfStringEncoding.WinAnsiEncoding, writer.SecurityHandler)); break; } base.WriteObject(writer); }
public void Write(PdfRectangle rect) { const string format = Config.SignificantFigures3; WriteSeparator(CharCat.Delimiter, '/'); WriteRaw(PdfEncoders.Format("[{0:" + format + "} {1:" + format + "} {2:" + format + "} {3:" + format + "}]", rect.X1, rect.Y1, rect.X2, rect.Y2)); _lastCat = CharCat.Delimiter; }
public void WriteDocStringHex(string text) { WriteSeparator(CharCat.Delimiter); //WriteRaw(PdfEncoders.DocEncodeHex(text)); byte[] bytes = PdfEncoders.DocEncoding.GetBytes(text); bytes = PdfEncoders.FormatStringLiteral(bytes, false, false, true, _securityHandler); _stream.Write(bytes, 0, bytes.Length); _lastCat = CharCat.Delimiter; }
public void WriteDocString(string text) { WriteSeparator(CharCat.Delimiter); //WriteRaw(PdfEncoders.DocEncode(text, false)); byte[] bytes = PdfEncoders.DocEncoding.GetBytes(text); bytes = PdfEncoders.FormatStringLiteral(bytes, false, false, false, _securityHandler); Write(bytes); _lastCat = CharCat.Delimiter; }
internal void SetupFromBrush(XRadialGradientBrush brush, XGraphicsPdfRenderer renderer) { if (brush == null) { throw new ArgumentNullException("brush"); } PdfColorMode colorMode = _document.Options.ColorMode; XColor color1 = ColorSpaceHelper.EnsureColorMode(colorMode, brush._color1); XColor color2 = ColorSpaceHelper.EnsureColorMode(colorMode, brush._color2); PdfDictionary function = new PdfDictionary(); Elements[Keys.ShadingType] = new PdfInteger(3); if (colorMode != PdfColorMode.Cmyk) { Elements[Keys.ColorSpace] = new PdfName("/DeviceRGB"); } else { Elements[Keys.ColorSpace] = new PdfName("/DeviceCMYK"); } XPoint p1 = renderer.WorldToView(brush._center1); XPoint p2 = renderer.WorldToView(brush._center2); var rv1 = renderer.WorldToView(new XPoint(brush._r1 + brush._center1.X, brush._center1.Y)); var rv2 = renderer.WorldToView(new XPoint(brush._r2 + brush._center2.X, brush._center2.Y)); var dx1 = rv1.X - p1.X; var dy1 = rv1.Y - p1.Y; var dx2 = rv2.X - p2.X; var dy2 = rv2.Y - p2.Y; var r1 = Math.Sqrt(dx1 * dx1 + dy1 * dy1); var r2 = Math.Sqrt(dx2 * dx2 + dy2 * dy2); const string format = Config.SignificantFigures3; Elements[Keys.Coords] = new PdfLiteral("[{0:" + format + "} {1:" + format + "} {2:" + format + "} {3:" + format + "} {4:" + format + "} {5:" + format + "}]", p1.X, p1.Y, r1, p2.X, p2.Y, r2); //Elements[Keys.Background] = new PdfRawItem("[0 1 1]"); //Elements[Keys.Domain] = Elements[Keys.Function] = function; //Elements[Keys.Extend] = new PdfRawItem("[true true]"); string clr1 = "[" + PdfEncoders.ToString(color1, colorMode, true) + "]"; string clr2 = "[" + PdfEncoders.ToString(color2, colorMode, true) + "]"; function.Elements["/FunctionType"] = new PdfInteger(2); function.Elements["/C0"] = new PdfLiteral(clr1); function.Elements["/C1"] = new PdfLiteral(clr2); function.Elements["/Domain"] = new PdfLiteral("[0 1]"); function.Elements["/N"] = new PdfInteger(1); }
/// <summary> /// Writes the specified value to the PDF stream. /// </summary> public void Write(PdfString value) { WriteSeparator(CharCat.Delimiter); PdfStringEncoding encoding = (PdfStringEncoding)(value.Flags & PdfStringFlags.EncodingMask); string pdf = (value.Flags & PdfStringFlags.HexLiteral) == 0 ? PdfEncoders.ToStringLiteral(value.Value, encoding, SecurityHandler) : PdfEncoders.ToHexStringLiteral(value.Value, encoding, SecurityHandler); WriteRaw(pdf); _lastCat = CharCat.Delimiter; }
/// <summary> /// Returns the string. /// </summary> public override string ToString() { #if true PdfStringEncoding encoding = (PdfStringEncoding)(_flags & PdfStringFlags.EncodingMask); string pdf = (_flags & PdfStringFlags.HexLiteral) == 0 ? PdfEncoders.ToStringLiteral(_value, encoding, null) : PdfEncoders.ToHexStringLiteral(_value, encoding, null); return(pdf); #else return(_value); #endif }
/// <summary> /// Writes the specified value to the PDF stream. /// </summary> public void Write(PdfString value) { WriteSeparator(CharCat.Delimiter); #if true PdfStringEncoding encoding = (PdfStringEncoding)(value.Flags & PdfStringFlags.EncodingMask); string pdf; if ((value.Flags & PdfStringFlags.HexLiteral) == 0) { pdf = PdfEncoders.ToStringLiteral(value.Value, encoding, SecurityHandler); } else { pdf = PdfEncoders.ToHexStringLiteral(value.Value, encoding, SecurityHandler); } WriteRaw(pdf); #else switch (value.Flags & PdfStringFlags.EncodingMask) { case PdfStringFlags.Undefined: case PdfStringFlags.PDFDocEncoding: if ((value.Flags & PdfStringFlags.HexLiteral) == 0) { WriteRaw(PdfEncoders.DocEncode(value.Value, false)); } else { WriteRaw(PdfEncoders.DocEncodeHex(value.Value, false)); } break; case PdfStringFlags.WinAnsiEncoding: throw new NotImplementedException("Unexpected encoding: WinAnsiEncoding"); case PdfStringFlags.Unicode: if ((value.Flags & PdfStringFlags.HexLiteral) == 0) { WriteRaw(PdfEncoders.DocEncode(value.Value, true)); } else { WriteRaw(PdfEncoders.DocEncodeHex(value.Value, true)); } break; case PdfStringFlags.StandardEncoding: case PdfStringFlags.MacRomanEncoding: case PdfStringFlags.MacExpertEncoding: default: throw new NotImplementedException("Unexpected encoding"); } #endif this.lastCat = CharCat.Delimiter; }
private static string Format(string format, params double?[] values) { int length = values.Length; object[] objValues = new object[length]; for (int i = 0; i < length; i++) { objValues[i] = values[i] ?? (object)"null"; } return(PdfEncoders.Format(format, objValues)); }
public void RealizeBrush(XBrush brush, PdfColorMode colorMode) { if (brush is XSolidBrush) { XColor color = ((XSolidBrush)brush).Color; color = ColorSpaceHelper.EnsureColorMode(colorMode, color); if (colorMode != PdfColorMode.Cmyk) { if (this.realizedFillColor.Rgb != color.Rgb) { this.renderer.Append(PdfEncoders.ToString(color, PdfColorMode.Rgb)); this.renderer.Append(" rg\n"); } } else { if (!ColorSpaceHelper.IsEqualCmyk(this.realizedFillColor, color)) { this.renderer.Append(PdfEncoders.ToString(color, PdfColorMode.Cmyk)); this.renderer.Append(" k\n"); } } if (this.renderer.Owner.Version >= 14 && this.realizedFillColor.A != color.A) { PdfExtGState extGState = this.renderer.Owner.ExtGStateTable.GetExtGStateNonStroke(color.A); string gs = this.renderer.Resources.AddExtGState(extGState); this.renderer.AppendFormat("{0} gs\n", gs); // Must create transparany group if (this.renderer.page != null && color.A < 1) { this.renderer.page.transparencyUsed = true; } } this.realizedFillColor = color; } else if (brush is XLinearGradientBrush) { XMatrix matrix = this.renderer.defaultViewMatrix; matrix.Prepend(this.Transform); PdfShadingPattern pattern = new PdfShadingPattern(this.renderer.Owner); pattern.SetupFromBrush((XLinearGradientBrush)brush, matrix); string name = this.renderer.Resources.AddPattern(pattern); this.renderer.AppendFormat("/Pattern cs\n", name); this.renderer.AppendFormat("{0} scn\n", name); // Invalidate fill color this.realizedFillColor = XColor.Empty; } }
internal override void WriteObject(PdfWriter writer) { PdfPage dest = null; //pdf.AppendFormat(CultureInfo.InvariantCulture, // "{0} 0 obj\n<<\n/Type/Annot\n/Subtype/Link\n" + // "/Rect[{1} {2} {3} {4}]\n/BS<</Type/Border>>\n/Border[0 0 0]\n/C[0 0 0]\n", // this.ObjectID.ObjectNumber, rect.X1, rect.Y1, rect.X2, rect.Y2); if (Elements[Keys.BS] == null) { Elements[Keys.BS] = new PdfLiteral("<</Type/Border>>"); } if (Elements[Keys.Border] == null) { Elements[Keys.Border] = new PdfLiteral("[0 0 0]"); } switch (this.linkType) { case LinkType.Document: // destIndex > Owner.PageCount can happen rendering pages using PDFsharp directly int destIndex = this.destPage; if (destIndex > Owner.PageCount) { destIndex = Owner.PageCount; } destIndex--; dest = this.Owner.Pages[destIndex]; //pdf.AppendFormat("/Dest[{0} 0 R/XYZ null null 0]\n", dest.ObjectID); Elements[Keys.Dest] = new PdfLiteral("[{0} 0 R/XYZ null null 0]", dest.ObjectNumber); break; case LinkType.Web: //pdf.AppendFormat("/A<</S/URI/URI{0}>>\n", PdfEncoders.EncodeAsLiteral(this.url)); Elements[Keys.A] = new PdfLiteral("<</S/URI/URI{0}>>", //PdfEncoders.EncodeAsLiteral(this.url)); PdfEncoders.ToStringLiteral(this.url, PdfStringEncoding.WinAnsiEncoding, writer.SecurityHandler)); break; case LinkType.File: //pdf.AppendFormat("/A<</Type/Action/S/Launch/F<</Type/Filespec/F{0}>> >>\n", // PdfEncoders.EncodeAsLiteral(this.url)); Elements[Keys.A] = new PdfLiteral("<</Type/Action/S/Launch/F<</Type/Filespec/F{0}>> >>", //PdfEncoders.EncodeAsLiteral(this.url)); PdfEncoders.ToStringLiteral(this.url, PdfStringEncoding.WinAnsiEncoding, writer.SecurityHandler)); break; } base.WriteObject(writer); }
private void RealizeFillColor(XColor color, bool overPrint, PdfColorMode colorMode) { color = ColorSpaceHelper.EnsureColorMode(colorMode, color); switch (color.ColorSpace) { case XColorSpace.Rgb: if (_realizedFillColor.IsEmpty || _realizedFillColor.Rgb != color.Rgb) { _renderer.Append(PdfEncoders.ToString(color, PdfColorMode.Rgb)); _renderer.Append(" rg\n"); } break; case XColorSpace.Cmyk: if (_realizedFillColor.IsEmpty || !ColorSpaceHelper.IsEqualCmyk(_realizedFillColor, color)) { _renderer.Append(PdfEncoders.ToString(color, PdfColorMode.Cmyk)); _renderer.Append(" k\n"); } break; case XColorSpace.GrayScale: if (_realizedFillColor.IsEmpty || _realizedFillColor.GS != color.GS) { _renderer.Append(PdfEncoders.ToString(color, PdfColorMode.Undefined)); _renderer.Append(" g\n"); } break; default: break; } if (_renderer.Owner.Version >= 14 && color.ColorSpace != XColorSpace.GrayScale && (_realizedFillColor.A != color.A || _realizedNonStrokeOverPrint != overPrint)) { PdfExtGState extGState = _renderer.Owner.ExtGStateTable.GetExtGStateNonStroke(color.A, overPrint); string gs = _renderer.Resources.AddExtGState(extGState); _renderer.AppendFormatString("{0} gs\n", gs); // Must create transparency group. if (_renderer._page != null && color.A < 1) { _renderer._page.TransparencyUsed = true; } } _realizedFillColor = color; _realizedNonStrokeOverPrint = overPrint; }
public void WriteDocString(string text, bool unicode) { WriteSeparator(CharCat.Delimiter); //WriteRaw(PdfEncoders.DocEncode(text, unicode)); byte[] bytes; if (!unicode) { bytes = PdfEncoders.DocEncoding.GetBytes(text); } else { bytes = PdfEncoders.UnicodeEncoding.GetBytes(text); } bytes = PdfEncoders.FormatStringLiteral(bytes, unicode, true, false, _securityHandler); Write(bytes); _lastCat = CharCat.Delimiter; }
/// <summary> /// Writes the specified value to the PDF stream. /// </summary> public void Write(PdfString value) { WriteSeparator(CharCat.Delimiter); //#if true PdfStringEncoding encoding = (PdfStringEncoding)(value.Flags & PdfStringFlags.EncodingMask); string pdf = (value.Flags & PdfStringFlags.HexLiteral) == 0 ? PdfEncoders.ToStringLiteral(value.Value, encoding, SecurityHandler) : PdfEncoders.ToHexStringLiteral(value.Value, encoding, SecurityHandler); WriteRaw(pdf); //#else // switch (value.Flags & PdfStringFlags.EncodingMask) // { // case PdfStringFlags.Undefined: // case PdfStringFlags.PDFDocEncoding: // if ((value.Flags & PdfStringFlags.HexLiteral) == 0) // WriteRaw(PdfEncoders.DocEncode(value.Value, false)); // else // WriteRaw(PdfEncoders.DocEncodeHex(value.Value, false)); // break; // case PdfStringFlags.WinAnsiEncoding: // throw new NotImplementedException("Unexpected encoding: WinAnsiEncoding"); // case PdfStringFlags.Unicode: // if ((value.Flags & PdfStringFlags.HexLiteral) == 0) // WriteRaw(PdfEncoders.DocEncode(value.Value, true)); // else // WriteRaw(PdfEncoders.DocEncodeHex(value.Value, true)); // break; // case PdfStringFlags.StandardEncoding: // case PdfStringFlags.MacRomanEncoding: // case PdfStringFlags.MacExpertEncoding: // default: // throw new NotImplementedException("Unexpected encoding"); // } //#endif _lastCat = CharCat.Delimiter; }
private void RealizeFillColor(XColor color, bool overPrint, PdfColorMode colorMode) { color = ColorSpaceHelper.EnsureColorMode(colorMode, color); if (colorMode != PdfColorMode.Cmyk) { if (_realizedFillColor.IsEmpty || _realizedFillColor.Rgb != color.Rgb) { _renderer.Append(PdfEncoders.ToString(color, PdfColorMode.Rgb)); _renderer.Append(" rg\n"); } } else { Debug.Assert(colorMode == PdfColorMode.Cmyk); if (_realizedFillColor.IsEmpty || !ColorSpaceHelper.IsEqualCmyk(_realizedFillColor, color)) { _renderer.Append(PdfEncoders.ToString(color, PdfColorMode.Cmyk)); _renderer.Append(" k\n"); } } if (_renderer.Owner.Version >= 14 && (_realizedFillColor.A != color.A || _realizedNonStrokeOverPrint != overPrint)) { PdfExtGState extGState = _renderer.Owner.ExtGStateTable.GetExtGStateNonStroke(color.A, overPrint); string gs = _renderer.Resources.AddExtGState(extGState); _renderer.AppendFormatString("{0} gs\n", gs); // Must create transparency group. if (_renderer._page != null && color.A < 1) { _renderer._page.TransparencyUsed = true; } } _realizedFillColor = color; _realizedNonStrokeOverPrint = overPrint; }
/// <summary> /// Initializes a new instance with the culture invariant formatted specified arguments. /// </summary> public PdfLiteral(string format, params object[] args) { _value = PdfEncoders.Format(format, args); }
public void Write(PdfRectangle rect) { WriteSeparator(CharCat.Delimiter, '/'); WriteRaw(PdfEncoders.Format("[{0:0.###} {1:0.###} {2:0.###} {3:0.###}]", rect.X1, rect.Y1, rect.X2, rect.Y2)); this.lastCat = CharCat.Delimiter; }
/// <summary> /// Returns the rectangle as a string in the form «[x1 y1 x2 y2]». /// </summary> public override string ToString() { const string format = Config.SignificantFigures3; return(PdfEncoders.Format("[{0:" + format + "} {1:" + format + "} {2:" + format + "} {3:" + format + "}]", _x1, _y1, _x2, _y2)); }
/// <summary> /// Returns the rectangle as a string in the form «[x1 y1 x2 y2]». /// </summary> public override string ToString() { return(PdfEncoders.Format("[{0:0.###} {1:0.###} {2:0.###} {3:0.###}]", this.x1, this.y1, this.x2, this.y2)); }
/// <summary> /// Writes a Glyphs to the content stream. /// </summary> private void WriteGlyphs(Glyphs glyphs) { WriteSaveState("begin Glyphs", glyphs.Name); // Transform also affects clipping and opacity mask bool transformed = glyphs.RenderTransform != null; if (transformed) { WriteRenderTransform(glyphs.RenderTransform); } bool clipped = glyphs.Clip != null; if (clipped) { WriteClip(glyphs.Clip); } if (glyphs.Opacity < 1) { MultiplyOpacity(glyphs.Opacity); } if (glyphs.OpacityMask != null) { WriteOpacityMask(glyphs.OpacityMask); } XMatrix textMatrix = new XMatrix(); textMatrix.TranslatePrepend(glyphs.OriginX, glyphs.OriginY); glyphs.OriginX = glyphs.OriginY = 0; // HACK: do not change model double emSize = glyphs.FontRenderingEmSize; textMatrix.ScalePrepend(glyphs.FontRenderingEmSize); glyphs.FontRenderingEmSize = 1; // HACK: do not change model bool boldSimulation = (glyphs.StyleSimulations & StyleSimulations.BoldSimulation) == StyleSimulations.BoldSimulation; // just a draft... if (boldSimulation) { boldSimulation = true; // draw black stroke if it is not a solid color brush XColor color = XColor.FromArgb(0, 0, 0); if (glyphs.Fill is SolidColorBrush) { SolidColorBrush brush = glyphs.Fill as SolidColorBrush; color = brush.Color; } WriteLiteral(String.Format(CultureInfo.InvariantCulture, "{0:0.###} {1:0.###} {2:0.###} RG\n", color.R / 255.0, color.G / 255.0, color.B / 255.0)); WriteLiteral("{0:0.###} w\n", emSize / 50); } if ((glyphs.StyleSimulations & StyleSimulations.ItalicSimulation) == StyleSimulations.ItalicSimulation) { textMatrix.SkewPrepend(-20, 0); } XForm xform = null; XImage ximage = null; RealizeFill(glyphs.Fill, ref xform, ref ximage); RealizeFont(glyphs); if (boldSimulation) { WriteLiteral("2 Tr\n", 1); } double x = glyphs.OriginX; double y = glyphs.OriginY; //switch (format.Alignment) //{ // case XStringAlignment.Near: // // nothing to do // break; // case XStringAlignment.Center: // x += (rect.Width - width) / 2; // break; // case XStringAlignment.Far: // x += rect.Width - width; // break; //} PdfFont realizedFont = this.graphicsState.realizedFont; Debug.Assert(realizedFont != null); realizedFont.AddChars(glyphs.UnicodeString); OpenTypeDescriptor descriptor = realizedFont.FontDescriptor._descriptor; //if (bold && !descriptor.IsBoldFace) //{ // // TODO: emulate bold by thicker outline //} //if (italic && !descriptor.IsBoldFace) //{ // // TODO: emulate italic by shearing transformation //} #if true string s2 = ""; string s = glyphs.UnicodeString; if (!String.IsNullOrEmpty(s)) { int length = s.Length; for (int idx = 0; idx < length; idx++) { char ch = s[idx]; int glyphID = 0; if (descriptor.FontFace.cmap.symbol) { glyphID = (int)ch + (descriptor.FontFace.os2.usFirstCharIndex & 0xFF00); glyphID = descriptor.CharCodeToGlyphIndex((char)glyphID); } else { glyphID = descriptor.CharCodeToGlyphIndex(ch); } s2 += (char)glyphID; } } s = s2; #endif byte[] bytes = PdfEncoders.RawUnicodeEncoding.GetBytes(s); bytes = PdfEncoders.FormatStringLiteral(bytes, true, false, true, null); string text = PdfEncoders.RawEncoding.GetString(bytes); if (glyphs.IsSideways) { textMatrix.RotateAtPrepend(-90, new XPoint(x, y)); XPoint pos = new XPoint(x, y); AdjustTextMatrix(ref pos); //WriteTextTransform(textMatrix); WriteLiteral("{0} Tj\n", text); } else { #if true //if (glyphs.BidiLevel % 2 == 1) // WriteLiteral("-1 Tc\n"); if (!textMatrix.IsIdentity) { WriteTextTransform(textMatrix); } WriteGlyphsInternal(glyphs, null); #else XPoint pos = new XPoint(x, y); AdjustTextMatrix(ref pos); WriteLiteral("{0:0.###} {1:0.###} Td {2} Tj\n", pos.x, pos.y, text); //PdfEncoders.ToStringLiteral(s, PdfStringEncoding.RawEncoding, null)); #endif } WriteRestoreState("end Glyphs", glyphs.Name); }
public void RealizePen(XPen pen, PdfColorMode colorMode) { const string frmt2 = Config.SignificantFigures2; const string format = Config.SignificantFigures3; XColor color = pen.Color; bool overPrint = pen.Overprint; color = ColorSpaceHelper.EnsureColorMode(colorMode, color); if (_realizedLineWith != pen._width) { _renderer.AppendFormatArgs("{0:" + format + "} w\n", pen._width); _realizedLineWith = pen._width; } if (_realizedLineCap != (int)pen._lineCap) { _renderer.AppendFormatArgs("{0} J\n", (int)pen._lineCap); _realizedLineCap = (int)pen._lineCap; } if (_realizedLineJoin != (int)pen._lineJoin) { _renderer.AppendFormatArgs("{0} j\n", (int)pen._lineJoin); _realizedLineJoin = (int)pen._lineJoin; } if (_realizedLineCap == (int)XLineJoin.Miter) { if (_realizedMiterLimit != (int)pen._miterLimit && (int)pen._miterLimit != 0) { _renderer.AppendFormatInt("{0} M\n", (int)pen._miterLimit); _realizedMiterLimit = (int)pen._miterLimit; } } if (_realizedDashStyle != pen._dashStyle || pen._dashStyle == XDashStyle.Custom) { double dot = pen.Width; double dash = 3 * dot; // Line width 0 is not recommended but valid. XDashStyle dashStyle = pen.DashStyle; if (dot == 0) { dashStyle = XDashStyle.Solid; } switch (dashStyle) { case XDashStyle.Solid: _renderer.Append("[]0 d\n"); break; case XDashStyle.Dash: _renderer.AppendFormatArgs("[{0:" + frmt2 + "} {1:" + frmt2 + "}]0 d\n", dash, dot); break; case XDashStyle.Dot: _renderer.AppendFormatArgs("[{0:" + frmt2 + "}]0 d\n", dot); break; case XDashStyle.DashDot: _renderer.AppendFormatArgs("[{0:" + frmt2 + "} {1:" + frmt2 + "} {1:" + frmt2 + "} {1:" + frmt2 + "}]0 d\n", dash, dot); break; case XDashStyle.DashDotDot: _renderer.AppendFormatArgs("[{0:" + frmt2 + "} {1:" + frmt2 + "} {1:" + frmt2 + "} {1:" + frmt2 + "} {1:" + frmt2 + "} {1:" + frmt2 + "}]0 d\n", dash, dot); break; case XDashStyle.Custom: { StringBuilder pdf = new StringBuilder("[", 256); int len = pen._dashPattern == null ? 0 : pen._dashPattern.Length; for (int idx = 0; idx < len; idx++) { if (idx > 0) { pdf.Append(' '); } pdf.Append(PdfEncoders.ToString(pen._dashPattern[idx] * pen._width)); } // Make an even number of values look like in GDI+ if (len > 0 && len % 2 == 1) { pdf.Append(' '); pdf.Append(PdfEncoders.ToString(0.2 * pen._width)); } pdf.AppendFormat(CultureInfo.InvariantCulture, "]{0:" + format + "} d\n", pen._dashOffset * pen._width); string pattern = pdf.ToString(); // BUG: [email protected] reported a realizing problem // HACK: I remove the if clause //if (_realizedDashPattern != pattern) { _realizedDashPattern = pattern; _renderer.Append(pattern); } } break; } _realizedDashStyle = dashStyle; } if (colorMode != PdfColorMode.Cmyk) { if (_realizedStrokeColor.Rgb != color.Rgb) { _renderer.Append(PdfEncoders.ToString(color, PdfColorMode.Rgb)); _renderer.Append(" RG\n"); } } else { if (!ColorSpaceHelper.IsEqualCmyk(_realizedStrokeColor, color)) { _renderer.Append(PdfEncoders.ToString(color, PdfColorMode.Cmyk)); _renderer.Append(" K\n"); } } if (_renderer.Owner.Version >= 14 && (_realizedStrokeColor.A != color.A || _realizedStrokeOverPrint != overPrint)) { PdfExtGState extGState = _renderer.Owner.ExtGStateTable.GetExtGStateStroke(color.A, overPrint); string gs = _renderer.Resources.AddExtGState(extGState); _renderer.AppendFormatString("{0} gs\n", gs); // Must create transparency group. if (_renderer._page != null && color.A < 1) { _renderer._page.TransparencyUsed = true; } } _realizedStrokeColor = color; _realizedStrokeOverPrint = overPrint; }
/// <summary> /// Creates a literal from an XMatrix /// </summary> public static PdfLiteral FromMatrix(XMatrix matrix) { return(new PdfLiteral("[" + PdfEncoders.ToString(matrix) + "]")); }
/// <summary> /// This is just a draft to see what to do in detail. /// </summary> private void WriteGlyphs_ClusterMapping(Glyphs glyphs) { string unicodeString = glyphs.UnicodeString; #if DEBUG_ if (!String.IsNullOrEmpty(unicodeString)) { if (unicodeString.StartsWith("abc")) { GetType(); } } #endif bool boldSimulation = (glyphs.StyleSimulations & StyleSimulations.BoldSimulation) == StyleSimulations.BoldSimulation; double boldSimulationFactor = 1; if (boldSimulation) { boldSimulationFactor = 1; } bool RightToLeft = glyphs.BidiLevel % 2 == 1; // TODOWPF: why is this a level?? what means "bidirectional nesting"? GlyphIndices indices = glyphs.Indices; if (indices == null) { indices = new GlyphIndices(); } int codeIdx = 0; int codeCount = String.IsNullOrEmpty(unicodeString) ? 0 : unicodeString.Length; int glyphCount = indices.Count; int glyphIdx = 0; bool stop = false; PdfFont realizedFont = this.graphicsState.realizedFont; OpenTypeDescriptor descriptor = realizedFont.FontDescriptor._descriptor; int glyphIndex; double x = glyphs.OriginX; double y = glyphs.OriginY; XPoint pos = new XPoint(x, y); // accumulation may lead to rounding error -> check it! double uOffset = 0; double vOffset = 0; StringBuilder outputText = new StringBuilder(); double accumulatedWidth = 0; int outputGlyphCount = 0; bool mustRender = false; bool hasOffset = false; do { GlyphIndices.GlyphMapping clusterMapping = new GlyphIndices.GlyphMapping(42); if (glyphIdx < glyphCount) { clusterMapping = indices[glyphIdx]; } for (int clusterGlyphIdx = 0; clusterGlyphIdx < clusterMapping.ClusterGlyphCount; clusterGlyphIdx++) { GlyphIndices.GlyphMapping mapping = new GlyphIndices.GlyphMapping(42); if (glyphIdx + clusterGlyphIdx < glyphCount) { mapping = indices[glyphIdx + clusterGlyphIdx]; } Debug.Assert(mustRender == false); // Determine whether to render accumulated glyphs if (outputGlyphCount > 0 && (hasOffset || mapping.HasAdvanceWidthOrOffset)) { outputText.Append('>'); WriteLiteral("{0:0.####} {1:0.####} Td {2}Tj\n", pos.X, pos.Y, outputText.ToString()); //double width = descriptor.GlyphIndexToPdfWidth(glyphIndex); //if (!PdfSharp.Internal.DoubleUtil.IsNaN(mapping.AdvanceWidth)) // width = mapping.AdvanceWidth * 10; //pos = new XPoint(accumulatedWidth + width / 1000 * glyphs.FontRenderingEmSize, 0); pos = new XPoint(accumulatedWidth, 0); // reset values accumulatedWidth = 0; outputGlyphCount = 0; outputText.Length = 0; mustRender = false; } mustRender = mapping.HasAdvanceWidth; //mustRender = true; // Adjust former uOffset if (uOffset != 0) { pos.X -= uOffset; uOffset = 0; mustRender = true; } // Adjust position by current former uOffset if (mapping.HasUOffset) { uOffset = mapping.UOffset * glyphs.FontRenderingEmSize / 100; pos.X += uOffset; mustRender = true; hasOffset = true; } // Adjust former vOffset if (vOffset != 0) { pos.Y += vOffset; vOffset = 0; mustRender = true; } // Adjust position by current former vOffset if (mapping.HasVOffset) { vOffset = mapping.VOffset * glyphs.FontRenderingEmSize / 100; pos.Y -= vOffset; mustRender = true; hasOffset = true; } // get index of current glyph if (mapping.HasGlyphIndex) { glyphIndex = mapping.GlyphIndex; } else { glyphIndex = descriptor.CharCodeToGlyphIndex(unicodeString[codeIdx]); } // add glyph index to the fonts 'used glyph table' realizedFont.AddGlyphIndices(new string((char)glyphIndex, 1)); #if true if (outputGlyphCount == 0) { outputText.Append('<'); } outputText.AppendFormat("{0:X2}{1:X2}", (byte)(glyphIndex >> 8), (byte)glyphIndex); #else byte[] bytes = new byte[2] { (byte)(glyphIndex >> 8), (byte)glyphIndex }; bytes = PdfEncoders.FormatStringLiteral(bytes, true, false, true, null); string output = PdfEncoders.RawEncoding.GetString(bytes); #endif // At the end of the glyph run we must always render if (!mustRender) { mustRender = codeIdx + clusterMapping.ClusterCodeUnitCount >= codeCount && // is it the last code unit cluster glyphIdx + clusterGlyphIdx + 1 >= glyphCount; // is it the last glyph index } //mustRender = true; if (mustRender) { outputText.Append('>'); WriteLiteral("{0:0.####} {1:0.####} Td {2}Tj\n", pos.X, pos.Y, outputText.ToString()); double width = descriptor.GlyphIndexToPdfWidth(glyphIndex); if (!PdfSharp.Internal.DoubleUtil.IsNaN(mapping.AdvanceWidth)) { width = mapping.AdvanceWidth * 10; } pos = new XPoint(accumulatedWidth + width * boldSimulationFactor / 1000 * glyphs.FontRenderingEmSize, 0); // reset values accumulatedWidth = 0; outputGlyphCount = 0; outputText.Length = 0; mustRender = false; } else // deferred rendering { // accumulate width Debug.Assert(DoubleUtil.IsNaN(mapping.AdvanceWidth)); double width = descriptor.GlyphIndexToPdfWidth(glyphIndex); width = width * boldSimulationFactor / 1000 * glyphs.FontRenderingEmSize; accumulatedWidth += width; outputGlyphCount++; } } codeIdx += clusterMapping.ClusterCodeUnitCount; glyphIdx += clusterMapping.ClusterGlyphCount; if (codeIdx >= codeCount && glyphIdx >= glyphCount) { stop = true; } }while (!stop); }
/// <summary> /// Builds the shading function of the specified gradient stop collection. /// </summary> protected PdfDictionary BuildShadingFunction(GradientStopCollection gradients, bool softMask, PdfColorMode colorMode, bool reverse, out PdfDictionary funcReverse) { PdfDictionary func = new PdfDictionary(); int count = gradients.Count; Debug.Assert(count >= 2); if (CanOptimizeForTwoColors(gradients)) { funcReverse = null; // Build a Type 3 function with an array of 2 Type 2 functions func.Elements["/FunctionType"] = new PdfInteger(3); // Type 3 - Stitching Function func.Elements["/Domain"] = new PdfLiteral("[0 1]"); PdfArray fnarray = new PdfArray(); func.Elements["/Functions"] = fnarray; StringBuilder bounds = new StringBuilder("["); StringBuilder encode = new StringBuilder("["); for (int idx = 1; idx < count; idx++) { PdfDictionary fn2 = new PdfDictionary(); fn2.Elements["/FunctionType"] = new PdfInteger(2); Color clr0 = gradients[idx - 1].Color; Color clr1 = gradients[idx].Color; if (softMask) { fn2.Elements["/C0"] = new PdfLiteral("[" + PdfEncoders.ToString(clr0.ScA) + "]"); fn2.Elements["/C1"] = new PdfLiteral("[" + PdfEncoders.ToString(clr1.ScA) + "]"); fn2.Elements["/Range"] = new PdfLiteral("[0 1]"); } else { fn2.Elements["/C0"] = new PdfLiteral("[" + PdfEncoders.ToString(clr0, colorMode) + "]"); fn2.Elements["/C1"] = new PdfLiteral("[" + PdfEncoders.ToString(clr1, colorMode) + "]"); fn2.Elements["/Range"] = new PdfLiteral("[0 1 0 1 0 1]"); } fn2.Elements["/Domain"] = new PdfLiteral("[0 1]"); fn2.Elements["/N"] = new PdfInteger(1); fnarray.Elements.Add(fn2); if (idx > 1) { bounds.Append(' '); encode.Append(' '); } if (idx < count - 1) { bounds.Append(PdfEncoders.ToString(gradients[idx].Offset)); } encode.Append(reverse ? "1 0" : "0 1"); } bounds.Append(']'); encode.Append(']'); func.Elements["/Bounds"] = new PdfLiteral(bounds.ToString()); func.Elements["/Encode"] = new PdfLiteral(encode.ToString()); } else { #if true funcReverse = BuildShadingFunction3(gradients, softMask, colorMode); Context.PdfDocument.Internals.AddObject(funcReverse); func.Elements["/FunctionType"] = new PdfInteger(3); // Type 3 - Stitching Function func.Elements["/Domain"] = new PdfLiteral("[0 1]"); func.Elements["/Encode"] = new PdfLiteral("[1 0]"); func.Elements["/Bounds"] = new PdfLiteral("[]"); func.Elements["/Range"] = new PdfLiteral("[0 1 0 1 0 1]"); PdfArray fnarray0 = new PdfArray(); fnarray0.Elements.Add(funcReverse); func.Elements["/Functions"] = fnarray0; #else // // Build a Type 3 function with an array of n-1 Type 2 functions PdfDictionary fn1 = new PdfDictionary(); func.Elements["/FunctionType"] = new PdfInteger(3); // Type 3 - Stitching Function func.Elements["/Domain"] = new PdfLiteral("[0 1]"); func.Elements["/Encode"] = new PdfLiteral("[1 0]"); func.Elements["/Bounds"] = new PdfLiteral("[]"); func.Elements["/Range"] = new PdfLiteral("[0 1 0 1 0 1]"); PdfArray fnarray0 = new PdfArray(); fnarray0.Elements.Add(fn1); func.Elements["/Functions"] = fnarray0; fn1.Elements["/FunctionType"] = new PdfInteger(3); // Type 3 - Stitching Function fn1.Elements["/Domain"] = new PdfLiteral("[0 1]"); fn1.Elements["/Range"] = new PdfLiteral("[0 1 0 1 0 1]"); PdfArray fnarray = new PdfArray(); fn1.Elements["/Functions"] = fnarray; StringBuilder bounds = new StringBuilder("["); StringBuilder encode = new StringBuilder("["); for (int idx = 1; idx < count; idx++) { PdfDictionary fn2 = new PdfDictionary(); fn2.Elements["/FunctionType"] = new PdfInteger(2); Color clr0 = gradients[idx - 1].Color; Color clr1 = gradients[idx].Color; if (softMask) { fn2.Elements["/C0"] = new PdfLiteral("[" + PdfEncoders.ToString(clr0.ScA) + "]"); fn2.Elements["/C1"] = new PdfLiteral("[" + PdfEncoders.ToString(clr1.ScA) + "]"); fn2.Elements["/Range"] = new PdfLiteral("[0 1]"); } else { fn2.Elements["/C0"] = new PdfLiteral("[" + PdfEncoders.ToString(clr0, colorMode) + "]"); fn2.Elements["/C1"] = new PdfLiteral("[" + PdfEncoders.ToString(clr1, colorMode) + "]"); fn2.Elements["/Range"] = new PdfLiteral("[0 1 0 1 0 1]"); } fn2.Elements["/Domain"] = new PdfLiteral("[0 1]"); fn2.Elements["/N"] = new PdfInteger(1); //this.renderer.Owner.Internals.AddObject(fn2); //fnarray.Elements.Add(fn2.Reference); fnarray.Elements.Add(fn2); if (idx > 1) { bounds.Append(' '); encode.Append(' '); } if (idx < count - 1) { bounds.Append(PdfEncoders.ToString(gradients[idx].Offset)); } encode.Append("0 1"); } bounds.Append(']'); encode.Append(']'); fn1.Elements["/Bounds"] = new PdfLiteral(bounds.ToString()); fn1.Elements["/Encode"] = new PdfLiteral(encode.ToString()); #endif } return(func); }
/// <summary> /// Setups the shading from the specified brush. /// </summary> public void SetupFromBrush(XLinearGradientBrush brush) { if (brush == null) { throw new ArgumentNullException("brush"); } PdfColorMode colorMode = this.document.Options.ColorMode; XColor color1 = ColorSpaceHelper.EnsureColorMode(colorMode, brush.color1); XColor color2 = ColorSpaceHelper.EnsureColorMode(colorMode, brush.color2); PdfDictionary function = new PdfDictionary(); Elements[Keys.ShadingType] = new PdfInteger(2); if (colorMode != PdfColorMode.Cmyk) { Elements[Keys.ColorSpace] = new PdfName("/DeviceRGB"); } else { Elements[Keys.ColorSpace] = new PdfName("/DeviceCMYK"); } double x1 = 0, y1 = 0, x2 = 0, y2 = 0; if (brush.useRect) { switch (brush.linearGradientMode) { case XLinearGradientMode.Horizontal: x1 = brush.rect.x; y1 = brush.rect.y; x2 = brush.rect.x + brush.rect.width; y2 = brush.rect.y; break; case XLinearGradientMode.Vertical: x1 = brush.rect.x; y1 = brush.rect.y; x2 = brush.rect.x; y2 = brush.rect.y + brush.rect.height; break; case XLinearGradientMode.ForwardDiagonal: x1 = brush.rect.x; y1 = brush.rect.y; x2 = brush.rect.x + brush.rect.width; y2 = brush.rect.y + brush.rect.height; break; case XLinearGradientMode.BackwardDiagonal: x1 = brush.rect.x + brush.rect.width; y1 = brush.rect.y; x2 = brush.rect.x; y2 = brush.rect.y + brush.rect.height; break; } } else { x1 = brush.point1.x; y1 = brush.point1.y; x2 = brush.point2.x; y2 = brush.point2.y; } Elements[Keys.Coords] = new PdfLiteral("[{0:0.###} {1:0.###} {2:0.###} {3:0.###}]", x1, y1, x2, y2); //Elements[Keys.Background] = new PdfRawItem("[0 1 1]"); //Elements[Keys.Domain] = Elements[Keys.Function] = function; //Elements[Keys.Extend] = new PdfRawItem("[true true]"); string clr1 = "[" + PdfEncoders.ToString(color1, colorMode) + "]"; string clr2 = "[" + PdfEncoders.ToString(color2, colorMode) + "]"; function.Elements["/FunctionType"] = new PdfInteger(2); function.Elements["/C0"] = new PdfLiteral(clr1); function.Elements["/C1"] = new PdfLiteral(clr2); function.Elements["/Domain"] = new PdfLiteral("[0 1]"); function.Elements["/N"] = new PdfInteger(1); }
//[Obsolete] // 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 // } // } // [Obsolete] // void RealizeRadialGradientBrush(RadialGradientBrush brush, XForm xform) // { // XMatrix matrix = new XMatrix(); // this.renderer.defaultViewMatrix; // //matrix.MultiplyPrepend(this.Transform); // matrix = this.currentTransform; // //matrix.MultiplyPrepend(XMatrix.CreateScaling(1.3, 1)); // 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); // shading.Elements[PdfShading.Keys.ShadingType] = new PdfInteger(3); // Radial shading // //if (colorMode != PdfColorMode.Cmyk) // shading.Elements[PdfShading.Keys.ColorSpace] = new PdfName("/DeviceRGB"); // //else // //shading.Elements[Keys.ColorSpace] = new PdfName("/DeviceCMYK"); // double x0 = brush.GradientOrigin.X; // double y0 = brush.GradientOrigin.Y; // double r0 = 0; // double x1 = brush.Center.X; // double y1 = brush.Center.Y; // double r1 = brush.RadiusX; // shading.Elements[PdfShading.Keys.Coords] = // new PdfLiteral("[{0:0.###} {1:0.###} {2:0.###} {3:0.###} {4:0.###} {5:0.###}]", x0, y0, r0, x1, y1, r1); // // old: Elements[Keys.Background] = new PdfRawItem("[0 1 1]"); // // old: Elements[Keys.Domain] = // shading.Elements[PdfShading.Keys.Function] = function; // 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) // { //#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 (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); // } //#endif // } // } //void RealizeImageBrush(ImageBrush brush, XForm xform) //{ //} //void RealizeVisualBrush(VisualBrush brush, XForm xform) //{ //} /// <summary> /// Builds the shading function of the specified gradient stop collection. /// </summary> PdfDictionary BuildShadingFunction(GradientStopCollection gradients, PdfColorMode colorMode) { bool softMask = this.writer.renderMode == RenderMode.SoftMask; PdfDictionary func = new PdfDictionary(); int count = gradients.Count; Debug.Assert(count >= 2); if (count == 2) { // Build one Type 2 function func.Elements["/FunctionType"] = new PdfInteger(2); // Type 2 - Exponential Interpolation Function Color clr0 = gradients[0].Color; Color clr1 = gradients[1].Color; if (softMask) { clr0 = Utils.AlphaToGray(clr0); clr1 = Utils.AlphaToGray(clr1); } func.Elements["/C0"] = new PdfLiteral("[" + PdfEncoders.ToString(clr0, colorMode) + "]"); func.Elements["/C1"] = new PdfLiteral("[" + PdfEncoders.ToString(clr1, colorMode) + "]"); func.Elements["/Domain"] = new PdfLiteral("[0 1]"); func.Elements["/N"] = new PdfInteger(1); // be linear } else { // Build a Type 3 function with an array of n-1 Type 2 functions func.Elements["/FunctionType"] = new PdfInteger(3); // Type 3 - Stitching Function func.Elements["/Domain"] = new PdfLiteral("[0 1]"); PdfArray fnarray = new PdfArray(); func.Elements["/Functions"] = fnarray; StringBuilder bounds = new StringBuilder("["); StringBuilder encode = new StringBuilder("["); for (int idx = 1; idx < count; idx++) { PdfDictionary fn2 = new PdfDictionary(); fn2.Elements["/FunctionType"] = new PdfInteger(2); Color clr0 = gradients[idx - 1].Color; Color clr1 = gradients[idx].Color; if (softMask) { clr0 = Utils.AlphaToGray(clr0); clr1 = Utils.AlphaToGray(clr1); } fn2.Elements["/C0"] = new PdfLiteral("[" + PdfEncoders.ToString(clr0, colorMode) + "]"); fn2.Elements["/C1"] = new PdfLiteral("[" + PdfEncoders.ToString(clr1, colorMode) + "]"); fn2.Elements["/Domain"] = new PdfLiteral("[0 1]"); fn2.Elements["/N"] = new PdfInteger(1); //this.renderer.Owner.Internals.AddObject(fn2); //fnarray.Elements.Add(fn2.Reference); fnarray.Elements.Add(fn2); if (idx > 1) { bounds.Append(' '); encode.Append(' '); } if (idx < count - 1) { bounds.Append(PdfEncoders.ToString(gradients[idx].Offset)); } encode.Append("0 1"); } bounds.Append(']'); //encode.Append(" 0 1"); encode.Append(']'); func.Elements["/Bounds"] = new PdfLiteral(bounds.ToString()); func.Elements["/Encode"] = new PdfLiteral(encode.ToString()); } return(func); }
void RealizeStrokeStyle(Path path) { if (this.realizedLineCap != (int)path.StrokeStartLineCap) { // HACK: Set Triangle to Square int[] pdfValue = { 0, 1, 2, 2 }; // Flat, Round, Square, Triangle, //int[] pdfValue = { 1, 1, 1, 1 }; // Flat, Round, Square, Triangle, int value = pdfValue[(int)path.StrokeStartLineCap]; this.writer.WriteLiteral("{0} J\n", value); this.realizedLineCap = value; } if (this.realizedLineJoin != (int)path.StrokeLineJoin) { int[] pdfValue = { 0, 2, 1 }; // Miter, Bevel, Round int value = pdfValue[(int)path.StrokeLineJoin]; this.writer.WriteLiteral("{0} j\n", value); this.realizedLineJoin = value; // TODO: Check implementation in PDFsharp PDF renderer! if (path.StrokeLineJoin == LineJoin.Miter) { if (this.realizedMiterLimit != path.StrokeMiterLimit && path.StrokeMiterLimit != 0) { this.writer.WriteLiteral("{0:0.##} M\n", path.StrokeMiterLimit); this.realizedMiterLimit = path.StrokeMiterLimit; } } } if (!String.IsNullOrEmpty(path.StrokeDashArray)) { string[] values = path.StrokeDashArray.Split(new char[] { ' ' }); int count = values.Length; double[] dashArray = new double[count]; for (int idx = 0; idx < count; idx++) { Double.TryParse(values[idx], NumberStyles.Float, CultureInfo.InvariantCulture, out dashArray[idx]); } // Line width 0 is not recommended but valid //XDashStyle dashStyle = pen.DashStyle; //if (dot == 0) // dashStyle = XDashStyle.Solid; double dot = path.StrokeThickness; double dash = 3 * path.StrokeThickness; if (dot > 0) { #if old //switch (dashStyle) //{ // case XDashStyle.Solid: // this.renderer.Append("[]0 d\n"); // break; // case XDashStyle.Dash: // this.renderer.AppendFormat("[{0:0.##} {1:0.##}]0 d\n", dash, dot); // break; // case XDashStyle.Dot: // this.renderer.AppendFormat("[{0:0.##}]0 d\n", dot); // break; // case XDashStyle.DashDot: // this.renderer.AppendFormat("[{0:0.##} {1:0.##} {1:0.##} {1:0.##}]0 d\n", dash, dot); // break; // case XDashStyle.DashDotDot: // this.renderer.AppendFormat("[{0:0.##} {1:0.##} {1:0.##} {1:0.##} {1:0.##} {1:0.##}]0 d\n", dash, dot); // break; // case XDashStyle.Custom: // { // StringBuilder pdf = new StringBuilder("[", 256); // int len = pen.dashPattern == null ? 0 : pen.dashPattern.Length; // for (int idx = 0; idx < len; idx++) // { // if (idx > 0) // pdf.Append(' '); // pdf.Append(PdfEncoders.ToString(pen.dashPattern[idx] * pen.width)); // } // // Make an even number of values look like in GDI+ // if (len > 0 && len % 2 == 1) // { // pdf.Append(' '); // pdf.Append(PdfEncoders.ToString(0.2 * pen.width)); // } // pdf.AppendFormat(CultureInfo.InvariantCulture, "]{0:0.###} d\n", pen.dashOffset * pen.width); // string pattern = pdf.ToString(); // // BUG: [email protected] reported a realizing problem // // HACK: I romove the if clause // //if (this.realizedDashPattern != pattern) // { // this.realizedDashPattern = pattern; // this.renderer.Append(pattern); // } // } // break; //} //this.realizedDashStyle = dashStyle; #endif StringBuilder pdf = new StringBuilder("[", 256); for (int idx = 0; idx < count; idx++) { if (idx > 0) { pdf.Append(' '); } pdf.Append(PdfEncoders.ToString(dashArray[idx] * path.StrokeThickness)); } // TODO: ?? // Make an even number of values look like in GDI+ if (count > 0 && count % 2 == 1) { pdf.Append(' '); pdf.Append(PdfEncoders.ToString(0.2 * path.StrokeThickness)); } pdf.AppendFormat(CultureInfo.InvariantCulture, "]{0:0.###} d\n", path.StrokeDashOffset * path.StrokeThickness); string pattern = pdf.ToString(); //// BUG: [email protected] reported a realizing problem //// HACK: I romove the if clause ////if (this.realizedDashPattern != pattern) //{ // this.realizedDashPattern = pattern; this.writer.WriteLiteral(pattern); //} } } }
/// <summary> /// Setups the shading from the specified brush. /// </summary> internal void SetupFromBrush(XLinearGradientBrush brush, XGraphicsPdfRenderer renderer) { if (brush == null) { throw new ArgumentNullException("brush"); } PdfColorMode colorMode = _document.Options.ColorMode; XColor color1 = ColorSpaceHelper.EnsureColorMode(colorMode, brush._color1); XColor color2 = ColorSpaceHelper.EnsureColorMode(colorMode, brush._color2); PdfDictionary function = new PdfDictionary(); Elements[Keys.ShadingType] = new PdfInteger(2); if (colorMode != PdfColorMode.Cmyk) { Elements[Keys.ColorSpace] = new PdfName("/DeviceRGB"); } else { Elements[Keys.ColorSpace] = new PdfName("/DeviceCMYK"); } double x1 = 0, y1 = 0, x2 = 0, y2 = 0; if (brush._useRect) { XPoint pt1 = renderer.WorldToView(brush._rect.TopLeft); XPoint pt2 = renderer.WorldToView(brush._rect.BottomRight); switch (brush._linearGradientMode) { case XLinearGradientMode.Horizontal: x1 = pt1.X; y1 = pt1.Y; x2 = pt2.X; y2 = pt1.Y; break; case XLinearGradientMode.Vertical: x1 = pt1.X; y1 = pt1.Y; x2 = pt1.X; y2 = pt2.Y; break; case XLinearGradientMode.ForwardDiagonal: x1 = pt1.X; y1 = pt1.Y; x2 = pt2.X; y2 = pt2.Y; break; case XLinearGradientMode.BackwardDiagonal: x1 = pt2.X; y1 = pt1.Y; x2 = pt1.X; y2 = pt2.Y; break; } } else { XPoint pt1 = renderer.WorldToView(brush._point1); XPoint pt2 = renderer.WorldToView(brush._point2); x1 = pt1.X; y1 = pt1.Y; x2 = pt2.X; y2 = pt2.Y; } const string format = Config.SignificantFigures3; Elements[Keys.Coords] = new PdfLiteral("[{0:" + format + "} {1:" + format + "} {2:" + format + "} {3:" + format + "}]", x1, y1, x2, y2); //Elements[Keys.Background] = new PdfRawItem("[0 1 1]"); //Elements[Keys.Domain] = Elements[Keys.Function] = function; //Elements[Keys.Extend] = new PdfRawItem("[true true]"); string clr1 = "[" + PdfEncoders.ToString(color1, colorMode) + "]"; string clr2 = "[" + PdfEncoders.ToString(color2, colorMode) + "]"; function.Elements["/FunctionType"] = new PdfInteger(2); function.Elements["/C0"] = new PdfLiteral(clr1); function.Elements["/C1"] = new PdfLiteral(clr2); function.Elements["/Domain"] = new PdfLiteral("[0 1]"); function.Elements["/N"] = new PdfInteger(1); }
PdfShadingPattern BuildPattern(RadialGradientBrush brush, XRect boundingBox, XMatrix transform) { //<< // /BBox [0 0 600 760] // /Length 123 // /Matrix [0.75 0 0 -0.75 0 480] // /PaintType 1 // /PatternType 1 // /Resources // << // /ColorSpace // << // /CS0 12 0 R // /CS1 12 0 R // >> // /ExtGState // << // /GS0 10 0 R // /GS1 16 0 R // >> // /Shading // << // /Sh0 15 0 R // >> // >> // /TilingType 3 // /Type /Pattern // /XStep 600 // /YStep 1520 //>> //stream // /CS0 cs 1 0 0 scn // 1 i // /GS0 gs // 0 0 600 759.999 re // f // q // 0 0 600 760 re // W n // q // 0 g // /GS1 gs // 1 0 0 0.5 0 0 cm // BX /Sh0 sh EX Q // Q //endstream XRect bbox = new XRect(-600, -700, 1200, 1520); // HACK XMatrix matrix = transform; //matrix.Prepend(brush.Transform.Matrix); double xStep = 600; double yStep = 1520; // HACK PdfShadingPattern pattern = Context.PdfDocument.Internals.CreateIndirectObject <PdfShadingPattern>(); pattern.Elements.SetInteger(PdfTilingPattern.Keys.PatternType, 1); // Tiling pattern.Elements.SetInteger(PdfTilingPattern.Keys.PaintType, 1); // Color pattern.Elements.SetInteger(PdfTilingPattern.Keys.TilingType, 3); // Constant spacing and faster tiling pattern.Elements.SetMatrix(PdfTilingPattern.Keys.Matrix, matrix); pattern.Elements.SetRectangle(PdfTilingPattern.Keys.BBox, new PdfRectangle(bbox)); pattern.Elements.SetReal(PdfTilingPattern.Keys.XStep, xStep); pattern.Elements.SetReal(PdfTilingPattern.Keys.YStep, yStep); double dx = 2 * brush.RadiusX; double dy = 2 * brush.RadiusY; XRect brushBox = new XRect(brush.Center.X - brush.RadiusX, brush.Center.Y - brush.RadiusY, dx, dy); Debug.Assert(dx * dy > 0, "Radius is 0."); double scaleX, scaleY; if (dx > dy) { scaleX = 1; scaleY = dy / dx; } else { scaleX = dx / dy; scaleY = 1; } PdfColorMode colorMode = PdfColorMode.Rgb; PdfDictionary funcReflected; PdfDictionary funcRegular = BuildShadingFunction(brush.GradientStops, false, colorMode, true, out funcReflected); if (brush.SpreadMethod != SpreadMethod.Pad) { if (CanOptimizeForTwoColors(brush.GradientStops)) { PdfDictionary dummy; funcReflected = BuildShadingFunction(brush.GradientStops, false, colorMode, false, out dummy); } else { Context.PdfDocument.Internals.AddObject(funcRegular); } } //PdfShading shading = BuildShading(brush, scaleX, scaleY); int shadingCount = 1; if (brush.SpreadMethod != SpreadMethod.Pad) { // TODO: Calculate number of required shadings shadingCount = Convert.ToInt32(Math.Max(boundingBox.Width / (2 * brush.RadiusX), boundingBox.Height / (2 * brush.RadiusY)) + 1); // HACK: Rule of thumb, better than nothing shadingCount *= 2; } PdfShading[] shadings = new PdfShading[shadingCount]; // Create the shadings for (int idx = 0; idx < shadingCount; idx++) { PdfShading shading = BuildShading2(brush, scaleX, scaleY, idx, brush.SpreadMethod == SpreadMethod.Reflect && idx % 2 == 1 ? funcReflected : funcRegular); shadings[idx] = shading; } PdfContentWriter writer = new PdfContentWriter(Context, pattern); writer.BeginContentRaw(); // Fill background (even if spread method is not pad) writer.WriteLiteral("q /DeviceRGB cs\n"); //writer.WriteLiteral(PdfEncoders.ToString(clr0, colorMode) + " rg 1 i\n"); writer.WriteLiteral(PdfEncoders.ToString(brush.GradientStops[brush.GradientStops.Count - 1].Color, PdfColorMode.Rgb) + " rg 1 i\n"); writer.WriteLiteral("1 i\n"); PdfExtGState gs = Context.PdfDocument.Internals.CreateIndirectObject <PdfExtGState>(); gs.SetDefault1(); writer.WriteGraphicsState(gs); writer.WriteLiteral("0 0 600 760 re f\n"); XMatrix mat = brush.Transform.Matrix; if (!mat.IsIdentity) { writer.WriteMatrix(mat); } // Just work: silly loop thru shadings for (int idx = shadingCount - 1; idx >= 0; idx--) { writer.WriteLiteral("q 0 0 600 760 re W n\n"); writer.WriteLiteral("q 0 g\n"); gs = Context.PdfDocument.Internals.CreateIndirectObject <PdfExtGState>(); gs.SetDefault2(); writer.WriteGraphicsState(gs); XMatrix transformation = new XMatrix(scaleX, 0, 0, scaleY, 0, 0); writer.WriteMatrix(transformation); string shName = writer.Resources.AddShading(shadings[idx]); writer.WriteLiteral("BX " + shName + " sh EX Q Q\n"); } writer.WriteLiteral("Q\n"); writer.EndContent(); return(pattern); }