Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

support of css style float and clear #262

Merged
merged 4 commits into from

2 participants

@woolfg

float text around images. support right, left floating of image elements and clear:both for resetting the floating again

<p>Para 3: <img src="test.jpg" style="float: right;" width="200" height="200">Hund! abscheuliches Unthier! - Wandle ihn, du unendlicher Geist!
wandle den Wurm wieder in seine Hundsgestalt, wie er sich oft
nächtlicher Weise[Weile] gefiel vor mir herzutrotten, dem harmlosen
Wandrer vor die Füße zu kollern und sich dem niederstürzenden auf die
Schultern zu hängen. Wandl' ihn wieder in seine Lieblingsbildung, daß er
vor mir im Sand auf dem Bauch krieche, ich ihn mit Füßen trete, den Verworfnen! - die erste nicht! - Jammer! Jammer! von keiner
Menschenseele zu fassen, daß mehr als ein Geschöpf in die Tiefe dieses
Elendes versank, daß nicht das erste genugthat für die Schuld aller
übrigen in seiner windenden Todesnoth vor den Augen des ewig
Verzeihenden! Mir wühlt es Mark und Leben durch das Elend dieser
einzigen, du grinsest gelassen über das Schicksal von Tausenden hin.
Bin ich doch noch so jung, so jung!
Und soll schon sterben!
  </p>

is also supported in e.g. header

<header><p>Header with floating image to the right and clearing div at the end<img src="test.jpg" style="float: right;" width="70" height="70"></p><div style="clear: both;"></div></header>
@diegocr
Collaborator

I can't get this to work properly, the image is upscaled and the letter-spacing is huge too:

142121181029

@diegocr
Collaborator

Re letter-spacing, looks like each letter is added separately when in a paragraph containing an image with float style:

0 -15.00 Td
/F1 10.50 Tf (P) Tj
0 -15.00 Td
/F1 10.50 Tf (e) Tj
0 -15.00 Td
/F1 10.50 Tf (r) Tj
0 -15.00 Td
/F1 10.50 Tf (m) Tj
0 -15.00 Td
/F1 10.50 Tf (i) Tj
0 -15.00 Td
/F1 10.50 Tf (s) Tj
0 -15.00 Td
/F1 10.50 Tf (s) Tj
0 -15.00 Td
/F1 10.50 Tf (i) Tj
0 -15.00 Td
/F1 10.50 Tf (o) Tj
0 -15.00 Td
/F1 10.50 Tf (n ) Tj
@woolfg

very strange, it is working fine in my setting (see screenshot). please, can you send me your html code so I can try to find the bug. What browser do you use?
screenshot6

@diegocr
Collaborator

That was on Firefox using our live demo, i've just added the missing callback there as shown on the screenshot.

Then, modified index.html as follow:

-               <p>Permission is hereby granted, free of charge, to any person obtaining
+               <p>
+               <img src="test.jpg" style="float: right;" width="200" height="200">
+               Permission is hereby granted, free of charge, to any person obtaining

And this is the used test.jpg file:

test

@woolfg

I used a pt-based jsPDF() object so I think there is some issue regarding the scale unit -> I will take a look at it

@diegocr
Collaborator

Oh, so this is related to #222 :$

Well, feel free to do it if isn't too much trouble. In the other hand, if you can provide a live demo working on your side i'll test it here, updating examples/basic.html is another choice :)

@diegocr
Collaborator

It works fine through Chrome. However, when created using Firefox:

14212513137


On Firefox the License block in inserted with more padding/margin than on Chrome, so the crow image ends up on the 3rd page. That may reveal a problem when the float:right is the first element on the page, since the right-aligned image on the first page works fine on Firefox.

142125132124


Also, on Chrome there seems to be some issue with elements being placed below the footer:

142125132618

@woolfg

Hi, I did some bug fixing and tested it on chrome and firefox - you can find the current version at http://probelix.inlupus.at/tmp/jspdf/align.html - I could not reproduce your screenshot which showed an overlapping text and image, is this problem still present?

