Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add resvg.dll the new export function (interface to commad line option --list-fonts) and describe it in the resvg.h file. #763

Open
Dimon-II opened this issue May 18, 2024 · 12 comments

Comments

@Dimon-II
Copy link

(In Windows, I don’t know about other systems) there is no API function for getting the font name from a file.
The result of a non-standard functions is often different from the name that RESVG uses.
First of all, I need a list of local (not installed on the system) font names.
PS I already asked for this feature in 2021...

@RazrFalcon
Copy link
Collaborator

resvg C API is limited to rendering by design. You cannot query much from it.

getting the font name from a file

What do you mean by that? Fonts loaded from the system by resvg or font families present in an SVG file?

The result of a non-standard functions is often different from the name that RESVG uses.

Not sure what this means either.

I already asked for this feature in 2021

I work on this project when I feel like it. Period.

@Dimon-II
Copy link
Author

Dimon-II commented May 20, 2024

resvg C API is limited to rendering by design. You cannot query much from it.

But this function has already appeared in your project, just without the interface from the DLL.
I use resvg.dll for rendering in a specific graphics editor (design and translation of game cards).
This is very convenient - that fonts do not have to be installed on the system and can be stored in the project directory.
Windows API offers only a strange mechanism with loading from a file (with locking file) - not from memory, the font loaded from memory is not listed only and after that - get a list of all installed fonts.

getting the font name from a file
What do you mean by that? Fonts loaded from the system by resvg or font families present in an SVG file?

image
For system fonts, the system font selection dialog is used.
The most popular is a short drop-down list of local fonts that are not in the system and that are used in the current project. But I can call this function before and after loading local fonts and compare the results. Fonts are frequently added and removed to the project directory, and there is a button to re-read local fonts.

The result of a non-standard functions is often different from the name that RESVG uses.

Not sure what this means either.

For example - MyriadPro-Cond.ttf, Windows shows the font as "Myriad Pro Cond", In the TTF table NAME is also the name,
image
but RESVG understands only "Myriad Pro" without COND.
image
image

PS The localized name (which will be stored to SVG font-family) can leads to errors because the same project can be opened on a computer with a different locale (Spanish, for example).

@RazrFalcon
Copy link
Collaborator

I'm not really sure what are you trying to do. resvg uses the default SVG/CSS/WEB font resolving logic. It doesn't care how Windows handles font names. Meaning that you have to provide family names in a way SVG understands them. You cannot override that behaviour (sort of).

Therefore I don't see how --list-fonts will help you here. And if you really need this method you can easily fork resvg C API and extend it with whatever API you want.

Windows API offers only a strange mechanism with loading from a file (with locking file) - not from memory, the font loaded from memory is not listed only and after that - get a list of all installed fonts.

I don't see how is this related to resvg. resvg doesn't interact with winapi at all.

As for localized names, you should simply use EN names in SVG.

@Dimon-II
Copy link
Author

Dimon-II commented May 20, 2024

Опишу ситуацию на более понятном нам обоим русском:

  1. В Windows API нет стандартной функции для чтения имени (font-family) шрифта из файла.

  2. Стандартный диалог Windows просмотра шрифта показывает НЕ ТО ИМЯ, которое используется в RESVG. То есть посмотреть "правильное" название в свойствах не установленного шрифта стандартными средствами не получается.

  3. Все примеры таких функций читают однозначное не локализованное название шрифта из таблицы name
    [The 'name' table] (https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html)

  4. Оптимальный для меня вариант: чтобы функция resvg_options_load_font_file возвращала имя этого шрифта, но, чтобы вам не менять формат вызова существующих функций - хотя бы отдельную функцию получения списка шрифтов, которая (будет?) добавлена в exe-вариант.

  5. Или сделать опцию, чтоб resvg распознавал шрифт по любому из нескольких названий...

@RazrFalcon
Copy link
Collaborator

Well, I will rather not use that language...

I think I understand now, but this feature is out of scope for resvg. I would suggest implementing a minimal TrueType parser for the name table on your side. It's not that hard: https://github.com/RazrFalcon/ttf-parser/blob/master/src/tables/name.rs

