Comments (19)
Looks good. Does the new metrics API that's in 0.3.2 (below) clear up the confusion as well?
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Metrics {
/// Whole pixel offset of the left-most edge of the bitmap. This may be negative to reflect the
/// glyph is positioned to the left of the origin.
pub xmin: i32,
/// Whole pixel offset of the bottom-most edge of the bitmap. This may be negative to refelct
/// the glyph is positioned below the baseline.
pub ymin: i32,
/// The width of the bitmap in whole pixels.
pub width: usize,
/// The height of the bitmap in whole pixels.
pub height: usize,
/// Advance width of the glyph in subpixels. Used in horizontal fonts.
pub advance_width: f32,
/// Advance height of the glyph in subpixels. Used in vertical fonts.
pub advance_height: f32,
/// The bounding box that contains the glyph's outline at the offsets specified by the font.
/// This is always a smaller box than the bitmap bounds.
pub bounds: OutlineBounds,
}
from fontdue.
So far, everything is working well for me. v0.3.2
From top to bottom are SourceHanSansSC-Regular.otf
as 24px in chrome
, fontdue
and ab-glyph
:
from fontdue.
Perfect! This API is much more clear and rendered text looks nice.
from fontdue.
I'm not seeing the same coarse edges. This error looks like you're using an incorrect width (potentially) for your glyphs at some point. You can see it in your glyphs being cutoff in the x axis. I would check the images in your pipeline are using the correct metrics.
Some text with SourceHanSansSC-Regular.otf at 48px
from fontdue.
char 'C' on 24.0px
SourceHanSansHC-Regular.otf
ab-glyph:
// with fix the scale error https://github.com/alexheretic/ab-glyph/issues/15
[src/main.rs:28] advance_width = 15.312
[src/main.rs:30] &rect = Rect {
min: point(1.0, -18.0),
max: point(15.0, 1.0),
}
// https://github.com/alexheretic/ab-glyph/blob/master/glyph/src/outlined.rs#L163-L173
[src/main.rs:31] rect.width() = 14.0
[src/main.rs:32] rect.height() = 19.0
fontdue:
[src/main.rs:49] metrics = Metrics {
width: 14,
height: 20,
advance_width: 15.312,
advance_height: 24.0,
bounds: AABB {
xmin: 1.392,
xmax: 14.448,
ymin: -0.312,
ymax: 17.928,
},
}
[src/main.rs:50] metrics.bounds.xmax - metrics.bounds.xmin = 13.056 // != 14.0
[src/main.rs:51] metrics.bounds.ymax - metrics.bounds.ymin = 18.24 // != 20.0
Zpix-beta-v3.0.2-beta.0.ttf
ab-glyph
[src/main.rs:28] advance_width = 13.992001
[src/main.rs:30] &rect = Rect {
min: point(0.0, -17.0),
max: point(11.0, 2.0),
}
[src/main.rs:31] rect.width() = 11.0
[src/main.rs:32] rect.height() = 19.0
fontdue
[src/main.rs:49] metrics = Metrics {
width: 11,
height: 19,
advance_width: 13.992001,
advance_height: 0.0,
bounds: AABB {
xmin: 0.0,
xmax: 10.008,
ymin: -1.992,
ymax: 16.008,
},
}
[src/main.rs:50] metrics.bounds.xmax - metrics.bounds.xmin = 10.008
[src/main.rs:51] metrics.bounds.ymax - metrics.bounds.ymin = 18.0
The results of rasterization are almost the same.(fontdue with a 1px top blank, but this is unimportance)
But fontdue's bounds is not correct(UV mapping not fix pixel size, smaller than the real size), so the rendering looks incomplete.
from fontdue.
This is what I fix bounds:
let xmax = metrics.width as f32 + metrics.bounds.xmin;
let ymax = metrics.height as f32 + metrics.bounds.ymin;
The size rendering looks correct.But position still has problems.(minxy not fix)
from fontdue.
Thank you for the detailed comparison. I do a correction such that I pad the xmin and ymin my the offset in the bounding box, I'll double check that's doing the right thing because it looks like that may be the case here. There should be no padding which indicates an issue with my naive repositioning.
from fontdue.
Some notes:
- I pushed a fix for the padding issue.
- Width and height are always
usize
and will always contain the glyph. Bounds isf32
because it represents the true bounding box around the glyph, and can be fractional. This fractional component is required for subpixel layout. - I'm not sure what the other issues are that you're pointing out; Could you elaborate more on that? I ran an image difference between ab_glyph and fontdue and didn't get a meaningful positioning difference, but it may have been fixed by my last push.
(Oh unrealted, try out the FontSetting {enable_offset_bounding_box: false ... etc}
if you want the old Fontdue behavior that made zpix really crisp at 12px.)
from fontdue.
Width and height are always usize and will always contain the glyph. Bounds is f32 because it represents the true bounding box around the glyph, and can be fractional. This fractional component is required for subpixel layout.
I still canβt calculate the UV coordinates accurately. For example:
[src/main.rs:51] metrics = Metrics {
width: 14,
height: 19,
advance_width: 15.312,
advance_height: 24.0,
bounds: AABB {
xmin: 1.392,
xmax: 14.448,
ymin: -0.312,
ymax: 17.928,
},
}
[src/main.rs:52] metrics.bounds.xmax - metrics.bounds.xmin = 13.056
[src/main.rs:53] metrics.bounds.ymax - metrics.bounds.ymin = 18.24
The bitmap is 14 * 19, if using pixel uv mapping, it is (0.0, 0.0) (1.0, 1.0)
But if as bounds uv mapping, it is:
uvx0 = 0; // maybe not 0, because rasterization may not start from zero, this is why cause the position error.
uvy0 = 0;
uvy1 = (metrics.bounds.xmax - metrics.bounds.xmin) / metrics.width;
uvy2 = (metrics.bounds.ymax - metrics.bounds.ymin) / metrics.height;
So: (uvx0, uvy0) (uvx1, uvy1) => (0.0, 0.0) -> (0.93257143, 0.96)
This increases the difficulty of drawing.We can use bounds for the real coordinate, but can not use real uv from the bitmap.
from fontdue.
I think there are two options:
-
like ab-glyph always based on pixels, although the bounds is not the real value, but offset by rasterization, the screen result is correct.
-
There is another params in Metrics like
uv_ bounds
to describe what the bounds mapping with bitmap.
from fontdue.
I'm confused on what you mean UV being hard to calculate, the width and height are correct, and you should use the whole bitmap and not take a subset of it. You do not want to take anything smaller than the width and height as they're the smallest unit the glyph can be represented correctly. The extra fraction of a pixel empty space around the glyph is required because the font specifics it to be there. In terms of correctness: ab_glyph is giving you incorrect results based on what the font specifies, unless I'm misunderstanding your pipeline.
from fontdue.
Width and height are always usize and will always contain the glyph.Bounds is f32 because it represents the true bounding box around the glyph.So they are not match, there is always a one pixel offset, because bitmap size is ceil() or floor().
If we use bitmap, we must know what the rounding px_bounds(but not true_boudns, because true_boudns is smaller than px_bounds). Or we use true_boudns, and must know what the precise region in bitmap.
from fontdue.
I have had somewhat same issues with positioning of glyphs. At first I used bounding box (metrics.xmin, metrics.xmax, metrics.ymin, metrics.ymax) values to calculate width (xmax - xmin) and height (ymax - ymin) of a glyph, and on layout stage (I use my own layout, not the crate's one) those values resulted in "jumping" glyphs, offset was small - something about 1px. I fixed this by switching to metrics.width and metrics.height. So real metrics of glyph are:
let left = metrics.xmin;
let top = metrics.ymin;
let width = metrics.width as f32;
let height = metrics.height as f32;
This was a bit confising and I spent about 2 hours trying to understand why layout is so weird.
from fontdue.
Thanks for expressing your concerns. This is a readability issue with the docs, not a technical issue. I would like to explore ways of making the right solution more obvious in the documentation/structures. Below I'll explain the context of the values and at the end I'll propose a solution that I would like both of your feedback on.
The aabb bounds of a glyph will not match with the width/height dimensions of the glyph. The bounds define the inner bounding box that the font specifies. This is the smallest box that encapsulates the glyph, and is defined in fractional units. It is defined in fractional units because the outline for the glyph does not align to the pixel grid, and is important to fractional positioning if the layout tool is aware. Take this example of:
Key:
Grid: Grey
Baseline: Black
Glyph: Blue
Glyph bounds: Purple
Glyph pixel bounds: Orange
Because the aabb bounds (purple) do not align with the pixel grid (grey), the bitmap fontdue produces is the smallest bounding box that encapsulates the full aabb (orange) rasterized. The width and height fields represent the orange box's dimensions.
Fontdue only uses bounds/width/height because all other information can be derived from this if the layout tool needs it. The builtin layout tool will output GlyphPosition's that represent the orange box and are aligned to the grid.
One solution I can see is replacing width/height/bounds with inner_ bounds (fractional, not grid aligned, the purple box), and outer_bounds (grid aligned, matches bitmap, the orange box), and documenting them as such. This would be a breaking change downstream but we're experimental and this is an issue.
Would that make it more clear if you were seeing the API for the first time?
from fontdue.
I think it would be good to do the same as FreeType does - it has bitmap_left
and bitmap_top
fields at glyph description, and separate field bitmap
which has its own fields width
, rows
(height). This in my opinion is less confusing because in most cases you need to know how to offset rasterized glyph in pixels, so there will be no problems with rounding and such stuff.
P.S. Thanks for the great crate, it was really easy to replace my own ttf loader/rasterizer (which has lots of issues) with fontdue.
from fontdue.
(v0.3.0) Some glyph rasterize incorrect when settings.enable_offset_bounding_box = true
(default is true)
Zpix-beta-v3.0.2-beta.0.ttf
char = 't'
px = '12.0'
settings.enable_offset_bounding_box = true
settings.enable_offset_bounding_box = false
SourceHanSansSC-Regular.otf
char = 'd'
px = '24.0'
settings.enable_offset_bounding_box = true
settings.enable_offset_bounding_box = false
If use settings.enable_offset_bounding_box = false
, rasterize position will incorrect(usually 1 pixel up and left offset)
SourceHanSansSC-Regular.otf
px = 12.0
settings.enable_offset_bounding_box = true
settings.enable_offset_bounding_box = false
SourceHanSansSC-Regular.otf
px = 24.0
settings.enable_offset_bounding_box = true
settings.enable_offset_bounding_box = false
SourceHanSansSC-Regular.otf
char = 'n'
px = 24.0
settings.enable_offset_bounding_box = true
settings.enable_offset_bounding_box = false
SourceHanSansSC-Regular.otf
char = 'h'
px = 24.0
settings.enable_offset_bounding_box = true
settings.enable_offset_bounding_box = false
What the problem does enable_offset_bounding_box
to fix.
If means enable_offset_bounding_box=false, rasterize will always start with position(0.0, 0.0) in bitmap?
In this case ,should fix metrics.xmin and metrics.ymin with offset?
from fontdue.
I made a typo in the change, I'll fix and push it in like 8 hours. I wrote (offset_y, offset_y)
instead of (offset_x, offset_y)
from fontdue.
0444701 Fixed
from fontdue.
Metrics should be fixed as well. Does 0.3.2 work for you two? @mrDIMAS, @TakWolf
from fontdue.
Related Issues (20)
- Newline showing up as missing character HOT 2
- Support Coverage Maps at Different Gamma Values HOT 2
- C interface HOT 6
- Fonts with variable weight? HOT 2
- Adding an example for calculating the bounding box HOT 8
- can fontdue rasterize with fractional pixel offsets? HOT 5
- SDF texture generation HOT 1
- Ligature support- pairing with other libraries
- Rasterize a whole string HOT 3
- Glyph metrics are incorrect HOT 1
- Font line metrics don't match character metrics
- Png Support HOT 1
- How to rasterize colored emojis HOT 1
- Can you add an example of how to create a simple letter and save as a font? HOT 1
- Option to drop the rest of a line instead of wrapping HOT 2
- Bounding box of laid out text for easy shiftnig of the origin?
- Misaligned pointer dereference in `get_bitmap` HOT 4
- Custom font colors HOT 1
- Live demo error when a glagolitic character ( β° ) is used HOT 3
- 0.7.4 is a semver break HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fontdue.