Beispiel #1
0
        protected XMatrix RotateByDegrees(double rotateAngle, XPoint center)
        {
            double  rotateRadians  = rotateAngle * System.Math.PI / 180;
            XMatrix transformation = XMatrix.Identity;

            transformation.RotateAtPrepend(rotateRadians, center);
            return(transformation);
        }
Beispiel #2
0
        private static XPoint DrawLineArrowInternal(XGraphics gfx, XPen pen, XSolidBrush brush, double x, double y, double angle, Core2D.Style.ArrowStyle style)
        {
            XPoint pt;
            var    rt = new XMatrix();
            var    c  = new XPoint(x, y);

            rt.RotateAtPrepend(angle, c);
            double rx = style.RadiusX;
            double ry = style.RadiusY;
            double sx = 2.0 * rx;
            double sy = 2.0 * ry;

            switch (style.ArrowType)
            {
            default:
            case Core2D.Style.ArrowType.None:
            {
                pt = new XPoint(x, y);
            }
            break;

            case Core2D.Style.ArrowType.Rectangle:
            {
                pt = rt.Transform(new XPoint(x - sx, y));
                var rect = new XRect(x - sx, y - ry, sx, sy);
                gfx.Save();
                gfx.RotateAtTransform(angle, c);
                DrawRectangleInternal(gfx, brush, pen, style.IsStroked, style.IsFilled, ref rect);
                gfx.Restore();
            }
            break;

            case Core2D.Style.ArrowType.Ellipse:
            {
                pt = rt.Transform(new XPoint(x - sx, y));
                gfx.Save();
                gfx.RotateAtTransform(angle, c);
                var rect = new XRect(x - sx, y - ry, sx, sy);
                DrawEllipseInternal(gfx, brush, pen, style.IsStroked, style.IsFilled, ref rect);
                gfx.Restore();
            }
            break;

            case Core2D.Style.ArrowType.Arrow:
            {
                pt = rt.Transform(new XPoint(x, y));
                var p11 = rt.Transform(new XPoint(x - sx, y + sy));
                var p21 = rt.Transform(new XPoint(x, y));
                var p12 = rt.Transform(new XPoint(x - sx, y - sy));
                var p22 = rt.Transform(new XPoint(x, y));
                DrawLineInternal(gfx, pen, style.IsStroked, ref p11, ref p21);
                DrawLineInternal(gfx, pen, style.IsStroked, ref p12, ref p22);
            }
            break;
            }

            return(pt);
        }
