1
0
Fork 0

🚧 Progress on workbench

This commit is contained in:
Joost De Cock 2019-05-06 17:01:44 +02:00
parent 158c19ae1d
commit a888922968
31 changed files with 716 additions and 153 deletions

View file

@ -38,6 +38,7 @@ plugin-svgattr: "A FreeSewing plugin to set SVG attributes"
plugin-theme: "A FreeSewing plugin that provides a default theme" plugin-theme: "A FreeSewing plugin that provides a default theme"
plugin-title: "A FreeSewing plugin to add a title to your pattern parts" plugin-title: "A FreeSewing plugin to add a title to your pattern parts"
plugin-validate: "A FreeSewing plugin that validates aspects of your code" plugin-validate: "A FreeSewing plugin that validates aspects of your code"
rendertest: "A freesewing pattern to test (y)our render engine our CSS"
shin: "A FreeSewing pattern for swim trunks" shin: "A FreeSewing pattern for swim trunks"
simon: "A FreeSewing pattern for a button down shirt" simon: "A FreeSewing pattern for a button down shirt"
sven: "A FreeSewing pattern for a straightforward sweater" sven: "A FreeSewing pattern for a straightforward sweater"

View file

@ -1,17 +1,14 @@
import React, { useState } from "react"; import React, { useState } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
const Circle = props => { const Circle = props => (
return null; <circle
let foo = ( cx={props.point.x}
<circle cy={props.point.y}
cx={props.point.x} r={props.point.attributes.get("data-circle")}
cy={props.point.y} {...props.point.attributes.asPropsIfPrefixIs("data-circle-")}
r={props.point.attributes.get("data-circle")} />
{...props.point.attributes.asPropsIfPrefixIs("data-circle-")} );
/>
);
};
Circle.propTypes = { Circle.propTypes = {
point: PropTypes.object.isRequired point: PropTypes.object.isRequired

View file

@ -0,0 +1,84 @@
import React from "react";
const Grid = props => {
let style = {
style: {
fill: "none",
stroke: "currentColor"
}
};
if (props.units === "imperial")
return (
<pattern
id="grid"
height="25.4"
width="25.4"
patternUnits="userSpaceOnUse"
key="grid"
>
<path
className="gridline lg imperial"
d="M 0 0 L 0 25.4 L 25.4 25.4"
{...style}
/>
<path
className="gridline lg imperial"
d="M 12.7 0 L 12.7 25.4 M 0 12.7 L 25.4 12.7"
{...style}
/>
<path
className="gridline sm imperial"
d="M 3.175 0 L 3.175 25.4 M 6.32 0 L 6.35 25.4 M 9.525 0 L 9.525 25.4 M 15.875 0 L 15.875 25.4 M 19.05 0 L 19.05 25.4 M 22.225 0 L 22.225 25.4"
{...style}
/>
<path
className="gridline sm imperial"
d="M 0 3.175 L 25.4 3.175 M 0 6.32 L 25.4 6.35 M 0 9.525 L 25.4 9.525 M 0 15.875 L 25.4 15.875 M 0 19.05 L 25.4 19.05 M 0 22.225 L 25.4 22.225"
{...style}
/>
</pattern>
);
else
return (
<pattern
id="grid"
height="100"
width="100"
patternUnits="userSpaceOnUse"
key="grid"
>
<path
className="gridline lg metric"
d="M 0 0 L 0 100 L 100 100"
{...style}
/>
<path
className="gridline metric"
d="M 50 0 L 50 100 M 0 50 L 100 50"
{...style}
/>
<path
className="gridline sm metric"
d="M 10 0 L 10 100 M 20 0 L 20 100 M 30 0 L 30 100 M 40 0 L 40 100 M 60 0 L 60 100 M 70 0 L 70 100 M 80 0 L 80 100 M 90 0 L 90 100"
{...style}
/>
<path
className="gridline sm metric"
d="M 0 10 L 100 10 M 0 20 L 100 20 M 0 30 L 100 30 M 0 40 L 100 40 M 0 60 L 100 60 M 0 70 L 100 70 M 0 80 L 100 80 M 0 90 L 100 90"
{...style}
/>
<path
className="gridline xs metric"
d="M 5 0 L 5 100 M 15 0 L 15 100 M 25 0 L 25 100 M 35 0 L 35 100 M 45 0 L 45 100 M 55 0 L 55 100 M 65 0 L 65 100 M 75 0 L 75 100 M 85 0 L 85 100 M 95 0 L 95 100"
{...style}
/>
<path
className="gridline xs metric"
d="M 0 5 L 100 5 M 0 15 L 100 15 M 0 25 L 100 25 M 0 35 L 100 35 M 0 45 L 100 45 M 0 55 L 100 55 M 0 65 L 100 65 M 0 75 L 100 75 M 0 85 L 100 85 M 0 95 L 100 95"
{...style}
/>
</pattern>
);
};
export default Grid;

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,34 @@
import React from "react";
const Markers = props => {
const markerProps = {
orient: "auto",
refX: "0.0",
refY: "0.0",
style: { overflow: "visible" }
};
const from = { d: "M 0,0 L 12,-4 C 10,-2 10,2 12, 4 z" };
const to = { d: "M 0,0 L -12,-4 C -10,-2 -10,2 -12, 4 z" };
const types = {
grainline: "note",
cutonfold: "note",
dimension: "mark"
};
let output = [];
for (let type in types) {
output.push(
<marker id={type + "From"} key={type + "-from"} {...markerProps}>
<path className={types[type] + " fill-" + types[type]} {...from} />
</marker>
);
output.push(
<marker id={type + "To"} key={type + "-to"} {...markerProps}>
<path className={types[type] + " fill-" + types[type]} {...to} />
</marker>
);
}
return output;
};
export default Markers;

View file

@ -0,0 +1,41 @@
import React from "react";
import logoPathString from "./logo-path";
const Snippets = props => {
const fill = { fill: "currentColor", stroke: "none" };
const stroke = { fill: "none", stroke: "currentColor" };
return [
<g id="notch" className="snippet notch" key="notch">
<circle cy="0" cx="0" r="1.4" {...fill} />
<circle cy="0" cx="0" r="2.8" {...stroke} />
</g>,
<g id="bnotch" className="snippet bnotch" key="bnotch">
<path d="M -1.1 -1.1 L 1.1 1.1 M 1.1 -1.1 L -1.1 1.1" {...stroke} />
<circle cy="0" cx="0" r="2.8" {...stroke} />
</g>,
<g id="button" className="snippet button" key="button">
<circle cx="0" cy="0" r="3.4" {...stroke} /> />
<circle cx="-1" cy="-1" r="0.5" {...fill} />
<circle cx="1" cy="-1" r="0.5" {...fill} />
<circle cx="1" cy="1" r="0.5" {...fill} />
<circle cx="-1" cy="1" r="0.5" {...fill} />
</g>,
<g id="buttonhole" className="snippet buttonhole" key="buttonhole">
<path d="M -1,-5 L 1,-5 L 1,5 L -1,5 z" {...stroke} />
<path
d="M -1,-5 L 1,-5 L 1,-4 L -1,-4 z M -1,5 L 1,5 L 1,4 L -1,4 z"
{...fill}
/>
</g>,
<g
id="logo"
className="snippet logo"
transform="translate(-23 -36)"
key="logo"
>
<path d={logoPathString} {...fill} />
</g>
];
};
export default Snippets;

File diff suppressed because one or more lines are too long

View file

@ -1,9 +1,37 @@
import React, { useState } from "react"; import React from "react";
import PropTypes from "prop-types"; import Markers from "./Markers";
import Snippets from "./Snippets";
import Grid from "./Grid";
const Defs = props => <defs>{props.defs}</defs>; const Defs = props => {
let paperlessGrids = null;
Defs.propTypes = { defs: PropTypes.string }; if (props.paperless) {
Defs.defaultProps = { defs: "" }; paperlessGrids = [];
for (let p in props.parts) {
let anchor = { x: 0, y: 0 };
if (typeof props.parts[p].points.gridAnchor !== "undefined")
anchor = props.parts[p].points.gridAnchor;
else if (typeof props.parts[p].points.anchor !== "undefined")
anchor = props.parts[p].points.anchor;
paperlessGrids.push(
<pattern
id={"grid-" + p}
key={"grid-" + p}
xlinkHref="#grid"
x={anchor.x}
y={anchor.y}
/>
);
}
}
return (
<defs>
<Markers />
<Snippets />
<Grid units={props.units} />
{paperlessGrids}
</defs>
);
};
export default Defs; export default Defs;

View file

@ -2,21 +2,45 @@ import React, { useState } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import Path from "../Path"; import Path from "../Path";
import Point from "../Point"; import Point from "../Point";
import Snippet from "../Snippet";
import { getProps } from "../utils"; import { getProps } from "../utils";
const Part = props => { const Part = props => {
console.log(props.part);
let grid = props.paperless ? (
<rect
x={props.part.topLeft.x}
y={props.part.topLeft.y}
width={props.part.width}
height={props.part.height}
className="grid"
fill={"url(#grid-" + props.name + ")"}
/>
) : null;
return ( return (
<g {...getProps(props.part)}> <g {...getProps(props.part)}>
{grid}
{Object.keys(props.part.points).map(name => ( {Object.keys(props.part.points).map(name => (
<Point <Point
key={name} key={name}
name={name} name={name}
part={props.name}
language={props.language} language={props.language}
point={props.part.points[name]} point={props.part.points[name]}
/> />
))} ))}
{Object.keys(props.part.paths).map(name => ( {Object.keys(props.part.paths).map(name => (
<Path key={name} name={name} path={props.part.paths[name]} /> <Path
key={name}
name={name}
part={props.name}
language={props.language}
path={props.part.paths[name]}
/>
))}
{Object.keys(props.part.snippets).map(name => (
<Snippet key={name} name={name} snippet={props.part.snippets[name]} />
))} ))}
</g> </g>
); );
@ -25,7 +49,9 @@ const Part = props => {
Part.propTypes = { Part.propTypes = {
part: PropTypes.object.isRequired, part: PropTypes.object.isRequired,
name: PropTypes.string.isRequired, name: PropTypes.string.isRequired,
language: PropTypes.string.isRequired language: PropTypes.string.isRequired,
paperless: PropTypes.bool.isRequired,
units: PropTypes.oneOf(["metric", "imperial"]).isRequired
}; };
export default Part; export default Part;

View file

@ -1,14 +1,36 @@
import React, { useState } from "react"; import React, { useState } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import TextOnPath from "../TextOnPath";
import { getProps } from "../utils"; import { getProps } from "../utils";
const Path = props => { const Path = props => {
if (!props.path.render) return null; if (!props.path.render) return null;
return <path d={props.path.asPathstring()} {...getProps(props.path)} />; const output = [];
const pathId = "path-" + props.part + "-" + props.name;
output.push(
<path
id={pathId}
key={"path-" + props.name}
d={props.path.asPathstring()}
{...getProps(props.path)}
/>
);
if (props.path.attributes.get("data-text"))
output.push(
<TextOnPath
key={"text-on-path-" + props.name}
pathId={pathId}
{...props}
/>
);
return output;
}; };
Path.propTypes = { Path.propTypes = {
path: PropTypes.object.isRequired path: PropTypes.object.isRequired,
name: PropTypes.string.isRequired,
language: PropTypes.string.isRequired
}; };
export default Path; export default Path;

View file

@ -0,0 +1,39 @@
import React, { useState } from "react";
import PropTypes from "prop-types";
import Text from "../Text";
import Circle from "../Circle";
const Snippet = props => {
const snippetProps = {
xlinkHref: "#" + props.snippet.def,
x: props.snippet.anchor.x,
y: props.snippet.anchor.y
};
let scale = props.snippet.attributes.get("data-scale");
let rotate = props.snippet.attributes.get("data-rotate");
if (scale || rotate) {
snippetProps.transform = "";
if (scale) {
snippetProps.transform += `translate(${snippetProps.x}, ${
snippetProps.y
}) `;
snippetProps.transform += `scale(${scale}) `;
snippetProps.transform += `translate(${snippetProps.x *
-1}, ${snippetProps.y * -1}) `;
}
if (rotate) {
snippetProps.transform += `rotate(${rotate}, ${snippetProps.x}, ${
snippetProps.y
}) `;
}
}
return <use {...snippetProps} />;
};
Snippet.propTypes = {
snippet: PropTypes.object.isRequired,
name: PropTypes.string.isRequired
};
export default Snippet;

View file

@ -30,7 +30,6 @@ const Text = props => {
); );
} }
} else text.push(<tspan key="tspan-1">{translated}</tspan>); } else text.push(<tspan key="tspan-1">{translated}</tspan>);
return null;
return ( return (
<text <text
x={props.point.x} x={props.point.x}
@ -43,7 +42,8 @@ const Text = props => {
}; };
Text.propTypes = { Text.propTypes = {
point: PropTypes.object.isRequired point: PropTypes.object.isRequired,
language: PropTypes.string.isRequired
}; };
export default Text; export default Text;

View file

@ -0,0 +1,40 @@
import React, { useState } from "react";
import PropTypes from "prop-types";
import { strings } from "@freesewing/i18n";
const TextOnPath = props => {
let text = [];
// Handle translation
let translated = "";
for (let string of props.path.attributes.getAsArray("data-text")) {
if (strings[props.language]["plugin." + string])
translated += strings[props.language]["plugin." + string];
else translated += string;
translated += " ";
}
let textPathProps = {
xlinkHref: "#" + props.pathId,
startOffset: "0%"
};
let align = props.path.attributes.get("data-text-class");
if (align && align.indexOf("center") > -1) textPathProps.startOffset = "50%";
else if (align && align.indexOf("right") > -1)
textPathProps.startOffset = "100%";
return (
<text>
<textPath {...textPathProps}>
<tspan {...props.path.attributes.asPropsIfPrefixIs("data-text-")}>
{translated}
</tspan>
</textPath>
</text>
);
};
TextOnPath.propTypes = {
path: PropTypes.object.isRequired,
language: PropTypes.string.isRequired
};
export default TextOnPath;

View file

@ -1,93 +0,0 @@
svg.freesewing {
/* Reset */
path,circle,rect{fill:none;stroke:none}
/* Defaults */
path,circle{
stroke:#000;
stroke-opacity:1;
stroke-width:.3;
stroke-linecap:round;
stroke-linejoin:round;
}
/* Stroke classes */
.fabric{
stroke-width:.6;
stroke:#212121
}
.lining{
stroke-width:.6;
stroke:#ff5b77;
}
.interfacing{
stroke-width:.6;
stroke:#64b5f6;
}
.canvas{
stroke-width:.6;
stroke:#ff9000;
}
.various{
stroke-width:.6;
stroke:#4caf50;
}
.note{
stroke-width:.4;
stroke:#dd60dd;
}
.mark{
stroke-width:.4;
stroke:blue;
}
.contrast{
stroke-width:.8;
stroke:red;
}
.stroke-xs{ stroke-width:.1; }
.stroke-sm{ stroke-width:.2; }
.stroke-lg{ stroke-width:.6; }
.stroke-xl{ stroke-width:1; }
.stroke-xxl{ stroke-width:2; }
.sa { stroke-dasharray:0.4,0.8; }
.help {
stroke-width:.2;
stroke-dasharray:15,1.5,1,1.5;
}
.dotted { stroke-dasharray:0.4,0.8; }
.dashed { stroke-dasharray:1,1.5; }
.lashed { stroke-dasharray:6,6; }
.hidden {
stroke:none;
fill:none;
}
/* Fill classes */
.fill-fabric{ fill:#212121; }
.fill-lining{ fill:#ff5b77; }
.fill-interfacing{ fill:#64b5f6; }
.fill-canvas{ fill:#ff9000; }
.fill-various{ fill:#4caf50; }
.fill-note{ fill:#dd69dd; }
.fill-mark{ fill:blue; }
.fill-contrast{ fill:red; }
/* Text */
text{
font-size:5px;
font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
fill:#000;
text-anchor:start;
font-weight:200;
dominant-baseline:ideographic;
}
.text-xs { font-size:3px; }
.text-sm { font-size:4px; }
.text-lg { font-size:7px; }
.text-xl { font-size:9px; }
.text-xxl{ font-size:12px; }
.center{ text-anchor:middle; }
.right{ text-anchor:end; }
}

View file

@ -1,8 +1,7 @@
import React, { useState } from "react"; import React, { useState } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import Svg from "./Svg"; import Svg from "./Svg";
//import Style from "./Style"; import Defs from "./Defs";
//import Defs from "./Defs";
import Part from "./Part"; import Part from "./Part";
const Draft = props => { const Draft = props => {
@ -14,11 +13,18 @@ const Draft = props => {
language={props.settings.locale} language={props.settings.locale}
id={props.settings.idPrefix + "svg"} id={props.settings.idPrefix + "svg"}
> >
<Defs
units={props.settings.units}
parts={props.parts}
paperless={props.settings.paperless}
/>
<g> <g>
{Object.keys(props.parts).map(name => ( {Object.keys(props.parts).map(name => (
<Part <Part
part={props.parts[name]} part={props.parts[name]}
language={props.settings.locale} language={props.settings.locale}
paperless={props.settings.paperless}
units={props.settings.units}
key={name} key={name}
name={name} name={name}
/> />

View file

@ -51,7 +51,7 @@ const OptionGroup = props => {
return <Count {...option} {...extraProps} />; return <Count {...option} {...extraProps} />;
break; break;
default: default:
throw new Error("Unsupport option type: " + type); throw new Error("Unsupported option type: " + type);
} }
}; };

View file

@ -64,7 +64,7 @@ const Footer = props => {
); );
} }
return ( return (
<div> <div key={l}>
<h4> <h4>
<FormattedMessage id={"app." + l} /> <FormattedMessage id={"app." + l} />
</h4> </h4>

View file

@ -58,6 +58,7 @@ const Workbench = props => {
}; };
const measurementsMissing = () => { const measurementsMissing = () => {
let required = props.config.measurements; let required = props.config.measurements;
if (required.length < 1) return false;
if (measurements === null) return true; if (measurements === null) return true;
for (let m of required) { for (let m of required) {
if (typeof measurements[m] === "undefined") return true; if (typeof measurements[m] === "undefined") return true;

View file

@ -595,7 +595,7 @@ Pattern.prototype.getRenderProps = function() {
props.parts[p] = { props.parts[p] = {
paths: this.parts[p].paths, paths: this.parts[p].paths,
points: this.parts[p].points, points: this.parts[p].points,
snippets: this.parts[p].points, snippets: this.parts[p].snippets,
attributes: this.parts[p].attributes, attributes: this.parts[p].attributes,
height: this.parts[p].height, height: this.parts[p].height,
width: this.parts[p].width, width: this.parts[p].width,

View file

@ -11,14 +11,14 @@ $fc-accentbg-dark: $oc-teal-8;
$fc-link-light: $oc-blue-6; $fc-link-light: $oc-blue-6;
$fc-link-dark: $oc-blue-3; $fc-link-dark: $oc-blue-3;
$fc-draft-lining-light: $oc-teal-6;
$fc-draft-fabric-light: $oc-gray-9; $fc-draft-fabric-light: $oc-gray-9;
$fc-draft-lining-light: $oc-lime-7;
$fc-draft-interfacing-light: $oc-red-7;
$fc-draft-canvas-light: $oc-yellow-7; $fc-draft-canvas-light: $oc-yellow-7;
$fc-draft-interfacing-light: $oc-gray-6; $fc-draft-various-light: $oc-grape-7;
$fc-draft-various-light: $oc-pink-5; $fc-draft-mark-light: $oc-blue-4;
$fc-draft-mark-light: $oc-indigo-6;
$fc-draft-contrast-light: $oc-orange-7; $fc-draft-contrast-light: $oc-orange-7;
$fc-draft-note-light: $oc-blue-7; $fc-draft-note-light: $oc-pink-7;
$fc-draft-lining-dark: $oc-teal-6; $fc-draft-lining-dark: $oc-teal-6;
$fc-draft-fabric-dark: $oc-gray-9; $fc-draft-fabric-dark: $oc-gray-9;

View file

@ -1,8 +1,7 @@
svg.freesewing.draft { svg.freesewing.draft {
max-width: 100%; max-width: 100%;
max-height: 90vh;
/* Reset */ /* Reset */
path,circle,rect{fill:none;stroke:none} path,circle{fill:none;stroke:none}
/* Defaults */ /* Defaults */
path,circle{ path,circle{
@ -13,25 +12,22 @@ svg.freesewing.draft {
} }
/* Stroke classes */ /* Stroke classes */
.note{ stroke-width:.8; } .stroke-xs{ stroke-width:.1; }
.mark{ stroke-width:.8; } .stroke-sm{ stroke-width:.4; }
.contrast{ stroke-width:1.2; } .stroke-l{ stroke-width:1.3; }
.stroke-xs{ stroke-width:.5; } .stroke-xl{ stroke-width:2; }
.stroke-sm{ stroke-width:.5; }
.stroke-xl{ stroke-width:1.4; }
.stroke-xxl{ stroke-width:2.4; }
.sa { stroke-dasharray:1,3; } .sa { stroke-dasharray:1,3; }
.help { .help {
stroke-width:.6; stroke-width:.6;
stroke-dasharray:15,5,2,5; stroke-dasharray:15,5,2,5;
} }
.dotted { stroke-dasharray:2,3; } .dotted { stroke-dasharray:0.5,1; }
.dashed { stroke-dasharray:2,5; } .dashed { stroke-dasharray:2,2; }
.lashed { stroke-dasharray:8,8; } .lashed { stroke-dasharray:8,3; }
.hidden { .hidden {
stroke:none; stroke:none!important;
fill:none; fill:none!important;
} }
/* Sampling */ /* Sampling */
@ -47,7 +43,7 @@ svg.freesewing.draft {
} }
.text-xs { font-size:4px; } .text-xs { font-size:4px; }
.text-sm { font-size:5px; } .text-sm { font-size:5px; }
.text-lg { font-size:8px; } .text-l { font-size:8px; }
.text-xl { font-size:10px; } .text-xl { font-size:10px; }
.text-xxl{ font-size:13px; } .text-xxl{ font-size:13px; }
@ -106,3 +102,52 @@ svg.freesewing.draft {
.fill-note{ fill: $fc-draft-note-dark; } .fill-note{ fill: $fc-draft-note-dark; }
} }
/* SVG defs (snippets) are in the shadow DOM */
g.snippet.notch > circle,
g.snippet.bnotch > circle,
g.snippet.bnotch > path,
g.snippet.utton > circle,
g.snippet.uttonhole > path {
color: $fc-draft-mark-light;
}
/* Same for paperless grid, also in shadow DOM */
rect.grid {
stroke-width: 1;
stroke: currentColor;
}
path.gridline {
stroke-linecap: butt;
stroke-width: 0.3!important;
stroke-dasharray: none;
}
path.gridline.sm {
stroke-width: 0.15!important;
}
path.gridline.xs {
stroke-width: 0.1!important;
}
path.gridline.metric.sm {
stroke-dasharray: 3 1;
}
path.gridline.metric.xs {
stroke-dasharray: 1 1;
}
path.gridline.imperial {
stroke-dasharray: 5 5;
}
path.gridline.imperial.sm {
stroke-dasharray: 2 2;
}
.light {
rect.grid,
path.gridline {
color: $oc-gray-5!important;
}
}
.dark {
rect.grid,
path.gridline {
color: $oc-gray-6!important;
}
}

View file

@ -1,5 +1,5 @@
--- ---
freesewingIsMadeByJoostDeCockAndContributors: Freesewing wurde von Joost De Cock und den Mitwirkenden kreiert freesewingIsMadeByJoostDeCockAndContributors: Freesewing wurde von Joost De Cock und den Mitwirkenden kreiert
theBlackOutsideOfThisBoxShouldMeasure: Die (schwarze) Außenseite dieses Rechtecks sollte messen theBlackOutsideOfThisBoxShouldMeasure: Die Außenseite dieses Rechtecks sollte messen
theWhiteInsideOfThisBoxShouldMeasure: Die (weiße) Innenseite dieses Rechtecks sollte messen theWhiteInsideOfThisBoxShouldMeasure: Die Innenseite dieses Rechtecks sollte messen
withTheFinancialSupportOfOurPatrons: mit der finanziellen Unterstützung unserer Gönner withTheFinancialSupportOfOurPatrons: mit der finanziellen Unterstützung unserer Gönner

View file

@ -1,4 +1,4 @@
freesewingIsMadeByJoostDeCockAndContributors: Freesewing is made by Joost De Cock and contributors freesewingIsMadeByJoostDeCockAndContributors: Freesewing is made by Joost De Cock and contributors
theBlackOutsideOfThisBoxShouldMeasure: The (black) outside of this box should measure theBlackOutsideOfThisBoxShouldMeasure: The outside of this box should measure
theWhiteInsideOfThisBoxShouldMeasure: The (white) inside of this box should measure theWhiteInsideOfThisBoxShouldMeasure: The inside of this box should measure
withTheFinancialSupportOfOurPatrons: with the financial support of our patrons withTheFinancialSupportOfOurPatrons: with the financial support of our patrons

View file

@ -1,5 +1,5 @@
--- ---
freesewingIsMadeByJoostDeCockAndContributors: Freesewing está hecho por Joost De Cock y colaboradores freesewingIsMadeByJoostDeCockAndContributors: Freesewing está hecho por Joost De Cock y colaboradores
theBlackOutsideOfThisBoxShouldMeasure: El (negro) fuera de este cuadro debe medir theBlackOutsideOfThisBoxShouldMeasure: El fuera de este cuadro debe medir
theWhiteInsideOfThisBoxShouldMeasure: El (blanco) dentro de este cuadro debe medir theWhiteInsideOfThisBoxShouldMeasure: El dentro de este cuadro debe medir
withTheFinancialSupportOfOurPatrons: con el apoyo económico de nuestros patrocinadores withTheFinancialSupportOfOurPatrons: con el apoyo económico de nuestros patrocinadores

View file

@ -1,5 +1,5 @@
--- ---
freesewingIsMadeByJoostDeCockAndContributors: Freesewing est la création de Joost De Cock et ses contributeurs freesewingIsMadeByJoostDeCockAndContributors: Freesewing est la création de Joost De Cock et ses contributeurs
theBlackOutsideOfThisBoxShouldMeasure: Le (noir) en dehors de cette case doit mesurer theBlackOutsideOfThisBoxShouldMeasure: L'extérieur de cette case doit mesurer
theWhiteInsideOfThisBoxShouldMeasure: L'intérieur (blanc) de cette case doit mesurer theWhiteInsideOfThisBoxShouldMeasure: L'intérieur de cette case doit mesurer
withTheFinancialSupportOfOurPatrons: avec le soutien financier de nos mécènes withTheFinancialSupportOfOurPatrons: avec le soutien financier de nos mécènes

View file

@ -1,5 +1,5 @@
--- ---
freesewingIsMadeByJoostDeCockAndContributors: FreeSewing is een project van Joost De Cock en vrijwillige medewerkers freesewingIsMadeByJoostDeCockAndContributors: FreeSewing is een project van Joost De Cock en vrijwillige medewerkers
theBlackOutsideOfThisBoxShouldMeasure: De (zwarte) buitenkant van dit kader meet theBlackOutsideOfThisBoxShouldMeasure: De buitenkant van dit kader meet
theWhiteInsideOfThisBoxShouldMeasure: De (witte) binnenkant van dit kader meet theWhiteInsideOfThisBoxShouldMeasure: De binnenkant van dit kader meet
withTheFinancialSupportOfOurPatrons: met de financiële steun van onze mecenassen withTheFinancialSupportOfOurPatrons: met de financiële steun van onze mecenassen

View file

@ -86,14 +86,14 @@ export default {
.line(this.points.__scaleboxImperialBottomRight) .line(this.points.__scaleboxImperialBottomRight)
.line(this.points.__scaleboxImperialTopRight) .line(this.points.__scaleboxImperialTopRight)
.close() .close()
.attr("style", "fill: #000; stroke: none;"); .attr("class", "scalebox imperial");
this.paths.__scaleboxMetric = new this.Path() this.paths.__scaleboxMetric = new this.Path()
.move(this.points.__scaleboxMetricTopLeft) .move(this.points.__scaleboxMetricTopLeft)
.line(this.points.__scaleboxMetricBottomLeft) .line(this.points.__scaleboxMetricBottomLeft)
.line(this.points.__scaleboxMetricBottomRight) .line(this.points.__scaleboxMetricBottomRight)
.line(this.points.__scaleboxMetricTopRight) .line(this.points.__scaleboxMetricTopRight)
.close() .close()
.attr("style", "fill: #FFF; stroke: none;"); .attr("class", "scalebox metric");
// Lead // Lead
this.points.__scaleboxLead = this.points.__scaleboxLead this.points.__scaleboxLead = this.points.__scaleboxLead
.attr("data-text", so.lead || "freesewing") .attr("data-text", so.lead || "freesewing")

View file

@ -0,0 +1,23 @@
import { version } from "../package.json";
export default {
name: "rendertest",
version,
design: "Joost De Cock",
code: "Joost De Cock",
department: "menswear",
type: "pattern",
difficulty: 1,
tags: ["test"],
optionGroups: {
fit: ["width"]
},
measurements: [],
dependencies: {},
parts: ["colors"],
inject: {},
hide: [],
options: {
width: { mm: 200, min: 50, max: 500 }
}
};

View file

@ -0,0 +1,5 @@
{
"env": {
"jest": true
}
}

View file

@ -0,0 +1,249 @@
export default function(part) {
let {
macro,
options,
Point,
Path,
points,
paths,
snippets,
Snippet,
complete,
paperless
} = part.shorthand();
let colors = [
"fabric",
"lining",
"interfacing",
"canvas",
"various",
"mark",
"contrast",
"note"
];
let sizes = ["xs", "sm", "", "l", "xl"];
let utility = ["dotted", "dashed", "lashed", "sa", "help", "hidden"];
let y = 0;
let w = options.width;
macro("hd", {
from: new Point(0, y),
to: new Point(w, y)
});
for (let i in colors) {
y += 15;
points["l" + i] = new Point(0, y);
points["r" + i] = new Point(w, y);
paths["heading" + i] = new Path()
.move(points["l" + i])
.line(points["r" + i])
.attr("class", colors[i])
.attr("data-text", colors[i]);
for (let j in sizes) {
y += 10;
points["sl" + i + j] = new Point(0, y);
points["sr" + i + j] = new Point(w, y);
paths["size" + i + j] = new Path()
.move(points["sl" + i + j])
.line(points["sr" + i + j])
.attr("class", colors[i])
.attr("class", "stroke-" + sizes[j])
.attr(
"data-text",
"path." + colors[i] + (sizes[j] === "" ? "" : ".stroke-" + sizes[j])
)
.attr("data-text-class", "center");
}
for (let j in utility) {
y += 10;
points["ul" + i + j] = new Point(0, y);
points["ur" + i + j] = new Point(w, y);
paths["util" + i + j] = new Path()
.move(points["ul" + i + j])
.line(points["ur" + i + j])
.attr("class", colors[i])
.attr("class", utility[j])
.attr("data-text", "path." + colors[i] + "." + utility[j])
.attr("data-text-class", "center");
}
}
y += 10;
points.ftl = new Point(0, y);
points.ftr = new Point(w, y);
paths.snip = new Path()
.move(points.ftl)
.line(points.ftr)
.attr("data-text", "fill");
y += 15;
for (let i of colors) {
let h = 10;
points["_bl" + i] = new Point(0, y);
points["_br" + i] = new Point(w, y);
points["_tr" + i] = new Point(w, y - h);
points["_tl" + i] = new Point(0, y - h);
paths["box" + i] = new Path()
.move(points["_bl" + i])
.line(points["_br" + i])
.line(points["_tr" + i])
.line(points["_tl" + i])
.close()
.attr("class", i)
.attr("class", "fill-" + i)
.attr("data-text", ".fill-" + i);
if (i === "fabric") paths["box" + i].attr("data-text-class", "fill-canvas");
y += h * 1.2;
}
let text = ["xs", "sm", "", "l", "xl", "xxl"];
y += 10;
points.tl = new Point(0, y);
points.tr = new Point(w, y);
paths.text = new Path()
.move(points.tl)
.line(points.tr)
.attr("data-text", "text");
y += 10;
points.tlc = new Point(0, y);
points.trc = new Point(w, y);
paths.textc = new Path()
.move(points.tlc)
.line(points.trc)
.attr("data-text", "text.center")
.attr("data-text-class", "center");
y += 10;
points.tlr = new Point(0, y);
points.trr = new Point(w, y);
paths.textr = new Path()
.move(points.tlr)
.line(points.trr)
.attr("data-text", "text.right")
.attr("data-text-class", "right");
for (let i in text) {
y += 15;
points["t" + i] = new Point(0, y)
.attr("data-text", "text" + text[i] === "" ? "" : ".text-" + text[i])
.attr("data-text-class", "text-" + text[i]);
}
let snips = {
logo: 25,
notch: 15,
bnotch: 15,
button: 15,
buttonhole: 15
};
y += 10;
points.tl = new Point(0, y);
points.tr = new Point(w, y);
paths.texts = new Path()
.move(points.tl)
.line(points.tr)
.attr("data-text", "snippets");
y += 10;
points["sl1"] = new Point(w * 0.25, y);
points["sl2"] = new Point(w * 0.5, y);
points["sl3"] = new Point(w * 0.75, y);
points["sl1"]
.attr("data-text", "data-scale: 1\ndata-rotate: 0")
.attr("data-text-class", "center text-sm")
.attr("data-text-lineheight", 5);
points["sl2"]
.attr("data-text", "data-scale: 1.25\ndata-rotate: 0")
.attr("data-text-class", "center text-sm")
.attr("data-text-lineheight", 5);
points["sl3"]
.attr("data-text", "data-scale: 0.75\ndata-rotate: 90")
.attr("data-text-class", "center text-sm")
.attr("data-text-lineheight", 5);
y += 55;
for (let i in snips) {
points["snt" + i] = new Point(0, y);
points["snt" + i].attr("data-text", i);
points["sn1" + i] = new Point(w * 0.25, y);
points["sn2" + i] = new Point(w * 0.5, y);
points["sn3" + i] = new Point(w * 0.75, y);
snippets["sn1" + i] = new Snippet(i, points["sn1" + i]);
snippets["sn2" + i] = new Snippet(i, points["sn2" + i]);
snippets["sn2" + i].attr("data-scale", 1.25);
snippets["sn3" + i] = new Snippet(i, points["sn3" + i]);
snippets["sn3" + i].attr("data-scale", 0.75).attr("data-rotate", 90);
y += snips[i];
}
y += 10;
points.ml = new Point(0, y);
points.mr = new Point(w, y);
paths.macros = new Path()
.move(points.ml)
.line(points.mr)
.attr("data-text", "macros");
y += 40;
macro("title", {
at: new Point(w / 2, y),
nr: 5,
title: "title"
});
y += 40;
macro("grainline", {
from: new Point(0, y),
to: new Point(w, y)
});
y += 20;
macro("cutonfold", {
from: new Point(w, y),
to: new Point(0, y)
});
y += 70;
points.dimf = new Point(20, y);
points.dimt = new Point(w - 20, y + 120);
points.dimv = new Point(20, y + 80);
paths.dims = new Path().move(points.dimf)._curve(points.dimv, points.dimt);
macro("hd", {
from: points.dimf,
to: points.dimt,
text: "hd",
y: y - 15
});
macro("vd", {
from: points.dimt,
to: points.dimf,
text: "vd",
x: 0
});
macro("ld", {
from: points.dimf,
to: points.dimt,
text: "ld"
});
macro("pd", {
path: paths.dims,
text: "pd",
d: 10
});
y += 170;
macro("scalebox", {
at: new Point(w / 2, y)
});
// Make sure nothing is cut off
paths.box = new Path()
.move(new Point(-10, -10))
.line(new Point(w + 10, y + 10))
.attr("class", "hidden");
// Complete?
if (complete) {
}
// Paperless?
if (paperless) {
}
return part;
}

View file

@ -0,0 +1,13 @@
import freesewing from "@freesewing/core";
import plugins from "@freesewing/plugin-bundle";
import config from "../config";
// Parts
import draftColors from "./colors";
// Create design
const Pattern = new freesewing.Design(config, plugins);
// Attach draft methods to prototype
Pattern.prototype.draftColors = part => draftColors(part);
export default Pattern;