You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@pdfbox.apache.org by "David KELLER (JIRA)" <ji...@apache.org> on 2015/11/11 22:27:11 UTC

[jira] [Updated] (PDFBOX-3099) Find suitable PDFont

     [ https://issues.apache.org/jira/browse/PDFBOX-3099?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

David KELLER updated PDFBOX-3099:
---------------------------------
    Description: 
What is the best way to find a suitable font ?

I assume that PDFont cannot load directly a java.awt.Font.

But I want to parse a PDF and find a text occurrence using "TextPosition textStart;"

A this moment I can retrieve the good font using  :
		float fontSize = textStart.getFontSize();
		PDFont font = textStart.getFont();

But in the PDF, the font is not complete (partial incorporated font).
So If I want to replace "#date#" by  "10 Novembre 2015", i can have this result  "1? Novembre 2?1?". Because "0" is not present in the "partial incorporated font"

So I need to determine the font used and find on the server the TTF font source, and then load it using .

I found on forums this thread http://stackoverflow.com/questions/13077611/how-to-retrieve-the-native-font-name-in-java

Then I wrote this source code to "do the job"

{code}

	public static PDFont findSuitableFont(PDDocument pdDocument, PDFont font) {
		
		String fontName = font.getFontDescriptor().getFontName();
		fontName = fontName.replace("+", "");
		fontName = fontName.replace("ABCDEE", "");
		
		GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
	    Font[] fonts = graphicsEnvironment.getAllFonts(); // Get the fonts
	    for (Font existingFont : fonts) {
		    if (existingFont.getFontName().equals(fontName)) {
			      try {

				      return getPDFont(existingFont, pdDocument);

			      } catch (Exception e) {
			    	  e.printStackTrace();
			      }
		    }
	    }
	    
	    return null;
	}


	public static PDFont getPDFont(Font font, PDDocument pdDocument)
	throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, 
	InvocationTargetException, NoSuchMethodException, IOException
	{
		Method method = font.getClass().getDeclaredMethod("getFont2D");
		method.setAccessible(true);
		Font2D f = (Font2D) method.invoke(font);

		return getPDFont(f, pdDocument);
	}

	public static PDFont getPDFont(Font2D font, PDDocument pdDocument) 
	throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException {
		if (font instanceof CompositeFont) {
			System.out.println("Font '" + font.getFontName(Locale.getDefault()) + "' is composed of:");

			CompositeFont cf = (CompositeFont) font;
			PDFont pdFont = null;
			for (int i = 0; i < cf.getNumSlots(); i++) {
				PhysicalFont pf = cf.getSlotFont(i);
				pdFont = getPDFont(pf, pdDocument);
				
				if (pdFont != null) {
					return pdFont;
				}
			}
		} else {
			Field platName = PhysicalFont.class.getDeclaredField("platName");
			platName.setAccessible(true);
			String fontPath = (String)platName.get(font);
			platName.setAccessible(false);
			System.out.println("-> " + font);
			System.out.println("fontPath: " + fontPath);
			return PDTrueTypeFont.loadTTF(pdDocument, fontPath);
		}
		
		return null;
	}


	protected void findSuitableFont(TextPosition textStart) {
		float fontSize = textStart.getFontSize();
		PDFont font = textStart.getFont();
		logger.info("fontSize: " + fontSize);
		logger.info("font: " + font.getBaseFont());

		PDFont pdFont = findSuitableFont(document, font);
		logger.info("suitable font: " + pdFont.getBaseFont());
     }

{code}

Is it a best way to do it ?


  was:
What is the best way to find a suitable font ?

I assume that PDFont cannot load directly a java.awt.Font.

But I want to parse a PDF and find a text occurrence using "TextPosition textStart;"

A this moment I can retrieve the good font using  :
		float fontSize = textStart.getFontSize();
		PDFont font = textStart.getFont();

But in the PDF, the font is not complete (partial incorporated font).
So If I want to replace "#date#" by  "10 Novembre 2015", i can have this result  "1? Novembre 2?1?". Because "0" is not present in the "partial incorporated font"

So I need to determine the font used and find on the server the TTF font source, and then load it using .

I found on forums this thread http://stackoverflow.com/questions/13077611/how-to-retrieve-the-native-font-name-in-java

Then I wrote this source code to "do the job"


	public static PDFont findSuitableFont(PDDocument pdDocument, PDFont font) {
		
		String fontName = font.getFontDescriptor().getFontName();
		fontName = fontName.replace("+", "");
		fontName = fontName.replace("ABCDEE", "");
		
		GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
	    Font[] fonts = graphicsEnvironment.getAllFonts(); // Get the fonts
	    for (Font existingFont : fonts) {
		    if (existingFont.getFontName().equals(fontName)) {
			      try {
				      return getPDFont(existingFont, pdDocument);
			      } catch (Exception e) {
			    	  e.printStackTrace();
			      }
		    }
	    }
	    
	    return null;
	}

	public static PDFont getPDFont(Font font, PDDocument pdDocument)
	throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, 
	InvocationTargetException, NoSuchMethodException, IOException
	{
		Method method = font.getClass().getDeclaredMethod("getFont2D");
		method.setAccessible(true);
		Font2D f = (Font2D) method.invoke(font);

		return getPDFont(f, pdDocument);
	}

	public static PDFont getPDFont(Font2D font, PDDocument pdDocument) 
	throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException {
		if (font instanceof CompositeFont) {
			System.out.println("Font '" + font.getFontName(Locale.getDefault()) + "' is composed of:");

			CompositeFont cf = (CompositeFont) font;
			PDFont pdFont = null;
			for (int i = 0; i < cf.getNumSlots(); i++) {
				PhysicalFont pf = cf.getSlotFont(i);
				pdFont = getPDFont(pf, pdDocument);
				
				if (pdFont != null) {
					return pdFont;
				}
			}
		} else {
			Field platName = PhysicalFont.class.getDeclaredField("platName");
			platName.setAccessible(true);
			String fontPath = (String)platName.get(font);
			platName.setAccessible(false);
			System.out.println("-> " + font);
			System.out.println("fontPath: " + fontPath);
			return PDTrueTypeFont.loadTTF(pdDocument, fontPath);
		}
		
		return null;
	}


	protected void findSuitableFont(TextPosition textStart) {
		float fontSize = textStart.getFontSize();
		PDFont font = textStart.getFont();
		logger.info("fontSize: " + fontSize);
		logger.info("font: " + font.getBaseFont());

		PDFont pdFont = findSuitableFont(document, font);
		logger.info("suitable font: " + pdFont.getBaseFont());
     }


Is it a best way to do it ?



> Find suitable PDFont
> --------------------
>
>                 Key: PDFBOX-3099
>                 URL: https://issues.apache.org/jira/browse/PDFBOX-3099
>             Project: PDFBox
>          Issue Type: Improvement
>          Components: PDModel
>    Affects Versions: 1.8.8
>         Environment: Windows / Linux
>            Reporter: David KELLER
>
> What is the best way to find a suitable font ?
> I assume that PDFont cannot load directly a java.awt.Font.
> But I want to parse a PDF and find a text occurrence using "TextPosition textStart;"
> A this moment I can retrieve the good font using  :
> 		float fontSize = textStart.getFontSize();
> 		PDFont font = textStart.getFont();
> But in the PDF, the font is not complete (partial incorporated font).
> So If I want to replace "#date#" by  "10 Novembre 2015", i can have this result  "1? Novembre 2?1?". Because "0" is not present in the "partial incorporated font"
> So I need to determine the font used and find on the server the TTF font source, and then load it using .
> I found on forums this thread http://stackoverflow.com/questions/13077611/how-to-retrieve-the-native-font-name-in-java
> Then I wrote this source code to "do the job"
> {code}
> 	public static PDFont findSuitableFont(PDDocument pdDocument, PDFont font) {
> 		
> 		String fontName = font.getFontDescriptor().getFontName();
> 		fontName = fontName.replace("+", "");
> 		fontName = fontName.replace("ABCDEE", "");
> 		
> 		GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
> 	    Font[] fonts = graphicsEnvironment.getAllFonts(); // Get the fonts
> 	    for (Font existingFont : fonts) {
> 		    if (existingFont.getFontName().equals(fontName)) {
> 			      try {
> 				      return getPDFont(existingFont, pdDocument);
> 			      } catch (Exception e) {
> 			    	  e.printStackTrace();
> 			      }
> 		    }
> 	    }
> 	    
> 	    return null;
> 	}
> 	public static PDFont getPDFont(Font font, PDDocument pdDocument)
> 	throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, 
> 	InvocationTargetException, NoSuchMethodException, IOException
> 	{
> 		Method method = font.getClass().getDeclaredMethod("getFont2D");
> 		method.setAccessible(true);
> 		Font2D f = (Font2D) method.invoke(font);
> 		return getPDFont(f, pdDocument);
> 	}
> 	public static PDFont getPDFont(Font2D font, PDDocument pdDocument) 
> 	throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException {
> 		if (font instanceof CompositeFont) {
> 			System.out.println("Font '" + font.getFontName(Locale.getDefault()) + "' is composed of:");
> 			CompositeFont cf = (CompositeFont) font;
> 			PDFont pdFont = null;
> 			for (int i = 0; i < cf.getNumSlots(); i++) {
> 				PhysicalFont pf = cf.getSlotFont(i);
> 				pdFont = getPDFont(pf, pdDocument);
> 				
> 				if (pdFont != null) {
> 					return pdFont;
> 				}
> 			}
> 		} else {
> 			Field platName = PhysicalFont.class.getDeclaredField("platName");
> 			platName.setAccessible(true);
> 			String fontPath = (String)platName.get(font);
> 			platName.setAccessible(false);
> 			System.out.println("-> " + font);
> 			System.out.println("fontPath: " + fontPath);
> 			return PDTrueTypeFont.loadTTF(pdDocument, fontPath);
> 		}
> 		
> 		return null;
> 	}
> 	protected void findSuitableFont(TextPosition textStart) {
> 		float fontSize = textStart.getFontSize();
> 		PDFont font = textStart.getFont();
> 		logger.info("fontSize: " + fontSize);
> 		logger.info("font: " + font.getBaseFont());
> 		PDFont pdFont = findSuitableFont(document, font);
> 		logger.info("suitable font: " + pdFont.getBaseFont());
>      }
> {code}
> Is it a best way to do it ?



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@pdfbox.apache.org
For additional commands, e-mail: dev-help@pdfbox.apache.org