Giter VIP home page Giter VIP logo

fontra's Introduction

Fontra

Fontra Icon

Fontra is an in-development browser-based font editor. It consists of two main parts:

  • Fontra client — runs in the browser, written in JavaScript
  • Fontra server — runs locally or on a remote machine, written in Python

Installing Fontra

Download and install Fontra Pak

Fontra Pak is a Fontra distribution for macOS and Windows. It is a self-contained Fontra server application, which allows you to view and edit fonts in the default browser. We don't have releases for it yet, but you can grab the latest nightly build from the topmost “Build Application” workflow.

Fontra Pak should also work on Linux and other platforms, but you will have to build it from the sources.

Install from the source code

Requirements

  • Ensure you have Python >= 3.10 installed, preferably from python.org

  • Ensure you have Node.js >= 19 installed, preferably from nodejs.org

Setup

  • Check out the Fontra repository (the one you are reading this from), cd into the root of the repository

  • Create a Python venv in the root of the repo:

    python3.10 -m venv venv --prompt=fontra

    (Replace python3.10 with python3.11 if you have 3.11 instead.)

  • Activate venv:

    source venv/bin/activate

  • Install general dependencies:

    pip install --upgrade pip

    pip install -r requirements.txt

    pip install -e .

Testing

The following steps are needed if you want to run the automated tests and if you want to contribute:

  • Install dependencies to run the automated tests:

    pip install -r requirements-dev.txt

  • Install pre-commit to run formatters and linters:

    pre-commit install --install-hooks

  • To verify if everything is working correctly, run both test suites:

    pytest

    npm test

Running

  • Start the fontra server with a path to a folder containing fonts (.designspace, .ufo, .ttf or .otf), using the filesystem subcommand:

    fontra --launch filesystem /path/to/a/folder

  • The default browser will then navigate to:

    http://localhost:8000/

  • To use Fontra with .rcjk data on disk, or to connect to a remote rcjk server, install the fontra-rcjk plugin package. Then you can start it with a robocjk server hostname, using the rcjk subcommand provided by the fontra-rcjk plugin:

    fontra --launch rcjk some-robocjk-server.some-domain.com

Roadmap

The following list of features is not complete, but gives you a rough idea of where we are now, and where we are headed. A green checkmark means: “This feature has been implemented”.

Input / Output

  • Read .designspace ✅
  • Write .designspace
  • Respond to external .designspace changes (automatic reload)
  • Read .ufo ✅
  • Write .ufo ✅
  • Respond to external .ufo changes (automatic reload) ✅
  • Read .ttf + variable .ttf ✅
  • Read .otf + variable .otf ✅
  • Write .ttf + variable .ttf (For “hot fixes”. Currently not planned, will still require export step.)
  • Write .otf + variable .otf (Ditto.)
  • Respond to external .ttf and .otf changes (automatic reload)
  • Read .glyphs and .glyphspackage ✅ (Via fontra-glyphs)
  • Write .glyphs and .glyphspackage

Text viewing / editing

  • Basic live text entry, including /glyphname notation ✅
  • Multi-line text ✅
  • Basic glyph selection (pick glyph from list) ✅
  • Basic designspace navigation (via axis sliders) ✅
  • Show live interpolation ✅
  • Hand tool for scrolling ✅
  • Scroll with gestures ✅
  • Zoom with gestures ✅
  • Zoom with short-cuts ✅
  • Advanced character / glyph search
  • Display kerning
  • Apply proper text shaping
  • Full screen mode
  • Right-to-left mode
  • Vertical top-to-bottom mode
  • Enter “edit mode” for glyph by double-clicking on a glyph in the text ✅