Beispiel #3
0
        internal PdfFormXObject(PdfDocument thisDocument, PdfImportedObjectTable importedObjectTable, XPdfForm form)
            : base(thisDocument)
        {
            Debug.Assert(ReferenceEquals(thisDocument, importedObjectTable.Owner));
            Elements.SetName(Keys.Type, "/XObject");
            Elements.SetName(Keys.Subtype, "/Form");

            if (form.IsTemplate)
            {
                Debug.Assert(importedObjectTable == null);
                // TODO more initialization here???
                return;
            }
            Debug.Assert(importedObjectTable != null);

            XPdfForm pdfForm = form;
            // Get import page
            PdfPages importPages = importedObjectTable.ExternalDocument.Pages;

            if (pdfForm.PageNumber < 1 || pdfForm.PageNumber > importPages.Count)
            {
                PSSR.ImportPageNumberOutOfRange(pdfForm.PageNumber, importPages.Count, form._path);
            }
            PdfPage importPage = importPages[pdfForm.PageNumber - 1];

            // Import resources
            PdfItem res = importPage.Elements["/Resources"];

            if (res != null) // unlikely but possible
            {
#if true
                // Get root object
                PdfObject root;
                if (res is PdfReference)
                {
                    root = ((PdfReference)res).Value;
                }
                else
                {
                    root = (PdfDictionary)res;
                }

                root = ImportClosure(importedObjectTable, thisDocument, root);
                // If the root was a direct object, make it indirect.
                if (root.Reference == null)
                {
                    thisDocument._irefTable.Add(root);
                }

                Debug.Assert(root.Reference != null);
                Elements["/Resources"] = root.Reference;
#else
                // Get transitive closure
                PdfObject[] resources = importPage.Owner.Internals.GetClosure(resourcesRoot);
                int         count     = resources.Length;
#if DEBUG_
                for (int idx = 0; idx < count; idx++)
                {
                    Debug.Assert(resources[idx].XRef != null);
                    Debug.Assert(resources[idx].XRef.Document != null);
                    Debug.Assert(resources[idx].Document != null);
                    if (resources[idx].ObjectID.ObjectNumber == 12)
                    {
                        GetType();
                    }
                }
#endif
                // 1st step. Already imported objects are reused and new ones are cloned.
                for (int idx = 0; idx < count; idx++)
                {
                    PdfObject obj = resources[idx];
                    if (importedObjectTable.Contains(obj.ObjectID))
                    {
                        // external object was already imported
                        PdfReference iref = importedObjectTable[obj.ObjectID];
                        Debug.Assert(iref != null);
                        Debug.Assert(iref.Value != null);
                        Debug.Assert(iref.Document == Owner);
                        // replace external object by the already clone counterpart
                        resources[idx] = iref.Value;
                    }
                    else
                    {
                        // External object was not imported ealier and must be cloned
                        PdfObject clone = obj.Clone();
                        Debug.Assert(clone.Reference == null);
                        clone.Document = Owner;
                        if (obj.Reference != null)
                        {
                            // add it to this (the importer) document
                            Owner.irefTable.Add(clone);
                            Debug.Assert(clone.Reference != null);
                            // save old object identifier
                            importedObjectTable.Add(obj.ObjectID, clone.Reference);
                            //Debug.WriteLine("Cloned: " + obj.ObjectID.ToString());
                        }
                        else
                        {
                            // The root object (the /Resources value) is not an indirect object
                            Debug.Assert(idx == 0);
                            // add it to this (the importer) document
                            Owner.irefTable.Add(clone);
                            Debug.Assert(clone.Reference != null);
                        }
                        // replace external object by its clone
                        resources[idx] = clone;
                    }
                }
#if DEBUG_
                for (int idx = 0; idx < count; idx++)
                {
                    Debug.Assert(resources[idx].XRef != null);
                    Debug.Assert(resources[idx].XRef.Document != null);
                    Debug.Assert(resources[idx].Document != null);
                    if (resources[idx].ObjectID.ObjectNumber == 12)
                    {
                        GetType();
                    }
                }
#endif

                // 2nd step. Fix up indirect references that still refers to the import document.
                for (int idx = 0; idx < count; idx++)
                {
                    PdfObject obj = resources[idx];
                    Debug.Assert(obj.Owner != null);
                    FixUpObject(importedObjectTable, importedObjectTable.Owner, obj);
                }

                // Set resources key to the root of the clones
                Elements["/Resources"] = resources[0].Reference;
#endif
            }

            // Take /Rotate into account
            PdfRectangle rect   = importPage.Elements.GetRectangle(PdfPage.Keys.MediaBox);
            int          rotate = importPage.Elements.GetInteger(PdfPage.Keys.Rotate);
            //rotate = 0;
            if (rotate == 0)
            {
                // Set bounding box to media box
                Elements["/BBox"] = rect;
            }
            else
            {
                // TODO: Have to adjust bounding box? (I think not, but I'm not sure -> wait for problem)
                Elements["/BBox"] = rect;

                // Rotate the image such that it is upright
                XMatrix matrix = new XMatrix();
                double  width  = rect.Width;
                double  height = rect.Height;
                matrix.RotateAtPrepend(-rotate, new XPoint(width / 2, height / 2));

                if (rotate != 180)
                {
                    // Translate the image such that its center lies on the center of the rotated bounding box
                    double offset = (height - width) / 2;
                    if (height > width)
                    {
                        matrix.TranslatePrepend(offset, offset);
                    }
                    else
                    {
                        matrix.TranslatePrepend(-offset, -offset);
                    }
                }

                //string item = "[" + PdfEncoders.ToString(matrix) + "]";
                //Elements[Keys.Matrix] = new PdfLiteral(item);
                Elements.SetMatrix(Keys.Matrix, matrix);
            }

            // Preserve filter because the content keeps unmodified
            PdfContent content = importPage.Contents.CreateSingleContent();
#if !DEBUG
            content.Compressed = true;
#endif
            PdfItem filter = content.Elements["/Filter"];
            if (filter != null)
            {
                Elements["/Filter"] = filter.Clone();
            }

            // (no cloning needed because the bytes keep untouched)
            Stream = content.Stream; // new PdfStream(bytes, this);
            Elements.SetInteger("/Length", content.Stream.Value.Length);
        }
