PhantomJS font rendering problems when generating PDF - pdf

I am using 2.0 build of PhantomJS and I render my HTML's to PDF. However, my fonts were looking very narrow and like glued together. I tried to give proper letter-spacing property to elements but then I realized that it is not a css or font issue, but an issue that is specific when creating PDF. I have no problem rendering to PNG.
So here is the original html that I use (I removed html tags, it was causing problems with the editor). I created the font-face with fontsquirrel using arial.ttf from Windows fonts folder.
<head>
<title>Trial</title>
<style>
#font-face {
font-family: 'arialregular';
src: url('arial-webfont.woff2') format('woff2'),
url('arial-webfont.woff') format('woff'),
url('arial-webfont.ttf') format('truetype');
font-weight: normal;
font-style: normal;
letter-spacing: normal;
}
body {
color: #000000;
font-family: arialregular, sans-serif;
margin-left: 15px;
margin-top: 15px;
font-size: 9pt;
}
</style>
</head>
<body>
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
</body>
I use rasterize.js to create png and pdf. Here is the png result, which is expected and have no problems.
phantomjs.exe rasterize.js my.html my.png a4
Arial font is rendered correctly. When I generate pdf using
phantomjs.exe rasterize.js my.html my.pdf a4
it generates the pdf without any error. And here is how it looks like just after opening it on Adobe PDF (not reader). When clicked to the container notice that there is no font shown.
When I click in the element to edit it, but without doing any edit and just putting the cursor, it shows me an embed font.
Looks like it tries to embed the font to the pdf, but it fails as the size of PDF is 6kb when font's is about half a MB.
When I commit to edit, like writing a space etc, it shows me the following error and falls back to Minion Pro.
You will be asking why I do not use just Arial as it is available, and I did all those above to debug the issue: Same happens to Arial. So when I change the css from above to this:
body {
color: #000000;
font-family: "Arial", sans-serif;
margin-left: 15px;
margin-top: 15px;
font-size: 9pt;
width: 21.5cm;
}
the PNG renders the same, without problems. The PDF, however, shows Arial when clicked, but when I try to edit it gives the same error saying Arial is not available and it falls back to Minion Pro again.
How can I fix this problem?

Related

How can I inject fonts and colour variables (fetched from backend api upon page load) into Nuxt.js styles?

I am building an application in Nuxt.js where each clients can configure custom fonts & colours depending on their brand. Clients can specify upto 3 fonts and 3 colours, which are exposed to the front-end via an api endpoint:
Fonts:
primary-font
secondary-font
tertiary-font
Colours:
primary-colour
seconday-colour
tertiary-colour
How can I inject these fonts and colours into the application when a user visits the clients link https://{client-slug}.{domain}.com ?
You can construct a FontFace object and inject it to the document.
Following are the example of how you can achieve it. You can run the code snippet:
const fontFamily = 'Sansita Swashed'; // your custom font family
const fontSrc = 'https://fonts.gstatic.com/s/sansitaswashed/v1/BXR8vFfZifTZgFlDDLgNkBydPKTt3pVCeYWqJnZSW7RpXTIfeymE.woff2' // your custom font source
function injectCustomFont() {
const customFont = new FontFace(fontFamily, `url(${fontSrc})`);
customFont.load().then((font) => {
document.fonts.add(font);
document.body.style.fontFamily = '"Sansita Swashedr", cursive';
});
}
document.getElementById('btnFontChanger').addEventListener('click', () => {
injectCustomFont();
});
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<button id="btnFontChanger" type="button">Click to change font</button>
FontFace() constructor can accept one more parameter. Learn more at here.
Note:
FontFace is still an experimental. You must double check the browser compatibility before using it.
Relatable links:
https://usefulangle.com/post/74/javascript-dynamic-font-loading
https://developer.mozilla.org/en-US/docs/Web/API/FontFace/FontFace

Mapbox GL JS markers go outside map

