Giter Club home page Giter Club logo

Comments (19)

mooman219 avatar mooman219 commented on June 4, 2024 2

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.

TakWolf avatar TakWolf commented on June 4, 2024 1

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:
image

from fontdue.

mrDIMAS avatar mrDIMAS commented on June 4, 2024 1

Perfect! This API is much more clear and rendered text looks nice.

from fontdue.

mooman219 avatar mooman219 commented on June 4, 2024

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
image

from fontdue.

TakWolf avatar TakWolf commented on June 4, 2024

char 'C' on 24.0px

SourceHanSansHC-Regular.otf

ab-glyph:

image
14 x 19 pixel

// 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:

image
14 x 20 pixel

[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.

TakWolf avatar TakWolf commented on June 4, 2024

This is what I fix bounds:

        let xmax = metrics.width as f32 + metrics.bounds.xmin;
        let ymax = metrics.height as f32 + metrics.bounds.ymin;

image

The size rendering looks correct.But position still has problems.(minxy not fix)

image
image

from fontdue.

mooman219 avatar mooman219 commented on June 4, 2024

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.

mooman219 avatar mooman219 commented on June 4, 2024

Some notes:

  1. I pushed a fix for the padding issue.
  2. 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.
  3. 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.

TakWolf avatar TakWolf commented on June 4, 2024

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.

TakWolf avatar TakWolf commented on June 4, 2024

I think there are two options:

  1. like ab-glyph always based on pixels, although the bounds is not the real value, but offset by rasterization, the screen result is correct.

  2. There is another params in Metrics like uv_ bounds to describe what the bounds mapping with bitmap.

from fontdue.

mooman219 avatar mooman219 commented on June 4, 2024

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.

TakWolf avatar TakWolf commented on June 4, 2024

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.

mrDIMAS avatar mrDIMAS commented on June 4, 2024

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.

mooman219 avatar mooman219 commented on June 4, 2024

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:

image

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.

mrDIMAS avatar mrDIMAS commented on June 4, 2024

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.

TakWolf avatar TakWolf commented on June 4, 2024

(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

image

settings.enable_offset_bounding_box = false

image


SourceHanSansSC-Regular.otf
char = 'd'
px = '24.0'

settings.enable_offset_bounding_box = true

image

settings.enable_offset_bounding_box = false

image


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

image

settings.enable_offset_bounding_box = false

image


SourceHanSansSC-Regular.otf
px = 24.0

settings.enable_offset_bounding_box = true

image
image

settings.enable_offset_bounding_box = false

image
image


SourceHanSansSC-Regular.otf
char = 'n'
px = 24.0

settings.enable_offset_bounding_box = true
image

settings.enable_offset_bounding_box = false
image


SourceHanSansSC-Regular.otf
char = 'h'
px = 24.0

settings.enable_offset_bounding_box = true
image

settings.enable_offset_bounding_box = false
image


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.

mooman219 avatar mooman219 commented on June 4, 2024

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.

mooman219 avatar mooman219 commented on June 4, 2024

0444701 Fixed

from fontdue.

mooman219 avatar mooman219 commented on June 4, 2024

Metrics should be fixed as well. Does 0.3.2 work for you two? @mrDIMAS, @TakWolf

from fontdue.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.