Beispiel #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="gfx"></param>
        /// <param name="line"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <param name="db"></param>
        /// <param name="r"></param>
        public void Draw(object gfx, Core2D.XLine line, double dx, double dy, ImmutableArray <Core2D.ShapeProperty> db, Core2D.Record r)
        {
            if (!line.IsStroked)
            {
                return;
            }

            var _gfx = gfx as XGraphics;

            XSolidBrush fillLine   = ToXSolidBrush(line.Style.Fill);
            XPen        strokeLine = ToXPen(line.Style, _scaleToPage);

            XSolidBrush fillStartArrow   = ToXSolidBrush(line.Style.StartArrowStyle.Fill);
            XPen        strokeStartArrow = ToXPen(line.Style.StartArrowStyle, _scaleToPage);

            XSolidBrush fillEndArrow   = ToXSolidBrush(line.Style.EndArrowStyle.Fill);
            XPen        strokeEndArrow = ToXPen(line.Style.EndArrowStyle, _scaleToPage);

            double _x1 = line.Start.X + dx;
            double _y1 = line.Start.Y + dy;
            double _x2 = line.End.X + dx;
            double _y2 = line.End.Y + dy;

            Core2D.XLine.SetMaxLength(line, ref _x1, ref _y1, ref _x2, ref _y2);

            double x1 = _scaleToPage(_x1);
            double y1 = _scaleToPage(_y1);
            double x2 = _scaleToPage(_x2);
            double y2 = _scaleToPage(_y2);

            var    sas = line.Style.StartArrowStyle;
            var    eas = line.Style.EndArrowStyle;
            double a1  = Math.Atan2(y1 - y2, x1 - x2) * 180.0 / Math.PI;
            double a2  = Math.Atan2(y2 - y1, x2 - x1) * 180.0 / Math.PI;

            var t1 = new XMatrix();
            var c1 = new XPoint(x1, y1);

            t1.RotateAtPrepend(a1, c1);

            var t2 = new XMatrix();
            var c2 = new XPoint(x2, y2);

            t2.RotateAtPrepend(a2, c2);

            XPoint pt1;
            XPoint pt2;

            double radiusX1 = sas.RadiusX;
            double radiusY1 = sas.RadiusY;
            double sizeX1   = 2.0 * radiusX1;
            double sizeY1   = 2.0 * radiusY1;

            switch (sas.ArrowType)
            {
            default:
            case Core2D.ArrowType.None:
            {
                pt1 = new XPoint(x1, y1);
            }
            break;

            case Core2D.ArrowType.Rectangle:
            {
                pt1 = t1.Transform(new XPoint(x1 - sizeX1, y1));
                var rect = new XRect(x1 - sizeX1, y1 - radiusY1, sizeX1, sizeY1);
                _gfx.Save();
                _gfx.RotateAtTransform(a1, c1);
                DrawRectangleInternal(_gfx, fillStartArrow, strokeStartArrow, sas.IsStroked, sas.IsFilled, ref rect);
                _gfx.Restore();
            }
            break;

            case Core2D.ArrowType.Ellipse:
            {
                pt1 = t1.Transform(new XPoint(x1 - sizeX1, y1));
                _gfx.Save();
                _gfx.RotateAtTransform(a1, c1);
                var rect = new XRect(x1 - sizeX1, y1 - radiusY1, sizeX1, sizeY1);
                DrawEllipseInternal(_gfx, fillStartArrow, strokeStartArrow, sas.IsStroked, sas.IsFilled, ref rect);
                _gfx.Restore();
            }
            break;

            case Core2D.ArrowType.Arrow:
            {
                pt1 = t1.Transform(new XPoint(x1, y1));
                var p11 = t1.Transform(new XPoint(x1 - sizeX1, y1 + sizeY1));
                var p21 = t1.Transform(new XPoint(x1, y1));
                var p12 = t1.Transform(new XPoint(x1 - sizeX1, y1 - sizeY1));
                var p22 = t1.Transform(new XPoint(x1, y1));
                DrawLineInternal(_gfx, strokeStartArrow, sas.IsStroked, ref p11, ref p21);
                DrawLineInternal(_gfx, strokeStartArrow, sas.IsStroked, ref p12, ref p22);
            }
            break;
            }

            double radiusX2 = eas.RadiusX;
            double radiusY2 = eas.RadiusY;
            double sizeX2   = 2.0 * radiusX2;
            double sizeY2   = 2.0 * radiusY2;

            switch (eas.ArrowType)
            {
            default:
            case Core2D.ArrowType.None:
            {
                pt2 = new XPoint(x2, y2);
            }
            break;

            case Core2D.ArrowType.Rectangle:
            {
                pt2 = t2.Transform(new XPoint(x2 - sizeX2, y2));
                var rect = new XRect(x2 - sizeX2, y2 - radiusY2, sizeX2, sizeY2);
                _gfx.Save();
                _gfx.RotateAtTransform(a2, c2);
                DrawRectangleInternal(_gfx, fillEndArrow, strokeEndArrow, eas.IsStroked, eas.IsFilled, ref rect);
                _gfx.Restore();
            }
            break;

            case Core2D.ArrowType.Ellipse:
            {
                pt2 = t2.Transform(new XPoint(x2 - sizeX2, y2));
                _gfx.Save();
                _gfx.RotateAtTransform(a2, c2);
                var rect = new XRect(x2 - sizeX2, y2 - radiusY2, sizeX2, sizeY2);
                DrawEllipseInternal(_gfx, fillEndArrow, strokeEndArrow, eas.IsStroked, eas.IsFilled, ref rect);
                _gfx.Restore();
            }
            break;

            case Core2D.ArrowType.Arrow:
            {
                pt2 = t2.Transform(new XPoint(x2, y2));
                var p11 = t2.Transform(new XPoint(x2 - sizeX2, y2 + sizeY2));
                var p21 = t2.Transform(new XPoint(x2, y2));
                var p12 = t2.Transform(new XPoint(x2 - sizeX2, y2 - sizeY2));
                var p22 = t2.Transform(new XPoint(x2, y2));
                DrawLineInternal(_gfx, strokeEndArrow, eas.IsStroked, ref p11, ref p21);
                DrawLineInternal(_gfx, strokeEndArrow, eas.IsStroked, ref p12, ref p22);
            }
            break;
            }

            _gfx.DrawLine(strokeLine, pt1, pt2);
        }
        /// <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);
        }