You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-users@xmlgraphics.apache.org by Karl Roberts <Ka...@macquarie.com> on 2006/04/19 02:09:24 UTC

RE: Re how to embed a font programatically

Hi Jeremias,

FYI
I've now had time to try the latest FOP trunk and patch it into my code
(instead of my workaround) and I can confirm the the URL resolving
issues when deploying FOP in a webapp so that URL's can be relative to
the ServletContext are gone when using the ServletContextURIResolver and
the FopFactory helper methods to set it up.
External graphics url's in the xsl-fo file are resolved OK (when the URL
scheme is servlet-context: )
And all references to the font "metrics-url" and "embed-url" in the
fopconfig xml are also resolved OK (again using the servlet-context:
scheme)

Thanks for all your help, it's a pleasure to use such an activly
maintained piece of software like FOP.

Cheers

Karl

PS for anyone wondering what this thread is about see the following code
snippets and config xml to see how to use the ServletContextURIResolver
to resolve URL's in XSL-FO and FOP config file relative to a web
applications ServletContext.

// code snippet .......
public void PDFDocumentGenerator(InputSource fopconfigInputSource,
ServletContext context, Source xmlSrc, Source xslSrc){

	//Set up stuff from fop config file if it exists		
	if(fopconfigInputSource!=null)
	{
	  try{
		DefaultConfigurationBuilder cfgBuilder = new
DefaultConfigurationBuilder();				
		Configuration cfg =
cfgBuilder.build(this.fopconfigInputSource);
		FopFactory ff =FopFactory.newInstance();
		ff.setUserConfig(cfg);
		FOUserAgent userAgent=ff.newFOUserAgent();
		//If ServletContext is not null then add
ServletContextURIResolver
		// incase URI's in the config file and xsl-fo input are
special ones that are relative to servlet-context:
		if(context!=null)
		{
			ff.setURIResolver(new
ServletContextURIResolver(context));
		}
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		// Construct fop with desired output format

		Fop fop = ff.newFop(MimeConstants.MIME_PDF,
userAgent,out);

		// Setup XSLT if exists// if not then we are assuming
src is already in xsl-fo format
		TransformerFactory factory =
TransformerFactory.newInstance();
		Transformer transformer;
		if(xslSource!=null)
		{
			transformer = factory.newTransformer(xslSrc);
		}
		else
		{
			transformer = factory.newTransformer();
		}				
		// Resulting SAX events (the generated FO) must be piped
through
		// to FOP
		Result res = new SAXResult(fop.getDefaultHandler());	
		// Start XSLT transformation and FOP processing
		transformer.transform(xmlSrc, res);

		//got here so no transform exceptions now deal with the
output collect as byte array (or just stream it somewhere)
		byte[] theBytes= out.toByteArray();
		.....etc....
		}catch(Exception e)
	   { ....deal with it ...}
	}
}

// fopconfig.xml using url's with servlet-context scheme
<fop version="1.0">
<!-- Base URL for resolving relative URLs -->
<base>./</base>
<source-resolution>72</source-resolution>
<target-resolution>72</target-resolution>
<!-- ie A4 -->
<default-page-settings height="29.7cm" width="21cm"/>
<renderers>
  <renderer mime="application/pdf">
    <filterList>
     <value>flate</value>
    </filterList>
    <fonts>
     <font metrics-url="servlet-context:///WEB-INF/Arial.xml"
kerning="no" embed-url="servlet-context:///WEB-INF/arial.ttf" >
      <font-triplet name="Arial" style="normal" weight="normal"/>
      <font-triplet name="ArialMT" style="normal" weight="normal"/>
     </font>
     <font metrics-url="servlet-context:///WEB-INF/ArialBd.xml"
kerning="no" embed-url="servlet-context:///WEB-INF/arialbd.ttf" >
      <font-triplet name="Arial" style="normal" weight="bold"/>
       <font-triplet name="ArialMT" style="normal" weight="bold"/>
     </font>	
    </fonts>
  </renderer>
</renderers>
</fop>

		
-----Original Message-----
From: Karl Roberts 
Sent: Tuesday, 28 March 2006 8:48 AM
To: fop-users@xmlgraphics.apache.org
Subject: RE: <SOLVED - sort of> Re how to embed a font programatically

