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 rich text and color support #95

Closed
wants to merge 15 commits into from

Commits on Jan 18, 2024

  1. Configuration menu
    Copy the full SHA
    8ec6ec7 View commit details
    Browse the repository at this point in the history
  2. Refactor library into concept of Words ahead of rich text support

    __WARNING:__ Still a WIP. See `// DEBUG` comments throughout.
    
    Instead of dealing with text as a string, introduce the concept of Words
    where a Word is either a visible, written word, or whitespace, and have
    the option to infer whitespace when an array of Words is given instead
    of a string.
    
    A Word then has its own formatting options aside from the "base" formatting
    set in the `CanvasTextConfig` object. If a Word doesn't have `format` options,
    it will simply use the "default" format in the 2D context, which may have been
    modified based on the `CanvasTextConfig` object provided to `drawText()`.
    
    To preserve the existing `drawText()` and `splitText()` APIs, `splitText()`
    splits the text into an array of Words and then calls the new `splitWords()`
    function that does all the work.
    
    For now, providing an array of Words to `drawText()` throws an error since
    this isn't supported yet. But everything else workds as before when providing
    a string: All supported alignments, including justification.
    
    Other fixes/changes:
    - Breaks cannot occur within a word anymore, even when the box width gets
      too narrow to fit anything. At this point, a minimum of one word is rendered
      per line, on top of any hard line breaks specified with newline characters.
    - The context's state is saved and restored in `drawText()`, meaning that
      after the call, the context's font, etc, styles/settings are back to what
      they were prior to calling it instead of being set to what was specified
      in the `CanvasTextConfig` object.
    stefcameron committed Jan 18, 2024
    Configuration menu
    Copy the full SHA
    f00f280 View commit details
    Browse the repository at this point in the history

Commits on Jan 19, 2024

  1. BREAKING: Move text placement into splitWords()

    __WARNING:__ See remaining `// DEBUG` comments.
    
    In order to make it possible to use a library other than canvas-txt to
    actually draw the text, yet still leverage this library's text wrapping
    and rich text features, `splitWords()` now does all the positioning
    that `drawText()` use to do, which means that `splitText()`, which calls
    `splitWords()` internally, must now be given many more parameters than
    it used to.
    
    Since `splitText()` was already exported as a utility from this library,
    this must be a breaking change (major version update).
    
    So now, `splitWords()` returns the positioned words along with the
    required `textAlign` and `textBaseline` to set on the 2D context
    in order to render the text what is now a very simple loop.
    
    This makes it possible to call `splitWords()` directly and then use
    the output to render each word using another library such as Konva
    where each word could then be dragged or hit-tested, or do it
    without a library altogether.
    
    Plain text (single text format) works at this point, but rich text
    still does not render properly due to misalignment issues.
    stefcameron committed Jan 19, 2024
    Configuration menu
    Copy the full SHA
    1298a13 View commit details
    Browse the repository at this point in the history

Commits on Jan 22, 2024

  1. Fix rich text rendering

    __WARNING:__ See `// DEBUG` comments for what still needs doing/fixing.
    
    Works quite well now, especially when NOT using different font sizes
    for different words. If all words use the same size, just alter their
    style, weight, or variant, it renders nicely.
    
    Updated the demo app to always set "ipsum" to italic, and "consectetur"
    to bold, if either is found in the sample text to render.
    stefcameron committed Jan 22, 2024
    Configuration menu
    Copy the full SHA
    348c404 View commit details
    Browse the repository at this point in the history

Commits on Jan 24, 2024

  1. Configuration menu
    Copy the full SHA
    883b713 View commit details
    Browse the repository at this point in the history

Commits on Jan 25, 2024

  1. Optimize for memory and performance

    __WARNING:__ There are still remaining `// DEBUG` items to address
    
    - Performance: Allow consumer to provide pre-computed `TextMetrics` objects
      in the `Words[]`, which would typically come from a previous call to
      `splitWords()` since the function now sets a new `Word.metrics` property
      to the measured metrics for the `Word.format` (if any). This will
      dramatically speed up the process when most Words have already been
      measured from a previous pass (assuming formatting hasn't changed).
    - Performance: Change `WordMap` key to a string hash of the Word's
      `text` and `format` in order to reuse associated metrics between
      identical Words. Also impacts memory use.
    - Memory: Re-use metrics between identical Words instead of re-measuring
      them unnecessarily. This is particularly significant with whitespace
      characters which show up in __huge__ numbers in any given set of Words
      and are nearly all identical.
    stefcameron committed Jan 25, 2024
    Configuration menu
    Copy the full SHA
    96bc34b View commit details
    Browse the repository at this point in the history

Commits on Jan 29, 2024

  1. Work with TextMetrics-like objects

    Native Canvas `TextMetrics` objects fail to serialize (cause an exception)
    when given as data to the `postMessage()` of a Web Worker thread (or from
    the main thread).
    
    Therefore, work with objects having a similar interface but not being
    actual `TextMetrics` instances.
    
    Also provide two JSON stringify helpers: `specToJson()` and `wordsToJson()`
    This should help consumers to deal with native `TextMetrics` objects.
    stefcameron committed Jan 29, 2024
    Configuration menu
    Copy the full SHA
    8de8d37 View commit details
    Browse the repository at this point in the history

Commits on Jan 31, 2024

  1. Configuration menu
    Copy the full SHA
    2b0ebb1 View commit details
    Browse the repository at this point in the history

Commits on Feb 1, 2024

  1. Configuration menu
    Copy the full SHA
    43a51ed View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    1ca4ffc View commit details
    Browse the repository at this point in the history

Commits on Feb 2, 2024

  1. Configuration menu
    Copy the full SHA
    3e2de3a View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    15a3ada View commit details
    Browse the repository at this point in the history

Commits on Feb 3, 2024

  1. Add missing '@types/offscreencanvas' dependency for OffscreenCanvas t…

    …ype, remove self as contributor from package
    stefcameron committed Feb 3, 2024
    Configuration menu
    Copy the full SHA
    67e0ee6 View commit details
    Browse the repository at this point in the history
  2. Fix tests and add fallback for missing fontBoundingBox* properties

    Node-based `canvas` rendering does not currently support the newer
    `fontBoundingBox*` TextMetrics properties, so use a `textBaseline='bottom'`
    fallback trick in that case.
    stefcameron committed Feb 3, 2024
    Configuration menu
    Copy the full SHA
    3cd14fa View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    115633f View commit details
    Browse the repository at this point in the history