Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: binaryimage rotation #91

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ function abstractComponentToPdf(
}
});

// svgToPdfKit doesn't seem to have great support currently, need to find workaround.

// if (component.rotation) {
// svgUpdated = `<svg transform="rotate(${component.rotation.x} ${component.rotation.y} ${component.rotation.z})">${svgUpdated}</svg>`;
// }

const imageWidth = component.bottomRight.x - component.topLeft.x;
const imageHeight = component.bottomRight.y - component.topLeft.y;
svgToPdfKit(pdf, svgUpdated, component.topLeft.x, component.topLeft.y, {
Expand Down
53 changes: 33 additions & 20 deletions packages/abstract-image/src/exporters/react-svg-export-image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as B64 from "base64-js";
import * as React from "react";
import * as AbstractImage from "../model/index";
import { TextEncoder } from "util";
import { Point3D } from "../model/index";

export interface ReactSvgCallbacks {
readonly onClick?: MouseCallback;
Expand Down Expand Up @@ -98,6 +99,7 @@ function _visit(key: string, component: AbstractImage.Component): Array<React.Re
width={component.bottomRight.x - component.topLeft.x}
height={component.bottomRight.y - component.topLeft.y}
id={makeIdAttr(component.id)}
{...(component.rotation && rotationStyle(component.rotation))}
href={url}
/>,
];
Expand All @@ -113,48 +115,48 @@ function _visit(key: string, component: AbstractImage.Component): Array<React.Re
stroke={colorToRgb(component.strokeColor)}
strokeWidth={component.strokeThickness}
strokeOpacity={colorToOpacity(component.strokeColor)}
{...(component.rotation && rotationStyle(component.rotation))}
/>,
];
case "text":
if (!component.text) {
return [];
}
const lineHeight = component.fontSize;

const shadowStyle = {
const baseStyle = {
textAnchor: getTextAnchor(component.horizontalGrowthDirection),
fontSize: component.fontSize.toString() + "px",
fontWeight: component.fontWeight === "mediumBold" ? "bold" : component.fontWeight,
fontFamily: component.fontFamily,
};

const shadowStyle = {
...baseStyle,
stroke: colorToRgb(component.strokeColor),
strokeWidth: component.strokeThickness,
};
const style = {
textAnchor: getTextAnchor(component.horizontalGrowthDirection),
fontSize: component.fontSize.toString() + "px",
fontWeight: component.fontWeight === "mediumBold" ? "bold" : component.fontWeight,
fontFamily: component.fontFamily,
fill: colorToRgb(component.textColor),
};
const dy = getBaselineAdjustment(component.verticalGrowthDirection);
const style = { ...baseStyle, fill: colorToRgb(component.textColor) };

const transform =
"rotate(" +
component.clockwiseRotationDegrees.toString() +
" " +
component.position.x.toString() +
" " +
component.position.y.toString() +
")";
// component.clockwiseRotationDegrees is legacy
const transform = component.rotation
? rotationTransform(component.rotation)
: "rotate(" +
component.clockwiseRotationDegrees.toString() +
" " +
component.position.x.toString() +
" " +
component.position.y.toString() +
")";

const dy = getBaselineAdjustment(component.verticalGrowthDirection);
const lines: Array<string> = component.text !== null ? component.text.split("\n") : [];
const tSpans = lines.map((t) =>
renderLine(
t,
component.position.x,
component.position.y + (lines.indexOf(t) + dy) * lineHeight,
component.position.y + (lines.indexOf(t) + dy) * component.fontSize,
component.fontSize,
lineHeight
component.fontSize
)
);
let cs: Array<React.ReactElement<{}>> = [];
Expand Down Expand Up @@ -189,6 +191,7 @@ function _visit(key: string, component: AbstractImage.Component): Array<React.Re
strokeOpacity={colorToOpacity(component.strokeColor)}
fillOpacity={colorToOpacity(component.fillColor)}
fill={colorToRgb(component.fillColor)}
{...(component.rotation && rotationStyle(component.rotation))}
/>,
];
case "polyline":
Expand All @@ -202,6 +205,7 @@ function _visit(key: string, component: AbstractImage.Component): Array<React.Re
strokeWidth={component.strokeThickness}
strokeOpacity={colorToOpacity(component.strokeColor)}
fill="none"
{...(component.rotation && rotationStyle(component.rotation))}
/>,
];
case "polygon":
Expand All @@ -216,6 +220,7 @@ function _visit(key: string, component: AbstractImage.Component): Array<React.Re
strokeOpacity={colorToOpacity(component.strokeColor)}
fillOpacity={colorToOpacity(component.fillColor)}
fill={colorToRgb(component.fillColor)}
{...(component.rotation && rotationStyle(component.rotation))}
/>,
];
case "rectangle":
Expand All @@ -232,6 +237,7 @@ function _visit(key: string, component: AbstractImage.Component): Array<React.Re
strokeOpacity={colorToOpacity(component.strokeColor)}
fillOpacity={colorToOpacity(component.fillColor)}
fill={colorToRgb(component.fillColor)}
{...(component.rotation && rotationStyle(component.rotation))}
/>,
];
default:
Expand Down Expand Up @@ -280,6 +286,13 @@ function renderLine(text: string, x: number, y: number, fontSize: number, lineHe
);
}

const rotationStyle = (rotation: Point3D): { readonly style: React.CSSProperties } => ({
style: { transform: rotationTransform(rotation) },
});

