private void WritePath(Path path)
{
if (WriteSingleLineStrokeWithSpecialCaps(path))
return;
WriteSaveState("begin Path", path.Name);
// Transform also affects clipping and opacity mask
if (path.RenderTransform != null && this.renderMode == RenderMode.Default)
{
MultiplyTransform(path.RenderTransform);
WriteRenderTransform(path.RenderTransform);
}
if (path.Clip != null && this.renderMode == RenderMode.Default)
WriteClip(path.Clip);
if (path.Opacity < 1)
MultiplyOpacity(path.Opacity);
if (path.OpacityMask != null)
WriteOpacityMask(path.OpacityMask);
if (path.Fill == null)
{
if (path.Stroke != null)
{
#if true
WriteStrokeGeometry(path);
#else
// Just stroke the path
RealizeStroke(path);
WriteGeometry(path.Data);
WritePathFillStroke(path);
#endif
}
else
Debug.Assert(false, "??? Path with neither Stroke nor Fill encountered.");
}
else
{
SolidColorBrush sBrush;
LinearGradientBrush lgBrush;
RadialGradientBrush rgBrush;
ImageBrush iBrush;
VisualBrush vBrush;
if ((sBrush = path.Fill as SolidColorBrush) != null)
{
Color color = sBrush.Color;
double opacity = Opacity * color.ScA;
if (opacity < 1)
RealizeFillOpacity(opacity);
WriteRgb(color, " rg\n");
if (path.Stroke != null)
RealizeStroke(path);
WriteGeometry(path.Data);
WritePathFillStroke(path);
}
else if ((lgBrush = path.Fill as LinearGradientBrush) != null)
{
// TODO: For better visual compatibility use a Shading Pattern if Opacity is not 1 and
// the Stroke Style is not solid. Acrobat 8 ignores this case.
PdfExtGState xgState = Context.PdfDocument.Internals.CreateIndirectObject<PdfExtGState>();
xgState.SetDefault1();
double opacity = Opacity * lgBrush.Opacity; ;
if (opacity < 1)
{
xgState.StrokeAlpha = opacity;
xgState.NonStrokeAlpha = opacity;
}
RealizeExtGState(xgState);
// 1st draw fill
if (lgBrush.GradientStops.HasTransparency)
{
// Create a FormXObject with a soft mask
PdfFormXObject form = LinearShadingBuilder.BuildFormFromLinearGradientBrush(Context, lgBrush, path.Data);
string foName = Resources.AddForm(form);
WriteLiteral(foName + " Do\n");
}
else
{
// Create just a shading
PdfShading shading = LinearShadingBuilder.BuildShadingFromLinearGradientBrush(Context, lgBrush);
string shName = Resources.AddShading(shading);
WriteLiteral("q\n");
WriteClip(path.Data);
WriteLiteral("BX " + shName + " sh EX Q\n");
}
// 2nd draw stroke
if (path.Stroke != null)
WriteStrokeGeometry(path);
}
else if ((rgBrush = path.Fill as RadialGradientBrush) != null)
{
PdfExtGState xgState = Context.PdfDocument.Internals.CreateIndirectObject<PdfExtGState>();
xgState.SetDefault1();
double avGradientOpacity = rgBrush.GradientStops.GetAverageAlpha(); // HACK
double opacity = Opacity * rgBrush.Opacity * avGradientOpacity;
if (opacity < 1)
{
xgState.StrokeAlpha = opacity;
xgState.NonStrokeAlpha = opacity;
}
//RealizeExtGState(xgState);
#if true
XRect boundingBox = path.Data.GetBoundingBox();
// Always creates a pattern, because the background must be filled
PdfShadingPattern pattern = RadialShadingBuilder.BuildFromRadialGradientBrush(Context, rgBrush, boundingBox, Transform);
string paName = Resources.AddPattern(pattern);
// stream
// /CS0 cs /P0 scn
// /GS0 gs
// 0 480 180 -90 re
// f*
// endstream
// endobj
WriteLiteral("/Pattern cs " + paName + " scn\n");
// move to here: RealizeExtGState(xgState);
RealizeExtGState(xgState);
WriteGeometry(path.Data);
if (path.Data.FillRule == FillRule.NonZero) // NonZero means Winding
WriteLiteral("f\n");
else
WriteLiteral("f*\n");
#else
#if true
// 1st draw fill
if (rgBrush.GradientStops.HasTransparentColors)
{
// Create a FormXObject with a soft mask
PdfFormXObject form = ShadingBuilder.BuildFormFromRadialGradientBrush(Context, rgBrush, path.Data);
string foName = Resources.AddForm(form);
WriteLiteral(foName + " Do\n");
}
else
{
// Create just a shading
PdfShading shading = ShadingBuilder.BuildShadingFromRadialGradientBrush(Context, rgBrush);
string shName = Resources.AddShading(shading);
WriteLiteral("q\n");
WriteClip(path.Data);
WriteLiteral("BX " + shName + " sh EX Q\n");
}
#else
// Establish graphic state dictionary
PdfExtGState extGState = new PdfExtGState(Context.PdfDocument);
Context.PdfDocument.Internals.AddObject(extGState);
string gsName = Resources.AddExtGState(extGState);
WriteLiteral(gsName + " gs\n");
// 1st draw fill
PdfShading shading = ShadingBuilder.BuildFormFromRadialGradientBrush(Context, rgBrush); //, extGState);
string shName = Resources.AddShading(shading);
WriteClip(path.Data);
WriteLiteral("BX " + shName + " sh EX\n");
#endif
#endif
// 2nd draw stroke
if (path.Stroke != null)
WriteStrokeGeometry(path);
}
else if ((iBrush = path.Fill as ImageBrush) != null)
{
PdfExtGState xgState = Context.PdfDocument.Internals.CreateIndirectObject<PdfExtGState>();
xgState.SetDefault1();
double opacity = Opacity * iBrush.Opacity;
if (opacity <= 1)
{
xgState.StrokeAlpha = opacity;
xgState.NonStrokeAlpha = opacity;
}
RealizeExtGState(xgState);
// 1st draw fill
PdfTilingPattern pattern = TilingPatternBuilder.BuildFromImageBrush(Context, iBrush, Transform);
string name = Resources.AddPattern(pattern);
WriteLiteral("/Pattern cs " + name + " scn\n");
WriteGeometry(path.Data);
WritePathFillStroke(path);
// 2nd draw stroke
if (path.Stroke != null)
WriteStrokeGeometry(path);
}
else if ((vBrush = path.Fill as VisualBrush) != null)
{
PdfExtGState xgState = Context.PdfDocument.Internals.CreateIndirectObject<PdfExtGState>();
xgState.SetDefault1();
double opacity = Opacity * vBrush.Opacity;
if (opacity < 1)
{
xgState.StrokeAlpha = opacity;
xgState.NonStrokeAlpha = opacity;
}
RealizeExtGState(xgState);
// 1st draw fill
PdfTilingPattern pattern = TilingPatternBuilder.BuildFromVisualBrush(Context, vBrush, Transform);
string name = Resources.AddPattern(pattern);
WriteLiteral("/Pattern cs " + name + " scn\n");
WriteGeometry(path.Data);
WritePathFillStroke(path);
// 2nd draw stroke
if (path.Stroke != null)
WriteStrokeGeometry(path);
}
else
{
Debug.Assert(false, "Unknown brush type encountered.");
}
}
// Checking is there a link attached with this Path
if (path.FixedPage_NavigateUri != null && !string.IsNullOrEmpty(path.FixedPage_NavigateUri.Trim()))
{
var bounds = path.Data.GetBoundingBox();
var xpsPage = path.Parent as FixedPage;
if (xpsPage != null)
{
var pxToPtScale = xpsPage.PointHeight/xpsPage.Height;
try
{
var uri = new Uri(path.FixedPage_NavigateUri);
page.AddWebLink(
new PdfRectangle(bounds.Left*pxToPtScale, page.Height - bounds.Top*pxToPtScale,
bounds.Right*pxToPtScale, page.Height - bounds.Bottom*pxToPtScale),
uri.AbsoluteUri);
}
catch (Exception)
{
Debug.Assert(false, "WritePath(...) > Invalid URI string provided");
}
}
}
WriteRestoreState("end Path", path.Name);
}