@diegocr
Collaborator

Hey Wolfgang, sorry for the extremely long delay, a quite busy month at work.

Well, i tested your updated page and unfortunately i'm still getting the same problem:

temp-75

Basically, Chrome and its inline pdf viewer is the only place where it's shown correctly, but apparently because it doesn't split the document into pages (?), as you can see that screenshoot is from Adobe Reader who report errors in the pdf when scrolling to the last page.

@woolfg

OK, now I can reproduce the problem - it is only present when using Windows. It works well on Linux (incl. acroread)....I will try to find the bug...

@diegocr
Collaborator

Oh, I was indeed confused, but didn't realized that could be a platform issue :confused:

@woolfg

It is very strange. The bug is also present in the current master branch when using the basic.html example (even without footer or header) -> see attached screenshot.
acrobat_error
I also checked out older versions such as ce42cba but got the same error when using windows and acrobat reader.

@diegocr
Collaborator

I'm sorry to say i was unable to reproduce that problem using the basic.html example.

Tested on w7 32b with Firefox 30 and Reader 11.0.07 through http://mrrio.github.io/jsPDF/examples/basic.html <-- are you able to reproduce it on that page?

142626172134

@diegocr
Collaborator

Check this, in your page i've removed the "Para 4:" paragraph and its left image, then generated the PDF and got the following with no errors at all:

(So, as pointed earlier the problem could be with positioning a float image at the very top of a page)

14262617479

@diegocr
Collaborator

Hey, and just replacing float:right by float:left on the crow i got it properly, so i think it's obvious to say the problem is rather with the code position the images on the right side...but only when it's the first element of a pdf page...because the float:right image for the "Para 3" shows fine (?)

142626175850

@diegocr
Collaborator

Hmm, for this last example if i let Firefox launch Reader i don't get an "error on this page" message, but going to the Temp folder (where Firefox saved the file) and double-clicking the PDF i then get it (:!?)

Edit: Erm.....and the same happens here for the basic.html-generated PDF, going nuts man ;)

So, actually we have two bugs here:

  1. Something related to our addPage() function... (coincidence or no, happening on the 3rd page on both cases)

  2. Positioning images on the right side, when it's at the top of the page.

:8ball:...

@woolfg

I got the same acrobat error when using the demo example at http://mrrio.github.io/jsPDF/examples/basic.html (w7, 32bit, acrobat 8.0.0) - the error is always shown on the last page irrespective of the number of pages in the document (expect docs with one page).

EDIT: I get the same error when using 868aa25 which introduces multiple pages

@woolfg

