Giter Club home page Giter Club logo

parley's People

Contributors

dfrg avatar jneem avatar waywardmonkeys avatar xorgy avatar xstrom avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

parley's Issues

Support bidirectional text

Implement BiDi resolution and reorder runs per line according to UAX #9. Properly handle "removed by X9" and neutral characters in reversed runs. Depends on #9

Normalize style spans

Style spans are supplied to the TextLayoutBuilder trait in arbitrary order with potentially overlapping ranges. Sort and break/merge ranges to generate non-overlapping spans with full coverage of the source text.

Apply font selection and fallback.

Integrate the fount crate for font enumeration. Assign desired fonts by style spans, choosing defaults for missing fonts or selecting fallbacks for scripts according to glyph coverage.

Add support for language/script fallback with a specific GenericFamily if available.

It is typical for a font stack to include a GenericFamily. Android and CoreText both have information about โ€˜UIโ€™ type fonts in fallback, differentiated from general text fonts; and Android has support for setting fallback families for generic familes. We should be able to support preferentially matching system-ui to variant="compact" when available on Android, and matching serif (or ui-serif) to fallback fonts with fallbackFor="serif".

This information probably belongs in FallbackKey but it would need to be wired through the style resolver.

Is it too early?

I am looking into creating my own GUI library in rust. I was researching how I would implement text rendering and stumbled upon the very appealing stack of using swash + fount + parley. But I see there has not been a commit here for a while. That got me wondering if usage of this stack is too early and that I should use fontdue instead.

Is it too early to use?

Generate simple text runs.

Extend the TextLayoutBuilder/TextLayout trait implementations to generate simple, single line text runs with nominal glyph mapping and default system fonts.

Support inline box layout

Motivation

One may wish to mix textual and non-textual content and have the non-textual content laid out in flow with the text. For example, in order to display images or even whole widgets within paragraphs of text. This is necessary in order to implement web-style "inline/flow" layout, but it's use is not limited to web layout contexts: it is a feature that is more generally useful to anyone wishing to layout mixed content.

Notes

The functionality required from the text layout system in order to implement "inline layout" is laying out fixed size boxes, possibly with some kind of supplementary baseline alignment / vertical alignment information. There is no need for the text layout system to size such boxes.

Proposed Implementation