Glyph editing

  • Basic outline editing (move points) ✅
  • Basic pen tool (draw points) ✅
  • Edit (variable) component parameters ✅
  • Decompose (variable) component ✅
  • First-class support for quadratic curves ✅
  • Multi-level undo/redo, per glyph ✅
  • Interactive sidebearing editing
  • Numeric sidebearing editing
  • Numeric advance width editing ✅
  • Pen tool for quadratic curves ✅ (experimental)
  • Decent outline editing (adding/removing points, removing contours) ✅ (with caveats)
  • Select segments ✅
  • Advanced outline editing: edit segments
  • Connecting open paths ✅
  • Show point coordinates and component origins numerically ✅
  • Knife tool
  • Shape tool
  • Measure tool ✅
  • Copy / paste ✅
  • Create new glyphs ✅
  • Add / remove (variable) components ✅
  • Anchors
  • Guidelines
  • View background layers
  • Edit local variation axes
  • Edit local sources/layers ✅
  • Built-in support for Non-Linear Interpolation
  • Remove overlap and other path operators

Font-level viewing / editing

  • Create new font project
  • Cell-based font overview
  • List-based font overview
  • Edit kerning
  • Edit OpenType features
  • Edit variation axes
  • Visualize and edit variation axis mapping (avar)

Multiple windows

  • Propagate changes across multiple windows in real time ✅
  • Browser URL encodes most view settings ✅

Deployment

  • Basic standalone desktop application for macOS and Windows ✅ (Via Fontra Pak)
  • Basic multi-user server deployment with database storage ✅ (Via fontra-rcjk, django-robo-cjk, behind NGINX)
  • Research GitHub REST API: can Fontra be a GitHub gateway in a practical way?
  • Research database solutions for server-based font storage
  • Desktop app with integrated browser and auto-update feature (made with Electron or similar)

Scripting

  • A Python scripting library that talks directly to the Fontra server
  • JS scripting for in-browser automation
  • Python scripting for in-browser automation via WASM/PyOdide
  • Add various plug-in APIs, for example:
    • Visualization layer plug-ins for the glyph editor
    • Tool plug-ins

Export

  • FontMake/Fontations integration
  • Incremental compilation using Fontations
  • Experimental glyf1 export ✅ (Via fontra-compile)

Collaborative features

  • Visualizing the selection of others
  • Add review notes / comments
  • Suggested edits

Code structure

  • Client/server architecture (JavaScript/Python) ✅
  • Local or (networked) remote server ✅
  • Client/server communication via JSON objects over a WebSocket ✅
  • Highly modular:
    • Pluggable client views ✅
    • Pluggable read/write storage backends ✅
    • Client-agnostic and storage-agnostic server centerpiece ✅
  • Asynchronous programming model using async/await ✅

Future possibilities

  • Serverless Fontra
  • Peer-to-peer collaboration

fontra's People

Contributors

blackfoundry avatar davelab6 avatar dependabot[bot] avatar fabiocaccamo avatar fatih-erikli avatar gaetanbaehr avatar justvanrossum avatar madig avatar nedkamburov avatar roeln 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

fontra's Issues

Need overlaying dialogs

  • message, with automatic dismissal after a timeout
  • message, with explicit dismiss button
  • ask yes/no/cancel

Rethink "edited glyph" and global axes vs local axes slider UI

In the viewed text, a glyph is currently either viewed or edited. There can only be a single glyph in "editing" state.

However, it may make sense to have a "selected" state, where we can play with the local axes.

There is always at most one glyph that is selected OR is in editing state.

  • Click on a glyph: current "selected" or "editing" glyph (if any) goes back to "view" state, clicked glyph becomes "selected"
  • Double click on a glyph: current "selected" or "editing" glyph (if any) goes back to "view" state, double clicked glyph becomes "editing"

The axis slider UI will only show global axes if no glyph is selected or is being edited, and it will additionally show the glyphs' local axes (if any) if it is selected or being edited.

If a selected/edited glyph has an axis with the same name as a global axis, then:

  • moving the global slider should make the local one move the local one as well (apply range mapping)
  • moving the local slider only affects the display of the selected glyph

Unlike the current situation, unselected glyphs should not be affected by local sliders, even if they have an axis with the same name.

