Skip to content

Commit

Permalink
Add fonts, review presets, update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
RobolabGs2 committed Feb 2, 2024
1 parent a64ca62 commit 17bb5c2
Show file tree
Hide file tree
Showing 13 changed files with 263 additions and 118 deletions.
29 changes: 28 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,36 @@

### Добавлено

- Шрифт Raleway.
- Шрифты:
- Bad Script
- JetBrains Mono
- Lora
- Marck Script
- Press Start 2P
- Raleway
- Tektur
- Unbounded
- Инструменты разработчика (Ctrl+F12, Shift+F12).

### Изменено

- Переименованы пресеты
- `TRUE IMPACT` -> `КАНОНИЧНЫЙ ИМПАКТ`
- `post-ironic lobster` -> `постироничный лобстер`
- `Arial bold subtitles` -> `Субтитры`
- `White Helvetica bold` -> `подпись с тенью`
- `Arial subtitles` -> `Arial с обводкой`
- `Black Arial` -> `Обычный текст`
- В персете `Субтитры` теперь тень.
- Обновлены фреймы с демонстрацией шрифтов и пресетов.

## Удалено

- Пресеты
- `Helvetica bold subtitles`
- `Black Arial bold`
- `Black Helvetica bold`

## [0.2.7] - 2024-01-31

### Добавлено
Expand Down
2 changes: 1 addition & 1 deletion src/lib/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@
</Modal>
<Modal bind:open={devTools}>
<svelte:fragment slot="title">Инструменты разработчика</svelte:fragment>
<DevTools />
<DevTools {memaker} />
</Modal>
<ClipboardErrorModal bind:fallbackBlob={showFirefoxCopyBlob} />
<MemeEditor
Expand Down
161 changes: 153 additions & 8 deletions src/lib/debug/DevTools.svelte
Original file line number Diff line number Diff line change
@@ -1,30 +1,175 @@
<script lang="ts">
import Button from '$lib/base/Button.svelte';
import Select from '$lib/base/Select.svelte';
import FrameSettings from '$lib/FrameSettings.svelte';
import { defaultBlockSettings, type Memaker } from '$lib/memaker';
import type { Block, Container, Frame, TextContent } from '$lib/meme';
import { fontsNames, prepareFontFamilyInterpolationDataZIP } from '$lib/text/fonts_store';
import { presets, applyStylePreset, defaultStyle } from '$lib/text/presets';
import { CanvasTextMeasurer } from '$lib/text/manager';
import type { TextMeasurer } from '$lib/text/metrics';
import { fontSettingsToKey, fontVariations, type TextMeasurer } from '$lib/text/metrics';
import { saveBlob } from '$lib/utils';
import { deepCopy } from '$lib/state';
import TextContentSettings from '$lib/text/TextContentSettings.svelte';
import NumberInput from '$lib/base/NumberInput.svelte';
export let memaker: Memaker;
let textContent: TextContent = {
text: 'Широкая электрификация южных губерний\nдаст мощный толчок подъёму сельского хозяйства.',
style: deepCopy(defaultStyle)
};
let frameSettings: Frame = {
id: 'placeholer',
backgroundAlpha: 1,
backgroundColor: '#ffffff',
height: 1080,
width: 1920,
blocks: []
};
let textMeasurer: TextMeasurer;
let fontFamily = '';
let columns = 2;
function generateData() {
if (!textMeasurer) textMeasurer = new CanvasTextMeasurer();
const fontFamily = textContent.style.font.family;
prepareFontFamilyInterpolationDataZIP(textMeasurer, fontFamily).then(
saveBlob(`${fontFamily}.zip`)
);
}
function addBlocksGrig(
frame: Frame,
rows: number,
columns: number,
newBlock: (container: Container, i: number, row: number, col: number) => Block,
count = rows * columns
) {
memaker.addFrame(frame);
const frameWidth = frame.width;
const frameHeight = frame.height;
const blockHeight = frameHeight / rows;
const blockWidth = frameWidth / columns;
for (let i = 0; i < count; i++) {
const row = i % rows | 0;
const col = (i / rows) | 0;
const container: Container = {
type: 'rectangle',
value: {
height: blockHeight,
width: 0.9 * blockWidth,
position: {
x: blockWidth / 2 + col * blockWidth,
y: blockHeight / 2 + row * blockHeight
},
rotation: 0
}
};
memaker.cloneBlock(newBlock(container, i, row, col));
}
}
function fontTestFrame(family = textContent.style.font.family) {
const variations = fontVariations(family);
const rows = Math.ceil(variations.length / columns);
addBlocksGrig(
deepCopy(frameSettings),
rows,
columns,
(container, i) => {
const fontSettings = variations[i];
const text = `${fontSettingsToKey(fontSettings).replaceAll('_', ' ')}\n${textContent.text}`;
return {
...defaultBlockSettings(),
id: 'placeholder',
container,
content: {
type: 'text',
value: {
text,
style: {
...deepCopy(textContent.style),
font: fontSettings
}
}
}
};
},
variations.length
);
}
function fontsTestFrame() {
const fontsCount = $fontsNames.length;
const rows = Math.ceil(fontsCount / columns);
addBlocksGrig(
deepCopy(frameSettings),
rows,
columns,
(container, i) => {
const family = $fontsNames[i];
const text = `${family}\n${textContent.text}`;
return {
...defaultBlockSettings(),
id: 'placeholder',
container,
content: {
type: 'text',
value: {
text,
style: {
...deepCopy(textContent.style),
font: {
...deepCopy(textContent.style.font),
family
}
}
}
}
};
},
fontsCount
);
}
function presetsTestFrame() {
const presetsCount = $presets.length;
const rows = Math.ceil(presetsCount / columns);
addBlocksGrig(
deepCopy(frameSettings),
rows,
columns,
(container, i) => {
const preset = $presets[i];
const text = `${preset.name}\n${textContent.text}`;
return {
...defaultBlockSettings(),
id: 'placeholder',
container,
content: {
type: 'text',
value: {
text,
style: applyStylePreset(preset, deepCopy(textContent.style))
}
}
};
},
presetsCount
);
}
</script>

