Commit 7db91930 authored by bzt's avatar bzt

More editor stuff

parent ccf3c585
......@@ -378,7 +378,8 @@ to get valid results. For this purpose, you can pass `SSFN_MODE_NONE` to the ren
`SSFN_FAMILY_BYNAME` to select exactly one font, and then you don't have to call ssfn_render). If
the character or the kerning pair not found, `x`and `y` will be left unchanged.
Kerning also takes glyph variants into considerations if `ssfn_variant()` used.
If you have use `ssfn_variant()` before rendering, then the same kerning modifier will be applied to
the advance value of the given variant.
### Parameters
......
......@@ -45,6 +45,8 @@ to detect optional blocks (see below).
### Glyphs
#### Vectors
Lines starting with `+!` are scalable character definitions, and look like `+!---(unicode)-(adv x)-(adv y)---` which
may be followed by comments (usually hex and UTF-8 representation of the code point), ended in a newline. After that
optionally comes two lines, one prefixed by `H`, the other `V` if there's a horizontal or vertical
......@@ -54,17 +56,28 @@ which identifies important grid coordinates.
H (x0) (x1) (xN) ...
V (y0) (y1) (yN) ...
```
Then the contour commands (move to, line to, quadratic curve to, bezier curve to, set color) follows, one of
Then the contour commands (move to, line to, quadratic curve to, bezier curve to, set color, set gradient) follows, one of
```
m (x),(y)
l (x),(y)
q (x),(y) (a),(b)
b (x),(y) (a),(b) (c),(d)
c (aarrggbb)
g (aarrggbb) (aarrggbb) (aarrggbb) (aarrggbb)
```
The contour path must start with a move command and goes on until the first line which does not start with a
The contour path must start with a move to (m) command and goes on until the first line which does not start with a
valid command.
Gradients contain 4 color codes for upper left, upper right, bottom left, bottom right corners of the glyph in order.
If one color is not specified, then it defaults to the foreground color and specified as a dot '.'. There can be only
one color (c) or gradient (g) command in a path, and if there is, it must come right after the move to command.
Line to (l), quadratic Bezier curve (q) to and cubic Bezier curve to (b) commands can be repeated as many times as
needed to describe a path. If the last command does not return to the move to command's coordinate, then an implicit
line to command will be added to close the path.
#### Bitmaps
Lines starting with `++` encode bitmap character definitions, and look like `++---(unicode)---` which may be followed
by comments (if advance is the same as bitmap width). Lines starting with `+=` also encode bitmap characters, but
similarily to contours, with advance values: `+=---(unicode)-(adv x)-(adv y)---`. After these lines comes a block which
......@@ -72,6 +85,8 @@ has glyph height lines, and each line has the same length. Those lines can conta
transparency, and 'X' (or anything else except '+') to encode foreground. The block goes on until the first line which
does not start with valid bitmap character.
#### Pixmaps
Lines starting with `+%` encode pixmap character definitions, and look like `+%---(unicode)-(adv x)-(adv y)---`.
After this line come glyph height lines with glyph width times hex colors `(aarrggbb)` in each, separated by a space.
Each line encode one row of the pixmap. The values `00000000` and `FF000000` mean transparency, which can be written
......@@ -101,7 +116,7 @@ offset. Coordinates can be negative values as well. If there's more, a comma com
The list is ended by an empty line or a `+@` character pair. This means that space and newline characters can't have
kerning information, but that's perfectly fine. If there's both horizontal and vertical value, now you must repeat
the UTF-8 sequence. In the future, `(right char) (coord)h (coord)v` format should be recognised.
the UTF-8 sequence. In the future, `(right char) (coord)h (coord)v, (right char) ...` format should be recognised.
### End Tag
......
Scalable Screen Font Editor
===========================
All windows are splited vertically into a tab navigation bar (on the top), and a
tab area (the rest, bigger part of the window). By clicking on the tab label in the
navigation bar, you can switch the tab area.
These keyboard shortcuts work in all windows.
| Key Combination | Description |
| --------------- | ----------- |
| <kbd>Esc</kbd> | Close the window |
| <kbd>Ctrl</kbd>+<kbd>s</kbd> | Save the font in SSFN format |
| <kbd>Shift</kbd>+<kbd>Ctrl</kbd>+<kbd>s</kbd> | Save the font in ASC format |
| <kbd>Tab</kbd> | Switch to next tab |
| <kbd>Shift</kbd>+<kbd>Tab</kbd> | Switch to previous tab |
Main Window
-----------
There's only one main window per font. If you want to edit more fonts in paralell,
then you have to start more instances of `sfnedit`. If you close this window, then
all windows will be closed and the application quits. If there are unsaved modifications
on the font, then you will be asked if you want to save them.
## Properties Tab
<img src='https://gitlab.com/bztsrc/scalable-font/raw/master/docs/sfnedit1.png'>
This tab shows the properties of the font. Changes made here are non-irreverisible,
meaning you cannot undo them. Changing grid size can take for a while, as it requires
the recalculation of all vector coordinates and the resize of all bitmap and pixmap
glyphs.
| Key Combination | Description |
| --------------- | ----------- |
| <kbd>Down</kbd> | Switch to next field |
| <kbd>Up</kbd> | Switch to previous field |
| <kbd>Right</kbd> | Change to next value (if applicable) |
| <kbd>Left</kbd> | Change to previous value (if applicable) |
| <kbd>Space</kbd> | Toggle check box value |
## Ranges Tab
<img src='https://gitlab.com/bztsrc/scalable-font/raw/master/docs/sfnedit2.png'>
This tab gives an overview of which characters are defined in the font. By clicking
"Uncovered ranges" the UNICODE blocks with absolutely no glyphs will be shown too.
It is possible to have more than 100% coverage if glyphs are defined for code points
undefined by UNICODE Inc.
| Key Combination | Description |
| --------------- | ----------- |
| <kbd>Space</kbd> | Toggle "Uncovered ranges" (if search is inactive) |
| <kbd>Down</kbd> / <kbd>Up</kbd> | Scroll the list |
| <kbd>Enter</kbd> | Select a range |
| any other key | Start a search |
You can search for UNICODE block names (both normal and short versions), and with
hex number for a range that contains that specific code point.
## Characters Tab
<img src='https://gitlab.com/bztsrc/scalable-font/raw/master/docs/sfnedit3.png'>
Here you can see the characters. If you have came here by selecting a range, then
the list will be restricted to that range. By clicking on tab label or switching
to this tab by pressing the <kbd>Tab</kbd>, you'll see the whole vast UNICODE range.
| Key Combination | Description |
| --------------- | ----------- |
| <kbd>Down</kbd> / <kbd>Up</kbd> | Scroll the list |
| <kbd>Left</kbd> / <kbd>Right</kbd | Select a glyph variant table |
| <kbd>Shift</kbd> + left click and move | Select a range |
| <kbd>Ctrl</kbd> + <kbd>c</kbd> | Copy the selected range to clipboard |
| <kbd>Ctrl</kbd> + <kbd>x</kbd> | Cut out the selected range and store it to clipboard |
| <kbd>Ctrl</kbd> + <kbd>p</kbd> | Paste a range from clipboard to cursor position |
| left click | Open glyph window for the character |
| any other key | Start a search |
You can search for a UNICODE code point name, for an UTF-8 character, or with a hex
number for a particular code point.
Glyph Windows
-------------
You can have as many of these windows as you want, but only one per character. In this
window you can edit and modify the properties of a glyph. Modification history is
accessible until you close this window, meaning you can undo anything up to the point
when you opened the window.
## Edit Tab
This is the main editing tab. On the left, there're icons, and on the right, which
occupies the rest of the window, is the edit area.
### Toolbar
You can select an icon from the toolbar by clicking, they are in order:
- Change horizontal advance
- Change vertical advance
- Set up hinting grid points
- Delete the entire glyph
- Remove glyph layer
- Edit glyph layer
- Add vector glyph layer
If you select "Delete the entire glyph", then you'll be asked for confirmation. If you
delete layers accidentally with "Remove glyph layer", don't be alarmed, just press undo.
If you click and hold down left mouse button on the "Add vector glyph layer" icon, then two
more icons will show up. You can select those by moving the pointer above them, and release the
mouse button there. They are "Add bitmap glyph layer" and "Add pixmap glyph layer". If you
already have a bitmap or pixmap layer, then no new layer will be added, but the appropriate
layer will be activated.
### Layers
Beneath the icon toolbar, you can see the available layers. There's only one bitmap or
pixmap layer, but you can have as many vector layers as you want. Moving the mouse pointer
above the layers and using the wheel you can scroll them. By clicking on one layer it will
became active, and the toolbar will switch to the "Edit glyph layer" icon.
### Color Selector
If you have choosen a vector layer, then you'll see 4 color boxes. Clicking on one of those
will bring up the palette and the color selector. With these you can specify the color gradients
to be used for that glyph layer.
If you have choosen the pixmap layer, then you'll see only one color box. Clicking on it will
bring up the palette, and also by scrolling vertically or using the mouse wheel with holding
<kbd>Shift</kbd> down, you can cycle through the palette. When you left click on the edit area,
the pixel under the pointer will change to this color.
To select a color (for gradient or pixmap), you have to click on the palette. At first, when your
palette is empty, all colors will be transparent. After selecting the palette index, the color
selector will show up. You can specify the color for that particular palette index there. The last
color, the 240th, which is in it's own line, is for selecting the background. That one is always
transparent and it does not bring up the color selector either.
### Coordinates
Whenever your mouse pointer is above the edit area, you'll see here on the bottom left corner
the coordinates in font's grid resolution, X axis above, and Y below.
### Edit Area
| Key Combination | Description |
| --------------- | ----------- |
| <kbd>g</kbd> | Toggle grid |
| <kbd>l</kbd> | Toggle lines for control points |
| <kbd>Shift</kbd> + left click and move | Select portion of the glyph |
| <kbd>Ctrl</kbd> + <kbd>c</kbd> | Copy the selected portion to clipboard |
| <kbd>Ctrl</kbd> + <kbd>x</kbd> | Cut out the selected portion and store it to clipboard |
| <kbd>Ctrl</kbd> + <kbd>p</kbd> | Paste a portion from clipboard to cursor position |
| <kbd>Ctrl</kbd> + <kbd>z</kbd> | Undo |
| <kbd>Ctrl</kbd> + <kbd>y</kbd> | Redo |
| left click | Select a point, or set foreground for bitmap and pixmap layers |
| left click + move | Without a selected point, move the canvas |
| left click + move | With a selected point (either on-curve or control), move that point |
| <kbd>Ctrl</kbd> + left click | Add a line to contour |
| <kbd>GUI</kbd> + left click | Add a cubic Bezier curve to contour |
| <kbd>Alt</kbd> + left click | Add a quadratic Bezier curve to contour |
| <kbd>Ctrl</kbd> + <kbd>GUI</kbd> + left click | Add a quadratic Bezier curve to contour |
| right click | Remove last contour, or clear to transparency for bitmap and pixmap layers |
| wheel | zooming in or out |
Grid lines are only shown if there's at least 2 pixels between grid coordinates. This means for
vector glyphs with large grids, you'll have to zoom in a lot until the grid finally shows up.
Control points (green X) cannot be moved beyond the bounding box of the layer, defined by the
on-curve points (blue dots). The editor tries to force this intelligently, not only when you move
a control point, but also when you move an on-curve point which defines one or more sides of the
bounding box. In the latter case, if you press undo, then not only the on-curve point, but all
modified control points will be restored too.
## Kerning
TODO
......@@ -183,12 +183,13 @@ offsets to the magic for fast access (see section Characters Table below).
| 00nnnnnn | 0 | Contour, up to 64 elements |
| 01NNNNNN | 1 | Contour, number of elements: (N << 8 + additional byte) + 1 |
Contour is described by a path, which consist of N+1 elements. There are four possible path
commands (move to, line to, quadratic Bezier curve to, cubic Bezier curve to), but how
they are stored with their point arguments heavily depend on the font's quality. The
"move to" and "line to" commands are encoded in 2 to 3 bytes, curves in 4 to 8 bytes.
(Grid sizes 2048 and above are not implemented yet, and probably never will be. 1024 x 1024
must be enough for a single screen letter.)
Contour is described by a path, which consist of N+1 elements. There are six possible path
commands (move to, line to, quadratic Bezier curve to, cubic Bezier curve to, set color,
set gradient), but how they are stored with their point arguments heavily depend on the
font's quality. The "move to" and "line to" commands are encoded in 2 to 3 bytes, curves in
4 to 8 bytes, color and gradient 2 to 5 bytes. (Grid sizes 2048 and above are not implemented
yet, and probably never will be. 1024 x 1024 should be enough for a single screen letter, as a
matter of fact most fonts can be stored on 256 x 256 grid without loosing any typeface detail.)
A path always starts with a "move to" command, which is not included in the number of commands,
and that's the only "move to" command the path can have. In other words a "move to" always defines
......@@ -199,59 +200,55 @@ a new path. So the contour fragment's header is followed by two coordinates:
| 0-4 | 256 | move to | 2 | xxxxxxxx xyyyyyyy |
| 5-8 | 4096 | move to | 3 | YYYYXXXX xxxxxxxx xyyyyyyy |
After that other commands follow, depending on quality:
If the path has a "color" or "gradient" command, it must come right after the "move to", and there
can be only one of them per path. The color command selects an ARGB from the color map. With gradients,
four colors are selected, which represents the four corners of the fragment's bounding box, c=top left,
d=top right, e=bottom left and f=bottom right. The glyph must be rasterized with gradients between
those. Color indeces above 239 selects the foreground color (see Pixmap fragment and Color Map).
| Quality | Grid size | Path command | Bytes | Command format |
| ------: | --------: | -------------- | ----: | -------------- |
| 0-3 | 128 | color (1) | 2 | 0000000C 0ccccccc |
| 0-3 | 128 | color | 2 | 0000000C 0ccccccc (where (uppercase<<7 + lowercase) gives the color index) |
| 0-3 | 128 | color gradient | 5 | 0000010C 0ccccccc dddddddd eeeeeeee ffffffff |
| 4-8 | 4096 | color | 2 | 00000000 cccccccc |
| 4-8 | 4096 | color gradient | 5 | 00000100 cccccccc dddddddd eeeeeeee ffffffff |
After that other commands follow, depending on quality:
| Quality | Grid size | Path command | Bytes | Command format |
| ------: | --------: | -------------- | ----: | -------------- |
| 0-3 | 128 | line to | 2 | 1xxxxxxx 0yyyyyyy |
| 0-3 | 128 | quad curve to | 4 | 0xxxxxxx 1yyyyyyy 0aaaaaaa 0bbbbbbb (where (a,b) is the control point) |
| 0-3 | 128 | cubic curve to | 6 | 1xxxxxxx 1yyyyyyy 0aaaaaaa 0bbbbbbb 0ccccccc 0ddddddd (where c1=(a,b), c2=(c,d)) |
| - | - | - | - | - |
| 4 | 256 | color | 2 | 00000000 cccccccc |
| 4 | 256 | color gradient | 5 | 00000100 cccccccc dddddddd eeeeeeee ffffffff |
| 4 | 256 | line to | 3 | 00000001 xxxxxxxx yyyyyyyy |
| 4 | 256 | quad curve to | 4 | 00000010 xxxxxxxx yyyyyyyy aaaaaaaa bbbbbbbb |
| 4 | 256 | cubic curve to | 6 | 00000011 xxxxxxxx yyyyyyyy aaaaaaaa bbbbbbbb cccccccc dddddddd |
| - | - | - | - | - |
| 5 | 512 | color | 2 | 00000000 cccccccc |
| 5 | 512 | color gradient | 5 | 00000100 cccccccc dddddddd eeeeeeee ffffffff |
| 5 | 512 | line to | 3 | 0000YX01 xxxxxxxx yyyyyyyy (where (uppercase<<8 + lowercase) gives the coordinate) |
| 5 | 512 | quad curve to | 5 | 00BAYX10 xxxxxxxx yyyyyyyy aaaaaaaa bbbbbbbb |
| 5 | 512 | cubic curve to | 7 | DCBAYX11 xxxxxxxx yyyyyyyy aaaaaaaa bbbbbbbb cccccccc dddddddd |
| - | - | - | - | - |
| 6 | 1024 | color | 2 | 00000000 cccccccc |
| 6 | 1024 | color gradient | 5 | 00000100 cccccccc dddddddd eeeeeeee ffffffff |
| 6 | 1024 | line to | 3 | 00YYXX01 xxxxxxxx yyyyyyyy |
| 6 | 1024 | quad curve to | 6 | 00YYXX10 xxxxxxxx yyyyyyyy 0000BBAA aaaaaaaa bbbbbbbb |
| 6 | 1024 | cubic curve to | 8 | 00YYXX11 xxxxxxxx yyyyyyyy DDCCBBAA aaaaaaaa bbbbbbbb cccccccc dddddddd |
| - | - | - | - | - |
| 7 (2) | 2048 | color | 2 | 00000000 cccccccc |
| 7 | 2048 | color gradient | 5 | 00000100 cccccccc dddddddd eeeeeeee ffffffff |
| 7 | 2048 | line to | 3 | YYYXXX01 xxxxxxxx yyyyyyyy |
| 7 (1) | 2048 | line to | 3 | YYYXXX01 xxxxxxxx yyyyyyyy |
| 7 | 2048 | quad curve to | 6 | YYYXXX10 xxxxxxxx yyyyyyyy 0BBB0AAA aaaaaaaa bbbbbbbb |
| 7 | 2048 | cubic curve to | 9 | YYYXXX11 xxxxxxxx yyyyyyyy 0BBB0AAA aaaaaaaa bbbbbbbb 0DDD0CCC cccccccc dddddddd |
| - | - | - | - | - |
| 8 (2) | 4096 | color | 2 | 00000000 cccccccc |
| 8 | 4096 | color gradient | 5 | 00000100 cccccccc dddddddd eeeeeeee ffffffff |
| 8 | 4096 | line to | 4 | 00XXXX01 xxxxxxxx 0000YYYY yyyyyyyy |
| 8 (1) | 4096 | line to | 4 | 00XXXX01 xxxxxxxx 0000YYYY yyyyyyyy |
| 8 | 4096 | quad curve to | 7 | 00XXXX10 xxxxxxxx 0000YYYY yyyyyyyy BBBBAAAA aaaaaaaa bbbbbbbb |
| 8 | 4096 | cubic curve to | 10 | 00XXXX11 xxxxxxxx 0000YYYY yyyyyyyy BBBBAAAA aaaaaaaa bbbbbbbb DDDDCCCC cccccccc dddddddd |
Note(1): the color command selects an ARGB from the color map. With gradients, four colors are selected, which
represents the four corners of the bounding box, c=top left, d=top right, e=bottom left and f=bottom right. The
glyph must be rasterized with gradients between those. If a "color" or "gradient" command present, it must come
right after the implicit "move to" command.
Note(2): contour commands for grid size 2048 and above are not implemented yet.
Note(1): contour commands for grid size 2048 and above are specified, but not implemented yet.
### Bitmap Fragment
| 1st byte | More bytes | Description |
| -------- | ---------- | ----------- |
| 100ppppp | h | Bitmap (up to 256x256) |
| 1010PPHH | p,h | Large bitmap |
| 100ppppp | h | Small bitmap (up to 256 x 256) |
| 1010PPHH | p,h | Large bitmap (up to 1024 x 1024) |
First byte encodes type and the pitch (number of bytes per row), the second byte the number of rows (height).
Bitmap widths are always multiple of 8.
......@@ -276,11 +273,11 @@ It is not possible to store separate alpha channel with this format (color map h
include a compressed pixmap bigger than 64k, then you're definitely doing the font thing wrong.
Compression: TGA RLE (not that bad ratio and damn easy to decode with a minimal code). Packets start
with a header byte, which encodes N (= header & 0x7F + 1). If header bit 7 is set, then next byte should
be repeated N times, if not, then the next N bytes are all indeces.
with a header byte, which encodes N (= header & 0x7F). If header bit 7 is set, then next byte should
be repeated N+1 times, if not, then the next N+1 bytes are all indeces.
NOTE: pixmaps are not splitted on the x axis, only on the y. A much much better compression ratio could
be achieved with that.
NOTE: currently pixmaps are not splitted on the x axis, only on the y. A much much better compression ratio
could be achieved using both axis.
| 1st byte | More bytes | Description |
| -------- | ---------- | ----------- |
......@@ -295,8 +292,8 @@ If you need many colors or separate alpha channel. To be implemented.
| 1110nnnn | 0 | number of autohint grid relative distances (up to 16) |
| 1111NNNN | 1 | number of autohint grid relative distances |
After that cames N+1 relative coordinates in 1 or 2 bytes each. The size depends on font quality, it's
a unsigned char if quality is less than 5, othervise it's a unsigned short int. Those are relative
After that cames N+1 relative coordinates in 1 or 2 bytes each. The size depends on header feature bit 6, it's
a unsigned char (1 byte) if feature bit is unset, othervise it's a unsigned short int (2 bytes). Those are relative
grid system distances to identify grid partitions in [hinting](https://gitlab.com/bztsrc/scalable-font/blob/master/docs/hinting.md).
Character Mappings
......@@ -317,16 +314,17 @@ mandatory.
| 11NNNNNN | 1 | Skip N+1 code points (N << 8 + additional byte, up to 16384) |
In edge case, when the variant does not encode any characters (shouldn't happen, at least
one character required), then the characters table contains 68 skip runs to cover the
entire UNICODE range, which is 136 bytes in the file. In this case the table's offset in
header is zero, and no runs are stored.
one character required), then the characters table would contain 68 skip runs to cover the
entire UNICODE range, which would need 136 bytes in the file (if the table is empty, then
the table's offset in font header is zero, and no runs are stored at all).
A TrueType font usually contains 2 or 3 tops composite glyphs. SSFN can store more than a
hundred compositions, and it compresses the glyphs by storing normalized glyph fragments.
The glyph for the 0th character is interpreted as a not defined glyph, which can be shown for
every character that is skipped. If no glyph is defined for the 0th character, then the
application should render an empty box (it can also write the hex code point inside the box).
The glyph for the 0th character of the first (default) variant is interpreted as a not defined
glyph, which can be shown for every character that is skipped. If no glyph is defined for the
0th character, then the application should render an empty box (it can also write the hex code
point inside the box).
### Glyph Header
......@@ -384,9 +382,9 @@ Otherwise (offset is above 1048576 or quality is above 6):
| 4 | 1 | x offset |
| 5 | 1 | y offset |
The offsets are relative to character's bearing. For hinting grid, the offset is one smaller,
therefore if bearing is zero, x=1 and y=0 encodes horizontal grid, and x=0 and y=1 vertical
grid hints.
The fragment offset is relative to the magic, and coordinate offsets are relative to character's
bearing. For hinting grid, the offset is one bigger, therefore if bearing is zero, x=1 and y=0
encodes horizontal grid, and x=0 and y=1 vertical grid hints.
Kerning Table (optional)
------------------------
......@@ -450,7 +448,7 @@ short int (depends on font header feature bit 5).
| -----: | -----: | ----------- |
| 2/3 | 1/2 | relative coordinate |
Note that feature bit 4 is independent from the grid size. It is possible that a 1024 grid font does
Note that feature bit 5 is independent from the grid size. It is possible that a 1024 grid font does
not use kerning offsets bigger than -128 .. 127 pixels, and thus does not need large coordinates in
the kerning table. On the other hand, 128 grid size will never use large coordinates for sure.
......
docs/sfnedit4.png

11.6 KB | W: | H:

docs/sfnedit4.png

11.8 KB | W: | H:

docs/sfnedit4.png
docs/sfnedit4.png
docs/sfnedit4.png
docs/sfnedit4.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -29,8 +29,8 @@
#include <stdlib.h>
#include <stdio.h>
#include "file.h"
#include "ui.h"
#include "file.h"
void view_layers(ui_win_t *win);
void view_coords(ui_win_t *win);
......
This diff is collapsed.
......@@ -31,8 +31,8 @@
#include <stdio.h>
#include <string.h>
#include "lang.h"
#include "file.h"
#include "ui.h"
#include "file.h"
#include "util.h"
#include "unicode.h"
#if HAS_ZLIB
......@@ -41,7 +41,7 @@
extern char gz;
ssfn_font_t *font = NULL;
char *fontfile = NULL, *fontfilebn = NULL, gzipped = 0;
char *fontfile = NULL, *fontfilebn = NULL, *fontfileext = NULL, gzipped = 0;
char *strtable[6];
uint32_t cmap[241];
uint8_t *cpal = (uint8_t*)&cmap, cpalidx[241], cpalrev[241];
......@@ -228,6 +228,7 @@ void file_delchar(int v, int chr)
numchars[v]--;
chars[v] = (char_t*)realloc(chars[v], numchars[v]*sizeof(char_t));
if(!chars[v]) error("file_delchar", ERR_MEM);
modified = 1;
}
/**
......@@ -466,7 +467,12 @@ void file_load(char *filename)
uint8_t *ptr, *end, *e, *bitmap, cmd;
char_t *c;
fontfile = filename;
i = strlen(filename);
fontfile = malloc(i+1);
if(!fontfile) error("file_load", ERR_MEM);
memcpy(fontfile, filename, i+1);
for(fontfilebn = fontfile + i; fontfilebn > fontfile && *(fontfilebn-1) != '/'; fontfilebn--);
for(fontfileext = fontfile + i; fontfileext > fontfilebn && (*(fontfileext-1) != '.' || *fontfileext == 'g'); fontfileext--);
ptr = load_file(fontfile, (int*)&size);
/* new file */
......@@ -798,11 +804,13 @@ void file_load(char *filename)
*/
void file_savesfn(int idx)
{
if(!fontfile) return;
if(!fontfile || !fontfileext) return;
memcpy(fontfileext, "sfn", 3);
file_sortcmap();
ui_saving(idx, 1000);
sleep(1);
ui_saving(idx, -1);
modified = 0;
}
/**
......@@ -810,10 +818,12 @@ void file_savesfn(int idx)
*/
void file_saveasc(int idx)
{
if(!fontfile) return;
if(!fontfile || !fontfileext) return;
memcpy(fontfileext, "asc", 3);
ui_saving(idx, 200000);
sleep(1);
ui_saving(idx, 0);
modified = 0;
}
/**
......@@ -822,6 +832,7 @@ void file_saveasc(int idx)
void file_setquality(int idx, int q)
{
if((q < 0 && font->quality == 0) || (q > 0 && font->quality == 6)) return;
modified = 1;
font->quality += q;
if(q<0) {
font->baseline >>= 1;
......@@ -839,6 +850,7 @@ void file_setquality(int idx, int q)
*/
void file_setbaseline(int idx)
{
modified = 1;
ui_saving(idx, 400000);
sleep(1);
}
......
......@@ -32,16 +32,6 @@
# include <ssfn.h>
#endif
typedef struct {
int type;
int px;
int py;
int c1x;
int c1y;
int c2x;
int c2y;
} cont_t;
typedef struct {
int type;
int len;
......
......@@ -35,6 +35,8 @@
#include "lang.h"
#include "util.h"
extern int minx, miny, maxx, maxy, movex, movey;
/**
* Undo
*/
......@@ -55,9 +57,11 @@ void hist_undo(ui_win_t *win)
win->frag = 0;
break;
case HIST_SETPIXEL: ((uint8_t*)frags[his->frag].data)[his->idx] = his->data.pixel.oldpix; break;
case HIST_SETADV: chr->adv_x = his->data.adv.oldx; chr->adv_y = his->data.adv.oldy; break;
case HIST_DELCONT: file_contadd(his->frag, his->data.cont.type, his->data.cont.px, his->data.cont.py,
his->data.cont.c1x, his->data.cont.c1y, his->data.cont.c2x, his->data.cont.c2y); break;
case HIST_ADDCONT: if(frags[his->frag].len) frags[his->frag].len--; break;
case HIST_MOVEPT: memcpy(frags[his->frag].data, his->data.contlist.oldc, frags[his->frag].len*sizeof(cont_t)); break;
}
}
}
......@@ -79,9 +83,11 @@ void hist_redo(ui_win_t *win)
file_removefrag(chr, i); if(win->frag > chr->len) { win->frag--; }
break;
case HIST_SETPIXEL: ((uint8_t*)frags[his->frag].data)[his->idx] = his->data.pixel.newpix; break;
case HIST_SETADV: chr->adv_x = his->data.adv.newx; chr->adv_y = his->data.adv.newy; break;
case HIST_DELCONT: if(frags[his->frag].len) frags[his->frag].len--; break;
case HIST_ADDCONT: file_contadd(his->frag, his->data.cont.type, his->data.cont.px, his->data.cont.py,
his->data.cont.c1x, his->data.cont.c1y, his->data.cont.c2x, his->data.cont.c2y); break;
case HIST_MOVEPT: memcpy(frags[his->frag].data, his->data.contlist.newc, frags[his->frag].len*sizeof(cont_t)); break;
}
win->histmin++;
}
......@@ -98,6 +104,14 @@ void hist_cleanup(ui_win_t *win, int idx)
for(i=idx;i<win->histmax;i++)
switch(win->hist[i].type) {
case HIST_DELLAYER: file_delfrag(win->hist[i].frag); break;
case HIST_MOVEPT:
if(win->hist[i].data.contlist.oldc)
free(win->hist[i].data.contlist.oldc);
win->hist[i].data.contlist.oldc = NULL;
if(win->hist[i].data.contlist.newc)
free(win->hist[i].data.contlist.newc);
win->hist[i].data.contlist.newc = NULL;
break;
}
}
}
......@@ -105,12 +119,14 @@ void hist_cleanup(ui_win_t *win, int idx)
/**
* Allocate memory for a new history element
*/
int hist_add(ui_win_t *win)
int hist_add(ui_win_t *win, int type)
{
hist_cleanup(win, win->histmin);
win->histmax = win->histmin + 1;
win->hist = (hist_t*)realloc(win->hist, win->histmax*sizeof(ui_win_t));
if(!win->hist) error("hist_add", ERR_MEM);
memset(&win->hist[win->histmin], 0, sizeof(hist_t));
win->hist[win->histmin].type = type;
return win->histmin;
}
......@@ -125,9 +141,8 @@ void hist_addlayer(ui_win_t *win, int type)
for(i=0;i<chr->len;i++)
if(frags[chr->frags[i]].type == type) { win->frag = i; return; }
}
i = hist_add(win);
i = hist_add(win, HIST_ADDLAYER);
win->histmin++;
win->hist[i].type = HIST_ADDLAYER;
win->frag = file_addemptyfrag(&chars[win->v][win->chr], type, -1);
win->hist[i].frag = chars[win->v][win->chr].frags[win->frag];
}
......@@ -137,10 +152,9 @@ void hist_addlayer(ui_win_t *win, int type)
*/
void hist_dellayer(ui_win_t *win)
{
int i = hist_add(win);
int i = hist_add(win, HIST_DELLAYER);
char_t *chr = &chars[win->v][win->chr];
win->hist[i].type = HIST_DELLAYER;
win->hist[i].frag = chr->frags[win->frag];
hist_redo(win);
modified = 1;
......@@ -151,11 +165,10 @@ void hist_dellayer(ui_win_t *win)
*/
void hist_setpixel(ui_win_t *win, int idx, uint8_t pixel)
{