1

I have a requirement where I need to portray an image using xsl-fo and the user should be able to click within the text / particular location of the image. To explain it further,

  • I have an image
  • It contains text
  • I have the co-ordinates of where the text occurs and need to provide hyper-link for those co-ordinates.

So, when I click on the text, I should be able to traverse to another location in the PDF document.

I have tried with <area> tag mentioning the co-ordinates within <fo:block>, but it does not work. My Fo structure is as follows:

<fo:block> <fo:external-graphic content-width="scale-to-fit" content-height="100%" width="100%" src="figures/test.png"/><area shape="rect" coords="148,147,195,162" <fo:basic-link>xyz</fo:basic-link></area>
</fo:block>

Could you please let me know if anyone has tried something like this and help me out?

lfurini
  • 3,729
  • 4
  • 30
  • 48
Dhinesh M
  • 15
  • 1
  • 9

2 Answers2

1

While XSL-FO does not have image maps (something analogous to the MAP element in HTML), it is possible to use an embedded SVG document to achieve the same result.

Have a look at this example:

<fo:block>
    <fo:instream-foreign-object>
        <svg width="5cm" height="3cm" viewBox="0 0 5 3" version="1.1"
             xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
            <image x="0" y="0" width="5" height="3" xlink:href="image.png"/>
            <a xlink:href="http://www.w3.org">
                <rect x="1" y="2" width="3" height="1" 
                      fill="#AAFFFF" stroke="none" opacity="0"/>
            </a>
        </svg>
    </fo:instream-foreign-object>
</fo:block>

Inside the svg document:

  • an image element places the bitmap image, having the same size of the document viewBox
  • an a element defines the link destination
  • a rect element inside the a defines the clickable area

I tested this example with FOP 2.1 and it works, with a couple of caveat:

  • in order to make the clickable rectangle completely transparent I used opacity="0"; I tried using fill="none" stroke="none" but this was not working, probably because the rectangle was completely discarded / ignored not having any visible mark
  • the clickable area in the PDF is rectangular even when using an ellipse element in the SVG
lfurini
  • 3,729
  • 4
  • 30
  • 48
  • The above answer is helpful, but I am not able to add the attribute. When I add, it says **"The attribute "width" of the element is required"** So, I have removed the and the image got generated. But, the whole image is selected like the way it is there with every PDF image. No particular part of the image is selectable and provided with the hyperlink. – Dhinesh M Jun 02 '16 at 11:37
  • @DhineshM If you know the (x1, y1, x2, y2) coordinates of the rectangle (`coords="148,147,195,162"` in your example) you can easily use them to compute the `x`, `y`, `width` and `height` attributes required to properly define the `rect` element: `width` is x2 - x1, `height` is y2 - y1. – lfurini Jun 02 '16 at 11:56
  • @DhineshM Actually, it depends on where the coordinates origin is located (SVG axes have origin in the upper left corner, positive x is toward the right, positive y is toward the bottom). If you set `opacity="0.5"` the rectangle is semi-transparent and you can see where it is and check you are computing its position and size in the right way. – lfurini Jun 02 '16 at 12:12
  • The images are getting placed and link is also shown. But the problem is that the images are shrinked. It is not shown in its original size. I have tried with fit to width, auto etc, but to no use. Pls suggest. I want the images to be in its original size – Dhinesh M Jun 03 '16 at 07:11
  • @DhineshM The desired dimension must be set in **three** different places: (1) `width` and `height` of the `svg` element; (2) `viewbox` of the `svg` element; (3) `width` and `height` of the `image` element. – lfurini Jun 03 '16 at 08:04
  • My images are not static. They are generated and the size varies. For this, the size for the `viewbox`, `svg` and `image` element cannot be set. That's where I face the issue. Even if the size of one image fits in the box, the others fail to fit. – Dhinesh M Jun 03 '16 at 08:51
  • I have identified the height and width of the image that has to be incorporated in the PDF. So, I have given like, ` height="349px" width="1008px" version="1.1" ` With this, the images are printed out of the PDF boundaries and also overlayed over the next paragraph. – Dhinesh M Jun 03 '16 at 10:08
  • You can try adding `width="100%" content-width="scale-to-fit"` to the `fo:instream-foreign-object` element. – lfurini Jun 03 '16 at 11:21
  • This also looks the same and no difference at all. The picture is not placed properly. – Dhinesh M Jun 03 '16 at 11:36
  • 1
    As this is a different problem from the original one, and the comment chain is getting long, I would suggest creating a new specific question (maybe linking to this one for additional context). – lfurini Jun 03 '16 at 12:13
1

An all-XSL-FO way is to put the fo:external-graphic inside an fo:inline-container or fo:block-container that has a specified width and height. The hotspots can then be fo:block-container that are positioned relative to the reference area of their containing fo:inline-container/fo:block-container.

This example adds a hotspot to an inline image. The following screenshot from the Antenna House GUI has the rulers visible so that you can see that the hotspot has the correct position and size. (The border and background properties were added just to make this obvious, and you are unlikely to need the properties.)

<fo:block text-align="center">
  <fo:inline-container width="200px" height="200px"
                       border="thin solid silver">
  <fo:block text-depth="0" line-height="0" font-size="0">
    <fo:external-graphic
        content-width="scale-to-fit"
        content-height="100%" width="100%"
        src="logo-antenna-200x200.png" />
  </fo:block>
  <fo:block-container
      position="absolute"
      left="148px"
      top="147px"
      width="47px"
      height="15px">
    <fo:block>
      <fo:basic-link internal-destination="xyz">
        <fo:block-container height="100%" width="100%"
                            background-color="magenta" />
      </fo:basic-link>
    </fo:block>
  </fo:block-container>
  </fo:inline-container>
</fo:block>

Antenna House logo with added hotspot

Tony Graham
  • 7,306
  • 13
  • 20