1

I'm trying to convert photoshop paths to SVG using PSD.js. Through PSD.js you can get mask data of a layer, and from that data you can get path data of a shape layer. This path data is in the form of Javascript array and conforms to the Photoshop file format specification https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_17587.This is all fine if I want to convert a simple shape with no holes. I get the path data, convert it into a SVG path string and render it. But Photoshop allows you to specify multiple paths to be a part of one shape and each path has certain operations that it uses to be drawn onto the shape. These are:

photoshop path operations

  • Unite - adds one path to another
  • Subtract - subtracts(makes a hole) a path from another path
  • Exclude - subtracts the overlapping area of two paths from one path and preserves
  • Intersect - only returns the overlapping area of two paths

This introduces holes that cannot be drawn using just svgs winding rules (svg winding rule can be non-zero or even-odd), because the direction of the path that makes the hole doesn't matter if the path operation is for example subtract. The path will create a hole regardless of the direction of the path (non-zero), which is not the case with svg (it will draw a hole only if the hole path is going in a different direction of the non-hole path). Same goes for an operation like Unite that will fill in an area regardless of the winding rule.

What I want is to extract the path operation type of a path and based on that construct a path that doesn't rely on the svg winding rules to draw holes.

The question is, is there a way to get the path operation for each individual path in a shape in PSD.js?

I tried drawing holes using SVG winding rules but holes are drawn in the same direction as the non-hole path and they are not treated as holes.

No holes even though path is drawn as a hole in Photoshop

  • psd.js doesn't seem to export the path operations as properties - you might post an issue report on github. In your case (according to your screenshot) applying `fill-rule="evenodd"` will do the trick. You can also reverse/fix path directions as described here ["auto colour fill when Generate Font from svg figma icon using icomoon"](https://stackoverflow.com/questions/72379177/auto-colour-fill-when-generate-font-from-svg-figma-icon-using-icomoon/72451714#72451714). – herrstrietzel Jul 20 '23 at 15:11
  • Uniting or subtracting paths could be done with [paper.js: "Merging two bezier-based shapes into one to create a new outline"](https://stackoverflow.com/questions/71077189/merging-two-bezier-based-shapes-into-one-to-create-a-new-outline/71082027#71082027). However I'm afraid there is no way to tell which path operation was initially applied from psd.js data. – herrstrietzel Jul 20 '23 at 15:15
  • @herrstrietzel Thanks for the reply. You're right, psd.js doesn't seem to support path operations but I couldn't find anything about path operations in the Photoshop specs either. But I think there's definitely a way to get this information from a psd file because online photo editor Photopea does support reading path operations from a psd. PS probably stores this data in a weird way. Once I get the paths with the path operations, as you said, Paper.js is the way to go for merging all of those paths. – Nikola Nesovic Jul 21 '23 at 07:18
  • Just an idea: I think the problem is in the `path_record.coffee` (in modules/psd/lib/psd/) script not including type 6 record. Unfortunately I wasn't able to read the fill rule record. – herrstrietzel Jul 21 '23 at 18:23

0 Answers0