#815 Rotation and flipping images
This commit is contained in:
@ -11,7 +11,7 @@ function createAnchor(drawingOptions: IDrawingOptions): Anchor {
|
||||
{
|
||||
fileName: "test.png",
|
||||
stream: new Buffer(""),
|
||||
dimensions: {
|
||||
transformation: {
|
||||
pixels: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
|
@ -1,5 +1,5 @@
|
||||
// http://officeopenxml.com/drwPicFloating.php
|
||||
import { IMediaData, IMediaDataDimensions } from "file/media";
|
||||
import { IMediaData, IMediaDataTransformation } from "file/media";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { IDrawingOptions } from "../drawing";
|
||||
import { HorizontalPosition, IFloating, SimplePos, VerticalPosition } from "../floating";
|
||||
@ -12,7 +12,7 @@ import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-propert
|
||||
import { AnchorAttributes } from "./anchor-attributes";
|
||||
|
||||
export class Anchor extends XmlComponent {
|
||||
constructor(mediaData: IMediaData, dimensions: IMediaDataDimensions, drawingOptions: IDrawingOptions) {
|
||||
constructor(mediaData: IMediaData, transform: IMediaDataTransformation, drawingOptions: IDrawingOptions) {
|
||||
super("wp:anchor");
|
||||
|
||||
const floating: IFloating = {
|
||||
@ -36,14 +36,14 @@ export class Anchor extends XmlComponent {
|
||||
behindDoc: floating.behindDocument === true ? "1" : "0",
|
||||
locked: floating.lockAnchor === true ? "1" : "0",
|
||||
layoutInCell: floating.layoutInCell === true ? "1" : "0",
|
||||
relativeHeight: floating.zIndex ? floating.zIndex : dimensions.emus.y,
|
||||
relativeHeight: floating.zIndex ? floating.zIndex : transform.emus.y,
|
||||
}),
|
||||
);
|
||||
|
||||
this.root.push(new SimplePos());
|
||||
this.root.push(new HorizontalPosition(floating.horizontalPosition));
|
||||
this.root.push(new VerticalPosition(floating.verticalPosition));
|
||||
this.root.push(new Extent(dimensions.emus.x, dimensions.emus.y));
|
||||
this.root.push(new Extent(transform.emus.x, transform.emus.y));
|
||||
this.root.push(new EffectExtent());
|
||||
|
||||
if (drawingOptions.floating !== undefined && drawingOptions.floating.wrap !== undefined) {
|
||||
@ -67,6 +67,6 @@ export class Anchor extends XmlComponent {
|
||||
|
||||
this.root.push(new DocProperties());
|
||||
this.root.push(new GraphicFrameProperties());
|
||||
this.root.push(new Graphic(mediaData, dimensions.emus.x, dimensions.emus.y));
|
||||
this.root.push(new Graphic(mediaData, transform));
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ function createDrawing(drawingOptions?: IDrawingOptions): Drawing {
|
||||
fileName: "test.jpg",
|
||||
stream: Buffer.from(imageBase64Data, "base64"),
|
||||
path: path,
|
||||
dimensions: {
|
||||
transformation: {
|
||||
pixels: {
|
||||
x: 100,
|
||||
y: 100,
|
||||
@ -165,6 +165,9 @@ describe("Drawing", () => {
|
||||
},
|
||||
{
|
||||
"a:xfrm": [
|
||||
{
|
||||
_attr: {},
|
||||
},
|
||||
{
|
||||
"a:ext": {
|
||||
_attr: {
|
||||
@ -392,6 +395,9 @@ describe("Drawing", () => {
|
||||
},
|
||||
{
|
||||
"a:xfrm": [
|
||||
{
|
||||
_attr: {},
|
||||
},
|
||||
{
|
||||
"a:ext": {
|
||||
_attr: {
|
||||
|
@ -22,10 +22,10 @@ export class Drawing extends XmlComponent {
|
||||
super("w:drawing");
|
||||
|
||||
if (!drawingOptions.floating) {
|
||||
this.inline = new Inline(imageData, imageData.dimensions);
|
||||
this.inline = new Inline(imageData, imageData.transformation);
|
||||
this.root.push(this.inline);
|
||||
} else {
|
||||
this.root.push(new Anchor(imageData, imageData.dimensions, drawingOptions));
|
||||
this.root.push(new Anchor(imageData, imageData.transformation, drawingOptions));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { IMediaData } from "file/media";
|
||||
import { IMediaData, IMediaDataTransformation } from "file/media";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
|
||||
import { GraphicDataAttributes } from "./graphic-data-attribute";
|
||||
@ -7,7 +7,7 @@ import { Pic } from "./pic";
|
||||
export class GraphicData extends XmlComponent {
|
||||
private readonly pic: Pic;
|
||||
|
||||
constructor(mediaData: IMediaData, x: number, y: number) {
|
||||
constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
|
||||
super("a:graphicData");
|
||||
|
||||
this.root.push(
|
||||
@ -16,7 +16,7 @@ export class GraphicData extends XmlComponent {
|
||||
}),
|
||||
);
|
||||
|
||||
this.pic = new Pic(mediaData, x, y);
|
||||
this.pic = new Pic(mediaData, transform);
|
||||
|
||||
this.root.push(this.pic);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// http://officeopenxml.com/drwPic.php
|
||||
import { IMediaData } from "file/media";
|
||||
import { IMediaData, IMediaDataTransformation } from "file/media";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
|
||||
import { BlipFill } from "./blip/blip-fill";
|
||||
@ -10,7 +10,7 @@ import { ShapeProperties } from "./shape-properties/shape-properties";
|
||||
export class Pic extends XmlComponent {
|
||||
private readonly shapeProperties: ShapeProperties;
|
||||
|
||||
constructor(mediaData: IMediaData, x: number, y: number) {
|
||||
constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
|
||||
super("pic:pic");
|
||||
|
||||
this.root.push(
|
||||
@ -19,11 +19,11 @@ export class Pic extends XmlComponent {
|
||||
}),
|
||||
);
|
||||
|
||||
this.shapeProperties = new ShapeProperties(x, y);
|
||||
this.shapeProperties = new ShapeProperties(transform);
|
||||
|
||||
this.root.push(new NonVisualPicProperties());
|
||||
this.root.push(new BlipFill(mediaData));
|
||||
this.root.push(new ShapeProperties(x, y));
|
||||
this.root.push(new ShapeProperties(transform));
|
||||
}
|
||||
|
||||
public setXY(x: number, y: number): void {
|
||||
|
@ -0,0 +1,93 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
import { Form } from "./form/form";
|
||||
|
||||
describe("Form", () => {
|
||||
describe("#constructor()", () => {
|
||||
it("should create", () => {
|
||||
const tree = new Formatter().format(
|
||||
new Form({
|
||||
pixels: {
|
||||
x: 100,
|
||||
y: 100,
|
||||
},
|
||||
emus: {
|
||||
x: 100,
|
||||
y: 100,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
expect(tree).to.deep.equal({
|
||||
"a:xfrm": [
|
||||
{
|
||||
_attr: {},
|
||||
},
|
||||
{
|
||||
"a:ext": {
|
||||
_attr: {
|
||||
cx: 100,
|
||||
cy: 100,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"a:off": {
|
||||
_attr: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("should create with flip", () => {
|
||||
const tree = new Formatter().format(
|
||||
new Form({
|
||||
pixels: {
|
||||
x: 100,
|
||||
y: 100,
|
||||
},
|
||||
emus: {
|
||||
x: 100,
|
||||
y: 100,
|
||||
},
|
||||
flip: {
|
||||
vertical: true,
|
||||
horizontal: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
expect(tree).to.deep.equal({
|
||||
"a:xfrm": [
|
||||
{
|
||||
_attr: {
|
||||
flipH: true,
|
||||
flipV: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"a:ext": {
|
||||
_attr: {
|
||||
cx: 100,
|
||||
cy: 100,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"a:off": {
|
||||
_attr: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -1,15 +1,38 @@
|
||||
// http://officeopenxml.com/drwSp-size.php
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
// http://officeopenxml.com/drwSp-rotate.php
|
||||
import { IMediaDataTransformation } from "file/media";
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
import { Extents } from "./extents/extents";
|
||||
import { Offset } from "./offset/off";
|
||||
|
||||
export class FormAttributes extends XmlAttributeComponent<{
|
||||
readonly flipVertical?: boolean;
|
||||
readonly flipHorizontal?: boolean;
|
||||
readonly rotation?: number;
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
flipVertical: "flipV",
|
||||
flipHorizontal: "flipH",
|
||||
rotation: "rot",
|
||||
};
|
||||
}
|
||||
|
||||
export class Form extends XmlComponent {
|
||||
private readonly extents: Extents;
|
||||
|
||||
constructor(x: number, y: number) {
|
||||
constructor(options: IMediaDataTransformation) {
|
||||
super("a:xfrm");
|
||||
|
||||
this.extents = new Extents(x, y);
|
||||
this.root.push(
|
||||
new FormAttributes({
|
||||
flipVertical: options.flip?.vertical,
|
||||
flipHorizontal: options.flip?.horizontal,
|
||||
rotation: options.rotation,
|
||||
}),
|
||||
);
|
||||
|
||||
this.extents = new Extents(options.emus.x, options.emus.y);
|
||||
|
||||
this.root.push(this.extents);
|
||||
this.root.push(new Offset());
|
||||
|
@ -1,7 +0,0 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
|
||||
export class NoFill extends XmlComponent {
|
||||
constructor() {
|
||||
super("a:noFill");
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
|
||||
import { NoFill } from "./no-fill";
|
||||
|
||||
describe("NoFill", () => {
|
||||
describe("#constructor()", () => {
|
||||
it("should create", () => {
|
||||
const tree = new Formatter().format(new NoFill());
|
||||
expect(tree).to.deep.equal({
|
||||
"a:noFill": {},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,19 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
import { Outline } from "./outline";
|
||||
|
||||
describe("Outline", () => {
|
||||
describe("#constructor()", () => {
|
||||
it("should create", () => {
|
||||
const tree = new Formatter().format(new Outline());
|
||||
expect(tree).to.deep.equal({
|
||||
"a:ln": [
|
||||
{
|
||||
"a:noFill": {},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -1,4 +1,5 @@
|
||||
// http://officeopenxml.com/drwSp-SpPr.php
|
||||
import { IMediaDataTransformation } from "file/media";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { Form } from "./form";
|
||||
// import { NoFill } from "./no-fill";
|
||||
@ -9,7 +10,7 @@ import { ShapePropertiesAttributes } from "./shape-properties-attributes";
|
||||
export class ShapeProperties extends XmlComponent {
|
||||
private readonly form: Form;
|
||||
|
||||
constructor(x: number, y: number) {
|
||||
constructor(transform: IMediaDataTransformation) {
|
||||
super("pic:spPr");
|
||||
|
||||
this.root.push(
|
||||
@ -18,7 +19,7 @@ export class ShapeProperties extends XmlComponent {
|
||||
}),
|
||||
);
|
||||
|
||||
this.form = new Form(x, y);
|
||||
this.form = new Form(transform);
|
||||
|
||||
this.root.push(this.form);
|
||||
this.root.push(new PresetGeometry());
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { IMediaData } from "file/media";
|
||||
import { IMediaData, IMediaDataTransformation } from "file/media";
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
import { GraphicData } from "./graphic-data";
|
||||
@ -14,7 +14,7 @@ class GraphicAttributes extends XmlAttributeComponent<{
|
||||
export class Graphic extends XmlComponent {
|
||||
private readonly data: GraphicData;
|
||||
|
||||
constructor(mediaData: IMediaData, x: number, y: number) {
|
||||
constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
|
||||
super("a:graphic");
|
||||
this.root.push(
|
||||
new GraphicAttributes({
|
||||
@ -22,7 +22,7 @@ export class Graphic extends XmlComponent {
|
||||
}),
|
||||
);
|
||||
|
||||
this.data = new GraphicData(mediaData, x, y);
|
||||
this.data = new GraphicData(mediaData, transform);
|
||||
|
||||
this.root.push(this.data);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// http://officeopenxml.com/drwPicInline.php
|
||||
import { IMediaData, IMediaDataDimensions } from "file/media";
|
||||
import { IMediaData, IMediaDataTransformation } from "file/media";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { DocProperties } from "./../doc-properties/doc-properties";
|
||||
import { EffectExtent } from "./../effect-extent/effect-extent";
|
||||
@ -12,7 +12,7 @@ export class Inline extends XmlComponent {
|
||||
private readonly extent: Extent;
|
||||
private readonly graphic: Graphic;
|
||||
|
||||
constructor(mediaData: IMediaData, private readonly dimensions: IMediaDataDimensions) {
|
||||
constructor(mediaData: IMediaData, private readonly transform: IMediaDataTransformation) {
|
||||
super("wp:inline");
|
||||
|
||||
this.root.push(
|
||||
@ -24,8 +24,8 @@ export class Inline extends XmlComponent {
|
||||
}),
|
||||
);
|
||||
|
||||
this.extent = new Extent(dimensions.emus.x, dimensions.emus.y);
|
||||
this.graphic = new Graphic(mediaData, dimensions.emus.x, dimensions.emus.y);
|
||||
this.extent = new Extent(transform.emus.x, transform.emus.y);
|
||||
this.graphic = new Graphic(mediaData, transform);
|
||||
|
||||
this.root.push(this.extent);
|
||||
this.root.push(new EffectExtent());
|
||||
@ -35,8 +35,8 @@ export class Inline extends XmlComponent {
|
||||
}
|
||||
|
||||
public scale(factorX: number, factorY: number): void {
|
||||
const newX = Math.round(this.dimensions.emus.x * factorX);
|
||||
const newY = Math.round(this.dimensions.emus.y * factorY);
|
||||
const newX = Math.round(this.transform.emus.x * factorX);
|
||||
const newY = Math.round(this.transform.emus.y * factorY);
|
||||
|
||||
this.extent.setXY(newX, newY);
|
||||
this.graphic.setXY(newX, newY);
|
||||
|
Reference in New Issue
Block a user