Skip to content

Commit

Permalink
additional options for drawing text
Browse files Browse the repository at this point in the history
Provide textRenderingMode, horizontalScaling, textRise, charcterSpacing and wordSpacing as an option for drawing text.
In operator.ts and PDFOperatorNames.ts those operators were already implementes. The function for the horizontalScaling (as it is called in the pdf standard) was called "setCharacterSqueeze" so far. To keep the standardized terminology, the function was renamed to "setHorizontalSpacing". However, for backward compatibility (if somebody had used setCharacterSqueeze in his own script; in the actual pdf-lib code there was no reference) the original function was kept as well with a deprecated note.
In the textOptions, not the standard names were used, but noun forms of it, to match the current options style (e.g. horizontalScale (options) instead of horizontalScaling (pdf standard)).
  • Loading branch information
retfah committed Apr 12, 2022
1 parent 93dd36e commit 39386a8
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 6 deletions.
8 changes: 4 additions & 4 deletions apps/node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { sep } from 'path';
import readline from 'readline';

import test1 from './tests/test1';
import test2 from './tests/test2';
/*import test2 from './tests/test2';
import test3 from './tests/test3';
import test4 from './tests/test4';
import test5 from './tests/test5';
Expand All @@ -21,7 +21,7 @@ import test14 from './tests/test14';
import test15 from './tests/test15';
import test16 from './tests/test16';
import test17 from './tests/test17';
import test18 from './tests/test18';
import test18 from './tests/test18';*/