As for resvg_options_load_font_file, the tricky part is that a font can have many faces and each face can have many names. Expressing this via C API would be highly problematic.

@Dimon-II
Copy link
Author

As for resvg_options_load_font_file, the tricky part is that a font can have many faces and each face can have many names. Expressing this via C API would be highly problematic.

I don’t need the complete typeface-name, I need the value that will be substituted into the font-family attribute.
This name may be the same when several files contain different styles of the same font.
The main thing is that it is the name that you use, and not the mismatched one that was received by a third-party parser. I already have a TTF 'name' table parser and it worked previously, but several versions ago you switched to a much more complex version of the localized name.

@RazrFalcon
Copy link
Collaborator

Support for localized names should not affect you in any way. You can always provide EN/US family name and it will work just fine.

@Dimon-II
Copy link
Author

Support for localized names should not affect you in any way. You can always provide EN/US family name and it will work just fine.

I have already given an example - in this font RESVG does not accept font values
[Family]='Miriad Pro Cond'
[Family Name]='Miriad Pro Cond'
The only option in which the font is rendered is the value of the
[Preferred Family]='Miriad Pro'.
That’s why I ask you to return the value that your program understands.
Examples of parsers work only with TTF and do not understand OTF...

image

@RazrFalcon
Copy link
Collaborator

Ok, I understand now. Here is the current implementation.
By SVG/WEB/Browsers standards Typographic/Preferred Family (id16) has a priority over the regular Family (id1). Meaning you have to do the same.

I know it's very convoluted, but this is how WEB works and we just have to deal with it.

Examples of parsers work only with TTF and do not understand OTF...

TTF and OTF are largely the same thing. One uses glyf for outlines and other uses CFF. Everything else is the same.

@Dimon-II
Copy link
Author

Dimon-II commented May 22, 2024

I see this is an absolutely fundamental position for you - not to add any functionality outside of rendering.
I just hoped that by adding this list of fonts feature to the in the EXE file, it would be possible to get it in the DLL...

The very first lines of the parsers available to me always check the file version, and ignore or raise an error if it is
if (ttOffsetTable.uMajorVersion<>1)or(ttOffsetTable.uMinorVersion<>0) then ...
Just by commenting it out, I don’t get the result.

So current priorities of naming from 4 options NameID/LanguageID?

  1. 16/1033
  2. 16/0
  3. 1/1033
  4. 1/0

PS It turns out that it is impossible to simultaneously use a font from a family that has regular and condensed variants...
image
image

@Dimon-II
Copy link
Author

Dimon-II commented May 22, 2024

A friend suggested that I make my own version of resvg with getting names, but this function has a memory leak, but I don’t know this programming language and can’t fix it.

#[no_mangle]
pub extern "C" fn resvg_options_load_font_file_leak(
    opt: *mut resvg_options,
    file_path: *const c_char,
) -> *const c_char {
    let null: *const c_char = std::ptr::null();
    let file_path = match cstr_to_str(file_path) {
        Some(v) => v,
        None => return null,
    };

    let opt = unsafe {
        assert!(!opt.is_null());
        &mut *opt
    };

    if opt.0.fontdb.load_font_file(file_path).is_ok() {
        let faces = opt.0.fontdb.faces();
        let face = &faces[faces.len() - 1];
        let c_string = CString::new(face.family.to_owned()).unwrap();
        let ptr = c_string.as_ptr();
        std::mem::forget(c_string);
        ptr
    } else {
        null
    }
}

@RazrFalcon
Copy link
Collaborator

It turns out that it is impossible to simultaneously use a font from a family that has regular and condensed variants...

It is possible. Just set font-stretch="condensed" in SVG.

but this function has a memory leak

Yes, you need

#[no_mangle]
pub extern "C" fn resvg_free_cstring(str: *mut c_char) {
    unsafe {
        let _ = CString::from_raw(str);
    }
}

Everything allocated in Rust have to be deallocated there as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants