I am trying to save a pdf of html text in Google Apps Script. The full script sends a stylized email with the html text but I would like to back up the body of the email as a pdf. Using the below code I am able to save a pdf, but it does not use the Avenir font as I'd expect.
function printToPDF() {
var htmlMessage = '<html style="font-family: `Avenir`;">Avenir test</html>';
var folder = DriveApp.getFolderById(folderId).createFolder('test')
var blob = Utilities.newBlob(htmlMessage, MimeType.HTML, "text.html");
var pdf = blob.getAs(MimeType.PDF);
var document = DriveApp.getFolderById(folderId).createFile(pdf);
}
General CSS styling works (followed this post Google Apps Script - Convert HTML with styling to PDF and attach to an email - Create a PDF blob from HTML).
I tried to replicate your code, test few font family and found out that not all fonts are accepted in PDF.
Example:
Here I tried using Comic Sans MS.
function printToPDF() {
var folderId = "id";
var html = HtmlService.createTemplateFromFile("ABCD");
var output = html.evaluate();
var blob = Utilities.newBlob(output.getContent(), MimeType.HTML, "text.html");
var pdf = blob.getAs(MimeType.PDF);
DriveApp.getFolderById(folderId).createFile(pdf);
}
ABCD.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<style>
body {
font-family: 'Comic Sans MS';
font-size: 48px;
}
</style>
</head>
<body>
Comic Sans MS
</body>
</html>
Output:
Since there is no proper documentation on what are the accepted fonts in PDF, what you can do for now is to search for fonts similar to Avenir and do a trial and error.
Related
I am in the process of writing some code to be viewed exclusively in Chrome (Windows and Android) which dynamically generates SVG images. My code goes something like this
<head>
<style>
#font-face
{
font-family:"toolbar";
src:url('https://cdn.jsdelivr.net/fontawesome/4.6.2/fonts/fontawesome-
webfont.ttf') format('truetype');
}
</style>
//font to be packaged as a resource in the APK in due course. My current
//tests are on Chrome in Windows
<script>
$(document).ready(function()
{
var s = Snap('#world');
s.text(821,1385,'').attr({fill:'#FAD411',
"font-size":"10vw","font-family":"toolbar"});
}
</head>
<body>
<div id='svgbox'>
<svg id='world' height="100%" width="100%" viewBox="0 0 2000 2547"
preserveAspectRatio="xMidYMid meet">
//the SVG is created in here dynamically from code
</svg>
</div>
</body>
</html>
While everything else works - and testing that the toolbar font family is actually available in normal html markup succeeds - in the SVG the text displayed is the literal string instead of the Fontawesome cart-plus icon as I expect. What am I doing wrong here.
You have to copy/paste the actual icon into the HTML. See this JSBin for an example. In your source code it will appear as an empty box, but when rendered it will properly display the icon. I copied the icon from the Font Awesome cheatsheet.
var s = Snap('#world');
var text = s.text(821, 1385, '');
text.attr({
fill: '#FAD411',
fontSize: "15vw",
fontFamily: "toolbar"
});
This answer is similar to what you were asking, except the only part that applies to this question is "just put the actual Unicode character you want into your document". No need to worry about the meta tags or encoding types.
I'm using PhantomJS to turn an html page into PDF. This page uses fonts from cloud.typography.com. Now the html page itself is fine, and if I manually print it to a PDF, that too is fine. However, when I use PhantomJS to turn it to a PDF, the server fonts do not show up.
I researched this issue, and while I could find general issues involving fonts, I could find nothing on this specific case. The closest thing I could find was a bug in which PhantomJS would use the fallback font even if the primary one was available, but removing the fallback font didn't fix the issue for me.
Is this a known bug? Did I do something wrong? Do you know of any work-arounds?
Here's the (generic) html to PDF rendering script I'm using. I'm parametizing the page on the command line:
var page = require('webpage').create(),
args = require('system').args,
if ( args[2].split('.').pop() == 'pdf' ) {
page.viewportSize = { width:1920, height:1080 };
page.paperSize = {
width: '8.5in',
height: '11in',
};
}
page.open(args[1], render);
function render() {
page.render(args[2]);
phantom.exit();
}
Here's a relevant html snippet that points to the font server and the style sheet:
<link rel="stylesheet" type="text/css" href="print.css">
<link rel="stylesheet" type="text/css" href="//cloud.typography.com/7787052/625786/css/fonts.css" />
And here's a relevant section from print.css that references the fonts:
body {
font-family: "Gotham SSm A", "Gotham SSm B", sans-serif;
font-weight: 400;
font-style: normal;
margin: 0;
padding: 0;
}
I am generating PDF using Grails export plugin (basically, Flying Saucer). My GSP page is an UTF-8 page (or at least properties are showing that it is UTF-8, also in the beginning of the GSP page there is a <?xml version="1.0" encoding="UTF-8"?> directive). At first generated PDF properly contained umlaut characters "äöüõ", but Cyrillic characters were missing from PDF (not rendered at all). Then I've changed my css file as described in documentation by adding following:
#font-face {
src: url(ARIALUNI.TTF);
-fs-pdf-font-embed: embed;
-fs-pdf-font-encoding: UTF-8;
}
body {
font-family: "Arial Unicode MS", Arial, sans-serif;
}
ArialUni.ttf is also deployed to the server. But now I am getting both umlaut characters and Cyrillic characters rendered as boxes. If I am changing -fs-pdf-encoding property value to Identity-H then umlaut characters are rendered properly, but Cyrillic characters are rendered as question marks.
Any ideas of what font can be used to properly render both umlaut and Cyrillic characters? Or may be my CSS is somehow wrong? Any hints would be much appreciated.
Upd 1:
I have also tried following css (which was generated by http://fontface.codeandmore.com/):
#font-face {
font-family: 'ArialUnicodeMS';
src: url('arialuni.ttf');
src: url('arialuni.eot?#iefix') format('embedded-opentype'),
url('arialuni.woff') format('woff'),
url('arialuni.ttf') format('truetype'),
url('arialuni.svg#arialuni') format('svg');
font-weight: normal;
font-style: normal;
-fs-pdf-font-embed: embed;
-fs-pdf-font-encoding: UTF-8;
}
body {
font-family:'ArialUnicodeMS';
}
I've added <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
I was also trying to run grails with -Dfile.encoding=UTF-8, as was mentioned here: http://grails.1312388.n4.nabble.com/PDF-plugin-Having-problems-with-instalation-td2297840.html, but nothing helps. Cyrillic characters are not shown at all. Any other ideas what might be the problem?
*BTW:*I am packaging my PDF as zip and sending it back to browser in the response like that:
response.setHeader "Content-disposition", "attachment; filename=test.zip"
response.setHeader "Content-Encoding", "UTF-8"
response.contentType = 'application/zip'
response.outputStream << zip
response.outputStream.flush()
response.outputStream.close()
Do I need to somehow consider encoding while zipping????, which I do like that:
public static byte[] zipBytes(Map<String, ByteArrayOutputStream> fileNameToByteContentMap) throws IOException {
ByteArrayOutputStream zipBaos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(zipBaos);
fileNameToByteContentMap.eachWithIndex {String fileName, ByteArrayOutputStream baos, i ->
byte[] content = baos.buf
ZipEntry entry = new ZipEntry(fileName)
entry.setSize(content.length)
zos.putNextEntry(entry)
zos.write(content)
zos.closeEntry()
}
zos.close()
return zipBaos.toByteArray();
}
I managed to "enable" unicode characters (cyrillic or czech) within java code and furthermore providing a true type font in my resources (CALIBRI.TTF).
import org.w3c.dom.Document;
import org.xhtmlrenderer.pdf.ITextRenderer;
import com.lowagie.text.pdf.BaseFont;
...
ITextRenderer renderer = new ITextRenderer();
URL fontResourceURL = getClass().getResource("fonts/CALIBRI.TTF");
//System.out.println("font-path:"+fontResourceURL.getPath());
/* HERE comes my solution: */
renderer.getFontResolver().addFont(fontResourceURL.getPath(),
BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
renderer.setDocument(doc, null);
renderer.layout();
baos = new ByteArrayOutputStream();
renderer.createPDF(baos);
baos.flush();
result = baos.toByteArray();
...
Finally I added the font-family 'Calibri' to the css section of my document:
...
<style type="text/css">
span { font-size: 11pt; font-family: Calibri; }
...
For some reason it started working with following css and .ttf file, which was generated by face-kit-generator:
#font-face {
src: url('arialuni.ttf');
-fs-pdf-font-embed: embed;
-fs-pdf-font-encoding: Identity-H;
}
body {
font-family: Arial Unicode MS, Lucida Sans Unicode, Arial, verdana, arial, helvetica, sans-serif;
font-size: 8.8pt;
}
Weird thing is that if I put font into some folder, let say "fonts", it will find the font but characters won't be rendered.
I have been using the Google Webfont loader to display parts of my website with nice fonts. I have this part work fine, all of my <p> show with the font I want. However, I would like only some classes of <p> (i.e. <p class="someclass">) to show with the webfonts, and then the rest with regular font (i.e. not Google Webfonts).
What is the best way for me to achieve this? At the moment, I am using this
<script type="text/javascript">
WebFontConfig = {
google: { families: [ 'McLaren' ] }
};
(function() {
var wf = document.createElement('script');
wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
'://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
wf.type = 'text/javascript';
wf.async = 'true';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(wf, s);
})();
</script>
<style type="text/css">
.wf-loading p.someclass {
font-family: serif
}
.wf-inactive p.someclass {
font-family: cursive
}
.wf-active p.someclass {
font-family: 'McLaren', cursive
}
</style>
and all <p> throughout the page display with the 'McLaren' font. I'm sure I am doing something dumb with the CSS selector but I'm not quite sure what.
Any help would be greatly appreciated. Thanks
First off you don’t necessarily need the js version of Google fonts I have just linked them through css and I have had no loading issues. Secondly, someone would need to see your body of your actual html BUT you don’t need the p prefix just add the fonts to your class .someclass{font-family:cursizve;} also like I said using css pseudo classes work better and a lot lighter on the client
I'm using v1.3.1 of PlayN. This issue is discussed in the following google groups thread but I'm not sure how to implement the suggestions proposed:
https://groups.google.com/forum/?fromgroups#!topic/playn/kiE2iEYJqM0
Perhaps someone can offer some sample code. Currently I'm following the technique referenced in the HTML link in this answer:
https://stackoverflow.com/a/9116829/1093087
My problem: on the home screen of my game, I display some text using loaded fonts. Works fine in Java version. However, in HTML version, the text doesn't display initially. On the next screen, or if I later return to the home screen, text is properly displayed. So I concluded that it was due to the asynchronous loading of fonts as discussed in the google groups thread.
My remedy was to add a splash screen that displays an image for a few seconds, giving the fonts a chance to load, before redirecting to screen with the text on it. But no matter how long I set the delay, the text is still not displayed.
Here's my HTML file which loads my game and the fonts:
<!DOCTYPE html>
<html>
<head>
<title>mygamePlayn</title>
<!-- fonts -->
<style>
#font-face {
font-family: "DroidSans-Bold";
src: url(mygame/fonts/DroidSans-Bold.ttf);
}
#font-face {
font-family: "UbuntuMono";
src: url(mygame/fonts/UbuntuMono-Bold.ttf);
}
</style>
</head>
<body bgcolor="black">
<script src="mygame/mygame.nocache.js"></script>
</body>
</html>
Here's my core Java code that generates the text that's not initially displaying (but works otherwise):
public static CanvasImage generateTextImage(String text, String fontName,
Integer fontSize, Integer fontColor, Style fontStyle, Integer padding) {
Font font = graphics().createFont(fontName, fontStyle, fontSize);
TextFormat fontFormat = new TextFormat().withFont(font).withTextColor(fontColor);
TextLayout layout = graphics().layoutText(text, fontFormat);
Integer width = (int) layout.width() + padding * 2;
Integer height = (int) layout.height() + padding * 2;
CanvasImage textImage = graphics().createImage(width, height);
textImage.canvas().drawText(layout, padding, padding);
return textImage;
}
I think I've finally figured out a solution to my problem. It required using Google WebFont Loader in the following somewhat roundabout fashion:
1) I saved the fonts -- in this case, DroidSans-Bold, Inconsolata, and UbuntuMono-Bold -- in my PlayN project's resources/fonts directory.
2) In resources/css, I add a fonts.css stylesheet where I add the #font-face definitions for my locally saved fonts. My fonts.css file:
#font-face {
font-family: DroidSans;
src: url('../fonts/DroidSans-Bold.ttf');
}
#font-face {
font-family: Inconsolata;
src: url('../fonts/Inconsolata.ttf');
}
#font-face {
font-family: UbuntuMono;
src: url('../fonts/UbuntuMono-Bold.ttf');
}
#font-face {
font-family: UbuntuMono;
font-weight: bold;
src: url('../fonts/UbuntuMono-Bold.ttf');
}
Note: I use the same value for my font-family name as that which I used for the font names in my PlayN code. For example, I load the DroidSans font in my PlayN code like this:
Font font = graphics().createFont("DroidSans", fontStyle, fontSize);
3) I then use Google WebFont Loader in my game's html file (MyGame.html) to load the fonts before the game loads. My MyGame.html file:
<!DOCTYPE html>
<html>
<head>
<title>MyGame</title>
<style>
body {
background-color:black;
color:white;
}
</style>
<!-- Google AJAX Libraries API -->
<script src="http://www.google.com/jsapi"></script>
<script>
google.load("jquery", "1.4.2");
google.load("webfont", "1");
WebFontConfig = {
custom: { families: ['DroidSans', 'UbuntuMono'],
urls: [ 'mygame/css/fonts.css' ]
},
loading: function() {
console.log("loading fonts");
},
fontloading: function(fontFamily, fontDescription) {
console.log("loading font: " + fontFamily + "-" + fontDescription);
},
fontactive: function(fontFamily, fontDescription) {
console.log(fontFamily + "-" + fontDescription + " is active");
},
fontinactive: function(fontFamily, fontDescription) {
console.log(fontFamily + "-" + fontDescription + " is INACTIVE");
},
active: function() {
console.log("font-loading complete");
},
};
google.setOnLoadCallback(function() {
console.log("Google onLoad callback");
WebFont.load(WebFontConfig);
});
</script>
</head>
<body>
<div id="playn-root">
<script src="mygame/mygame.nocache.js"></script>
</div>
</body>
</html>
The console logging in the WebFont.load callbacks helped verify that the fonts were successfully loaded before the PlayN game code.
I would have preferred to use WebFont Loader with the fonts served through googleapis.com, but I couldn't figure out how to sync up the references between my PlayN code and the stylesheet. (Now that I look at it, if I didn't want to host the fonts myself, I suppose I could have just used the same url listed in the googleapi.com stylesheets.) Whatever the case, this pattern seems to solve the problem.*
*For Google Chrome. I haven't tested any other browsers.