const cli = readline.createInterface({
input: process.stdin,
Expand Down Expand Up @@ -162,8 +162,8 @@ const main = async () => {

// prettier-ignore
const allTests = [
test1, test2, test3, test4, test5, test6, test7, test8, test9, test10,
test11, test12, test13, test14, test15, test16, test17, test18,
test1//, test2, test3, test4, test5, test6, test7, test8, test9, test10,
//test11, test12, test13, test14, test15, test16, test17, test18,
];

const tests = testIdx ? [allTests[testIdx - 1]] : allTests;
Expand Down
64 changes: 64 additions & 0 deletions apps/node/tests/test1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
StandardFonts,
typedArrayFor,
AFRelationship,
TextRenderingMode,
} from '../../..';

const ipsumLines = [
Expand Down Expand Up @@ -644,6 +645,69 @@ export default async (assets: Assets) => {

form.removeField(textField);

// This page tests different drawing operations as well as adding custom
// operators to the page content.

const page6 = pdfDoc.addPage([size, size]);

// Upper-left Quadrant
page6.moveTo(0, size / 2);

const text = "These are the test words. "
page6.drawText(text + 'regular', {
y: size - 20,
size: 20,
lineHeight: 20,
//horizontalScale: 50,
//rise: 0,
//wordSpace: 10,
//characterSpace: -2,
});
page6.drawText(text + '+5 raised and fontsize 12 instead of 20', {
y: size - 20,
x: 325,
size: 12,
lineHeight: 20,
//horizontalScale: 50,
rise: 5,
//wordSpace: 10,
//characterSpace: -2,
});
page6.drawText(text + '50% horizontal scale', {
y: size - 40,
size: 20,
lineHeight: 20,
horizontalScale: 50,
//rise: 0,
//wordSpace: 10,
//characterSpace: -2,
});
page6.drawText(text + '+10 word space', {
y: size - 60,
size: 20,
lineHeight: 20,
//horizontalScale: 50,
//rise: 0,
wordSpace: 10,
//characterSpace: -2,
renderingMode: TextRenderingMode.Outline,
});
page6.drawText(text + '+4 character space', {
y: size - 80,
size: 20,
lineHeight: 20,
//horizontalScale: 50,
//rise: 0,
//wordSpace: 10,
characterSpace: 4,
});
page6.drawText(text + 'textRenderingMode = outline', {
y: size - 100,
size: 20,
lineHeight: 20,
renderingMode: TextRenderingMode.Outline,
});

/********************** Print Metadata **********************/

console.log('Title:', pdfDoc.getTitle());
Expand Down
12 changes: 12 additions & 0 deletions src/api/PDFPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
translate,
LineCapStyle,
scale,
TextRenderingMode,
} from 'src/api/operators';
import PDFDocument from 'src/api/PDFDocument';
import PDFEmbeddedPage from 'src/api/PDFEmbeddedPage';
Expand Down Expand Up @@ -976,6 +977,11 @@ export default class PDFPage {
assertOrUndefined(options.lineHeight, 'options.lineHeight', ['number']);
assertOrUndefined(options.maxWidth, 'options.maxWidth', ['number']);
assertOrUndefined(options.wordBreaks, 'options.wordBreaks', [Array]);
assertOrUndefined(options.horizontalScale, 'options.horizontalScale', ['number']);
assertOrUndefined(options.wordSpace, 'options.wordSpace', ['number']);
assertOrUndefined(options.characterSpace, 'options.characterSpace', ['number']);
assertOrUndefined(options.rise, 'options.rise', ['number']);
assertIsOneOfOrUndefined(options.renderingMode, 'options.renderingMode', TextRenderingMode);
assertIsOneOfOrUndefined(options.blendMode, 'options.blendMode', BlendMode);

const { oldFont, newFont, newFontKey } = this.setOrEmbedFont(options.font);
Expand Down Expand Up @@ -1010,7 +1016,13 @@ export default class PDFPage {
x: options.x ?? this.x,
y: options.y ?? this.y,
lineHeight: options.lineHeight ?? this.lineHeight,
// optional:
graphicsState: graphicsStateKey,
horizontalScale: options.horizontalScale, // defaults to 100
wordSpace: options.wordSpace, // defaults to 0
characterSpace: options.characterSpace, // defaults to 0
rise: options.rise, // defaults to 0
renderingMode: options.renderingMode, // defaults to TextRenderingMode.Fill
}),
);

Expand Down
7 changes: 6 additions & 1 deletion src/api/PDFPageOptions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Color } from 'src/api/colors';
import PDFFont from 'src/api/PDFFont';
import { Rotation } from 'src/api/rotations';
import { LineCapStyle } from 'src/api/operators';
import { LineCapStyle,TextRenderingMode } from 'src/api/operators';

export enum BlendMode {
Normal = 'Normal',
Expand Down Expand Up @@ -32,6 +32,11 @@ export interface PDFPageDrawTextOptions {
lineHeight?: number;
maxWidth?: number;
wordBreaks?: string[];
horizontalScale?: number;
wordSpace?: number;
characterSpace?: number;
rise?: number;
renderingMode?: TextRenderingMode;
}

export interface PDFPageDrawImageOptions {
Expand Down
21 changes: 21 additions & 0 deletions src/api/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ import {
clip,
endPath,
appendBezierCurve,
TextRenderingMode,
setCharacterSpacing,
setHorizontalScaling,
setTextRenderingMode,
setTextRise,
setWordSpacing,
} from 'src/api/operators';
import { Rotation, degrees, toRadians } from 'src/api/rotations';
import { svgPathToOperators } from 'src/api/svgPath';
Expand All @@ -47,6 +53,11 @@ export interface DrawTextOptions {
x: number | PDFNumber;
y: number | PDFNumber;
graphicsState?: string | PDFName;
horizontalScale?: number | PDFNumber;
wordSpace?: number | PDFNumber;
characterSpace?: number | PDFNumber;
rise?: number | PDFNumber;
renderingMode?: TextRenderingMode;
}

export const drawText = (
Expand All @@ -66,6 +77,11 @@ export const drawText = (
options.x,
options.y,
),
options.horizontalScale && setHorizontalScaling(options.horizontalScale),
options.wordSpace && setWordSpacing(options.wordSpace),
options.characterSpace && setCharacterSpacing(options.characterSpace),
options.rise && setTextRise(options.rise),
options.renderingMode && setTextRenderingMode(options.renderingMode),
showText(line),
endText(),
popGraphicsState(),
Expand All @@ -86,6 +102,11 @@ export const drawLinesOfText = (
setFillingColor(options.color),
setFontAndSize(options.font, options.size),
setLineHeight(options.lineHeight),
options.horizontalScale && setHorizontalScaling(options.horizontalScale),
options.wordSpace && setWordSpacing(options.wordSpace),
options.characterSpace && setCharacterSpacing(options.characterSpace),
options.rise && setTextRise(options.rise),
options.renderingMode && setTextRenderingMode(options.renderingMode),
rotateAndSkewTextRadiansAndTranslate(
toRadians(options.rotate),
toRadians(options.xSkew),
Expand Down
10 changes: 9 additions & 1 deletion src/api/operators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,16 +213,24 @@ export const setFontAndSize = (
size: number | PDFNumber,
) => PDFOperator.of(Ops.SetFontAndSize, [asPDFName(name), asPDFNumber(size)]);

/** @param characterSpace extra space between characters; in unscaled text sapce units; can also be negative **/
export const setCharacterSpacing = (spacing: number | PDFNumber) =>
PDFOperator.of(Ops.SetCharacterSpacing, [asPDFNumber(spacing)]);

/**@param wordSpace space "between words" (actually extra space for every ASCII SPACE character); in unscaled text sapce units; can also be negative; NOTE: This only works for fonts that define code 32 (=space) as a single-byte code, according to the standard. (E.g. it works with Helvetica, but not with ubuntuFont.) **/
export const setWordSpacing = (spacing: number | PDFNumber) =>
PDFOperator.of(Ops.SetWordSpacing, [asPDFNumber(spacing)]);

/** @param squeeze horizontal character spacing */
/**
* DEPRECATED: use "setHorizontalScaling" instead
* @param squeeze horizontal character spacing */
export const setCharacterSqueeze = (squeeze: number | PDFNumber) =>
PDFOperator.of(Ops.SetTextHorizontalScaling, [asPDFNumber(squeeze)]);

/** @param horizontalScaling horizontal character spacing; value in %; default = 100 **/
export const setHorizontalScaling = (horizontalScaling: number | PDFNumber) =>
PDFOperator.of(Ops.SetTextHorizontalScaling, [asPDFNumber(horizontalScaling)]);

export const setLineHeight = (lineHeight: number | PDFNumber) =>
PDFOperator.of(Ops.SetTextLineHeight, [asPDFNumber(lineHeight)]);

Expand Down

0 comments on commit 39386a8

Please sign in to comment.