I think we can avoid involving inline boxes in ranged style resolution. Based on that assumption, my proposal is as follows:

  • Update Builder
    • Define:
    struct InlineBox {
        /// The width and height of the box in pixels
        size: kurbo::Vec2,
        /// The index into the text string at which the box should be placed.
        index: usize,
        /// An arbitrary user-defined id that consumers of parley can use to determine
        /// which inline box is which in the resultant layout
        id: u64,
    }
    • Add an inline_boxes: Vec<InlineBox> property to LayoutContext
    • Add a push_inline_box(box: InlineBox) method RangedBuilder which pushes to the inline_boxes property in the layout context
    • Sort the inline boxes by index in RangedBuilder::finish
  • Update run-splitting:
    • Update shape::shape_text to break text runs at text indexes where an inline box is present (in addition to all of the places where it already does so).
    • Define:
    enum RunOrBox {
         Run(RunData)
         Box(InlineBox)
    }
    • Change LayoutData.runs to LayoutData.runs_or_boxes using the new enum
    • Update shape::shape_text to push inline boxes to LayoutData.runs_or_boxes
  • Update line breaking
    • Define:
     struct InlineBoxPosition {
         /// The x and y position of the box
         position: kurbo::Vec2,
         /// The unique id of the box
         id: u64,
      }
      enum LineRunOrBox {
           Run(LineRunData)
           Box(InlineBoxPosition)
      }
    • Change LayoutData.line_runs to LayoutData.line_runs_or_boxes using the new enum
    • Update BreakLines::break_next to account for inline boxes when line breaking. This should:
      • Compute an (x, y) location for the box (either global or line-relative)
      • Affect the position of subsequent runs of text
      • Affect the line height of the line (flooring it by the box's height)
  • Update alignment
    • Update BreakLines::finish to account for boxes when performing alignment

Add infrastructure to Parley to facilitate text selection/editing

We want Parley to implement types and methods that Masonry and other editors will be able to use to create a text-editing widget, or to handle selection in non-editable text.

After some discussion we've settled on the following:

  • A TextMovement enum representing different possible changes to a text edit's selection and content. Possible variants might be eg MoveLeft, MoveToNextWord, SelectToNextParagraph, RemovePreviousWord, etc.
  • A function that maps a String, a cursor position(/span) and a TextMovement to a StringDiff and position(/span).
  • Later down the road, once we want to implement spans, a function that maps a span and a StringDiff to an optional span.

Possible signatures:

enum TextMovement {
  MoveLeft,
  MoveRight,
  // ...
}

struct StringDiff {
  removed_span: usize..usize,
  new_position: usize,
  added_text: String,
}

fn apply_movement(string: &str, movement: TextMovement, byte_offset: usize) -> StringDiff;

fn map_span(span: usize..usize, diff: StringDiff) -> Option<usize..usize>;

We night use Parley's Cursor type instead of byte offsets in these interfaces.

Search paths for fonts on Apple platforms

Currently, the CoreText source is searching in "/System/Library/Fonts/" for fonts, but it should probably be searching in more than that.

Fonts can be found in:

  • The user's home directory library, but this one is tricky.
  • "/Library/Fonts"
  • "/System/Library/Fonts"
  • "/Network/Library/Fonts"

The user's home directory might be tricky due to sandboxing and so we shouldn't just put together the paths ourselves, but use the system APIs for this instead. (In sandboxed applications, one doesn't have direct access to ~/Library/ but has access to something in ~/Library/Containers/<application id>/data/Library which contains a symlink to the Fonts directory.)

I think the right thing to do would be to use NSSearchPathForDirectoriesInDomains (https://developer.apple.com/documentation/foundation/1414224-nssearchpathfordirectoriesindoma?language=objc) with NSLibraryDirectory or (NSAllLibrariesDirectory, I don't know which) and a mask of NSAllDomainsMask. We should be able to get this from objc2_foundation (https://docs.rs/objc2-foundation/latest/objc2_foundation/fn.NSSearchPathForDirectoriesInDomains.html)

And finally ... there are ALSO fonts in /System/Library/Fonts/Supplemental which should be scanned.

Variable font support

Add support for applying font variation settings by axis tag/value pairs. Coordinate with piet on API.

Shape text runs

Using the swash crate, shape text runs according to script, locale and selected font.

panic on linux

playing around with piet-gpu and parley using your piet-gpu integration. however I haven't gotten it to work yet. my guess is that since fount mentions it only supports windows and macos that this is currently expected.

MESA-INTEL: warning: Performance support disabled, consider sysctl dev.i915.perf_stream_paranoid=0

thread 'main' panicked at 'range end index 1 out of range for slice of length 0', /home/dvc/cloudpeer/parley/src/layout/line/greedy.rs:510:26
stack backtrace:
   0: rust_begin_unwind
             at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/panicking.rs:517:5
   1: core::panicking::panic_fmt
             at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/panicking.rs:100:14
   2: core::slice::index::slice_end_index_len_fail
             at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/slice/index.rs:41:5
   3: <core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index
             at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/slice/index.rs:240:13
   4: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index
             at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/slice/index.rs:15:9
   5: <alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index
             at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/alloc/src/vec/mod.rs:2496:9
   6: parley::layout::line::greedy::commit_line
             at /home/dvc/cloudpeer/parley/src/layout/line/greedy.rs:510:26
   7: parley::layout::line::greedy::BreakLines<B>::break_next
             at /home/dvc/cloudpeer/parley/src/layout/line/greedy.rs:222:12
   8: parley::layout::line::greedy::BreakLines<B>::break_remaining
             at /home/dvc/cloudpeer/parley/src/layout/line/greedy.rs:257:15
   9: parley::layout::Layout<B>::break_all_lines
             at /home/dvc/cloudpeer/parley/src/layout/mod.rs:110:9
  10: <piet_parley::ParleyTextLayoutBuilder as piet::text::TextLayoutBuilder>::build
             at /home/dvc/cloudpeer/parley/piet-parley/src/lib.rs:148:9
  11: engine_rs::render
             at ./main.rs:201:18
  12: engine_rs::main::{{closure}}
             at ./main.rs:93:17
  13: winit::platform_impl::platform::sticky_exit_callback
             at /home/dvc/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.26.1/src/platform_impl/linux/mod.rs:753:5
  14: winit::platform_impl::platform::wayland::event_loop::EventLoop<T>::run_return
             at /home/dvc/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.26.1/src/platform_impl/linux/wayland/event_loop/mod.rs:394:21
  15: winit::platform_impl::platform::wayland::event_loop::EventLoop<T>::run
             at /home/dvc/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.26.1/src/platform_impl/linux/wayland/event_loop/mod.rs:209:9
  16: winit::platform_impl::platform::EventLoop<T>::run
             at /home/dvc/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.26.1/src/platform_impl/linux/mod.rs:669:56
  17: winit::event_loop::EventLoop<T>::run
             at /home/dvc/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.26.1/src/event_loop.rs:154:9
  18: engine_rs::main
             at ./main.rs:50:5
  19: core::ops::function::FnOnce::call_once
             at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

OpenType feature support

Implement support for applying OpenType feature settings by feature tag/value pairs. Coordinate with piet on API design.

Advanced text selection support

Add support for selection affinity to handle selections that border on mixed directional runs. Implement both logical and visual cursor movement. Requires coordinate with piet.

Layout is empty

My code looks something like this, based on your code in https://github.com/dfrg/piet-gpu-text

    // let font = Font::from_file("assets/fonts/Inter Variable/Inter.ttf", 0).unwrap();
    let font = Font::from_file("assets/fonts/ttf/FiraCode-Regular.ttf", 0).unwrap();
    let font = font.as_ref();

    // experimenting with the scaler, glyph outlines are returned fine

    let mut context = ScaleContext::new();
    let mut scaler = context
        .builder(font)
        .hint(true)
        .size(14.)
        .variations(&[("wght", 400.0)])
        .build();
    let glyph_id = font.charmap().map('H');
    let outline = scaler.scale_outline(glyph_id).unwrap();

    // -- Layout

    let mut font_ctx = FontContext::new();
    let font_family = font_ctx.register_fonts(font.data.to_vec()).unwrap();
    let mut layout_ctx: LayoutContext<[u8; 4]> = LayoutContext::new();

    let mut builder = layout_ctx.ranged_builder(&mut font_ctx, "a quick brown fox?", 1.);
    builder.push_default(&StyleProperty::FontStack(FontStack::Single(
        FontFamily::Named(&font_family),
    )));
    builder.push_default(&StyleProperty::FontSize(14.));
    builder.push_default(&StyleProperty::Brush([255, 255, 255, 255]));
    let layout = builder.build();

    for line in layout.lines() {
        let mut last_x = 0.0;
        let mut last_y = 0.0;
        // base transform [1, 0, 0, -1]
        println!("hi!");

        for glyph_run in line.glyph_runs() {
            let run = glyph_run.run();
            // let color = &glyph_run.style().brush.0;
            let font = run.font();
            let font = font.as_ref();

            let mut first = true;

            // TODO: move let scaler here
            for glyph in glyph_run.positioned_glyphs() {
               // ...
            }
        }
    }

I had to make a small modification to font.rs to compile on Linux since Library::default is missing.

let mut builder = LibraryBuilder::default();
builder.build()

For some reason the layout is always empty and contains no data. I'm not relying on any system paths and instead manually registering the font, then using the font family name returned by FontContext.

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.