Log in

View Full Version : Exact graphical equivalence between browsers (especially with fonts)?



djr33
10-22-2012, 05:46 PM
Following the information in this thread:
http://www.dynamicdrive.com/forums/showthread.php?71756-Ideas-for-displaying-as-it-would-print-on-a-webpage
I now have a working PDF/HTML system so that I can display the same content in each, within the same space. It's working fairly well.


My new problem is getting browsers to display content identically. Is this doomed to failure?

The specific problem at the moment, although I wouldn't be surprised by more problems later, is fonts. I've set the fonts in mm, but they're still varying just slightly between browsers. In Safari vs Firefox, once in a while an extra word is cut off at the end of a line, and in the end this changes the length of the text by one or two lines-- changing the page breaks.

Is there anything I can do about this? Is it even remotely possible to guarantee the exact same dimensions in two browsers?


My goal is to develop an HTML preview of what will later be generated as PDFs.



For what it's worth, the PHP PDF extension (mpdf) is working fine, and it seems to be identical to Firefox. So for the moment I'm not worrying about it.

traq
10-22-2012, 06:09 PM
I seriously doubt you'll be able to get pixel-perfect fonts between browsers. Firefox specifically renders fonts differently (heavier) than most other browsers. Further, between operating systems, it's impossible AFAIK.

microsoft, for example, takes not only a different technical approach than apple, but their approach is philosophically different: ms pushes the font glyphs around to fit onto the screen pixel grid (sharper letters, but less true to the actual glyphs), while apple uses heavy anit-aliasing algorithms to try to preserve the shapes of the glyphs (fuzzier letters, but truer to the font glyphs).

A good "fallback" might be to offer a PDF preview (most modern browsers have no problem viewing PDFs), though constantly rendering previews might be an increased load on your server.

djr33
10-22-2012, 07:36 PM
I was worried about those things. You mentioned an important point I hadn't thought of, though, about the OS font rendering.

Hm. Maybe this is impossible. Annoying.


The entire purpose is to avoid using a PDF. I'm trying to create ebooks that can be viewed as webpages (HTML) or downloaded as PDFs. In order to make the page breaks fall in reasonable places, the PDF's paging must be shown in the HTML.

I can't actually use PDFs in the webpage because not enough browsers support that and I want people to be able to easily cut and paste text anyway. (And it would be a lot of work for the server. These could be 100 page books with graphics.)


So... ok... how do PDFs work? They look the same, or at least have the same page-breaking on various OSs? So is there some theoretical way to design HTML to do the same thing? Would it involve manually positioning each letter/word/line? I'm not sure that's actually reasonable for my current project, but I'd like to find some way to do this.

I don't care about pixel perfect similarity; I care about where things fall on the page. It doesn't need to be identical, but it can't be 1 page for some people and 2 pages for others. I'm not sure if there's any way around getting pixel-level precision then. Maybe/probably not.


Additionally, though this may no longer be relevant, I can also specifically limit the HTML to only contain certain objects. So I don't need to worry about everything being identical, just that some (important) layout things are.

jscheuer1
10-22-2012, 07:46 PM
I hate it but cufon (http://cufon.shoqolate.com/generate/) might work for this.

bernie1227
10-22-2012, 08:03 PM
There are a couple of options mentioned in this stack overflow thread (http://stackoverflow.com/questions/521832/consistent-font-size-across-browsers-web-development) that you could use.



I don't care about pixel perfect similarity; I care about where things fall on the page. It doesn't need to be identical, but it can't be 1 page for some people and 2 pages for others. I'm not sure if there's any way around getting pixel-level precision then. Maybe/probably not.

Something that may help with that; remember to use mono-spaced fonts such as courier new, or <pre> tags.

another link (http://www.codecouch.com/2007/04/how-to-get-consistent-font-sizes-across-all-browsers/)

this one (http://www.sputnikweb.co.uk/Blog/how-to-attain-cross-browser-font-size-consistency.html) mentions cross OS consistency

If you hadn't realised, the main theme of these is just resetting the css for font sizes, to try and get consistency across browsers and platforms. Yahoo actually use css resets as the basis for their cross-browser consistency.

traq
10-22-2012, 08:17 PM
... It doesn't need to be identical, but it can't be 1 page for some people and 2 pages for others.

well... a few ideas:


1. you could be a little on the restrictive side with widths, margins, and padding in the working (html) version, and then relax them a little when you generate the pdf. You'd have to do some experimenting with what the "best" compromises would be (and you might end up with the opposite problems: two pages in the preview, only one in the pdf).

2. after rendering the pdf, check that the expected:actual number of pages match. If not, change widths, margins, etc. a little bit until they do. This still puts extra work on your server and sacrifices some control, however...

3. I don't know if you can programatically (javascript) find the positioning offset of particular letters on the screen. If you can, then you can determine where lines break, and preserve them even when increasing the actual page margins.

bernie1227
10-22-2012, 08:39 PM
3. I don't know if you can programatically (javascript) find the positioning offset of particular letters on the screen. If you can, then you can determine where lines break, and preserve them even when increasing the actual page margins.
http://jsfiddle.net/cgXa3/4/
The idea of this one, is to get a letter, wrap it with a span with a class, and then offset it as well as getting its offset and alerting it (note: this jsfiddle is choosing a random letter). It's also quite possible, and a lot easier to do the same thing but have a pre-existing span around specific words and then get the offset.

traq
10-22-2012, 10:45 PM
Cool - that's what I was thinking - but I can't think of a way to apply it to what Daniel needs, except to literally loop through every letter, check its position, and then determine which are at the ends of their line. Seems inefficient.

bernie1227
10-22-2012, 11:57 PM
Get the id of the last letter on a page and make sure it stays on the right page?

traq
10-23-2012, 12:41 AM
actually, I was thinking more like:

1. start with bigger page margins than you want to end up with (e.g., 1" around the page instead of 3/4")
2. find the last letter on each line
3. insert a line break right after it ("hardwrapping" the paragraph, so to speak)
4. use the (smaller) desired margins for the PDF to ensure everything fits on the page; while the linebreaks will prevent any change in text wrapping.

djr33
10-23-2012, 02:14 AM
Thanks everyone for the helpful ideas. It's been a crazy day so I'm just working through this now. I really want to find a way to make this work. I was thinking earlier about some way of individually measuring characters/words/something. Seems excessive, but I can't imagine another approach.

However, I may have uncovered one option that will help a lot. mpdf offers a function for this, I think:
function GetStringWidth($s)
I think I can play with it and make it work. I'll look into the ideas above as well.


If I can figure out line breaks, I can figure out page breaks with a lot of complicated steps. I think. It'll be a real pain to do this for something like tables, but I can try!



I've already decided that I'd like to concentrate on the PDF looking good and allowing a little more flexibility in the HTML. Based on some ideas above, that may work.

djr33
10-23-2012, 08:02 PM
Just an update: mpdf actually has a more directly useful function:

$mpdf->WordWrap($text, 200, 1);
//$mpdf-> WordWrap($text,$widthmm,$splitlongwords);

So, I can put a paragraph in and get the location where the text will break in the PDF. Then I can use nl2br() or something similar to manually break the paragraph into lines rather than allowing the HTML to do so. So, no more cross-browser differences in where the text breaks. It'll be a little indirect to get the final HTML layout, but I think this is actually solved!

It even seems to work for other character sets (I've tried Arabic and Chinese), which is crucial for my website as a language learning site. :)

Still working on implementing all of that, but it's a good start. Now I need to test for other things that may, like fonts, vary between browsers and create similar workarounds. However, I think this is the biggest problem out of the way.

I'll keep posting updates as I work this out.