const rotationTransform = (rotation: Point3D): string =>
`rotateX(${rotation.x}deg) rotateY(${rotation.y}deg) rotateZ(${rotation.z}deg)`;

function getBaselineAdjustment(d: AbstractImage.GrowthDirection): number {
if (d === "up") {
return 0.0;
Expand Down
49 changes: 31 additions & 18 deletions packages/abstract-image/src/exporters/svg-export-image.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as B64 from "base64-js";
import * as AbstractImage from "../model/index";
import { Point3D } from "../model/index";

export function createSVG(image: AbstractImage.AbstractImage, pixelWidth?: number, pixelHeight?: number): string {
const imageElements = image.components.map((c: AbstractImage.Component) => abstractComponentToSVG(c));
Expand Down Expand Up @@ -36,6 +37,7 @@ function abstractComponentToSVG(component: AbstractImage.Component): string {
width: (component.bottomRight.x - component.topLeft.x).toString(),
height: (component.bottomRight.y - component.topLeft.y).toString(),
href: url,
style: rotationStyle(component.rotation),
},
[]
);
Expand All @@ -52,6 +54,7 @@ function abstractComponentToSVG(component: AbstractImage.Component): string {
stroke: colorToRgb(component.strokeColor),
strokeOpacity: colorToOpacity(component.strokeColor),
strokeWidth: component.strokeThickness.toString(),
style: rotationStyle(component.rotation),
},
[]
);
Expand All @@ -64,44 +67,45 @@ function abstractComponentToSVG(component: AbstractImage.Component): string {
stroke: colorToRgb(component.strokeColor),
strokeOpacity: colorToOpacity(component.strokeColor),
strokeWidth: component.strokeThickness.toString(),
style: rotationStyle(component.rotation),
},
[]
);
case "text":
if (!component.text) {
return "";
}
const lineHeight = component.fontSize;

const shadowStyle = {
const baseStyle = {
textAnchor: getTextAnchor(component.horizontalGrowthDirection),
fontSize: component.fontSize.toString() + "px",
fontWeight: component.fontWeight,
fontFamily: component.fontFamily,
};

const shadowStyle = {
...baseStyle,
stroke: colorToRgb(component.strokeColor),
strokeOpacity: colorToOpacity(component.strokeColor),
strokeWidth: component.strokeThickness.toString() + "px",
};

const style = {
textAnchor: getTextAnchor(component.horizontalGrowthDirection),
fontSize: component.fontSize.toString() + "px",
fontWeight: component.fontWeight,
fontFamily: component.fontFamily,
...baseStyle,
fill: colorToRgb(component.textColor),
fillOpacity: colorToOpacity(component.textColor),
};

const dy = getBaselineAdjustment(component.verticalGrowthDirection);

const transform =
"rotate(" +
component.clockwiseRotationDegrees.toString() +
" " +
component.position.x.toString() +
" " +
component.position.y.toString() +
")";
// component.clockwiseRotationDegrees is legacy
const transform = component.rotation
? rotationTransform(component.rotation)
: "rotate(" +
component.clockwiseRotationDegrees.toString() +
" " +
component.position.x.toString() +
" " +
component.position.y.toString() +
")";

const lines: Array<string> = component.text !== null ? component.text.split("\n") : [];

Expand All @@ -110,8 +114,8 @@ function abstractComponentToSVG(component: AbstractImage.Component): string {
"tspan",
{
x: component.position.x.toString(),
y: (component.position.y + (lines.indexOf(t) + dy) * lineHeight).toString(),
height: lineHeight.toString() + "px",
y: (component.position.y + (lines.indexOf(t) + dy) * component.fontSize).toString(),
height: component.fontSize.toString() + "px",
},
[
t
Expand Down Expand Up @@ -163,6 +167,7 @@ function abstractComponentToSVG(component: AbstractImage.Component): string {
strokeWidth: component.strokeThickness.toString(),
fill: colorToRgb(component.fillColor),
fillOpacity: colorToOpacity(component.fillColor),
style: rotationStyle(component.rotation),
},
[]
);
Expand All @@ -176,6 +181,7 @@ function abstractComponentToSVG(component: AbstractImage.Component): string {
strokeWidth: component.strokeThickness.toString(),
fill: colorToRgb(component.fillColor),
fillOpacity: colorToOpacity(component.fillColor),
style: rotationStyle(component.rotation),
},
[]
);
Expand All @@ -192,6 +198,7 @@ function abstractComponentToSVG(component: AbstractImage.Component): string {
strokeWidth: component.strokeThickness.toString(),
fill: colorToRgb(component.fillColor),
fillOpacity: colorToOpacity(component.fillColor),
style: rotationStyle(component.rotation),
},
[]
);
Expand Down Expand Up @@ -291,6 +298,12 @@ function colorToOpacity(color: AbstractImage.Color): string {
return (color.a / 255).toString();
}

const rotationStyle = (rotation: Point3D | undefined): string =>
rotation ? `transform: ${rotationTransform(rotation)}` : "";

const rotationTransform = (rotation: Point3D): string =>
`rotateX(${rotation.x}deg) rotateY(${rotation.y}deg) rotateZ(${rotation.z}deg)`;

function getImageUrl(format: AbstractImage.BinaryFormat, data: AbstractImage.ImageData): string {
if (data.type === "url") {
return data.url;
Expand Down
Loading