I fixed the bug "Positioning images on the right side, when it's at the top of the page" (see current commit 45b5f8e and http://probelix.inlupus.at/tmp/jspdf/align.html ) - the problem was an overlap between the header's right floating logo and the right floated crow at the beginning of the new page.

@diegocr
Collaborator

Great! Let's merge it hard! :)

Thanks for your excellent work and the patience fixing that last bug there :+1:

@diegocr diegocr merged commit 78eac71 into from
@woolfg woolfg deleted the branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 26, 2014
  1. @woolfg

    floating around image

    woolfg authored
    floating advanced, clearing divs and watcher functions adapted
  2. @woolfg

    problem of lost lines solved

    woolfg authored
  3. @woolfg
Commits on Jun 27, 2014
  1. @woolfg

    image floating

    woolfg authored
This page is out of date. Refresh to see the latest.
Showing with 137 additions and 4 deletions.
  1. +137 −4 jspdf.plugin.from_html.js
View
141 jspdf.plugin.from_html.js
@@ -33,6 +33,8 @@
FontNameDB,
FontStyleMap,
FontWeightMap,
+ FloatMap,
+ ClearMap,
GetCSS,
PurgeWhiteSpace,
Renderer,
@@ -101,6 +103,8 @@
this.x = x;
this.y = y;
this.settings = settings;
+ //list of functions which are called after each element-rendering process
+ this.watchFunctions = [];
this.init();
return this;
};
@@ -208,6 +212,9 @@
css["padding-left"] = ResolveUnitedNumber(computedCSSElement("padding-left")) || 0;
css["padding-right"] = ResolveUnitedNumber(computedCSSElement("padding-right")) || 0;
}
+ //float and clearing of floats
+ css["float"] = FloatMap[computedCSSElement("cssFloat")] || "none";
+ css["clear"] = ClearMap[computedCSSElement("clear")] || "none";
return css;
};
elementHandledElsewhere = function (element, renderer, elementHandlers) {
@@ -323,6 +330,9 @@
while (i < l) {
cn = cns[i];
if (typeof cn === "object") {
+
+ //execute all watcher functions to e.g. reset floating
+ renderer.executeWatchFunctions(cn);
/*** HEADER rendering **/
if (cn.nodeType === 1 && cn.nodeName === 'HEADER') {
@@ -347,14 +357,74 @@
renderer.pdf.addPage();
renderer.y = renderer.pdf.margins_doc.top;
}
+
} else if (cn.nodeType === 1 && !SkipNode[cn.nodeName]) {
+ /*** IMAGE RENDERING ***/
if (cn.nodeName === "IMG" && images[cn.getAttribute("src")]) {
if ((renderer.pdf.internal.pageSize.height - renderer.pdf.margins_doc.bottom < renderer.y + cn.height) && (renderer.y > renderer.pdf.margins_doc.top)) {
renderer.pdf.addPage();
renderer.y = renderer.pdf.margins_doc.top;
+ //check if we have to set back some values due to e.g. header rendering for new page
+ renderer.executeWatchFunctions(cn);
+ }
+
+ var imagesCSS = GetCSS(cn);
+ var imageX = renderer.x;
+ //if float is set to right, move the image to the right border
+ if (imagesCSS['float'] !== undefined && imagesCSS['float'] === 'right') {
+ imageX += renderer.settings.width-cn.width;
}
- renderer.pdf.addImage(images[cn.getAttribute("src")], renderer.x, renderer.y, cn.width, cn.height);
- renderer.y += cn.height;
+
+ renderer.pdf.addImage(images[cn.getAttribute("src")], imageX, renderer.y, cn.width, cn.height);
+ //if the float prop is specified we have to float the text around the image
+ if (imagesCSS['float'] !== undefined) {
+ if (imagesCSS['float'] === 'right' || imagesCSS['float'] === 'left') {
+
+ //add functiont to set back coordinates after image rendering
+ renderer.watchFunctions.push((function(diffX , thresholdY, diffWidth, el) {
+ //undo drawing box adaptions which were set by floating
+ if (renderer.y >= thresholdY) {
+ renderer.x += diffX;
+ renderer.settings.width += diffWidth;
+ return true;
+ } else if(el && el.nodeType === 1 && !SkipNode[el.nodeName] && renderer.x+el.width > (renderer.pdf.margins_doc.left + renderer.pdf.margins_doc.width)) {
+ renderer.x += diffX;
+ renderer.y = thresholdY;
+ renderer.settings.width += diffWidth;
+ return true;
+ } else {
+ return false;
+ }
+ }).bind(this, (imagesCSS['float'] === 'left') ? -cn.width : 0, renderer.y+cn.height, cn.width));
+
+ //reset floating by clear:both divs
+ //just set cursorY after the floating element
+ renderer.watchFunctions.push((function(yPositionAfterFloating, pages, el) {
+ if (renderer.y < yPositionAfterFloating && pages === renderer.pdf.internal.getNumberOfPages()) {
+ if (el.nodeType === 1 && GetCSS(el).clear === 'both') {
+ renderer.y = yPositionAfterFloating;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return true;
+ }
+ }).bind(this, renderer.y+cn.height, renderer.pdf.internal.getNumberOfPages()));
+
+ //if floating is set we decrease the available width by the image width
+ renderer.settings.width -= cn.width;
+ //if left just add the image width to the X coordinate
+ if (imagesCSS['float'] === 'left') {
+ renderer.x += cn.width;
+ }
+ }
+ //if no floating is set, move the rendering cursor after the image height
+ } else {
+ renderer.y += cn.height;
+ }
+
+ /*** TABLE RENDERING ***/
} else if (cn.nodeName === "TABLE") {
table2json = tableToJson(cn, renderer);
renderer.y += 10;
@@ -574,6 +644,25 @@
y : this.y
};
};
+
+ //Checks if we have to execute some watcher functions
+ //e.g. to end text floating around an image
+ Renderer.prototype.executeWatchFunctions = function(el) {
+ var ret = false;
+ var narray = [];
+ if (this.watchFunctions.length > 0) {
+ for(var i=0; i< this.watchFunctions.length; ++i) {
+ if (this.watchFunctions[i](el) === true) {
+ ret = true;
+ } else {
+ narray.push(this.watchFunctions[i]);
+ }
+ }
+ this.watchFunctions = narray;
+ }
+ return ret;
+ };
+
Renderer.prototype.splitFragmentsIntoLines = function (fragments, styles) {
var currentLineLength,
defaultFontSize,
@@ -669,14 +758,22 @@
};
Renderer.prototype.RenderTextFragment = function (text, style) {
var defaultFontSize,
- font;
+ font,
+ maxLineHeight;
+
+ maxLineHeight = 0;
+ defaultFontSize = 12;
+
if (this.pdf.internal.pageSize.height - this.pdf.margins_doc.bottom < this.y + this.pdf.internal.getFontSize()) {
this.pdf.internal.write("ET", "Q");
this.pdf.addPage();
this.y = this.pdf.margins_doc.top;
this.pdf.internal.write("q", "BT", this.pdf.internal.getCoordinateString(this.x), this.pdf.internal.getVerticalCoordinateString(this.y), "Td");
+ //move cursor by one line on new page
+ maxLineHeight = Math.max(maxLineHeight, style["line-height"], style["font-size"]);
+ this.pdf.internal.write(0, (-1 * defaultFontSize * maxLineHeight).toFixed(2), "Td");
}
- defaultFontSize = 12;
+
font = this.pdf.internal.getFont(style["font-family"], style["font-style"]);
//set the word spacing for e.g. justify style
@@ -735,6 +832,7 @@
//stores the current indent of cursor position
var currentIndent = 0;
+
while (lines.length) {
line = lines.shift();
maxLineHeight = 0;
@@ -766,6 +864,32 @@
i++;
}
this.y += maxLineHeight * fontToUnitRatio;
+
+ //if some watcher function was executed sucessful, so e.g. margin and widths were changed,
+ //reset line drawing and calculate position and lines again
+ //e.g. to stop text floating around an image
+ if (this.executeWatchFunctions(line[0][1]) && lines.length > 0) {
+ var localFragments = [];
+ var localStyles = [];
+ //create fragement array of
+ lines.forEach(function(localLine) {
+ var i = 0;
+ var l = localLine.length;
+ while (i !== l) {
+ if (localLine[i][0]) {
+ localFragments.push(localLine[i][0]+' ');
+ localStyles.push(localLine[i][1]);
+ }
+ ++i;
+ }
+ });
+ //split lines again due to possible coordinate changes
+ lines = this.splitFragmentsIntoLines(PurgeWhiteSpace(localFragments), localStyles);
+ //reposition the current cursor
+ out("ET", "Q");
+ out("q", "BT", this.pdf.internal.getCoordinateString(this.x), this.pdf.internal.getVerticalCoordinateString(this.y), "Td");
+ }
+
}
if (cb && typeof cb === "function") {
cb.call(this, this.x - 9, this.y - fontSize / 2);
@@ -818,6 +942,15 @@
center : "center",
justify : "justify"
};
+ FloatMap = {
+ none : 'none',
+ right: 'right',
+ left: 'left'
+ };
+ ClearMap = {
+ none : 'none',
+ both : 'both'
+ };
UnitedNumberMap = {
normal : 1
};
Something went wrong with that request. Please try again.