<main>
<section>
<Button type="primary" disabled={!fontFamily} on:click={generateData}>
Сгенерировать данные для шрифта
<Button type="primary" on:click={() => fontTestFrame()}>Фрейм с вариациями шрифта</Button>
<Button type="primary" on:click={() => $fontsNames.forEach((family) => fontTestFrame(family))}>
Фреймы для всех шрифтов
</Button>
<Select type="primary" bind:value={fontFamily} items={$fontsNames} let:item>
{item || 'Выберите шрифт'}
</Select>
</section>
<section>
<Button type="primary" on:click={fontsTestFrame}>Фрейм со шрифтами</Button>
<Button type="primary" on:click={presetsTestFrame}>Фрейм с пресетами</Button>
</section>
<section>
<section>Колонки: <NumberInput bind:value={columns} /></section>
<FrameSettings bind:value={frameSettings} />
</section>
<TextContentSettings bind:content={textContent} />
<Button type="danger" on:click={generateData}>Сгенерировать данные для шрифта</Button>
</main>

<style lang="scss">
Expand Down
9 changes: 7 additions & 2 deletions src/lib/memaker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function isSkinsMap(raw: Record<string, Record<string, FileImport[]>>): r
return Object.values(raw).every(isSkin);
}

function defaultBlockSettings(): Omit<Block, 'id' | 'container' | 'content'> {
export function defaultBlockSettings(): Omit<Block, 'id' | 'container' | 'content'> {
return {
effects: [],
layer: { blendMode: 'normal', composeMode: 'source_over', alpha: 1.0 }
Expand Down Expand Up @@ -487,7 +487,12 @@ export class Memaker {
: this.newFrame(
this.placeholdersTextures[Math.floor(Math.random() * this.placeholdersTextures.length)]
);
this.meme.frames.push(frame);
let index = this.meme.frames.length;
if (index) {
const currentIndex = this.meme.frames.findIndex((frame) => frame === this.activeFrame);
if (currentIndex != -1) index = currentIndex + 1;
}
this.meme.frames.splice(index, 0, frame);
this.activeFrame = frame;
frame.blocks.forEach((b) => this.addImageUsage(b));
this.memeUpdated();
Expand Down
6 changes: 4 additions & 2 deletions src/lib/meme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,11 @@ export class FrameDrawer {
drawFrame(frame: Frame) {
this.graphics.resize(frame.width, frame.height);
const gl = this.gl;
const backgroundAlpha = frame.backgroundAlpha ?? 1.0;
const backgroundColor = parseColorBytes(frame.backgroundColor ?? '#ff0000').map((c) => c);
twgl.setTextureFromArray(gl, this.backgroundTexture, [
...parseColorBytes(frame.backgroundColor ?? '#ff0000'),
(frame.backgroundAlpha ?? 1.0) * 255
...backgroundColor,
backgroundAlpha * 255
]);
let effectBuffer = this.graphics.buffersPull.get(frame.width, frame.height);
const layerBuffer = this.graphics.buffersPull.get(frame.width, frame.height);
Expand Down
Binary file modified src/lib/resources/placeholders/default/empty/3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 13 additions & 2 deletions src/lib/text/TextSettings.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,19 @@
{/each}
</section>
</DropDown>
<Select title="Шрифт" bind:value={font.family} items={$fontsNames} on:change let:item>
<section style="font-family: {item}">{item}</section>
<Select
css={{
height: '48px',
width: '100%',
main: 'min-width: 128px;'
}}
title="Шрифт"
bind:value={font.family}
items={$fontsNames}
on:change
let:item
>
<section style="font-family: '{item}'">{item}</section>
</Select>
<Select
title="Регистр"
Expand Down
2 changes: 1 addition & 1 deletion src/lib/text/font.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ export function fontSettingsToCSS({ italic, smallCaps, bold, family }: FontSetti
const style = italic ? 'italic' : 'normal';
const variant = smallCaps ? 'small-caps' : 'normal';
const weight = bold ? 'bold' : 'normal';
return `${style} ${variant} ${weight} ${size}px ${family}`;
return `${style} ${variant} ${weight} ${size}px "${family}"`;
}
Binary file modified src/lib/text/fonts_metrics.zip
Binary file not shown.
31 changes: 20 additions & 11 deletions src/lib/text/fonts_store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,26 @@ import {
type TextMeasurer
} from './metrics';

export const fontsNames = writable([
'Impact',
'Lobster',
'Arial',
'Helvetica',
'Next art',
'Pacifico',
'Caveat',
'Comforter',
'Raleway'
]);
export const fontsNames = writable(
[
'Arial', // Гротеск
'Impact', // Брусковый гротеск
'Lobster', // Рукописный
'Helvetica', // Гротеск
'Next art', // Гротеск?
'Pacifico', // Рукописный
'Caveat', // Рукописный
'Comforter', // Рукописный
'Raleway', // Гротеск
'Lora', // С засечками/антиква
'Marck Script', // Рукописный
'Bad Script', // Рукописный
'Tektur', // Гротеск?
'Unbounded',
'Press Start 2P', // Пиксельный
'JetBrains Mono' // Моноширинный гротеск?
].sort()
);

export function loadFontStatisticsCSV(url: string) {
const store = new FontMetricsStore();
Expand Down
8 changes: 8 additions & 0 deletions src/lib/text/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,14 @@ export function fontFamilyStatistics(measurer: TextMeasurer, family: string) {
return statistics;
}

export function fontVariations(family: string): FontSettings[] {
const variations = new Array<FontSettings>();
for (const italic of [false, true])
for (const smallCaps of [false, true])
for (const bold of [false, true]) variations.push({ family, italic, smallCaps, bold });
return variations;
}

export class FontMetricsStore {
data?: Map<string, FontMetrics>;
get(font: FontSettings): FontMetrics {
Expand Down
Loading

0 comments on commit 17bb5c2

Please sign in to comment.