Skip to content

Commit

Permalink
feat(vidavidorra-logo): add option to make an inscribed-circle PNG
Browse files Browse the repository at this point in the history
The inscribed circle PNG can be useful for usage as profile picture that is shown as a circle.
  • Loading branch information
jdbruijn committed Aug 2, 2020
1 parent 66f961a commit 3be65ad
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 8 deletions.
5 changes: 5 additions & 0 deletions src/vidavidorra-logo/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ const questions = [
choices: [
{ name: 'Rectangle', value: 'rectangle' },
{ name: 'Square', value: 'square' },
{
name: 'Square with inscribed circle fitting the logo',
short: 'Square inscribed circle',
value: 'square-inscribed-circle',
},
],
default: 'rectangle',
},
Expand Down
55 changes: 47 additions & 8 deletions src/vidavidorra-logo/vidavidorra-logo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ interface Options {
lineThickness: number;
colour: string;
pngHeight: number;
pngFormat: 'rectangle' | 'square';
pngFormat: 'rectangle' | 'square' | 'square-inscribed-circle';
}

/**
Expand Down Expand Up @@ -119,16 +119,53 @@ export class VidavidorraLogo {
}

private createPng(): Promise<void> {
const background: sharp.Color = { r: 0, g: 0, b: 0, alpha: 0 };
const svgHeight = Math.ceil(this.maximumHeight());

const resizeOptions: sharp.ResizeOptions = {
height: this.options.pngHeight,
background,
};
const extendOptions: sharp.ExtendOptions = {
top: 0,
bottom: 0,
left: 0,
right: 0,
background,
};

if (this.options.pngFormat === 'square') {
if (
this.options.pngFormat === 'square' ||
this.options.pngFormat === 'square-inscribed-circle'
) {
resizeOptions.width = this.options.pngHeight;
resizeOptions.fit = 'contain';
resizeOptions.background = { r: 0, g: 0, b: 0, alpha: 0 };
}

if (this.options.pngFormat === 'square-inscribed-circle') {
/**
* Imagine the given size, which is a square, has an inscribed circle. The
* diameter of the circle is be the same as the diagonal of the square.
* Imagine that circle would have an inscribed square, lets call this the
* inner square, which is of course smaller than the outter square.
* Using the Pythagorean theorem, we know that the each side's length of
* the inner square is $r \sqrt{2}$. Putting that together for the inner
* square means that each side's length is $r \sqrt{2}$ where $r$ is half
* of the outer square's side length.
*
*/
const inscribedCircleRadius = this.options.pngHeight / 2;
const innerSquareSideLength = Math.floor(
inscribedCircleRadius * Math.sqrt(2),
);
resizeOptions.width = innerSquareSideLength;
resizeOptions.height = innerSquareSideLength;

const sideLengthDifference =
this.options.pngHeight - innerSquareSideLength;
extendOptions.top = Math.ceil(sideLengthDifference / 2);
extendOptions.bottom = Math.floor(sideLengthDifference / 2);
extendOptions.left = Math.floor(sideLengthDifference / 2);
extendOptions.right = Math.ceil(sideLengthDifference / 2);
}

/**
Expand All @@ -146,16 +183,18 @@ export class VidavidorraLogo {
),
})
.resize(resizeOptions)
.extend(extendOptions)
.png()
.toBuffer({ resolveWithObject: true })
.then(({ data, info }) => {
console.log(
`Output: ${this.name}-${info.width}x${info.height}.png`,
);
let suffix = '';
if (this.options.pngFormat === 'square-inscribed-circle') {
suffix = '-inscribed-circle';
}
fs.writeFileSync(
path.join(
this.options.outputDirectory,
`${this.name}-${info.width}x${info.height}.png`,
`${this.name}-${info.width}x${info.height}${suffix}.png`,
),
data,
);
Expand Down

0 comments on commit 3be65ad

Please sign in to comment.