Skip to content

Commit

Permalink
fix: text-shadow (#555)
Browse files Browse the repository at this point in the history
### Description
- Fix text-shadow.
- Refactor the **text** to improve readability. Since the refactoring
changes may be extensive, to prevent bugs caused by refactoring from
being hard to locate, it will be implemented in multiple PRs
step-by-step.
  • Loading branch information
LuciNyan committed Oct 6, 2023
1 parent bdd0dca commit 461b0ef
Show file tree
Hide file tree
Showing 12 changed files with 381 additions and 236 deletions.
9 changes: 8 additions & 1 deletion src/builder/shadow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,14 @@ const SCALE = 1.1

export function buildDropShadow(
{ id, width, height }: { id: string; width: number; height: number },
style: Record<string, any>
style: {
shadowColor: string[]
shadowOffset: {
width: number
height: number
}[]
shadowRadius: number[]
}
) {
if (
!style.shadowColor ||
Expand Down
51 changes: 40 additions & 11 deletions src/font.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,39 @@ import opentype from '@shuding/opentype.js'
import { Locale, locales, isValidLocale } from './language.js'

export type Weight = 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
type WeightName = 'normal' | 'bold'
export type Style = 'normal' | 'italic'
export type WeightName = 'normal' | 'bold'
export type FontWeight = Weight | WeightName
export type FontStyle = 'normal' | 'italic'
const SUFFIX_WHEN_LANG_NOT_SET = 'unknown'

export interface FontOptions {
data: Buffer | ArrayBuffer
name: string
weight?: Weight
style?: Style
style?: FontStyle
lang?: string
}

export type FontEngine = {
has: (s: string) => boolean
baseline: (s?: string, resolvedFont?: any) => number
height: (s?: string, resolvedFont?: any) => number
measure: (s: string, style: any) => number
getSVG: (s: string, style: any) => string
measure: (
s: string,
style: {
fontSize: number
letterSpacing: number
}
) => number
getSVG: (
s: string,
style: {
fontSize: number
top: number
left: number
letterSpacing: number
}
) => string
}

function compareFont(
Expand Down Expand Up @@ -74,7 +89,7 @@ function compareFont(

export default class FontLoader {
defaultFont: opentype.Font
fonts = new Map<string, [opentype.Font, Weight?, Style?][]>()
fonts = new Map<string, [opentype.Font, Weight?, FontStyle?][]>()
constructor(fontOptions: FontOptions[]) {
this.addFonts(fontOptions)
}
Expand All @@ -87,7 +102,7 @@ export default class FontLoader {
}: {
name: string
weight: Weight | WeightName
style: Style
style: FontStyle
}) {
if (!this.fonts.has(name)) {
return null
Expand Down Expand Up @@ -175,8 +190,8 @@ export default class FontLoader {
fontStyle = 'normal',
}: {
fontFamily?: string | string[]
fontWeight?: Weight | WeightName
fontStyle?: Style
fontWeight?: FontWeight
fontStyle?: FontStyle
},
locale: Locale | undefined
): FontEngine {
Expand Down Expand Up @@ -351,10 +366,24 @@ export default class FontLoader {
(lineHeight / 1.2)
)
},
measure: (s: string, style: any) => {
measure: (
s: string,
style: {
fontSize: number
letterSpacing: number
}
) => {
return this.measure(resolveFont, s, style)
},
getSVG: (s: string, style: any) => {
getSVG: (
s: string,
style: {
fontSize: number
top: number
left: number
letterSpacing: number
}
) => {
return this.getSVG(resolveFont, s, style)
},
}
Expand Down
66 changes: 54 additions & 12 deletions src/handler/expand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import parseTransformOrigin, {
} from '../transform-origin.js'
import { isString, lengthToNumber, v, splitEffects } from '../utils.js'
import { MaskProperty, parseMask } from '../parser/mask.js'
import { FontWeight, FontStyle } from '../font.js'

// https://react-cn.github.io/react/tips/style-props-value-px.html
const optOutPx = new Set([
Expand Down Expand Up @@ -172,21 +173,22 @@ function handleSpecialCase(
if (name === 'textShadow') {
// Handle multiple text shadows if provided.
value = value.toString().trim()
if (value.includes(',')) {
const shadows = splitEffects(value)
const result = {}
for (const shadow of shadows) {
const styles = getStylesForProperty('textShadow', shadow, true)
for (const k in styles) {
if (!result[k]) {
result[k] = [styles[k]]
} else {
result[k].push(styles[k])
}
const result = {}

const shadows = splitEffects(value)

for (const shadow of shadows) {
const styles = getStylesForProperty('textShadow', shadow, true)
for (const k in styles) {
if (!result[k]) {
result[k] = [styles[k]]
} else {
result[k].push(styles[k])
}
}
return result
}

return result
}

return
Expand Down Expand Up @@ -232,6 +234,11 @@ type MainStyle = {
wordBreak: string
textAlign: string
lineHeight: number
letterSpacing: number

fontFamily: string | string[]
fontWeight: FontWeight
fontStyle: FontStyle

borderTopWidth: number
borderLeftWidth: number
Expand All @@ -249,6 +256,13 @@ type MainStyle = {
gap: number
rowGap: number
columnGap: number

textShadowOffset: {
width: number
height: number
}[]
textShadowColor: string[]
textShadowRadius: number[]
}

type OtherStyle = Exclude<Record<PropertyKey, string | number>, keyof MainStyle>
Expand Down Expand Up @@ -391,6 +405,34 @@ export default function expand(
transform[type] = len
}
}

if (prop === 'textShadowRadius') {
const textShadowRadius = value as unknown as Array<number | string>

serializedStyle.textShadowRadius = textShadowRadius.map((_v) =>
lengthToNumber(_v, baseFontSize, 0, inheritedStyle, false)
)
}

if (prop === 'textShadowOffset') {
const textShadowOffset = value as unknown as Array<{
width: number | string
height: number | string
}>

serializedStyle.textShadowOffset = textShadowOffset.map(
({ height, width }) => ({
height: lengthToNumber(
height,
baseFontSize,
0,
inheritedStyle,
false
),
width: lengthToNumber(width, baseFontSize, 0, inheritedStyle, false),
})
)
}
}

return serializedStyle
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export type {
FontOptions as Font,
Weight as FontWeight,
Style as FontStyle,
FontStyle,
} from './font.js'
export type { Locale } from './language.js'

Expand Down
2 changes: 1 addition & 1 deletion src/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import { SVGNodeToImage } from './handler/preprocess.js'
import computeStyle from './handler/compute.js'
import FontLoader from './font.js'
import buildTextNodes from './text.js'
import buildTextNodes from './text/index.js'
import rect from './builder/rect.js'
import { Locale, normalizeLocale } from './language.js'
import { SerializedStyle } from './handler/expand.js'
Expand Down
File renamed without changes.
Loading

1 comment on commit 461b0ef

@vercel
Copy link

@vercel vercel bot commented on 461b0ef Oct 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.