Large texts are problematic

  • The axis UI starts to not be very responsive anymore

  • Large URLs are probematic for the server, and for NGINX

  • We should probably limit the maximum number of glyphs that can be displayed

  • We should probably limit the URL length somehow (what info to drop? how to compress?)

Safari renders some SVG icons weirdly

As if it's adding a white stroke around the black strokes:

image

I had the same issue with the "T" icon, where I worked around it, may have to do something similar for the "i".

Need to fix local axis settings shortcomings

  • Ideally, each occurrance of a glyph in the display string should have its own local axis settings
    • This is complicated when the string is edited in the text entry field: we effectively need editing of an attributed string
  • All local axis settings in the display string should be encoded in the URL
    • This will change the URL format quite a bit

General TODO items

To be split into proper items and PRs.

  • View and edit component parameters
  • Need a simple "form" UI mechanism, to more easily implement UI for the things like the previous point
  • Write changes back to backend: backend API needs to evolve methods for that #48
  • Get/view/edit project-wide font info
  • Get/view/edit font metrics: should have sources like glyphs, perhaps even layers #78
  • Get/view/edit kerning: should have sources like glyphs, perhaps even layers

Text entry doesn't work for chars outside the BMP

Looping over a string will yield surrogate pairs, which we'll need to hande separately. Eg. entering "𠂭" will not work, even if the code point exists in the font.

Likewise, non-BMP unicode values are (likely) incorrectly converted to string, as fromCharCode() only support 16-bit numbers.

View CJK Design Frame with black glyph

This could be done as an alternate behavior for the space key. One idea is to use modifier keys. For example:

  • Space key: super clean view (this is the current situation)
  • Space + option key: clean view, but don't hide UI elements
  • Space + shift key: clean view, but don't hide CJK design frame

Tool items / View items

Tool items:

View items:

  • scroll hand
  • zoom plus and minus
  • enter/exit full screen #189
  • recenter around selection / selected glyph

Rethink overlay items auto-collapse

Often, the glyph search, axis box or selection info box collapse earlier than you'd like.

Perhaps they should only collapse if clicking in empty space but not on a glyph.

Perhaps they should grow an explicit close X button thing.

