Outils pour utilisateurs

Outils du site


issue193:inkscape

Ceci est une ancienne révision du document !


In the previous instalment, I looked at the new multi-page tool introduced in Inkscape 1.2. As I often delve into the guts of Inkscape’s SVG files in this series, I thought it would be interesting to see exactly how multiple pages have been implemented. What I’ve found is a little disappointing, because I think the developers have made a slightly bad choice that limits the usefulness of multi-page mode more than was necessary. In this article, we’ll take a look at exactly what that mistake was, and a couple of ways to work around it.

To investigate this, we’ll be using a simple multi-page Inkscape file. Each page contains a colored rectangle that fills the whole page area (so it’s easier to see the page boundary when loaded into a web browser), plus a random single object in the middle, as a placeholder for the real content you might put in your document.

The first thing to do is to load the SVG file directly into a web browser and see what appears. You don’t win any prizes for guessing that only the first page is displayed. This is simply the same behaviour as a single-page Inkscape document. It could be argued that the main purpose of the multi-page tool is for importing and exporting PDFs, so it’s hardly surprising that a web browser won’t show the extra pages, but since SVG is a first-class format for the web, it does seem a shame that there’s no easy way to view the other pages. But the key word there is “easy”. If you’re prepared to get a little technical, it is possible to work around this limitation.

First, let’s take a look at what’s going on inside the SVG file itself. You can simply open it in a text editor, but as this is an Inkscape column, I’m going to look at it via the Edit > XML Editor… option (below).

In the left pane, we can see the tree of XML elements that make up our file. At the top is the ‘root’ node, shown as <svg:svg …>, followed by a <sodipodi:namedview …>. If you’re new to Inkscape, you may not realise it was forked from an older program named Sodipodi, the fingerprints of which are still present inside Inkscape’s SVG files. In this case, we have a <namedview> element which is in the ‘sodipodi’ namespace. Namespaces are a means of mixing multiple different XML languages together in one file and ensuring they don’t clash with each other. In the case of Inkscape, it means that anything in the ‘sodipodi’ or ‘inkscape’ namespaces are not part of the SVG standard, and will simply be ignored by most other programs.

As hinted by its Sodipodi heritage, the <namedview> element has been present in Inkscape files right from the start. It contains metadata about how the file should be displayed when loaded into Inkscape: this is where you’ll find XML attributes that store the window size, zoom factor, and page color, amongst other things. But with a multi-page Inkscape document the <namedview> element has gained something else: children. Expanding the <namedview> entry in the XML editor reveals an <inkscape:page …> element for each page in your document. To clarify, these are <page> elements in the ‘inkscape’ namespace, so other applications – including your web browser – have no idea what to do with them.

In this screenshot, I’ve selected the second page in the document. You can see the attributes of the <page> element in the right-hand pane. These consist of the width and height of the page, and the coordinates of the top-left corner of the page (x and y). There’s also an auto-generated ID, and an ‘inkscape:label’ attribute which holds any custom name you may have given to the page. If you’re familiar with the internals of SVG files, then you may recognise the four dimension-related attributes as being the same as those used in an SVG viewBox definition. That fact gives us our first workaround for viewing pages in a browser.