Cheers  Jeremias,

FYI BEFORE you fix it, the issue exists in another place too! When
embedding a TTF font (before I was using enc-ansi so never saw the
issue) inside the ServletContext the following method also calls
"URL.openstream()" rather than using the URIResolver

org.apache.fop.pdf.PDFDocument.resolveURI(String uri)

The TODO gives it away! "todo Temporary hack to compile, improve later"
;-)

Cheers

Karl

 PS my code looked too complex to me too, I agree that a direct setter
method is a nicer option and look forward to testing it! 
My code was just a hack to get around the issue while highlighting the
problem, with as little change to the existing code as possible, so that
we wouldn't have to maintain too much difference in a separate branch
until the fix came through. 



-----Original Message-----
From: Jeremias Maerki [mailto:dev@jeremias-maerki.ch]
Sent: Monday, 27 March 2006 5:24 PM
To: fop-users@xmlgraphics.apache.org
Subject: Re: <SOLVED - sort of> Re how to embed a font programatically

Hi Karl

On 27.03.2006 05:39:01 Karl Roberts wrote:
> Hi Jeremias,
> Don't worry next time I'll create a patch for bugzilla! :-) Where are 
> the changes so I can test them?

In our Subversion repository in "Trunk", of course. See:
http://xmlgraphics.apache.org/fop/download.html#source

You should download the latest sources using Subversion.

> I am not using FOUserAgent more than once per rendering run.
> 
> The ThreadLocal stuff was there to guarantee that the FOUserAgent 
> being used was thread safe, when the "FontReder.createFont(String 
> path)" method calls "AgentHelper.getInstance().getFOUserAgent()".

Ah, I see. FontReader (or any other class from the font package for that
matter) should not reference FOUserAgent. That's why I added the
FontResolver. The DefaultFontResolver in the render package contains the
reference to FOUserAgent to keep the dependencies clean.

> The reason is because I am using FOP embedded from within a clustered 
> Web App environment and putting a ServletContextURIReader in 
> FOUserAgent. ServletContextURIReader has a reference to the 
> ServletContext in it's constructor, and so I just wanted to guarantee 
> that the FOUserAgent I'm using had the same ServletContext reference 
> if it was pre-empted, given that the AgentHelper uses a static
Singleton.

Looks too complicated to me. It's probably better to add a setter method
to ServletContextURIResolver (not "Reader"!) to update the
ServletContext if that changes. This can be done in the doGet() method.

When I've finished my current task of merging our API finalization
branch back into Trunk, I'll do that, too.

> If the UserAgent had been referencable to "FontReder.createFont(String

> path)" I'd have used it.

<snip/>


Jeremias Maerki


---------------------------------------------------------------------
To unsubscribe, e-mail: fop-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-users-help@xmlgraphics.apache.org



NOTICE
This e-mail and any attachments are confidential and may contain
copyright material of Macquarie Bank or third parties. If you are not
the intended recipient of this email you should not read, print,
re-transmit, store or act in reliance on this e-mail or any attachments,
and should destroy all copies of them. Macquarie Bank does not guarantee
the integrity of any emails or any attached files. The views or opinions
expressed are the author's own and may not reflect the views or opinions
of Macquarie Bank.


---------------------------------------------------------------------
To unsubscribe, e-mail: fop-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-users-help@xmlgraphics.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: fop-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-users-help@xmlgraphics.apache.org


Re: Re how to embed a font programatically

Posted by Jeremias Maerki <de...@jeremias-maerki.ch>.
Karl, thanks for the heads-up. One comment on your Java class: To
improve performance you should reuse the FopFactory and the
TransformerFactory instead of constructing them each time.

See also: http://xmlgraphics.apache.org/fop/trunk/embedding.html#basics

