Skip to content

Commit

Permalink
Merge pull request #11 from sowrensen/feat/custom-font
Browse files Browse the repository at this point in the history
Custom font support
  • Loading branch information
sowrensen authored May 2, 2023
2 parents f147a21 + 69567c8 commit 78c3091
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 8 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

All notable changes to `svg-avatar-generator` will be documented in this file.

## 1.4.0

- Support for custom fonts.
- New keys `custom_font_url` and `font_family` in config.
- Moved font family config to `font-family.blade.php` file.

## 1.3.1

- Revert `Shape::CIRCLE` back as default shape which was changed to `Shape::RECTANGLE` by mistake.
Expand Down
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ another package for same task?

Well, this one has some subtle but nifty advantages over available packages, here's a few of them:

- [x] No external api call is required, it's totally offline. 🛰️
- [x] Unlike some other available options, doesn't require heavy-weight image processing libraries like **Intervention**.
🧺
- [x] Doesn't have any binary dependency, so nothing needs to be installed on server. 🗃️
- [x] Supports custom font. 🧣
- [x] Supports gradient background. 🦜
- [x] Supports random gradients based on defined presets in config. 🦚
- [x] Multiple shapes: rectangular, rounded-rectangular, or circular. 💎
- [x] Ability to customize initials and extractor. ✍🏼
- [x] No external api call is required, it's totally offline. 🛰️
- [x] Unlike some other available options, doesn't require heavy-weight image processing libraries like **Intervention**.
🧺
- [x] Doesn't have any binary dependency, so nothing needs to be installed on server. 🗃️

## Requirements

Expand Down Expand Up @@ -85,6 +86,8 @@ use Sowren\SvgAvatarGenerator\Enums\FontWeight;
Svg::for('John Doe')
->asCircle() // or, asRectangle() along with optional setCornerRadius($radius) method
->setSize(64)
->setCustomFontUrl('https://api.fontshare.com/v2/css?f[]=kola@400&display=swap')
->setFontFamily('Kola')
->setFontSize(40)
->setFontWeight(FontWeight::SEMIBOLD)
->setForeground('#FFFFFF')
Expand Down Expand Up @@ -138,7 +141,7 @@ After doing that, set the class as default extractor in config.

## Sample Output

<img src="https://user-images.githubusercontent.com/13097375/227495887-99a0430f-925f-4f1f-acac-0dca21686bfd.png" height="128"/>
<img src="https://user-images.githubusercontent.com/13097375/235597587-791dc36f-640a-47a2-8717-337edcfe3612.png" height="128"/>

## Testing

Expand Down
32 changes: 32 additions & 0 deletions config/svg-avatar.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,38 @@
*/
'corner_radius' => 0,

/*
|--------------------------------------------------------------------------
| Custom Font URL
|--------------------------------------------------------------------------
|
| Specify the URL of the font family you want to use. You can use
| Google Fonts, Fontshare or other services.
|
| e.g. https://api.fontshare.com/v2/css?f[]=kola@400&display=swap
|
| Type: string
| Default: null
|
*/
'custom_font_url' => null,

/*
|--------------------------------------------------------------------------
| Font Family
|--------------------------------------------------------------------------
|
| If you are using a custom font, specify the name of the family here,
| otherwise it won't work. For example, for the URL in the previous
| `custom_font_url` section's example, you should define 'Kola'
| as the family name in this key.
|
| Type: string
| Default: null
|
*/
'font_family' => null,

/*
|--------------------------------------------------------------------------
| Font Size
Expand Down
24 changes: 24 additions & 0 deletions resources/views/elements/font-family.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@php
/**
* @var Sowren\SvgAvatarGenerator\SvgAvatarGenerator $generator
*/
@endphp

@if(($url = $generator->getCustomFontUrl()) && ($family = $generator->getFontFamily()))
<style>
/*<![CDATA[*/
@import url({{ $url }});
/*]]>*/
</style>
<style>
svg {
font-family: {{ $family }}, "sans-serif";
}
</style>
@else
<style>
svg {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
}
</style>
@endif
6 changes: 5 additions & 1 deletion resources/views/elements/svg.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@
viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>

@include('svg::elements.font-family')

<defs>
@include('svg::elements.linear-gradient')
</defs>

@include($generator->getShape()->render())

<text
x="50%" y="50%" style="line-height: 1;"
font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif"
alignment-baseline="middle" text-anchor="middle"
font-size="{{ $generator->getFontSize() }}"
font-weight="{{ $generator->getFontWeight()->value }}"
Expand Down
11 changes: 11 additions & 0 deletions src/Exceptions/InvalidUrlException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Sowren\SvgAvatarGenerator\Exceptions;

class InvalidUrlException extends \Exception
{
public static function create(string $url): InvalidUrlException
{
return new self("`{$url}` is not a valid URL.");
}
}
2 changes: 2 additions & 0 deletions src/Http/Controllers/SvgController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Sowren\SvgAvatarGenerator\Exceptions\InvalidGradientRotationException;
use Sowren\SvgAvatarGenerator\Exceptions\InvalidGradientStopException;
use Sowren\SvgAvatarGenerator\Exceptions\InvalidSvgSizeException;
use Sowren\SvgAvatarGenerator\Exceptions\InvalidUrlException;
use Sowren\SvgAvatarGenerator\Exceptions\MissingTextException;
use Sowren\SvgAvatarGenerator\SvgAvatarGenerator;