When the map loads, all of the burgers / markers are visible (I intentionally set the zoom to account for all the burgers in the area.) For some reason, when I pan around on the map or zoom in/out, the burgers / markers follow the pan and escape the map's bounds / edges. I tried using default markers and removing the script that programmatically adds popups to the markers. I'll post some relevant code here.
You can see that the burgers not only show up outside the map, but stretch the width of the window as they move.
HTML
<div class="content">
<div class="story-list"></div>
<div class="story-map">
<div class="story-map-container" id="story-map-container"></div>
</div>
</div>
CSS
.content {
padding: 6.5%;
width: 87%;
background-image: url("../media/images/temp-gradient-low.jpg");
background-repeat: no-repeat;
background-size: cover;
background-position: center;
}
/* story-list */
.story-list {
display: inline-block;
position: relative;
width: 66%;
z-index: 1;
vertical-align: top;
font-size: 0;
padding-bottom: 1%;
}
/* story-map */
.story-map { /* using id='' in order to override the position set by mapbox*/
/*background-color: white;*/
display: inline-block;
position: sticky;
top: 0;
width: 33%;
height: 100vh;
/*padding-left: 2.5%;*/
z-index: 0;
vertical-align: top;
/*float: right;*/
}
#story-map-container {
background-color: lightgreen;
width: 100%;
/*margin-left: 2.5%;*/
height: 100%;
overflow: visible;
}
.mapboxgl-map {
position: absolute;
overflow: visible;
}
.mapboxgl-marker {
background-image: url("../media/icons/burger-marker.png");
background-size: cover;
width: 50px;
height: 50px;
border-radius: 50%;
cursor: pointer;
}
.mapboxgl-popup {
max-width: 200px;
}
.mapboxgl-popup-content {
text-align: center;
}
JS
var map = null;
function initMapbox() {
mapboxgl.accessToken = 'pk.eyJ1IjoiZGFua3NreSIsImEiOiJjanNmbTA0YWkwdWx5NDNtdG1idHpwNTE3In0.Y16huX7_p26tsDlcJTWWFQ';
map = new mapboxgl.Map({
container: 'story-map-container',
style: 'mapbox://styles/mapbox/streets-v11',
zoom: 10,
center: [-118.338604, 34.083480]
});
}
function parseStuff() {
const lorem = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.`;
const list = Array.from({length: 10}, (x,i) => {
return {
name: 'The Burger Place',
address: '123 Yumyum Hwy',
coordinates: {lat: 34.083480 + Math.random() * 0.1, lng: -118.348604 + Math.random() * 0.1},
phoneNumber: '1-123-456-7890',
website: {
text: 'BURGERSITE',
url: 'http://google.com'
},
description: 'A happy place for people who eat meat.',
review: lorem.substring(0, lorem.length * 0.6)
};
});
console.log(list);
list.forEach((element, index) => {
var customMarker = document.createElement('div');
customMarker.className = 'mapboxgl-marker';
customMarker.onclick = (e) => {
map.panTo([element.coordinates.lng, element.coordinates.lat]);
window.location.hash = `burger-place-${index}`
};
var popupContent = `${element.name}<br />${element.phoneNumber}`
var marker = new mapboxgl.Marker(customMarker)
.setLngLat([element.coordinates.lng, element.coordinates.lat]);
marker.setPopup(new mapboxgl.Popup({ offset: 25 }).setHTML(popupContent))
.addTo(map);
})
$('.story-list').html(componentList);
}
window.onload = () => {
initMapbox();
parseStuff();
};
.story-map {
overflow: hidden;
//...
}
fixes your issues. Though I'm also somewhat confused as to why mapbox draws the markers beyond its canvas.

How to create a text formatter

I have this code
.large
My First Document
.normal
.paragraph
This is my
.italics
very first
.regular
document, and I am very proud that I am getting this on the string. While this paragraph is not filled, the following one has automatic filling set:
.paragraph
.indent
.fill
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
.nofill
.outdent
Well, that was
.bold
exciting
.regular
good luck!
and I need to be able to enter this and it executes the above commands (that start with .) and prints out the text then saves it to a PDF.
The commands are:
- .paragraph Starts a new paragraph
- .fill enables sets indentation to fill for paragrahs, where the last character of a line must
end at the end of the margin (except for the last line of a paragarph)
- .nofill the default, sets the formatter to regular formatting
- .regular resets the font to the normal font
- .italic sets the font to italic
- .bold sets the font to bold
- .indent indents the text by a tab (or equivalent)
- .outdent outdents the text by a tab (or equivalent)
Any idea how I'd go about this? Incredibly stuck at the moment.

#media queries being ignored when viewing html emails via iOS Mail

i am dealing with very strange problem. I have tested on iphone6s and iphone6
1) the email is sent to a non-gmail account that is configured on the iphone
2) the html message is viewed from iOS Mail
3) here is where it gets weird and i will try to describe best as possible
a) if i view the email directly from the client by click on the email from the list of emails. The media query is not respected.
b) if i view the message, click the down arrow to view the previous message and then click the up to view the original message, the media query is respected.
4) i have tried both icloud and yahoo accounts and two different iphones (6 and 6s)
i have got it down to this simple example.
of course all the simple emulators work as you would expect and not exhibit the problem
<!DOCTYPE html>
<html lang="en">
<head>
<title>this is a test</title>
<meta charset="UTF-8">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
/* ----------- iPhone 5 and 5S ----------- */
/* Portrait */
#media only screen and (min-device-width: 320px) and (max-device-width: 568px) and (-webkit-min-device-pixel-ratio: 2) and (orientation: portrait) {
#main-wrapper{
max-width: 320px;
margin: 2px auto;
background-color: red;
}
}
</style>
</head>
<body>
<div id="main-wrapper" style=" background-color: #ffffff;">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis in ante velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Maecenas imperdiet erat metus, sed maximus tortor dignissim vel. Fusce luctus eget turpis a pretium. Nunc sagittis vulputate risus et porta. Cras eros nisl, placerat id ultricies sit amet, eleifend vel augue. Nullam dignissim sodales rhoncus. Morbi hendrerit aliquam tortor.
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla tellus massa, accumsan ac ex a, congue lobortis ipsum. Sed vitae ultrices purus. Nam vulputate lacus vitae massa laoreet scelerisque. Duis in risus non elit sodales pharetra. Nunc ultrices nisl quis leo mollis, sed consectetur tortor placerat. Fusce ultricies eleifend nisi, in congue metus iaculis ut.
</div>
</body>
</html>
Assuming that by the default IOS email reader you mean iOS Mail, media queries should be supported. Two things
You shouldn't need an initial-scale attribute in your viewport tag, have you tried <meta name="viewport" content="width=device-width">?
Depending on how specific an environment you want this CSS to impact, you might not need such a loaded #media tag either. Have you tried something like #media screen and (max-device-width: 568px)?

create pdf with long lines, fit to pagewidth without wordwrap

i'd like to create a large pdf (not typical page size) with long lines, max ~1000 characters / line, where the page size and font are such that no lines need to wrap.
the intention is not for the text in this document to be readable when the full page is viewed on any reasonably-sized monitor -- instead the reader can zoom to individual portions of interest within the document.
i attempted this with a small font in latex, but no success.
any help is greatly appreciated. thanks.
This works with pdflatex:
\documentclass{article}
\pdfpagewidth 200cm
\pdfpageheight 200cm
\textwidth 190cm
\def\lorem{Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.}
\begin{document}
\lorem \lorem \lorem \lorem
\end{document}