On 19.04.2006 02:09:24 Karl Roberts wrote:
> Hi Jeremias,
> 
> FYI
> I've now had time to try the latest FOP trunk and patch it into my code
> (instead of my workaround) and I can confirm the the URL resolving
> issues when deploying FOP in a webapp so that URL's can be relative to
> the ServletContext are gone when using the ServletContextURIResolver and
> the FopFactory helper methods to set it up.
> External graphics url's in the xsl-fo file are resolved OK (when the URL
> scheme is servlet-context: )
> And all references to the font "metrics-url" and "embed-url" in the
> fopconfig xml are also resolved OK (again using the servlet-context:
> scheme)
> 
> Thanks for all your help, it's a pleasure to use such an activly
> maintained piece of software like FOP.
> 
> Cheers
> 
> Karl
> 
> PS for anyone wondering what this thread is about see the following code
> snippets and config xml to see how to use the ServletContextURIResolver
> to resolve URL's in XSL-FO and FOP config file relative to a web
> applications ServletContext.
> 
> // code snippet .......
> public void PDFDocumentGenerator(InputSource fopconfigInputSource,
> ServletContext context, Source xmlSrc, Source xslSrc){
> 
> 	//Set up stuff from fop config file if it exists		
> 	if(fopconfigInputSource!=null)
> 	{
> 	  try{
> 		DefaultConfigurationBuilder cfgBuilder = new
> DefaultConfigurationBuilder();				
> 		Configuration cfg =
> cfgBuilder.build(this.fopconfigInputSource);
> 		FopFactory ff =FopFactory.newInstance();
> 		ff.setUserConfig(cfg);
> 		FOUserAgent userAgent=ff.newFOUserAgent();
> 		//If ServletContext is not null then add
> ServletContextURIResolver
> 		// incase URI's in the config file and xsl-fo input are
> special ones that are relative to servlet-context:
> 		if(context!=null)
> 		{
> 			ff.setURIResolver(new
> ServletContextURIResolver(context));
> 		}
> 		ByteArrayOutputStream out = new ByteArrayOutputStream();
> 		// Construct fop with desired output format
> 
> 		Fop fop = ff.newFop(MimeConstants.MIME_PDF,
> userAgent,out);
> 
> 		// Setup XSLT if exists// if not then we are assuming
> src is already in xsl-fo format
> 		TransformerFactory factory =
> TransformerFactory.newInstance();
> 		Transformer transformer;
> 		if(xslSource!=null)
> 		{
> 			transformer = factory.newTransformer(xslSrc);
> 		}
> 		else
> 		{
> 			transformer = factory.newTransformer();
> 		}				
> 		// Resulting SAX events (the generated FO) must be piped
> through
> 		// to FOP
> 		Result res = new SAXResult(fop.getDefaultHandler());	
> 		// Start XSLT transformation and FOP processing
> 		transformer.transform(xmlSrc, res);
> 
> 		//got here so no transform exceptions now deal with the
> output collect as byte array (or just stream it somewhere)
> 		byte[] theBytes= out.toByteArray();
> 		.....etc....
> 		}catch(Exception e)
> 	   { ....deal with it ...}
> 	}
> }
> 
> // fopconfig.xml using url's with servlet-context scheme
> <fop version="1.0">
> <!-- Base URL for resolving relative URLs -->
> <base>./</base>
> <source-resolution>72</source-resolution>
> <target-resolution>72</target-resolution>
> <!-- ie A4 -->
> <default-page-settings height="29.7cm" width="21cm"/>
> <renderers>
>   <renderer mime="application/pdf">
>     <filterList>
>      <value>flate</value>
>     </filterList>
>     <fonts>
>      <font metrics-url="servlet-context:///WEB-INF/Arial.xml"
> kerning="no" embed-url="servlet-context:///WEB-INF/arial.ttf" >
>       <font-triplet name="Arial" style="normal" weight="normal"/>
>       <font-triplet name="ArialMT" style="normal" weight="normal"/>
>      </font>
>      <font metrics-url="servlet-context:///WEB-INF/ArialBd.xml"
> kerning="no" embed-url="servlet-context:///WEB-INF/arialbd.ttf" >
>       <font-triplet name="Arial" style="normal" weight="bold"/>
>        <font-triplet name="ArialMT" style="normal" weight="bold"/>
>      </font>	
>     </fonts>
>   </renderer>
> </renderers>
> </fop>
<snip/>


Jeremias Maerki


---------------------------------------------------------------------
To unsubscribe, e-mail: fop-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-users-help@xmlgraphics.apache.org