I'm trying to split and SVG into many different SVG files each one containing one element original file.
My main problem is not the slipt in itself since for each element I have to split, I get the svg element, remove everything else from the original svg, add back the element into the main layer and then save the file with the name I want. This works fine.
The real problem is that each file I create has the view centered and dimensioned as in the original svg file. So usually it's misplaced and wide (since in the original file it would contain all elements that now are split into different files).
So I need to resize the canvas to the element that remains in the file.
This very function is done by inkscape with the command
inkscape --verb=FitCanvasToDrawing --verb=FileSave --verb=FileClose
But unfortunally this verb doesn't work in --without-gui mode, so if I call it in the code I see thousands of inkscape instances opening, fitting the canvas and then save and close the windows. It works but it's not good for a batch application (they have this "bug" since quite some years).
So I resorted to use SVG engine (https://github.com/vvvv/SVG) but it has a bug that prevents the right calculation of the element bounds (https://github.com/vvvv/SVG/issues/331), so I cannot change the viewbox or the svg element to the right values.
Any suggestion on how to calculate the right position and size? Or any other library (any language that can run in a batch) that works for that?
Related
I'm trying to generate a PDF via code because not all actual PDF .NET libraries support the new Windows Runtime for Windows/Windows Phone 8.1.
The PDF is saved correctly, with only a bug of stream position count that I can fix easily, but, as you can see, the text doesn't wrap if line is too long.
I tried with PDF NewLine char (\n), but C# automatically convert it in the input string
Also, I can't understand the position of lines or objects to put into the document, because I follow this guide online that talk about a reversing axis disposition (x for height and y for width), but seems I didn't catch the right methodology (I put in my code a constant left position, at 40, and a variable top descreasing value (from 600, I'm not manage now the multipage if the value is less than 0).
This is the code of PDF generated:
http://pastebin.com/ZkZmbJdM
(Sorry if I use Pastebin, but using this editor Code function the code seems to be unformatted for special characters used for it)
Where am I doing wrong?
PDF is a graphical format trying to make you think it's a document format. But nope, it's just like drawing with GDI+ for instance. This is the reason why it can achieve the same rendered output across many platforms/programs/etc as opposed to text flow formats like doc/docx. And also, this is why it can really render anything.
So, as opposed to document formats, it is the responsibility of the program that generates the PDF to get the layout right. Think of it just as if you'd draw with GDI+.
In documents like docx or html, it's the rendering program that has to do the layout work. With such document, you just write text and the viewer will take care of laying it out.
Your PDF library certainly has the necessary code to measure the text length. Maybe even it has some code to provide some layout capabilities. You'll have to use these functions to do the layout.
How (if possible to do so) can I create an SVG image, using C#? I wish to take one SVG, overlay another SVG on it, and save it as a third SVG image.
In my specific case, I allow a module of my software to provide an icon for a folder. I want to overlay a warning or error icon on top of the folder icon when there is an error in the contained data.
I recommend using SVG Rendering Engine to do this. Create a third document, and put the two given svgs one after the other into it. (Nesting svg documents in each other is completely valid):
var icon = SvgDocument.Open(...);
var overlayIcon = SvgDocument.Open(...);
var overlayed = new SvgDocument();
overlayed.Children.Add(icon);
overlayed.Children.Add(overlayIcon);
overlayed.Write(...); // saving
Note: check the overlaying icon's size, viewbox, etc., you may have to change these through SvgDocument.Width, SvgDocument.Height, SvgDocument.ViewBox to get proper result.
SVG is a very simple text format, even simpler than HTML. Overlaying SVGs is a work for XML library. You can just open it and append every node from one file to another file.
Just try taking these two text files:
http://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg
http://upload.wikimedia.org/wikipedia/commons/6/6b/Bitmap_VS_SVG.svg
Open the first one, copy contents of the the <svg>...</svg>, paste at the end of the other file (just before the ending </svg> tag). You can check in some editor or validator that the result is just a perfectly fine SVG file.
Use System.Xml or System.Xml.Linq for handling it from your C# code. Additionally you can add new nodes, edit attributes like width, height, color, etc... if you want:
<svg width="637" height="637">
<path style="fill:white" d="... "/>
...
</svg>
Have fun.
Short question here: I have a SVG chart with nodes. Is there a way to be able to have clicking the SVG trigger a function in the page code behind? Specifically, have it be able to tell which node in the chart was clicked. I've noticed that the asp controls have this type of functionality built in, but not the more generic html components.
Well, today I got a solution to work. I will share here for anyone else looking.
My click-event trigger is an asp:ImageMap that has been placed over the SVG using CSS z-index.
Before displaying the SVG, the code-behind in the Page_Load function takes the SVG and parses it into XML so I can read/modify it like an XML document. First the program checks the 'g' element for any transformations and saves the offset to use when plotting coordinates. Then, the program looks at each shape (rect, circle, etc) element in the XML and pulls the x,y coordinates from the shape and creates a corresponding ImageMap HotSpot and adds it to the ImageMap.
Whew!
Ok ive had a lot of bad luck using a visualbrush to try to print out pages from subsections of a large canvas. Works in general, but tends to rasterize some parts and creates bad output. (I've asked questions about this before).
So now I'm creating a bunch of copies of the canvas with all the same contents, and pinching down to invidual portions to print as a single page. This works, but obviously is slow and will only get slower with more pages.
So what might work well is, is there some way to do something similar toa visual brush, but to instead have it copy the contents from its "view" as a new geometry object of some kind? The contents of my canvas are a combination of lines, images, etc, so what would be nice is to be able to define the view of a brush and tell it to make an intersection copy of all the vector and raster objects visible into a new container of some kind.
This would allow me to use a single canvas, and take "snapshots" of the contents at different places to be used for printing the individual pages.
You could use RenderTargetBitmap to get a bitmap copy of the Canvas, and then crop the portion you wanted. If you specifically want a vector copy you'd need to write the canvas out to XPS.
Edit: If you want a vector copy, have you tried using XamlWriter.Save, edit the Xaml, and then XamlReader.Load?
In normal C# it is easy to draw to a bitmap using the Grpahics.DrawString() method. Silverlight seems to have done away with Bitmap objects and Graphics is no longer available either. So...How am I meant to manipulate/create a bitmap when using Silverlight? If it helps, I am using Silverlight 3.
Let me tell you what I am doing. I am being given a template, basically a pre-rendered image. The user is then able to select from multiple images and enter the deisred text. I then render it to the image, adjusting size etc... within bounds and centering it in the pre-defined area of the image. If I can calculate the size (as in the MeasureString method) and then draw the string (as in the Graphics.DrawString method) that would be fine. The real question, no matter why I want to be able to do this, is can it be done?
The question is: why do you want to? Why not just use a TextBlock?
If you are trying to dynamically generate an image, use standard Silverlight/WPF controls (including TextBlock) and render them to a WritableBitmap.
Edit:
Ok, you've updated and expanded, which gives me more to go on. Unfortunately, you're not going to like the answer. First, keep in mind that Silverlight and WPF in general are vector based, and intended to be used as such. Although the Canvas allows you to do pseudo-pixel manipulations, you cannot be nearly as pixel-accurate as old-school GDI. This is a factor of your medium. If you absolutely have to measure things the way you want to measure them, I suggest you build your images on a remote server and transmit them to your Silverlight app.
You can calculate the size on-screen of the text rendered via a TextBlock using the ActualWidth and ActualHeight properties. But it only works on an already rendered control. Something like MeasureString is simply not available in Silverlight. Based on your description of your app, some user interaction could accomplish what you want. The user selects the image, enters the text, and is shown a preview. The user can then adjust the width and height of the various text areas until satisfied, at which point you can take a snapshot using the render method I liked to above.
The following may work, its a bit nebulous because I haven't tried yet myself.
The object you are looking for is the WritableBitmap.
You create a Visual tree, for example create your self a Grid or Canvas (you're not adding this to the UI). Add to it the selected image and a TextBlock positioned and sized as you prefer.
Create a new WritableBitmap either of a specific size or using the selected image to initialize it.
Use the WritableBitmap Render method passing the above root Grid or Canvas to it.
Now you have a bitmap which you should able to use to do whatever its you needed to do that required all this hoop jumping in the first place.