Skip to content

Commit

Permalink
feat: support for verticalAlign "super" and "sub" (diegomura#2214)
Browse files Browse the repository at this point in the history
* implement support for verticalAlign: super/sub

* add tests for verticalAlignment

* add verticalAlign to types

* removed font scaling

* add snapshot test

* changeset

---------

Co-authored-by: Dmitry Ivakhnenko <[email protected]>
  • Loading branch information
KODIKAS-NL and jeetiss authored Mar 7, 2023
1 parent b194b61 commit 2db67a3
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .changeset/afraid-schools-carry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@react-pdf/textkit': minor
'@react-pdf/layout': minor
'@react-pdf/types': minor
---

added base support for verticalAlign "super" and "sub"
2 changes: 2 additions & 0 deletions packages/layout/src/text/getAttributedString.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const getFragments = (fontStore, instance, parentLink, level = 0) => {
letterSpacing,
textIndent,
opacity,
verticalAlign,
} = instance.style;

const opts = { fontFamily, fontWeight, fontStyle };
Expand Down Expand Up @@ -70,6 +71,7 @@ const getFragments = (fontStore, instance, parentLink, level = 0) => {
underlineColor: textDecorationColor || color,
link: parentLink || instance.props?.src || instance.props?.href,
lineHeight: lineHeight ? lineHeight * fontSize : null,
verticalAlign,
};

for (let i = 0; i < instance.children.length; i += 1) {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions packages/renderer/tests/text.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable react/jsx-one-expression-per-line */
/* eslint-disable react/no-array-index-key */
import renderToImage from './renderComponent';
import { Document, Page, View, Text, Link, Font, StyleSheet } from '..';
Expand Down Expand Up @@ -101,4 +102,20 @@ describe('text', () => {

expect(image).toMatchImageSnapshot();
});

test('should support verticalAlign super and sub', async () => {
const image = await renderToImage(
<Document>
<Page size={[90, 35]}>
<Text style={{ fontFamily: 'Oswald' }}>
Lorem
<Text style={{ verticalAlign: 'super', fontSize: 10 }}>ipsum</Text>
<Text style={{ verticalAlign: 'sub', fontSize: 10 }}>dolor</Text>
</Text>
</Page>
</Document>,
);

expect(image).toMatchImageSnapshot();
});
});
1 change: 1 addition & 0 deletions packages/textkit/src/layout/applyDefaultStyles.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const applyAttributes = a => ({
strikeColor: a.strikeColor || a.color || 'black',
strikeStyle: a.strikeStyle || 'solid',
stroke: a.stroke || false,
verticalAlign: a.verticalAlign || null,
wordSpacing: a.wordSpacing || 0,
yOffset: a.yOffset || 0,
});
Expand Down
2 changes: 2 additions & 0 deletions packages/textkit/src/layout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import splitParagraphs from './splitParagraphs';
import finalizeFragments from './finalizeFragments';
import resolveAttachments from './resolveAttachments';
import applyDefaultStyles from './applyDefaultStyles';
import verticalAlignment from './verticalAlign';

/**
* A LayoutEngine is the main object that performs text layout.
Expand All @@ -28,6 +29,7 @@ const layoutEngine = engines => (attributedString, container, options = {}) => {
resolveYOffset(engines, options),
resolveAttachments(engines, options),
generateGlyphs(engines, options),
verticalAlignment(options),
wrapWords(engines, options),
);

Expand Down
24 changes: 24 additions & 0 deletions packages/textkit/src/layout/verticalAlign.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* eslint-disable no-restricted-syntax */

/**
* Apply scaling and yOffset for verticalAlign 'sub' and 'super'.
*
* @param {Object} layout options
* @param {Object} attributed string
* @return {Object} attributed string
*/
const verticalAlignment = () => attributedString => {
attributedString.runs.forEach(run => {
const { attributes } = run;
const { verticalAlign } = attributes;

if (verticalAlign === 'sub') {
attributes.yOffset = -0.2;
} else if (verticalAlign === 'super') {
attributes.yOffset = 0.4;
}
});
return attributedString;
};

export default verticalAlignment;
2 changes: 2 additions & 0 deletions packages/textkit/tests/layout/applyDefaultStyles.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const DEFAULTS = {
strikeColor: 'black',
strikeStyle: 'solid',
stroke: false,
verticalAlign: null,
wordSpacing: 0,
yOffset: 0,
};
Expand Down Expand Up @@ -67,6 +68,7 @@ const OVERRIDES = {
strikeColor: 'red',
strikeStyle: 'dashed',
stroke: true,
verticalAlign: 'super',
wordSpacing: 5,
yOffset: 5,
};
Expand Down
56 changes: 56 additions & 0 deletions packages/textkit/tests/layout/verticalAlign.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import verticalAlignment from '../../src/layout/verticalAlign';

describe('verticalAlign', () => {
test('should apply vertical alignment "super" to string', () => {
const instance = verticalAlignment();
const text = {
string: 'Lorem',
runs: [
{
start: 0,
end: 5,
attributes: { fontSize: 12, color: 'red', verticalAlign: 'super' },
},
],
};

const result = instance(text);
// expect yOffset to be 0.4
expect(result.runs[0].attributes).toHaveProperty('yOffset', 0.4);
});
test('should apply vertical alignment "sub" to string', () => {
const instance = verticalAlignment();
const text = {
string: 'Lorem',
runs: [
{
start: 0,
end: 5,
attributes: { fontSize: 12, color: 'red', verticalAlign: 'sub' },
},
],
};

const result = instance(text);
// expect yOffset to be 0.4
expect(result.runs[0].attributes).toHaveProperty('yOffset', -0.2);
});

test('should ignore vertical alignment value if it is not "sub" or "super"', () => {
const instance = verticalAlignment();
const text = {
string: 'Lorem',
runs: [
{
start: 0,
end: 5,
attributes: { fontSize: 12, color: 'red', verticalAlign: 'center' },
},
],
};

const result = instance(text);
// expect yOffset property to be undefined
expect(result.runs[0].attributes).not.toHaveProperty('yOffset');
});
});
1 change: 1 addition & 0 deletions packages/types/style.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export interface Style {
textIndent?: any; // ?
textOverflow?: 'ellipsis';
textTransform?: 'capitalize' | 'lowercase' | 'uppercase';
verticalAlign?: 'sub' | 'super';

// Sizing/positioning

Expand Down

0 comments on commit 2db67a3

Please sign in to comment.