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 (); } }
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 (); }
/* [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); }