Пример #1
0
		public static void Main(string[] args)
		{
			// call the snippets
			Snippets snip = new Snippets();
			foreach (string snippet in Snippets.snippets)
			{
				string filename = "./" + snippet + ".svg";
				Surface surface = new SvgSurface(filename, IMAGE_WIDTH, IMAGE_WIDTH);
				Context cr = new Context(surface);
			
				cr.Save();
				Snippets.InvokeSnippet(snip, snippet, cr, IMAGE_WIDTH, IMAGE_HEIGHT);
				cr.ShowPage();
				cr.Restore();
				surface.Finish ();
			}
		}
Пример #2
0
        public void Export(string filename, ExportFormat format)
        {
            this.UnselectAll();

            double leftMost   = double.MaxValue,
                   rightMost  = 0,
                   topMost 	  = double.MaxValue,
                   bottomMost = 0;

            Shape leftLayer   = new Shape(),
                  rightLayer  = new Shape(),
                  topLayer    = new Shape(),
                  bottomLayer = new Shape();

            foreach(Shape l in this)
            {
                if(l.Position.X + l.Boundaries.Width / 2 > rightMost)
                {
                    rightMost =  l.Position.X + l.Boundaries.Width / 2;
                    rightLayer = l;
                }
                if(l.Position.X - l.Boundaries.Width / 2 < leftMost)
                {
                    leftMost = l.Position.X - l.Boundaries.Width / 2;
                    leftLayer = l;
                }
                if((l.Position.Y - l.Boundaries.Height / 2) < topMost)
                {
                    topMost = l.Position.Y - l.Boundaries.Height / 2;
                    topLayer = l;
                }
                if(l.Position.Y + l.Boundaries.Height > bottomMost)
                {
                    bottomMost = l.Position.Y + l.Boundaries.Height;
                    bottomLayer = l;
                }
            }

            Size size;

            //TODO: to keep or not to keep the 1px border, that is the question.
            size.Width = (rightLayer.Position.X + rightLayer.Boundaries.Width / 2) -
                         (leftLayer.Position.X - leftLayer.Boundaries.Width / 2) + 1;

            size.Height = (bottomLayer.Position.Y + bottomLayer.Boundaries.Height / 2) -
                          (topLayer.Position.Y - topLayer.Boundaries.Height / 2) + 1;

            Surface surface;

            //TODO: each surface is handling the size differently... BUT WHY?
            switch(format)
            {
                case ExportFormat.SVG:
                    surface = new SvgSurface(filename, size.Width, size.Height);
                    break;
                case ExportFormat.PDF:
                    surface = new PdfSurface(filename, size.Width, size.Height);
                    break;
                case ExportFormat.PNG:
                    surface = new ImageSurface(Format.ARGB32,
                                           	   (int)size.Width,
                                               (int)size.Height);
                    break;
                default:
                    surface = new SvgSurface(filename, size.Width, size.Height);
                    break;
            }

            Cairo.Context c = new Context(surface);

            c.Translate(-leftLayer.Position.X + leftLayer.Boundaries.Width / 2,
                        -(topLayer.Position.Y - topLayer.Boundaries.Height / 2));

            this.Draw(c);

            if(format == ExportFormat.PNG)
                surface.WriteToPng(filename);
            surface.Finish();

            c.Target.Dispose();

            ((IDisposable) c).Dispose ();
        }