Edit behavior

  • Handles moving along with their neighbors around a "smooth" point (Done in #62)
  • Tangent handles (Done in #62)
  • Single quad off-curve (Done in #62)
  • Refactoring, to allow the next items (Done in #66)
  • Shift constraint (Done in #68)
  • Alternative behavior (command-drag) (Done in #73)
  • Alternative shift behavior (command-shift-drag)

Keep in mind: good quadratics behavior.

Fix touch events on mobile / iOS

  • On iOS scrolling doesn't properly work
  • On Android many things don't properly work

(But then we will also have to consider the UI design from a tablet-perspective.)

Make empty glyph clickable / double clickable

It is currently not possible to select or edit a glyph that has no outlines, such as space.

See for example FontGoggles: for empty glyphs it uses the advance width + ascender/descender box.

Watch External Changes

This currently works for for glyph changes in filesystem fonts (.designspace, .ufo and .rcjk), but only , but not for adding/deleting glyphs.

Things to do:

  • Respond to glyph addition and deletion #153

  • Similarly, respond to (reversed) cmap changes (May need #114)

  • Respond to designspace changes #152

  • Respond to RoboCJK MySQL DB changes (googlefonts/fontra-rcjk#27)

Share more code between rcjk fs and rcjk mysql backends

Currently, the rcjk file system back end leans on rcjktools, and the rcjk mysql backend does not (or hardly). The two implementations are quite distinct.

rcjktools was mostly written for viewing/reading/building, and not so much for editing.

My idea is to make a simple abstraction layer for getting the raw data, which will have two implementations (file system + mysql), and that all the conversion to Fontra objects can be shared.

Investigate peer-to-peer, especially peerjs, a JS lib for WebRTC

Possible scenario:

  • We run a signalling server at fontra-collab.black-foundry.com (or something, maybe we should grab "fontra.xyz")
  • User A runs a local (desktop) Fontra app
  • User A offers to share a project, tells the signalling server, receives a URL to share that contains a temp token
  • User A sends URL to User B
  • User B goes to URL, receives all Fontra assets from our server, but makes a data connection to User A directly

(Hm, the assets could also come from User A, but I'm not yet sure how to do that over a data connection. The Fontra client app really likes regular HTTP for assets.)

Type over selected glyph

When you type a character, the selected glyph should be replaced by that character.

Question: also if the glyph is being edited? Perhaps it will get in the way of (future) short cuts.

Create Pen Tool

  • Improve infrastructure so adding/deleting points/contours works #115
  • Basic pen tool to draw an open polygon #115
  • Close contour #137
  • Attach to other open contour
  • Drag BCP handles while adding new points #137
  • DrawBCP handle from arbitrary point
  • Insert point on segment #296
  • Alt-click switches to pointer tool (maybe redundant, as we have 123 shortcuts for tool selection)
  • Hover should highlight a node when something special happens when we click or drag on it

Relates to #9

A simple optimistic auto-locking scheme

Adjacent to #19, here is the outline of a simple auto-locking scheme.

The idea is that we assume a glyph is unlocked/editabe, expecting this to be the common case by far, and simply go ahead with an edit (say, drag some points). But it will stop an edit-in-progress once the system finds out it is already being edited by someone else. I would like multiple clients to be able to have a glyph in "edit mode", so I don't want to tie glyph locking to the edit mode. I would like to lock only when actual editing takes place.

Prerequisites:

  • The unit of locking is "variable glyph" (but could also be "kerning", "font info", etc.)
  • A lockable object has a version token

Steps:

  • Client: tells server it will edit, and the object version token it has, but does not wait for permission (we don't want lag)
  • Server: if another client is editing this object: reject edit, send rejection notification to client
  • Server: if the current version token doesn't match the version token the client sends: reject edit, send rejection notification to client
  • Client: until the reject notification is received, just continue sending edit changes, which will be ignored by the server; then: rollback the edit locally, notify user why the edit was rejected
  • Client: if the edit is done, send final edit message, then await the answer, as the edit can still be rejected at this point. If rejected: rollback edit, notify user. If not rejected, receive new version token.

(The server could let clients pro-actively know which glyphs are locked, which would be a little friendlier for the user in most cases. But the above is still necessary to avoid race conditions: what if two users start editing a glyph at roughly the same time, before either can be notified? The server will have to reject one of them while it is already editing.)

This is much simpler than a full CRDT, and has the following drawbacks:

  • The client-server connection must exist: editing cannot continue if the connection gets dropped
  • No concurrent edits possible on the same object: once locked, no other client can edit. Practically, this means that while one user is editing the Regular of a glyph, no one else can edit the Bold.

Compared to RoboCJK, this has the following advantage:

  • Locking starts only when an actual edit is made, and ends immediately after the edit (say, a point drag)

This scheme can be made to work with RoboCJK's locking mechanism:

  • Fontra client initiates edit, and goes ahead without waiting for permission
  • Fontra server does the steps outlined above to see if any other Fontra client is editing
  • Meanwhile, Fontra server asks robocjk for a locked glyph
  • If this fails: reject edit
  • If succeeded, compare received (locked) glyph data with previously received (not locked) glyph data; if different: reject edit (in this case, the version token could be a hash of the glyph data)
  • After edit: unlock robocjk glyph

(This will cause quite some traffic between the Fontra server and the RoboCJK server, if edits come in quick succession, such as when dragging points. Perhaps it can be streamlined, eg. by delaying unlocking a little, so rapid successive edits can use the same lock.)

Auto-reload when a new version is available

Ideally, every time when the server process is restarted, the browser should automatically reload all static content, so users don't have to do a manual deep reload.

Idea: a version cookie could be used, and compared to a previously read version cookie.

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.