Expand All @@ -24,6 +25,7 @@ public function __construct()
* Generate an SVG and send it as an HTTP response.
*
* @throws InvalidCornerRadius
* @throws InvalidUrlException
* @throws MissingTextException
* @throws InvalidSvgSizeException
* @throws InvalidFontSizeException
Expand Down
61 changes: 61 additions & 0 deletions src/SvgAvatarGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
use Sowren\SvgAvatarGenerator\Exceptions\InvalidGradientRotationException;
use Sowren\SvgAvatarGenerator\Exceptions\InvalidGradientStopException;
use Sowren\SvgAvatarGenerator\Exceptions\InvalidSvgSizeException;
use Sowren\SvgAvatarGenerator\Exceptions\InvalidUrlException;
use Sowren\SvgAvatarGenerator\Exceptions\MissingTextException;
use Sowren\SvgAvatarGenerator\Extractors\Extractor;
use URL;

class SvgAvatarGenerator
{
Expand All @@ -33,8 +35,21 @@ class SvgAvatarGenerator
*/
protected Shape $shape;

/**
* Corner radius of Rectangle shape.
*/
protected int $cornerRadius;

/**
* URL of the custom font family.
*/
protected ?string $customFontUrl;

/**
* Name of the font family.
*/
protected ?string $fontFamily;

/**
* Font size of the SVG.
*/
Expand Down Expand Up @@ -82,6 +97,7 @@ class SvgAvatarGenerator

/**
* @throws InvalidCornerRadius
* @throws InvalidUrlException
* @throws InvalidSvgSizeException
* @throws InvalidFontSizeException
* @throws InvalidGradientStopException
Expand Down Expand Up @@ -214,6 +230,48 @@ public function setCornerRadius(int $radius): static
return $this;
}

/**
* Get the custom font url.
*/
public function getCustomFontUrl(): ?string
{
return $this->customFontUrl;
}

/**
* Set the custom font url.
*
* @throws InvalidUrlException
*/
public function setCustomFontUrl(?string $url = null): static
{
if (! empty($url) && ! URL::isValidUrl($url)) {
throw InvalidUrlException::create($url);
}

$this->customFontUrl = $url;

return $this;
}

/**
* Get the SVG font family.
*/
public function getFontFamily(): ?string
{
return $this->fontFamily;
}

/**
* Set the SVG font family.
*/
public function setFontFamily(?string $name = null): static
{
$this->fontFamily = $name;

return $this;
}

/**
* Get the font size.
*/
Expand Down Expand Up @@ -383,13 +441,16 @@ protected function setGradientSet(): static
* @throws InvalidGradientRotationException
* @throws InvalidSvgSizeException
* @throws InvalidGradientStopException
* @throws InvalidUrlException
*/
protected function build(): void
{
$this
->setSize($this->config['size'])
->setShape($this->config['shape'])
->setCornerRadius($this->config['corner_radius'])
->setCustomFontUrl($this->config['custom_font_url'] ?? null)
->setFontFamily($this->config['font_family'] ?? null)
->setFontSize($this->config['font_size'])
->setFontWeight($this->config['font_weight'])
->setForeground($this->config['foreground'])
Expand Down
16 changes: 16 additions & 0 deletions tests/CustomFontTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

use Sowren\SvgAvatarGenerator\SvgAvatarGenerator;

it('will have a custom font family defined', function () {
$generator = new SvgAvatarGenerator('Saul Goodman');

$svg = (string) $generator
->setCustomFontUrl('https://api.fontshare.com/v2/css?f[]=kola@400&display=swap')
->setFontFamily('Kola')
->render();

expect($svg)
->toContain('Kola')
->toContain('@import url(https://api.fontshare.com');
});
10 changes: 8 additions & 2 deletions tests/ExceptionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use Sowren\SvgAvatarGenerator\Exceptions\InvalidGradientRotationException;
use Sowren\SvgAvatarGenerator\Exceptions\InvalidGradientStopException;
use Sowren\SvgAvatarGenerator\Exceptions\InvalidSvgSizeException;
use Sowren\SvgAvatarGenerator\Exceptions\InvalidUrlException;
use Sowren\SvgAvatarGenerator\Exceptions\MissingTextException;
use Sowren\SvgAvatarGenerator\SvgAvatarGenerator;

Expand Down Expand Up @@ -42,12 +43,17 @@
$generator->getInitials();
})->throws(MissingTextException::class);

it('it will throw exception if gradient stop less than minimum is provided', function () {
it('will throw exception if gradient stop less than minimum is provided', function () {
config(['svg-avatar.gradient_stops' => [-1, 1]]);
new SvgAvatarGenerator('Lyanna Stark');
})->throws(InvalidGradientStopException::class);

it('it will throw exception if gradient stop greater than maximum is provided', function () {
it('will throw exception if gradient stop greater than maximum is provided', function () {
config(['svg-avatar.gradient_stops' => [0, 2]]);
new SvgAvatarGenerator('Benjen Stark');
})->throws(InvalidGradientStopException::class);

it('will throw exception if invalid font url is provided', function () {
config(['svg-avatar.custom_font_url' => 'invalid_url']);
new SvgAvatarGenerator('Rickard Stark');
})->throws(InvalidUrlException::class);

0 comments on commit 78c3091

Please sign in to comment.