Comparing version 2.0.0-alpha.4 to 2.0.0-alpha.5
# Changelog | ||
## 2.0.0-alpha.5 | ||
- implement font kerning (with a [minor limitation](https://github.com/rkusa/pdfjs/issues/82#issuecomment-376072547)) | ||
- fixed PDF text not being printed when using macOS print dialog #83 (as a consequence, set PDF version of documents to 1.6) | ||
## 2.0.0-alpha.4 | ||
@@ -4,0 +9,0 @@ |
@@ -28,3 +28,3 @@ 'use strict' | ||
this.version = '1.3' | ||
this.version = '1.6' | ||
this.info = Object.assign({}, opts.properties, { id: uuid.v4() }) | ||
@@ -31,0 +31,0 @@ this.width = opts.width || 595.296 |
@@ -8,2 +8,3 @@ 'use strict' | ||
const Base = require('./base') | ||
const StringWidth = Base.StringWidth | ||
@@ -51,3 +52,5 @@ module.exports = class AFMFont extends Base { | ||
stringWidth(str, size) { | ||
const scale = size / 1000 | ||
let width = 0 | ||
const kerning = [] | ||
for (let i = 0, len = str.length; i < len; ++i) { | ||
@@ -61,16 +64,13 @@ const left = this._charCodeFor(str[i]) | ||
// TODO: re-enable, however while this adjusts the string widths correctly, the font kerning | ||
// is not properly applied in the PDF currently (also break text alignmen justify) | ||
// kerning | ||
// if (str[i + 1] !== undefined && left in this._data.kerning) { | ||
// const right = this._charCodeFor(str[i + 1]) | ||
// const offset = this._data.kerning[left][right] | ||
// if (offset !== undefined) { | ||
// width += offset | ||
// } | ||
// } | ||
if (str[i + 1] !== undefined && left in this._data.kerning) { | ||
const right = this._charCodeFor(str[i + 1]) | ||
const offset = this._data.kerning[left][right] | ||
if (offset !== undefined) { | ||
width += offset | ||
kerning.push({ pos: i + 1, offset: -offset }) | ||
} | ||
} | ||
} | ||
const scale = size / 1000 | ||
return width * scale | ||
return new StringWidth(width * scale, kerning) | ||
} | ||
@@ -77,0 +77,0 @@ |
'use strict' | ||
module.exports = class Font { | ||
class Font { | ||
static isFont(font) { | ||
@@ -8,1 +8,15 @@ return font && font instanceof Font | ||
} | ||
class StringWidth { | ||
constructor(width, kerning) { | ||
this.width = width | ||
this.kerning = kerning | ||
} | ||
valueOf() { | ||
return this.width | ||
} | ||
} | ||
Font.StringWidth = StringWidth | ||
module.exports = Font |
@@ -12,2 +12,3 @@ 'use strict' | ||
const Base = require('./base') | ||
const StringWidth = Base.StringWidth | ||
@@ -45,2 +46,3 @@ module.exports = class OTFFontFactory extends Base { | ||
const glyphs = this.font.stringToGlyphs(str) | ||
const kerning = [] | ||
@@ -53,11 +55,13 @@ let width = 0 | ||
width += left.advanceWidth | ||
if (right) { | ||
const offset = -this.font.getKerningValue(left, right) * scale; | ||
if (right) { | ||
// TODO: re-enable, however while this adjusts the string widths correctly, the font kerning | ||
// is not properly applied in the PDF currently (also break text alignmen justify) | ||
// width += this.font.getKerningValue(left, right) | ||
if (offset !== 0) { | ||
width += offset | ||
kerning.push({ pos: i + 1, offset: offset }) | ||
} | ||
} | ||
} | ||
return width * scale | ||
return new StringWidth(width * scale, kerning) | ||
} | ||
@@ -213,3 +217,3 @@ | ||
const file = new PDFStream() | ||
file.object.prop('Subtype', 'CIDFontType0C') | ||
file.object.prop('Subtype', 'OpenType') | ||
file.object.prop('Length', hex.length + 1) | ||
@@ -216,0 +220,0 @@ file.object.prop('Length1', data.byteLength) |
@@ -35,7 +35,7 @@ 'use strict' | ||
TJ(arr) { | ||
return this.write('[' + arr.map((v, i) => { | ||
if (i % 2 === 0) { | ||
return this.write('[' + arr.map(v => { | ||
if (typeof v === 'number') { | ||
return this.toFixed(v, precision) | ||
} else { | ||
return v | ||
} else { | ||
return this.toFixed(v, precision) | ||
} | ||
@@ -42,0 +42,0 @@ }).join(' ') + ']', 'TJ') |
@@ -123,4 +123,5 @@ 'use strict' | ||
if (word) { | ||
wordWidth = offsetWidth = font.stringWidth(word, fontSize) | ||
spaceWidth = font.stringWidth(' ', fontSize) | ||
wordWidth = font.stringWidth(word, fontSize) | ||
offsetWidth = wordWidth.width | ||
spaceWidth = font.stringWidth(' ', fontSize).width | ||
@@ -144,10 +145,10 @@ // add whitespace length for every word, except the first on in the line | ||
for (let i = word.length - 1; i >= 0; --i) { | ||
const w = font.stringWidth(word[i], fontSize) | ||
wordWidth -= w | ||
offsetWidth -= w | ||
const w = font.stringWidth(word.slice(i), fontSize) | ||
if (this._spaceLeft >= offsetWidth) { | ||
if (this._spaceLeft >= offsetWidth - w.width) { | ||
const subword = word.slice(0, i) | ||
this._line.push( | ||
new TextChunk({ | ||
wordWidth, spaceWidth, word: word.slice(0, i), | ||
wordWidth: font.stringWidth(subword, fontSize), | ||
spaceWidth, word: subword, | ||
font, fontSize, color, decoration, | ||
@@ -157,2 +158,3 @@ link, destination, goTo | ||
) | ||
offsetWidth -= w.width | ||
this._spaceLeft -= offsetWidth | ||
@@ -315,7 +317,3 @@ | ||
if (out.length > 0) { | ||
if (spacing === 0) { | ||
chunk += ops.Tj(this._previousFont.encode(out.join(''))) | ||
} else { | ||
chunk += ops.TJ(out) | ||
} | ||
chunk += ops.TJ(out) | ||
} | ||
@@ -342,17 +340,23 @@ | ||
if (spacing === 0) { | ||
const isLast = i === this._line.length - 1 | ||
out.push(w.word + (!isLast && w.spaceWidth > 0 ? ' ' : '')) | ||
const kerning = w.wordWidth.kerning | ||
if (kerning.length > 0) { | ||
let pos = 0 | ||
for (let i = 0; i < kerning.length; ++i) { | ||
let subword = w.word.substring(pos, kerning[i].pos) | ||
out.push(w.font.encode(subword), kerning[i].offset) | ||
pos = kerning[i].pos | ||
} | ||
out.push(w.font.encode(w.word.substring(pos))) | ||
} else { | ||
out.push(w.font.encode(w.word), calcSpaceWidth(spacing, w.font, w.fontSize)) | ||
out.push(w.font.encode(w.word)) | ||
} | ||
} | ||
if (out.length > 0) { | ||
if (spacing === 0) { | ||
chunk += ops.Tj(this._previousFont.encode(out.join(''))) | ||
} else { | ||
chunk += ops.TJ(out) | ||
if (i < this._line.length - 1 && w.spaceWidth > 0) { | ||
// if is not last and has spaceWidth set | ||
out.push(calcSpaceWidth(spacing, w.font, w.fontSize)) | ||
} | ||
} | ||
if (out.length > 0) { | ||
chunk += ops.TJ(out) | ||
} | ||
@@ -426,5 +430,2 @@ await this._doc._write(chunk) | ||
function calcSpaceWidth(spacing, font, fontSize) { | ||
if (spacing === 0 || !font) { | ||
return 0 | ||
} | ||
const scaleFactor = 1000 / fontSize | ||
@@ -431,0 +432,0 @@ return -(spacing + font.stringWidth(' ', fontSize)) * scaleFactor |
{ | ||
"name": "pdfjs", | ||
"author": "Markus Ast <npm.m@rkusa.st>", | ||
"version": "2.0.0-alpha.4", | ||
"version": "2.0.0-alpha.5", | ||
"description": "A Portable Document Format (PDF) generation library targeting both the server- and client-side.", | ||
@@ -6,0 +6,0 @@ "keywords": [ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
256027
4305