Commit b88fd362 authored by bzt's avatar bzt

Sfnedit saving to ASC added

parent 69469bc4
......@@ -108,7 +108,8 @@ this renderer.
Font Editor
-----------
Besides of the converters that can import various font formats, there's also an SSFN font editor available:
Besides of the [converters](https://gitlab.com/bztsrc/scalable-font/tree/master/sfnconv) that can import various
font formats, there's also an [SSFN font editor](https://gitlab.com/bztsrc/scalable-font/tree/master/sfnedit) available:
<img alt="Scalable Screen Font Editor" src="https://gitlab.com/bztsrc/scalable-font/raw/master/docs/sfnedit4.png">
......@@ -158,11 +159,31 @@ bitmap for "A" already).
The [autohinting](https://gitlab.com/bztsrc/scalable-font/blob/master/docs/compare.md) code is very very basic
at the moment, it only uses one axis partitions instead of two axis partitioned boxes.
A [portable SSFN editor with GUI](https://gitlab.com/bztsrc/scalable-font/tree/master/sfnedit). I'm already on it.
It' still very early in development, you can't modify yet, but it's good enough to preview any SSFN font.
Converters only write the default glyph variants except for SSFN ASCII files where all variants are supported. The
editor is capable of handling all variant layers.
editor is capable of handling all variant layers. It would be great to have that if I can figure out how to tell
the converters which variant they are converting.
The SSFN file format and the editor can handle colors and gradients in vector fonts, although the normal renderer
can only render to alpha channel without colors. I'm planning to introduce `SSFN_MODE_ARGB` [mode](https://gitlab.com/bztsrc/scalable-font/blob/master/docs/modes.md)
or another version of the renderer to support colored typefaces. (Using colorless vector glyphs allows a much faster
and less memory eager algorithm to be used, which merges polygons before rasterization. With polygons of different
colors you can't merge in advance.)
Good Programmer Font
--------------------
A few thoughts on what makes a font good for programming:
- it has to be limited proportinal or fixed (that is, it uses the same fixed width within a scripting system. That's okay
if it has a single width for all Latin letters and the same double width for all CJK and other Asian scripts.)
- numbers are clearly distinguishable from letters and ideographic numbers. Unlike uppercase O, 0 should have a dot in the
middle or crossed with a slash. Unlike lowercase l, 1 should have a "head" in an angle, and probably as big "foot" as
the 2. 3 should have a vertical line at the top, clearly different from Cyrillic letter Ze З and reversed Latin open E ɜ etc.
- single quote ' and double quote " are clearly distinguishable from combining accent, apostrophe ʼ, single quotation mark ’
and double prime ʺ, double apostrophe ˮ, double quotation mark ” etc.
- parenthesis (, ) are clearly distinguishable from ideographic ones like ❨, ❪, ⟮, or (.
- operators +, *, -, /, % etc. are clearly distinguishable from other similar symbols like ➕, ⁎, –, ⁄, ⁒ etc.
- comparition operators are represented as is, using the same character count, for example =< is not replaced by the ≤ ligature.
Authors
-------
......
......@@ -58,7 +58,7 @@ The FreeSerif font with a decent Basic Multilingual Plane coverage from the GNU
| Format | Quality | Size | Gzipped | Grid size | Compression |
| ------ | ------: | -----: | ------: | ----------: | ----------: |
| .otf | - | 2.0 M | 1.3 M | 1000 x 1000 | 0% |
| .sfn | 6 | 1.1 M | 766 K | 1024 x 1024 | -45.0% |
| .sfn | 6 | 1.1 M | 762 K | 1024 x 1024 | -45.8% |
| .sfn | 3 | 831 K | 492 K | 128 x 128 | -59.4% |
For most vector fonts, quality 4 (256 x 256 grid) is perfectly sufficient. Some simpler fonts can be
......
......@@ -4,7 +4,7 @@ Scalable Screen Font Editor
Command Line
------------
Very simple, there is only one aregument, the name of the font file you want to edit.
Very simple, there is only one argument, the name of the font file you want to edit.
```sh
$ ./sfnedit
Scalable Screen Font Editor by bzt Copyright (C) 2019 MIT license
......@@ -14,7 +14,8 @@ Scalable Screen Font Editor by bzt Copyright (C) 2019 MIT license
```
That font can be in [SSFN](https://gitlab.com/bztsrc/scalable-font/blob/master/docs/sfn_format.md) or
in [ASC](https://gitlab.com/bztsrc/scalable-font/blob/master/docs/asc_format.md) format, and if the
editor was compiled with libz support, then it can be gzip compressed.
editor was compiled with zlib support, then it can be gzip compressed. The editor does not care if
the filename has an additional .gz extension, it decides to use gzip depending on magic bytes.
The editor is multilingual, and autodetects the language from the environment. If you want to use
a different language than your OS' default, you can specify it in the LANG environment variable:
......@@ -26,7 +27,7 @@ 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.
These keyboard shortcuts work in all windows and in all tabs.
| Key Combination | Description |
| --------------- | ----------- |
......@@ -37,7 +38,6 @@ These keyboard shortcuts work in all windows.
| <kbd>Tab</kbd> | Switch to next tab |
| <kbd>Shift</kbd>+<kbd>Tab</kbd> | Switch to previous tab |
Main Window
-----------
......@@ -48,12 +48,18 @@ on the font, then you will be asked if you want to save them.
## Properties Tab
This tab shows the properties of the font. Changes made here are not reverisible,
meaning you cannot undo them.
<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.
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. Going to a lower grid size
could loose typeface detail of the font. This is not always bad, because fonts are often
have bugs, and downgrading to 256 x 256 grid makes the misplaced points properly aligned.
Grid size below 256 x 256 often requires manual grid fitting of points to keep font
readability, and 16 x 16 is recommended only for bitmap glyphs and maybe for very special
low-detail vector glyphs.
| Key Combination | Description |
| --------------- | ----------- |
......@@ -65,12 +71,14 @@ glyphs.
## Ranges Tab
This tab gives an overview of which UNICODE character blocks have glyph definitions
in the font.
<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.
By clicking "Uncovered ranges" then 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 that are undefined by UNICODE Inc.
| Key Combination | Description |
| --------------- | ----------- |
......@@ -84,11 +92,17 @@ hex number for a range that contains that specific code point.
## Characters Tab
Here you can see the characters for which the font has glyphs.
<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.
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> key, you'll
see the whole vast UNICODE range. Glyphs with window's background color are not defined by
UNICODE. Light background with a dark, low-res bitmap glyph representation means the code
point is specified by UNICODE, but has no glyph in the font. Dark background with light
glyphs are generated from the font, and are real-time representations of all modifications
you may have done on the font.
| Key Combination | Description |
| --------------- | ----------- |
......@@ -109,15 +123,15 @@ 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
accessible until you close this window, meaning you can undo everything up to the point
when you opened the window.
## Edit Tab
<img src='https://gitlab.com/bztsrc/scalable-font/raw/master/docs/sfnedit5.png'>
This is the main editing tab. On the left, there's the toolbar, and on the right (which
occupies the rest of the window) is the edit area.
occupies the rest of the window) is the main edit area.
<img src='https://gitlab.com/bztsrc/scalable-font/raw/master/docs/sfnedit5.png'>
### Toolbar
......@@ -131,6 +145,8 @@ You can select an icon from the toolbar by clicking, the icons are in order:
- Edit glyph layer
- Add vector glyph layer
Note that advances are exclusive. It is either horizontal or vertical, but never both.
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.
......@@ -138,7 +154,7 @@ If you click and hold down left mouse button on the "Add vector glyph layer" ico
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.
layer will be activated. For vector layers a new layer is always generated.
### Layers
......@@ -147,16 +163,22 @@ pixmap layer, but you can have as many vector layers as you want. Moving the mou
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.
By pressing <kbd>Ctrl</kbd>+<kbd>a</kbd> you can select all layers at once. In this mode
only a limited set of tools are available (like moving or copying the layers).
### 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.
to be used for that glyph layer. Please note that colored vector glyphs are only supported by
the editor for now. The normal renderer in ssfn.h ignores the color command in fonts because it
renders to alpha channels only.
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.
the pixel under the pointer will change to this color. The normal renderer in ssfn.h supports
colored pixmaps in CMAP mode, otherwise it generates a grayscale alpha channel of them.
<img src='https://gitlab.com/bztsrc/scalable-font/raw/master/docs/sfnedit6.png'>
......@@ -194,6 +216,8 @@ the coordinates in font's grid resolution, X axis above, and Y below.
| right click | Remove last contour, or clear to transparency for bitmap and pixmap layers |
| wheel | zooming in or out |
Selecting a portion of a vector glyph can only work if the path in the selection is contiguous.
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.
......@@ -205,4 +229,50 @@ modified control points will be restored too.
## Kerning
TODO
In this tab you can set up relative character pair offsets. Unlike advances, you can set
up both horizontal and vertical offsets for the same pair. This is very handy in glyph
composition, when you need to place an accent above or below a base glyph.
<img src='https://gitlab.com/bztsrc/scalable-font/raw/master/docs/sfnedit7.png'>
On the top, there are 7 checkboxes for displaying glyph variants to help you with kerning.
All glyph variants share the same relative kerning offsets, but they have different advance
values, therefore aligned to the red advance line differently. The last checkbox is for
toggling right-to-left direction (more on this later).
On the left, you can see a list of characters paired with the character you're editing.
In the searchbox, you can search for hex code point, UTF-8 character match and UNICODE
character names. If there are no matches for paired characters, then the search will continue
on all code points which have a glyph defined. By pressing <kbd>Enter</kbd> or <kbd>Down</kbd>,
you'll switch to the right-side character list. Selecting a previously undefined pair will add
offsets of 0 and 0 which you can then modify. To delete a kerning pair, simply reset the offsets
to 0 and 0 and that pair won't be stored into the font file upon save.
On the right, in the big area, you'll see the choosen character pair. Depending whether
you have choosen vertical or horizontal advance on the Edit tab, the pair is shown
horizontally or vertically. You should not mix advance directions for glyph variants
for the same character, and kerning area only respects the default variant's direction.
Most scripts (including Latin, Cyrillic, Greek, etc.) are left-to-right horizontal. This
distinction between horizontal and vertical is stored within the font file.
<img src='https://gitlab.com/bztsrc/scalable-font/raw/master/docs/sfnedit8.png'>
With an Y advance, kerning looks like this (I've used Mahjongg tiles because they are
kind of CJK and most CJK scripts are up-to-down vertical).
Unfortunatelly just by the UNICODE code point, you can't always tell if the glyph
has to be written in right-to-left direction. Therefore sfnedit tries to figure it
out, but lets the user change that by clicking on the "RTL" checkbox or pressing
<kbd>r</kbd>. This distinction between left-to-right and right-to-left is NOT stored
within the font file, and requires a BiDi state machine to be applied correctly when
rendering the font. Read more on this in the [API](https://gitlab.com/bztsrc/scalable-font/blob/master/docs/API.md)
documentation.
<img src='https://gitlab.com/bztsrc/scalable-font/raw/master/docs/sfnedit9.png'>
| Key Combination | Description |
| --------------- | ----------- |
| <kbd>r</kbd> | Toggle right-to-left flag on glyph. This does not influence the font, only the editor |
| <kbd>Up</kbd> / <kbd>Down</kbd> | Switch input field (if neither kerning editor area nor right character list is active) |
| <kbd>Up</kbd> / <kbd>Down</kbd> | Select right-side character (if right character list is active) |
| <kbd>Up</kbd> / <kbd>Down</kbd> / <kbd>Left</kbd> / <kbd>Right</kbd> | Change kerning (if kerning editor area is active) |
......@@ -197,8 +197,8 @@ a new path. So the contour fragment's header is followed by two coordinates:
| Quality | Grid size | Path command | Bytes | Command format |
| ------: | --------: | -------------- | ----: | -------------- |
| 0-4 | 256 | move to | 2 | xxxxxxxx xyyyyyyy |
| 5-8 | 4096 | move to | 3 | YYYYXXXX xxxxxxxx xyyyyyyy |
| 0-4 | 256 | move to | 2 | xxxxxxxx yyyyyyyy |
| 5-8 | 4096 | move to | 3 | YYYYXXXX xxxxxxxx yyyyyyyy |
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,
......
docs/sfnedit1.png

13 KB | W: | H:

docs/sfnedit1.png

13.1 KB | W: | H:

docs/sfnedit1.png
docs/sfnedit1.png
docs/sfnedit1.png
docs/sfnedit1.png
  • 2-up
  • Swipe
  • Onion skin
docs/sfnedit2.png

12.4 KB | W: | H:

docs/sfnedit2.png

12.2 KB | W: | H:

docs/sfnedit2.png
docs/sfnedit2.png
docs/sfnedit2.png
docs/sfnedit2.png
  • 2-up
  • Swipe
  • Onion skin
docs/sfnedit3.png

13.6 KB | W: | H:

docs/sfnedit3.png

13.5 KB | W: | H:

docs/sfnedit3.png
docs/sfnedit3.png
docs/sfnedit3.png
docs/sfnedit3.png
  • 2-up
  • Swipe
  • Onion skin
docs/sfnedit4.png

11.8 KB | W: | H:

docs/sfnedit4.png

22.1 KB | W: | H:

docs/sfnedit4.png
docs/sfnedit4.png
docs/sfnedit4.png
docs/sfnedit4.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -1130,7 +1130,7 @@ void asc(char *ptr, int size)
if(cmd=='c' || cmd=='g') {
par[p++] = *ptr=='.' ? 240 : cpal_add(
gethex((char*)ptr+2, 2), gethex((char*)ptr+4, 2),
gethex((char*)ptr+6,2), gethex((char*)ptr,2));
gethex((char*)ptr+6, 2), gethex((char*)ptr, 2));
} else
par[p++] = atoi(ptr);
while(*ptr!=' ' && *ptr!=',' && ptr[1] && ptr[1]!='\n' && ptr[1]!='+') ptr++;
......@@ -1512,7 +1512,6 @@ int main(int argc, char **argv)
str = malloc(BUFSIZ);
if(!str) { fprintf(stderr,"memory allocation error\n"); return 2; }
memset(str, 0, BUFSIZ);
printf("arg_name '%s'\n",arg_name);
if(!arg_name) arg_name=infile;
i = strlen(arg_name)+1; memcpy(str+s, arg_name, i); s += i;
if(!arg_family) arg_family="No family";
......
......@@ -226,7 +226,8 @@ bitmap: if(x*y > 65535) fprintf(f, "bitmap %d x %d too large\n", x, y);
case 3:
x = raw[0] & 0x7F; y = raw[1] & 0x7F;
switch(t) {
case 0: a = (x << 8) | y; raw += 2; break;
case 0: a = ((x & 1) << 7) | y;
if(raw[0] & 4) { b = raw[2]; c = raw[3]; d = raw[4]; raw += 5; } else { b=c=d=a; raw += 2; } break;
case 1: raw += 2; break;
case 2: a = raw[2] & 0x7F; b = raw[3] & 0x7F; raw += 4; break;
case 3: a = raw[2] & 0x7F; b = raw[3] & 0x7F; c = raw[4] & 0x7F; d = raw[5] & 0x7F; raw += 6; break;
......@@ -236,7 +237,8 @@ bitmap: if(x*y > 65535) fprintf(f, "bitmap %d x %d too large\n", x, y);
case 4:
x = raw[1]; y = raw[2];
switch(t) {
case 0: a = raw[1]; raw += 2; break;
case 0: a = raw[1];
if(raw[0] & 4) { b = raw[2]; c = raw[3]; d = raw[4]; raw += 5; } else { b=c=d=a; raw += 2; } break;
case 1: raw += 3; break;
case 2: a = raw[3]; b = raw[4]; raw += 5; break;
case 3: a = raw[3]; b = raw[4]; c = raw[5]; d = raw[6]; raw += 7; break;
......@@ -246,7 +248,8 @@ bitmap: if(x*y > 65535) fprintf(f, "bitmap %d x %d too large\n", x, y);
case 5:
x = ((raw[0] & 4) << 6) | raw[1]; y = ((raw[0] & 8) << 5) | raw[2];
switch(t) {
case 0: a = raw[1]; raw += 2; break;
case 0: a = raw[1];
if(raw[0] & 4) { b = raw[2]; c = raw[3]; d = raw[4]; raw += 5; } else { b=c=d=a; raw += 2; } break;
case 1: raw += 3; break;
case 2: a = ((raw[0] & 16) << 4) | raw[3]; b = ((raw[0] & 32) << 3) | raw[4]; raw += 5; break;
case 3: a = ((raw[0] & 16) << 4) | raw[3]; b = ((raw[0] & 32) << 3) | raw[4];
......@@ -257,7 +260,8 @@ bitmap: if(x*y > 65535) fprintf(f, "bitmap %d x %d too large\n", x, y);
default:
x = ((raw[0] & 12) << 6) | raw[1]; y = ((raw[0] & 48) << 4) | raw[2];
switch(t) {
case 0: a = raw[1]; raw += 2; break;
case 0: a = raw[1];
if(raw[0] & 4) { b = raw[2]; c = raw[3]; d = raw[4]; raw += 5; } else { b=c=d=a; raw += 2; } break;
case 1: raw += 3; break;
case 2: a = ((raw[3] & 3) << 8) | raw[4]; b = ((raw[3] & 12) << 6) | raw[5]; raw += 6; break;
case 3: a = ((raw[3] & 3) << 8) | raw[4]; b = ((raw[3] & 12) << 6) | raw[5];
......@@ -266,7 +270,30 @@ bitmap: if(x*y > 65535) fprintf(f, "bitmap %d x %d too large\n", x, y);
break;
}
switch(t) {
case 0: fprintf(f,"c %02X%02X%02X%02X\n",cmap[a*4+3],cmap[a*4+2],cmap[a*4+1],cmap[a*4+0]); break;
case 0:
if(a<240 && b==a && c==a && d==a)
fprintf(f,"c %02X%02X%02X%02X",cmap[a*4+3],cmap[a*4+2],cmap[a*4+1],cmap[a*4+0]);
else if(a<240 || b<240 || c<240 || d<240) {
fprintf(f,"g");
if(a<240)
fprintf(f," %02X%02X%02X%02X",cmap[a*4+3],cmap[a*4+2],cmap[a*4+1],cmap[a*4+0]);
else
fprintf(f," .");
if(b<240)
fprintf(f," %02X%02X%02X%02X",cmap[b*4+3],cmap[b*4+2],cmap[b*4+1],cmap[b*4+0]);
else
fprintf(f," .");
if(c<240)
fprintf(f," %02X%02X%02X%02X",cmap[c*4+3],cmap[c*4+2],cmap[c*4+1],cmap[c*4+0]);
else
fprintf(f," .");
if(d<240)
fprintf(f," %02X%02X%02X%02X",cmap[d*4+3],cmap[d*4+2],cmap[d*4+1],cmap[d*4+0]);
else
fprintf(f," .");
fprintf(f,"\n");
}
break;
case 1: fprintf(f,"l %d,%d\n",ox+x,oy+y); break;
case 2: fprintf(f,"q %d,%d %d,%d\n",ox+x,oy+y,ox+a,oy+b); break;
case 3: fprintf(f,"b %d,%d %d,%d %d,%d\n",ox+x,oy+y,ox+a,oy+b,ox+c,oy+d); break;
......@@ -365,10 +392,13 @@ int main(int argc, char **argv)
font->kerning_offs > font->size || font->fragments_offs > font->characters_offs[0]) {
fprintf(stderr,"bad file format %s\n", infile);
if(dump) {
if(memcmp(font->magic, SSFN_MAGIC, 4))
if(memcmp(font->magic, SSFN_MAGIC, 4)) {
if(!memcmp(font->magic, SSFN_COLLECTION, 4))
fprintf(stderr, " This is a collection, extract it first with sfn2sfn\n");
fprintf(stderr," bad magic '%c%c%c%c' != 'SSFN'\n",
font->magic[0], font->magic[1], font->magic[2], font->magic[3]);
else {
font->magic[0] < 32 ? '?' : font->magic[0], font->magic[1] < 32 ? '?' : font->magic[1],
font->magic[2] < 32 ? '?' : font->magic[2], font->magic[3] < 32 ? '?' : font->magic[3]);
} else {
if(origsize != font->size)
fprintf(stderr," bad font size, %d != %ld\n", font->size, origsize);
else {
......@@ -669,7 +699,7 @@ int main(int argc, char **argv)
ptr3 = malloc(0x110000);
if(!ptr3) { fprintf(stderr,"memory allocation error\n"); return 2; }
}
for(v=0;v<8;v++) {
for(v=0;v<SSFN_NUMVARIANTS;v++) {
if(!font->characters_offs[v]) continue;
printf("\n---Characters Table (SSFN_VARIANT_LOCAL%d, SSFN_VARIANT_%s)---\n", v, dump_var[v]);
if(dump!=99 && ((uint64_t)ptr-(uint64_t)font)!=font->characters_offs[v]) {
......@@ -761,6 +791,7 @@ int main(int argc, char **argv)
}
}
if(dump!=99) free(ptr3);
free(frgoffs);
if(font->kerning_offs) {
printf("\n---Kerning---\n");
......
......@@ -569,65 +569,65 @@ int main(int argc, char **argv)
memset(ssfn_strings, 0, BUFSIZ);
if(arg_name) { /* unique font name */
s = strlen(arg_name)+1;
s = strlen(arg_name);
memcpy(ssfn_strings, arg_name, s);
while(ssfn_strings[s-1]==' ' || ssfn_strings[s-1]=='\t') s--;
ssfn_strings[s] = 0;
ssfn_strings[s++] = 0;
} else if(!FT_Get_Sfnt_Name(face, 3, &name)) {
memcpy(ssfn_strings, name.string, name.string_len);
s += name.string_len+1;
s += name.string_len;
while(ssfn_strings[s-1]==' ' || ssfn_strings[s-1]=='\t') s--;
ssfn_strings[s] = 0;
ssfn_strings[s++] = 0;
} else if(!FT_Get_Sfnt_Name(face, 20, &name)) {
memcpy(ssfn_strings + s, name.string, name.string_len);
s += name.string_len+1;
s += name.string_len;
while(ssfn_strings[s-1]==' ' || ssfn_strings[s-1]=='\t') s--;
ssfn_strings[s] = 0;
ssfn_strings[s++] = 0;
} else s++;
if(!FT_Get_Sfnt_Name(face, 1, &name)) { /* family name */
memcpy(ssfn_strings + s, name.string, name.string_len);
s += name.string_len+1;
s += name.string_len;
while(ssfn_strings[s-1]==' ' || ssfn_strings[s-1]=='\t') s--;
ssfn_strings[s] = 0;
ssfn_strings[s++] = 0;
} else s++;
if(!FT_Get_Sfnt_Name(face, 2, &name)) { /* subfamily name */
memcpy(ssfn_strings + s, name.string, name.string_len);
s += name.string_len+1;
s += name.string_len;
while(ssfn_strings[s-1]==' ' || ssfn_strings[s-1]=='\t') s--;
ssfn_strings[s] = 0;
ssfn_strings[s++] = 0;
} else s++;
if(!FT_Get_Sfnt_Name(face, 5, &name)) { /* version */
memcpy(ssfn_strings + s, name.string, name.string_len);
s += name.string_len+1;
s += name.string_len;
while(ssfn_strings[s-1]==' ' || ssfn_strings[s-1]=='\t') s--;
ssfn_strings[s] = 0;
ssfn_strings[s++] = 0;
} else s++;
if(!FT_Get_Sfnt_Name(face, 8, &name)) { /* manufacturer */
memcpy(ssfn_strings + s, name.string, name.string_len);
s += name.string_len+1;
s += name.string_len;
while(ssfn_strings[s-1]==' ' || ssfn_strings[s-1]=='\t') s--;
ssfn_strings[s] = 0;
ssfn_strings[s++] = 0;
} else if(!FT_Get_Sfnt_Name(face, 9, &name)) {
memcpy(ssfn_strings + s, name.string, name.string_len);
s += name.string_len+1;
s += name.string_len;
while(ssfn_strings[s-1]==' ' || ssfn_strings[s-1]=='\t') s--;
ssfn_strings[s] = 0;
ssfn_strings[s++] = 0;
} else s++;
if(!FT_Get_Sfnt_Name(face, 0, &name)) { /* copyright */
memcpy(ssfn_strings + s, name.string, name.string_len);
s += name.string_len+1;
s += name.string_len;
while(ssfn_strings[s-1]==' ' || ssfn_strings[s-1]=='\t') s--;
ssfn_strings[s] = 0;
ssfn_strings[s++] = 0;
} else if(!FT_Get_Sfnt_Name(face, 7, &name)) {
memcpy(ssfn_strings + s, name.string, name.string_len);
s += name.string_len+1;
s += name.string_len;
while(ssfn_strings[s-1]==' ' || ssfn_strings[s-1]=='\t') s--;
ssfn_strings[s] = 0;
ssfn_strings[s++] = 0;
} else s++;
ssfn_hdr.size = ssfn_hdr.fragments_offs = sizeof(ssfn_font_t) + s;
......@@ -940,7 +940,9 @@ int main(int argc, char **argv)
FT_Get_Kerning(face, chars[i].unicode, chars[j].unicode, 0, &v);
v.x = (((v.x*(gridsize-1)+(max_s/2))/max_s)+63)/64;
v.y = (((v.y*(gridsize-1)+(max_s/2))/max_s)+63)/64;
if(v.x==0 && v.y==0) continue;
/* skip if scaling to 2/3 of maximum rasterizer resolution gives 0 */
if( !(((v.x << (16 - (4+ssfn_hdr.quality))) * 192 + (1 << 16) - 1) >> 16) &&
!(((v.y << (16 - (4+ssfn_hdr.quality))) * 192 + (1 << 16) - 1) >> 16)) continue;
if(chars[i].klen>32767) {
fprintf(stderr,"Too many kerning pairs for U+%06x, truncated to 32768\n", chars[i].unicode);
break;
......
......@@ -14,7 +14,3 @@ autodetects zlib too. If found, then the editor can read and write gzip compress
then decompression will be still available by a built-in tiny inflate library (also used for
several internal data), but no gzip compression will be possible for writes. Other than those,
requires libc only.
<img src='https://gitlab.com/bztsrc/scalable-font/raw/master/docs/sfnedit3.png'>
<img src='https://gitlab.com/bztsrc/scalable-font/raw/master/docs/sfnedit4.png'>
/*
* sfnedit/copypaste.c
*
* Copyright (C) 2019 bzt ([email protected])
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* @brief Copy'n'paste functions
*
*/
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include "lang.h"
#include "ui.h"
#include "file.h"
#include "util.h"
char *clipboardfn = NULL;
/**
* Get clipboard file name
*/
void copypaste_init()
{
char *home = getenv("HOME");
char *name = getenv("LOGNAME");
struct stat st;
if(clipboardfn) return;
clipboardfn = malloc((home?strlen(home):(name?strlen(name):4))+32);
if(!clipboardfn) error("copypaste_init", ERR_MEM);
if(!home) {
sprintf(clipboardfn, "/home/%s", name);
if(stat(clipboardfn, &st))
sprintf(clipboardfn, "/tmp/sfnclipbrd.%s", name?name:"UNKNOWN");
else {
sprintf(clipboardfn, "/home/%s/.cache", name);
goto mdir;
}
} else {