Skip to content

Commit

Permalink
fix marker rendering (yWorks#184)
Browse files Browse the repository at this point in the history
 - fix bounding box calculation
 - fix attribute inheritance

fix yWorks#170
  • Loading branch information
HackbrettXXX authored Jul 20, 2021
1 parent 7467913 commit d1bc8a4
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 12 deletions.
114 changes: 114 additions & 0 deletions src/applyparseattributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,3 +308,117 @@ export function applyAttributes(
)
}
}

export function applyContext(context: Context): void {
const { attributeState, pdf } = context

let fillOpacity = 1.0,
strokeOpacity = 1.0

fillOpacity *= attributeState.fillOpacity
fillOpacity *= attributeState.opacity
if (
attributeState.fill instanceof ColorFill &&
typeof attributeState.fill.color.a !== 'undefined'
) {
fillOpacity *= attributeState.fill.color.a
}

strokeOpacity *= attributeState.strokeOpacity
strokeOpacity *= attributeState.opacity
if (
attributeState.stroke instanceof ColorFill &&
typeof attributeState.stroke.color.a !== 'undefined'
) {
strokeOpacity *= attributeState.stroke.color.a
}

const gState: GState = {}
gState['opacity'] = fillOpacity
gState['stroke-opacity'] = strokeOpacity
pdf.setGState(new GState(gState))

if (
attributeState.fill &&
attributeState.fill instanceof ColorFill &&
attributeState.fill.color.ok
) {
// text fill color will be applied through setTextColor()
pdf.setFillColor(
attributeState.fill.color.r,
attributeState.fill.color.g,
attributeState.fill.color.b
)
} else {
pdf.setFillColor(0, 0, 0)
}

pdf.setLineWidth(attributeState.strokeWidth)

if (attributeState.stroke instanceof ColorFill) {
pdf.setDrawColor(
attributeState.stroke.color.r,
attributeState.stroke.color.g,
attributeState.stroke.color.b
)
} else {
pdf.setDrawColor(0, 0, 0)
}

pdf.setLineCap(attributeState.strokeLinecap)
pdf.setLineJoin(attributeState.strokeLinejoin)

if (attributeState.strokeDasharray) {
pdf.setLineDashPattern(attributeState.strokeDasharray, attributeState.strokeDashoffset)
} else {
pdf.setLineDashPattern([], 0)
}

pdf.setLineMiterLimit(attributeState.strokeMiterlimit)

let font: string | undefined
if (fontAliases.hasOwnProperty(attributeState.fontFamily)) {
font = fontAliases[attributeState.fontFamily]
} else {
font = attributeState.fontFamily
}

if (
attributeState.fill &&
attributeState.fill instanceof ColorFill &&
attributeState.fill.color.ok
) {
const fillColor = attributeState.fill.color
pdf.setTextColor(fillColor.r, fillColor.g, fillColor.b)
} else {
pdf.setTextColor(0, 0, 0)
}

let fontStyle: string | undefined = ''
if (attributeState.fontWeight === 'bold') {
fontStyle = 'bold'
}
if (attributeState.fontStyle === 'italic') {
fontStyle += 'italic'
}

if (fontStyle === '') {
fontStyle = 'normal'
}

if (font !== undefined || fontStyle !== undefined) {
if (font === undefined) {
if (fontAliases.hasOwnProperty(attributeState.fontFamily)) {
font = fontAliases[attributeState.fontFamily]
} else {
font = attributeState.fontFamily
}
}
pdf.setFont(font, fontStyle)
} else {
pdf.setFont('helvetica', fontStyle)
}

// correct for a jsPDF-instance measurement unit that differs from `pt`
pdf.setFontSize(attributeState.fontSize * pdf.internal.scaleFactor)
}
1 change: 0 additions & 1 deletion src/markerlist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ export class MarkerList {

// as the marker is already scaled by the current line width we must not apply the line width twice!
context.pdf.saveGraphicsState()
context.pdf.setLineWidth(1.0)
await context.refsHandler.getRendered(marker.id, null, node =>
(node as MarkerNode).apply(context)
)
Expand Down
29 changes: 19 additions & 10 deletions src/nodes/marker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { NonRenderedNode } from './nonrenderednode'
import { svgNodeAndChildrenVisible } from '../utils/node'
import { Rect } from '../utils/geometry'
import { Matrix } from 'jspdf'
import { applyContext } from '../applyparseattributes'

export class MarkerNode extends NonRenderedNode {
async apply(parentContext: Context): Promise<void> {
Expand All @@ -13,15 +14,23 @@ export class MarkerNode extends NonRenderedNode {
const bBox = this.getBoundingBox(parentContext)

parentContext.pdf.beginFormObject(bBox[0], bBox[1], bBox[2], bBox[3], tfMatrix)

const childContext = new Context(parentContext.pdf, {
refsHandler: parentContext.refsHandler,
styleSheets: parentContext.styleSheets,
viewport: parentContext.viewport,
svg2pdfParameters: parentContext.svg2pdfParameters
})

// "Properties do not inherit from the element referencing the 'marker' into the contents of the
// marker. However, by using the context-stroke value for the fill or stroke on elements in its
// definition, a single marker can be designed to match the style of the element referencing the
// marker."
// -> we need to reset all attributes
applyContext(childContext)

for (const child of this.children) {
await child.render(
new Context(parentContext.pdf, {
refsHandler: parentContext.refsHandler,
styleSheets: parentContext.styleSheets,
viewport: parentContext.viewport,
svg2pdfParameters: parentContext.svg2pdfParameters
})
)
await child.render(childContext)
}
parentContext.pdf.endFormObject(this.element.getAttribute('id'))
}
Expand All @@ -36,8 +45,8 @@ export class MarkerNode extends NonRenderedNode {
return [
(vb && vb[0]) || 0,
(vb && vb[1]) || 0,
(vb && vb[2]) || parseFloat(this.element.getAttribute('marker-width') || '0'),
(vb && vb[3]) || parseFloat(this.element.getAttribute('marker-height') || '0')
(vb && vb[2]) || parseFloat(this.element.getAttribute('markerWidth') || '3'),
(vb && vb[3]) || parseFloat(this.element.getAttribute('markerHeight') || '3')
]
}

Expand Down
Binary file modified test/specs/complete-social-network/reference.pdf
Binary file not shown.
Binary file modified test/specs/markers/reference.pdf
Binary file not shown.
8 changes: 7 additions & 1 deletion test/specs/markers/spec.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit d1bc8a4

Please sign in to comment.