Пример #3
0
        /*
        [XmlIgnore]
        public FontFamily font;
        */
        public void InternalRegenerateCloud()
        {
            r = new Random();
            int id = 0;
            double minSize = Entries.Min(e => e.SizeValue);
            double maxSize = Entries.Max(e => e.SizeValue);
            double range = Math.Max(0.00001, maxSize - minSize);

            _source = new ImageSurface(Format.Argb32,ActualWidth,ActualHeight);
            pixelss = _source.Data;
            g = new Context(_source);
            g.Color = new Color(1.0,1.0,1.0);
            //g.Rectangle(0.0,0.0,ActualWidth,ActualHeight);
            g.Paint();

            g.SelectFontFace(fontname,FontSlant.Normal,FontWeight.Bold);
            g.SetFontSize(100.0);
            TextExtents te = g.TextExtents("x");
            double areaPerLetter = te.Width;

            strides = _source.Stride;
            int arraySize = (int)((ActualWidth / 4) + 2) * (int)((ActualHeight / 4) + 2);
            _mapping = new int[arraySize];
            for (int i = 0; i < arraySize; i++) _mapping[i] = -1;

            if(svgfn != null) {
                svgs = new SvgSurface(svgfn,ActualWidth,ActualHeight);
                svg = new Context(svgs);
                svg.SelectFontFace(fontname,FontSlant.Normal,FontWeight.Bold);
            }
            if(pdffn != null) {
                pdfs = new PdfSurface(pdffn,ActualWidth,ActualHeight);
                pdf = new Context(pdfs);
                pdf.SelectFontFace(fontname,FontSlant.Normal,FontWeight.Bold);
            }

            double fontMultiplier;

            if(CoverRatio > 0.0) {
                double totalsize = 0.0;
                MinFontSize = 24.0; // use big fonts for testing
                if(FontMaxRatio < 1.0 || FontMaxRatio > 500.0) FontMaxRatio = 6.0;
                MaxFontSize = FontMaxRatio*MinFontSize;
                fontMultiplier = (MaxFontSize - MinFontSize) / range;
                foreach(WordCloudEntry e in Entries) {
                    float fontsize = (float)(((e.SizeValue - minSize) * fontMultiplier) + MinFontSize);
                    g.SetFontSize(fontsize);
                    TextExtents te1 = g.TextExtents(e.Word);
                    totalsize += te1.Width*te1.Height;
                }
                double actualsize = ActualHeight*ActualWidth;
                double ratio1 = totalsize / actualsize; //this should be == CoverRatio
                //we assume that totalsize ~ MinFontSize^2 in this case
                MinFontSize = MinFontSize*Math.Sqrt(CoverRatio / ratio1);
                MaxFontSize = FontMaxRatio*MinFontSize;
                fontMultiplier = (MaxFontSize - MinFontSize) / range;
                LargestSizeWidthProportion = 0.9;
            }

            double targetWidth = Math.Max(ActualWidth, ActualHeight) * LargestSizeWidthProportion;
            WordCloudEntry od = Entries.OrderByDescending(e => (e.SizeValue - minSize) * e.Word.Length).First();
            double maxFontSize;
            if(MaxFontSize > 0.0 && CoverRatio <= 0.0) {
                maxFontSize = MaxFontSize;
                if(maxFontSize < MinFontSize) maxFontSize = MinFontSize*2.7;
            }
            else {
                g.SetFontSize(100.0);
                TextExtents te2 = g.TextExtents(od.Word);
                maxFontSize = 97.0*targetWidth / te2.Width;
                //maxFontSize = Math.Max(MinFontSize * 2.7, 100.0 / ((od.Word.Length * areaPerLetter) / targetWidth));
                if(maxFontSize > MinFontSize + 100) maxFontSize = MinFontSize + 100;
            }
            if(CoverRatio > 0.0) {
                if(maxFontSize < MaxFontSize) MaxFontSize = maxFontSize;
                fontMultiplier = (maxFontSize - MinFontSize) / range;
            }
            else fontMultiplier = (maxFontSize - MinFontSize) / range;

            var points = new[]
                             {
                                 new Point((int) (ActualWidth/2), (int) (ActualHeight/2)),
                                 new Point((int) (ActualWidth/4), (int) (ActualHeight/4)),
                                 new Point((int) (ActualWidth/4), (int) (3*ActualHeight/2)),
                                 new Point((int) (3*ActualWidth/4), (int) (ActualHeight/2)),
                                 new Point((int) (3*ActualWidth/4), (int) (3*ActualHeight/4))
                             };

            int currentPoint = 0;
            foreach (WordCloudEntry e in Entries.OrderByDescending(e => e.SizeValue))
            {
            again:
                double position = 0.0;
                Point centre = points[currentPoint];

                double angle = 0.0;
                if(vratio > 0.0)
                {
                    if(r.NextDouble() < vratio) angle = 90.0;
                }
                float fontsize = (float)(((e.SizeValue - minSize) * fontMultiplier) + MinFontSize);
                ImageSurface bm;
            imgretry:
                bm = CreateImage(e.Word,fontsize,e.Color,angle);
                // test if it fits
                if(angle == 90.0) {
                    if(bm.Height > ActualHeight) {
                        if(ActualWidth > ActualHeight) {
                            angle = 0.0;
                            bm.Destroy();
                            bm = null;
                            goto imgretry;
                        }
                        // crop the end
                        ImageSurface bm2 = new ImageSurface(Format.Argb32,bm.Width,(int)(ActualHeight*0.95));
                        Context g2 = new Context(bm2);
                        g2.SetSource(bm,0,ActualHeight-bm.Height);
                        g2.Paint();
                        ((IDisposable)g2).Dispose();
                        bm.Destroy();
                        bm = bm2;
                    }
                }
                else {
                    if(bm.Width > ActualWidth) {
                        if(ActualHeight > ActualWidth) {
                            angle = 90.0;
                            bm.Destroy();
                            bm = null;
                            goto imgretry;
                        }
                        // crop the end
                        ImageSurface bm2 = new ImageSurface(Format.Argb32,(int)(ActualWidth*0.95),bm.Height);
                        Context g2 = new Context(bm2);
                        g2.SetSource(bm,0,0);
                        g2.Paint();
                        ((IDisposable)g2).Dispose();
                        bm.Destroy();
                        bm = bm2;
                    }
                }
                //WordBitmap bm2 = new WordBitmap(bm);
                Dictionary<Point, List<Point>> lst = CreateCollisionList(bm);
                bool collided = true;
                do
                {
                    Point spiralPoint = GetSpiralPoint(position);
                    int offsetX = (bm.Width / 2);
                    int offsetY = (bm.Height / 2);
                    var testPoint = new Point((int)(spiralPoint.X + centre.X - offsetX), (int)(spiralPoint.Y + centre.Y - offsetY));
                    if (position > (2 * Math.PI) * 580)
                    {
                        //bm2.Dispose();
                        if (++currentPoint >= points.Length)
                            goto done;
              					goto again;
                    }
                    int cols = CountCollisions(testPoint, lst);
                    if (cols == 0)
                    {
                    tryagain:
                        double oldY = testPoint.Y;
                        if (Math.Abs(testPoint.X + offsetX - centre.X) > 10)
                        {
                            if (testPoint.X + offsetX < centre.X)
                            {
                                do
                                {
                                    testPoint.X += 2;
                                } while (testPoint.X + offsetX < centre.X && CountCollisions(testPoint, lst) == 0);
                                testPoint.X -= 2;
                            }
                            else
                            {
                                do
                                {
                                    testPoint.X -= 2;
                                } while (testPoint.X + offsetX > centre.X && CountCollisions(testPoint, lst) == 0);
                                testPoint.X += 2;
                            }
                        }
                        if (Math.Abs(testPoint.Y + offsetY - centre.Y) > 10)
                        {
                            if (testPoint.Y + offsetY < centre.Y)
                            {
                                do
                                {
                                    testPoint.Y += 2;
                                } while (testPoint.Y + offsetY < centre.Y && CountCollisions(testPoint, lst) == 0);
                                testPoint.Y -= 2;
                            }
                            else
                            {
                                do
                                {
                                    testPoint.Y -= 2;
                                } while (testPoint.Y + offsetY > centre.Y && CountCollisions(testPoint, lst) == 0);
                                testPoint.Y += 2;
                            }
                            if (testPoint.Y != oldY)
                                goto tryagain;
                        }

                        collided = false;
                        CopyBits(testPoint, bm, lst, Entries.IndexOf(e));
                        Console.Error.WriteLine("id: {0}, word: {1}, score: {7}, fontsize: {8}," +
                            "x: {2}, y: {3}, w: {4}, h: {5}, angle: {6}",id,e.Word,testPoint.X,testPoint.Y,
                                             bm.Width,bm.Height,angle,e.SizeValue,fontsize);
                        id++;
                        bm.Destroy();
                        if(svg != null) {
                            svg.SetFontSize(fontsize);
                            TextExtents te2 = svg.TextExtents(e.Word);
                            svg.Save();

                            if(angle == 90.0) {
                                svg.MoveTo(testPoint.X-te2.YBearing,testPoint.Y+te2.Width+te2.XBearing);
                                svg.Rotate(-0.5*Math.PI);
                            }
                            else {
                                svg.MoveTo(testPoint.X-te2.XBearing,testPoint.Y-te2.YBearing);
                            }
                            svg.Color = e.Color;
                            svg.ShowText(e.Word);
                            svg.Restore();
                        }
                        if(pdf != null) {
                            pdf.SetFontSize(fontsize);
                            TextExtents te2 = pdf.TextExtents(e.Word);
                            pdf.Save();

                            if(angle == 90.0) {
                                pdf.MoveTo(testPoint.X-te2.YBearing,testPoint.Y+te2.Width+te2.XBearing);
                                pdf.Rotate(-0.5*Math.PI);
                            }
                            else {
                                pdf.MoveTo(testPoint.X-te2.XBearing,testPoint.Y-te2.YBearing);
                            }
                            pdf.Color = e.Color;
                            pdf.ShowText(e.Word);
                            pdf.Restore();
                        }
                    }
                    else
                    {
                        if (cols <= 2)
                        {
                            position += (2 * Math.PI) / 100;
                        }
                        else

                            position += (2 * Math.PI) / 40;
                    }
                } while (collided);
            }
            done:
            ((IDisposable)g).Dispose();
            if(svgfn != null) ((IDisposable)svg).Dispose();
            if(pdffn != null) ((IDisposable)pdf).Dispose();
            Console.Error.WriteLine("# {0} words placed",id);
        }