public void Main() { IRenderingElement renderingElements = null; #region SvgDrawVisitor visitor = new SvgDrawVisitor(50, 50, Depiction.UnitsMM); visitor.Visit(renderingElements); string svg = visitor.ToString(); #endregion }
public void Empty() { string empty = new SvgDrawVisitor(50, 50, Depiction.UnitsMM).ToString(); Assert.AreEqual( "<?xml version='1.0' encoding='UTF-8'?>\n" + "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n" + "<svg version='1.2' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='50mm' height='50mm' viewBox='0 0 50 50'>\n" + " <desc>Generated by the Chemistry Development Kit (http://github.com/cdk)</desc>\n" + "</svg>\n", empty); }
public void MarkedElementTest() { SvgDrawVisitor visitor = new SvgDrawVisitor(50, 50, Depiction.UnitsMM); visitor.Visit(MarkedElement.Markup(new LineElement(new WPF.Point(0, 0), new WPF.Point(1, 1), 0.5, Colors.Red), "test-class")); Assert.AreEqual( "<?xml version='1.0' encoding='UTF-8'?>\n" + "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n" + "<svg version='1.2' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='50mm' height='50mm' viewBox='0 0 50 50'>\n" + " <desc>Generated by the Chemistry Development Kit (http://github.com/cdk)</desc>\n" + " <g stroke-linecap='round' stroke-linejoin='round'>\n" + " <line x1='0' y1='0' x2='1' y2='1' stroke='#FF0000' stroke-width='0.5'/>\n" + " </g>\n" + "</svg>\n", visitor.ToString()); }
public void RectElements() { SvgDrawVisitor visitor = new SvgDrawVisitor(100, 100, Depiction.UnitsMM); visitor.Visit(new RectangleElement(new WPF::Rect(0, 0, 100, 100), Colors.White)); Assert.AreEqual( "<?xml version='1.0' encoding='UTF-8'?>\n" + "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n" + "<svg version='1.2' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='100mm' height='100mm' viewBox='0 0 100 100'>\n" + " <desc>Generated by the Chemistry Development Kit (http://github.com/cdk)</desc>\n" + " <g stroke-linecap='round' stroke-linejoin='round'>\n" + " <rect x='0' y='-100' width='100' height='100' fill='none' stroke='#FFFFFF'/>\n" + " </g>\n" + "</svg>\n", visitor.ToString()); }
public void TextElements() { SvgDrawVisitor visitor = new SvgDrawVisitor(100, 100, Depiction.UnitsMM); visitor.Visit(new TextElement(new WPF::Point(50, 50), "PNG < EPS < SVG", Colors.Red)); Assert.AreEqual( "<?xml version='1.0' encoding='UTF-8'?>\n" + "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n" + "<svg version='1.2' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='100mm' height='100mm' viewBox='0 0 100 100'>\n" + " <desc>Generated by the Chemistry Development Kit (http://github.com/cdk)</desc>\n" + " <g stroke-linecap='round' stroke-linejoin='round'>\n" + " <text x='50' y='50' fill='#FF0000' text-anchor='middle'>PNG < EPS < SVG</text>\n" + " </g>\n" + "</svg>\n", visitor.ToString()); }
public void FilledPath() { SvgDrawVisitor visitor = new SvgDrawVisitor(50, 50, Depiction.UnitsMM); visitor.Visit(GeneralPath.ShapeOf(CreateRoundRectangle(new WPF::Rect(0, 0, 10, 10), 2, 2), Colors.Blue)); var str = visitor.ToString(); Assert.AreEqual( "<?xml version='1.0' encoding='UTF-8'?>\n" + "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n" + "<svg version='1.2' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='50mm' height='50mm' viewBox='0 0 50 50'>\n" + " <desc>Generated by the Chemistry Development Kit (http://github.com/cdk)</desc>\n" + " <g stroke-linecap='round' stroke-linejoin='round'>\n" + " <path d='M1 0h8c0.55 0 1 0.45 1 1v8c0 0.55 -0.45 1 -1 1h-8c-0.55 0 -1 -0.45 -1 -1v-8c0 -0.55 0.45 -1 1 -1z' stroke='none' fill='#0000FF'/>\n" + " </g>\n" + "</svg>\n", str); }
internal override string ToVectorString(string fmt, string units) { // format margins and padding for raster images var margin = GetMarginValue( units.Equals(Depiction.UnitsMM) ? DepictionGenerator.DefaultMillimeterMargin : DepictionGenerator.DefaultPixelMargin); var padding = GetPaddingValue(DefaultPaddingFactor * margin); var scale = model.GetScale(); var zoom = model.GetZoomFactor(); // All vector graphics will be written in mm not px to we need to // adjust the size of the molecules accordingly. For now the rescaling // is fixed to the bond length proposed by ACS 1996 guidelines (~5mm) if (units.Equals(Depiction.UnitsMM)) { zoom *= RescaleForBondLength(Depiction.ACS1996BondLength); } // row and col offsets for alignment var yOffset = new double[nRow + 1]; var xOffset = new double[nCol + 1]; var required = Dimensions.OfGrid(elements, yOffset, xOffset).Scale(zoom * scale); var total = CalcTotalDimensions(margin, padding, required, fmt); var fitting = CalcFitting(margin, padding, required, fmt); // create the image for rendering var visitor = new SvgDrawVisitor(total.width, total.height, units); if (fmt.Equals(SvgFormatKey)) { SvgPrevisit(fmt, scale * zoom * fitting, (SvgDrawVisitor)visitor, elements); } else { // TODO: handle rounding // pdf can handle fraction coordinations just fine // ((AWTDrawVisitor)visitor).setRounding(false); } visitor.Visit(new RectangleElement(new Point(0, -total.height), total.width, total.height, true, model.GetBackgroundColor()), new ScaleTransform(1, -1)); // compound the fitting and scaling into a single value var rescale = zoom * fitting * scale; // x,y base coordinates include the margin and centering (only if fitting to a size) var xBase = margin + (total.width - 2 * margin - (nCol - 1) * padding - (rescale * xOffset[nCol])) / 2; var yBase = margin + (total.height - 2 * margin - (nRow - 1) * padding - (rescale * yOffset[nRow])) / 2; for (int i = 0; i < elements.Count; i++) { var row = i / nCol; var col = i % nCol; // calculate the 'view' bounds: // amount of padding depends on which row or column we are in. // the width/height of this col/row can be determined by the next offset var x = xBase + col * padding + rescale * xOffset[col]; var y = yBase + row * padding + rescale * yOffset[row]; var w = rescale * (xOffset[col + 1] - xOffset[col]); var h = rescale * (yOffset[row + 1] - yOffset[row]); Draw(visitor, zoom, elements[i], new Rect(x, y, w, h)); } return(visitor.ToString()); }
internal override string ToVectorString(string fmt, string units) { // format margins and padding for raster images double scale = model.GetScale(); double margin = GetMarginValue(units.Equals(Depiction.UnitsMM) ? DepictionGenerator.DefaultMillimeterMargin : DepictionGenerator.DefaultPixelMargin); double padding = GetPaddingValue(DefaultPaddingFactor * margin); // All vector graphics will be written in mm not px to we need to // adjust the size of the molecules accordingly. For now the rescaling // is fixed to the bond length proposed by ACS 1996 guidelines (~5mm) double zoom = model.GetZoomFactor(); if (units.Equals(Depiction.UnitsMM)) { zoom *= RescaleForBondLength(Depiction.ACS1996BondLength); } // work out the required space of the main and side components separately // will draw these in two passes (main then side) hence want different offsets for each var nSideCol = xOffsetSide.Length - 1; var nSideRow = yOffsetSide.Length - 1; var sideRequired = sideDim.Scale(scale * zoom); var mainRequired = mainDim.Scale(scale * zoom); var condRequired = condDim.Scale(scale * zoom); var titleRequired = new Dimensions(title.Width, title.Height).Scale(scale * zoom); var firstRowHeight = scale * zoom * yOffsets[1]; var total = CalcTotalDimensions(margin, padding, mainRequired, sideRequired, titleRequired, firstRowHeight, fmt); var fitting = CalcFitting(margin, padding, mainRequired, sideRequired, titleRequired, firstRowHeight, fmt); var visitor = new SvgDrawVisitor(total.width, total.height, units); if (fmt.Equals(SvgFormatKey)) { SvgPrevisit(fmt, scale * zoom * fitting, (SvgDrawVisitor)visitor, mainComp); } else { // TODO: handle reounding // pdf can handle fraction coordinates just fine //((WPFDrawVisitor) visitor).SetRounding(false); } // background color visitor.Visit(new RectangleElement(new Point(0, -total.height), total.width, total.height, true, model.GetBackgroundColor()), new ScaleTransform(1, -1)); // compound the zoom, fitting and scaling into a single value var rescale = zoom * fitting * scale; double mainCompOffset = 0; // shift product x-offset to make room for the arrow / side components mainCompOffset = fitting * sideRequired.height + nSideRow * padding - fitting * firstRowHeight / 2; for (int i = arrowIdx + 1; i < xOffsets.Length; i++) { xOffsets[i] += sideRequired.width * 1 / (scale * zoom); } // MAIN COMPONENTS DRAW // x,y base coordinates include the margin and centering (only if fitting to a size) var totalRequiredWidth = 2 * margin + Math.Max(0, nCol - 1) * padding + Math.Max(0, nSideCol - 1) * padding + (rescale * xOffsets[nCol]); var totalRequiredHeight = 2 * margin + Math.Max(0, nRow - 1) * padding + (!title.IsEmpty() ? padding : 0) + Math.Max(mainCompOffset, 0) + fitting * mainRequired.height + fitting * Math.Max(0, titleRequired.height); var xBase = margin + (total.width - totalRequiredWidth) / 2; var yBase = margin + Math.Max(mainCompOffset, 0) + (total.height - totalRequiredHeight) / 2; for (int i = 0; i < mainComp.Count; i++) { var row = i / nCol; var col = i % nCol; // calculate the 'view' bounds: // amount of padding depends on which row or column we are in. // the width/height of this col/row can be determined by the next offset var x = xBase + col * padding + rescale * xOffsets[col]; var y = yBase + row * padding + rescale * yOffsets[row]; var w = rescale * (xOffsets[col + 1] - xOffsets[col]); var h = rescale * (yOffsets[row + 1] - yOffsets[row]); // intercept arrow draw and make it as big as need if (i == arrowIdx) { w = rescale * (xOffsets[i + 1] - xOffsets[i]) + Math.Max(0, nSideCol - 1) * padding; Draw(visitor, 1, // no zoom since arrows is drawn as big as needed CreateArrow(w, arrowHeight * rescale), MakeRect(x, y, w, h)); continue; } // extra padding from the side components if (i > arrowIdx) { x += Math.Max(0, nSideCol - 1) * padding; } // skip empty elements var bounds = this.mainComp[i]; if (bounds.IsEmpty()) { continue; } Draw(visitor, zoom, bounds, MakeRect(x, y, w, h)); } // RXN TITLE DRAW if (!title.IsEmpty()) { var y = yBase + nRow * padding + rescale * yOffsets[nRow]; var h = rescale * title.Height; Draw(visitor, zoom, title, MakeRect(0, y, total.width, h)); } // SIDE COMPONENTS DRAW xBase += arrowIdx * padding + rescale * xOffsets[arrowIdx]; yBase -= mainCompOffset; for (int i = 0; i < sideComps.Count; i++) { int row = i / nSideCol; int col = i % nSideCol; // calculate the 'view' bounds: // amount of padding depends on which row or column we are in. // the width/height of this col/row can be determined by the next offset var x = xBase + col * padding + rescale * xOffsetSide[col]; var y = yBase + row * padding + rescale * yOffsetSide[row]; var w = rescale * (xOffsetSide[col + 1] - xOffsetSide[col]); var h = rescale * (yOffsetSide[row + 1] - yOffsetSide[row]); Draw(visitor, zoom, sideComps[i], MakeRect(x, y, w, h)); } // CONDITIONS DRAW if (!conditions.IsEmpty()) { yBase += mainCompOffset; // back to top yBase += (fitting * mainRequired.height) / 2; // now on center line (arrow) yBase += arrowHeight; // now just bellow Draw(visitor, zoom, conditions, MakeRect(xBase, yBase, fitting * condRequired.width, fitting * condRequired.height)); } // reset shared xOffsets if (sideComps.Any()) { for (int i = arrowIdx + 1; i < xOffsets.Length; i++) { xOffsets[i] -= sideRequired.width * 1 / (scale * zoom); } } return(visitor.ToString()); }
protected internal void SvgPrevisit(string fmt, double rescale, SvgDrawVisitor visitor, IEnumerable <IRenderingElement> elements) { visitor.Transform = new TranslateTransform(rescale, rescale); visitor.Previsit(elements); visitor.Transform = null; }