When loading an SVG file into a web browser, there’s a little-known trick that can be used to override the default viewBox definition from the main <svg> element. I covered this previously in part 79 of this series (FCM issue #139), but the summary is that you can use the ‘fragment identifier’ of the file’s URL to specify the x, y, width and height values of the viewBox you wish to use. Let’s look at this with an example: first, we’ll load the SVG file directly into Firefox and, as expected, we see only the first page. To access other pages, we first need to find the coordinates (x, y) and dimensions (width, height) from the relevant <inkscape:page> element. You can see from the screenshot of the XML editor that Inkscape stores these to quite a high precision but, in practice, you can usually truncate them to just a couple of decimal places – perhaps even less if there’s a little free space between the edge of the page and the content. You then need to take these values, swap them into the following string, and append the whole thing to the URL in your web browser:

#svgView(viewBox(x,y,width,height))

In the case of this example, the filename is ‘multi_page.svg’, and the values for the second page are shown in the earlier screenshot of the XML editor. The URL for viewing the second page therefore becomes:

…/multi_page.svg#svgView(viewBox(112.6,0,102.6,102.6))

This syntax works wherever the browser expects an image URL, so web developers can also use it in <img> elements, and even in CSS url() values.

It’s a clever trick, which gives you access to all the pages in a multi-page Inkscape file, but it’s not without its limitations. The biggest of these, quite clearly, is the need to dig into the SVG file to find the page size and position, then copy those values into the URL directly. The resultant link also lacks semantics – that specific combination of numbers doesn’t exactly scream ‘page 2’ to the uninitiated. However, SVG also allows us to add ‘named views’ to the file (not the same thing as the <sodipodi:namedView> element), which still requires digging out the magic numbers, but does at least allow us to map each viewBox to a more meaningful name. The downside of this approach is that we will need to edit the SVG file, either with a text editor or using Inkscape’s XML editor.

If you’re comfortable editing XML files in a text editor, that’s probably the easiest method. Just make sure you don’t have the file open in Inkscape at the same time, or you may find your hand-crafted edits are automatically replaced. That approach is also described in part 79 of this series, so this time I’m instead going to show you how to make the same edits within Inkscape.

Once again, you’ll need the x, y, width and height parameters from the relevant <inkscape:page> element. This time, I’ll use the values for page 3 in the file. Again, these were obtained by selecting the relevant <inkscape:page> element in the XML editor, and looking at the attributes in the second pane. Once again, we’ll truncate these to 1 decimal place, giving this set of values: x: 225.3 y: 0 width: 102.6 height: 102.6

Observant readers may have noticed that only the x value has changed compared with the values for page 2. This makes sense, as the third page is the same size as the others, and has only been displaced horizontally. If your multi-page documents all use the same page size, with the pages aligned in a single row, it will always be the case that only the x value differs between them.

Now we need to create a new element in the document, which we can do via the XML editor. This can actually go anywhere in the document, and I’ve previously advocated putting it in the <defs> section – but now I’ve changed my mind. To keep similar items grouped together, I’m actually going to create it as a child of the appropriate <inkscape:page> element. To achieve this, first select the <inkscape:page> element in the left-hand pane of the XML editor. While it’s highlighted, you might want to note down those all-important dimensions that are shown in the second pane (which could actually be below rather than to the right, depending on the orientation buttons in the bottom-right of the dialog).

With the existing element selected, click the first button in the dialog’s toolbar: “New element node”. This will open a much smaller dialog with a single text field and a couple of buttons, where you should enter the name (including the namespace reference) of the new element you wish to create. In this case the string to type is “svg:view” – with no spaces, and without the quotes.

Click the ‘Create’ button, and you should find your new element appears in the first pane as a child of the <inkscape:page>. It should already be selected, with no attributes present in the second pane. We will need to add two attributes to this element. Let’s start with the ‘id’, which you can create by clicking on the ‘+’ button at the top of the second pane, and entering ‘id’ into the name field that appears in the list below. When you press enter, the value field will be focused, and it’s here that you should put the more semantic name you wish to use for the page. Note that this is an XML ID, which means it can’t contain any whitespace characters – so no ‘Page 3’ for example. In practice it’s best to stick to alphanumeric characters, underscores and hyphens. The first character should be a letter, and I tend to stick to lowercase characters. In practice, therefore, something like ‘page-3’ is ideal.

Now repeat the process to add a second attribute, this time with a name of ‘viewBox’ (watch the capitalization), and a value of your four values, separated by space characters, in the order ‘x y width height’. If all has gone well, the XML editor should look something like that shown below.

Repeat the process for each page, using the appropriate values and different IDs before saving your file to commit the changes to disk. Then, to view a page in the browser, you simply have to use the base URL for your SVG file, and append a hash (#) followed by the ID of the page. In this example, therefore, the URL becomes ‘…/multi_page.svg#page-3’:

Once again, this trick works with any place that the browser expects a URL, including <img> tags and CSS. In practice, I suggest picking better semantic IDs than simply ‘page-n’ if you possibly can. Suppose we had used ‘yellow-spiral’ as my ID in this case: if we subsequently wanted to rearrange the pages within the SVG document we would only have to update the coordinates in the <svg:view> elements, but any website that referred to the page by that ID would still work without modification.

Perhaps you can now see why I think the Inkscape developers made a mistake when implementing multi-page support. The <inkscape:page> element has attributes for an ID, an optional label (in the ‘inkscape’ namespace), and the four dimension and position values. The SVG standard <view> element, on the other hand, has an ID and a viewBox (which consists of the four dimension and position values). It’s lacking a label attribute, but this could legitimately be added within the ‘inkscape’ namespace, without breaking any XML or SVG rules. I fail to see, therefore, why the Inkscape developers chose to use a non-standard <page> element in their own namespace, rather than just use the existing SVG <view> element, adding custom attributes where required. Had they done so, every Inkscape page would automatically get a named view, and therefore be much easier to access via a web browser.

Sadly, this missed opportunity leaves users either having to extract the details of each page’s viewbox in order to construct a suitable #svgView(…) fragment identifier, or manually creating their own <view> elements to achieve the same effect but with nicer URLs. Next month we’ll look at a different approach to ‘fixing’ this problem – though one that unfortunately comes with its own set of limitations.

issue193/inkscape.1685339335.txt.gz · Dernière modification : 2023/05/29 07:48 de d52fr