Создание профессионального инструмента для дизайна в Интернете

Наше видение будущего инструментов дизайна заключается в том, чтобы и инструмент, и контент были легко доступны для всех и в любом месте. Вот почему мы создали Figma, инструмент для совместного проектирования интерфейсов, который мы недавно запустили в виде облачной службы на основе браузера. Когда мы приступили к созданию Figma, мы знали, что это будет непросто. Чтобы действительно добиться успеха, он должен был обеспечить высококачественное редактирование, которое профессионалы приняли бы и должны были работать постоянно везде.

Осуществить это было действительно сложно; мы фактически закончили тем, что создали браузер внутри браузера.

Причина, по которой это сложно, заключается в том, что Интернет не задумывался как универсальная вычислительная платформа. Это началось как технология, в первую очередь для документов, и к ней было прикручено множество вещей для разработки приложений. Эти вещи обычно принимали форму конкретных API-интерфейсов для одноразовых случаев вместо предоставления общих примитивов, которые можно использовать для реализации всевозможных вещей. Некоторые примеры:

Отсутствие общих примитивов в сети начинает меняться, и теперь есть такие технологии, как WebGL и asm.js, которые позволяют разработчикам обходить браузер и напрямую общаться с оборудованием. Именно это достижение наконец сделало практичными высокопроизводительные графические веб-приложения. Разработчикам больше не нужно ждать точных функций, которые им нужно добавить в Интернет, они могут создавать эти функции сами!

Emscripten

Наш редактор написан на C ++ и скомпилирован в JavaScript с помощью кросс-компилятора emscripten. Компилятор emscripten нацелен на подмножество JavaScript asm.js, которое обеспечивает способ заставить JavaScript JIT генерировать предсказуемый компактный машинный код и широко поддерживается во всех современных браузерах. Это дает следующие преимущества:

  • Мы полностью контролируем структуру памяти и можем использовать компактные 32-битные числа с плавающей запятой или даже байты, когда это необходимо, вместо 64-битных двойников JavaScript. Это очень важно для таких приложений, как наше, которые используют большие объемы данных.
  • Сгенерированный код полностью контролирует распределение, что значительно упрощает достижение 60 кадров в секунду, избегая пауз сборщика мусора. Все объекты C ++ - это просто зарезервированные диапазоны в заранее выделенном типизированном массиве, поэтому сборщик мусора JavaScript никогда не задействуется.
  • Сгенерированный код предварительно оптимизирован с помощью расширенного оптимизатора LLVM. В сочетании со специализацией шаблонов C ++ это создает очень эффективный код, который может иметь коэффициент вдвое больше собственной производительности или лучше.
  • Гарантируется, что весь код asm.js не содержит точек деоптимизации, поэтому JIT могут выполнять предварительную компиляцию и обеспечивать предсказуемую производительность. Обычный код JavaScript вместо этого полагается на эвристику JIT, и производительность иногда может сильно различаться между последующими запусками одного и того же кода.

Нельзя сказать, что emscripten идеален. Как и в случае с любой новой технологией, на дороге были неровности. Одна большая проблема для нас заключалась в том, что некоторые конфигурации браузера не могли выделить большие диапазоны непрерывного адресного пространства для огромного типизированного массива, который содержит все пространство памяти emscripten. Худшим случаем был 32-битный Chrome в Windows, который иногда даже не мог выделить 256-мегабайтный типизированный массив, потому что ASLR фрагментировал адресное пространство. С тех пор это было исправлено.

Уловка, которая также помогает, заключается в использовании дескрипторов данных вне кучи для больших ресурсов, таких как буферы изображений и геометрии. У нас есть внутренний API под названием IndirectBuffer (исходный код которого мы открываем здесь), который ссылается на внешний типизированный массив и делает его доступным для C ++. Перемещение больших выделений из основной кучи уменьшает проблемы фрагментации памяти для длительных сеансов, позволяет нам использовать больше ограниченного адресного пространства в 32-битных браузерах и позволяет нам преодолеть ограничение размера 31-битного типизированного массива в 64-битных браузерах.

Текущая поддержка asm.js уже неплоха, но впереди еще много интересных изменений. WebAssembly - это попытка реализовать двоичный формат для кода asm.js, чтобы резко сократить время синтаксического анализа, с которым работают все основные производители браузеров. На данный момент единственной формой многопоточности является использование веб-воркеров с передачей сообщений, но грядущая спецификация общего типизированного массива сделает реальностью многопоточность с общей памятью.

Рендеринг

Мы внедрили собственный механизм рендеринга, чтобы контент отображался быстро и единообразно на разных платформах. В браузерах есть потрясающая реализация графики, и мы изначально пытались использовать их вместо создания нового движка рендеринга. Без низкоуровневого API для доступа к дереву визуализации браузера доступны варианты HTML, SVG или 2D-холста. Ни один из этих вариантов не был удовлетворительным по многим причинам:

  • HTML и SVG содержат много багажа и часто работают намного медленнее, чем API 2D-холста из-за доступа к DOM. Обычно они оптимизированы для прокрутки, а не для масштабирования, а геометрия часто повторно тесселируется после каждого изменения масштаба.
  • Нет никаких гарантий относительно ускорения графического процессора, и многие вещи по-прежнему обрабатываются центральным процессором, который в некоторых случаях может быть довольно медленным.
  • Поддержка режимов маскирования, размытия и наложения в HTML и SVG сильно различается между браузерами и часто не сглаживается или имеет слишком низкое разрешение на дисплеях с высоким разрешением.
  • API-интерфейс 2D-холста - это API-интерфейс немедленного режима, а не API-интерфейс сохраненного режима, поэтому всю геометрию необходимо повторно загружать на видеокарту каждый кадр. Это излишне расточительно и может стать узким местом.
  • Макет текста несовместим между браузерами и даже несовместим между одним и тем же браузером на разных платформах.
  • Мы хотели иметь возможность добавлять такие функции, как угловые градиенты, которые не поддерживаются ни одним из этих API рендеринга.

Вместо того, чтобы пытаться заставить один из них работать, мы реализовали все с нуля, используя WebGL. Наш рендерер - это высокооптимизированный движок на основе тайлов с поддержкой маскирования, размытия, размытых градиентов, режимов наложения, непрозрачности вложенных слоев и многого другого. Весь рендеринг выполняется на графическом процессоре и полностью сглажен. Внутренне наш код очень похож на браузер внутри браузера; у нас есть собственная модель DOM, собственный наборщик текста, собственный механизм верстки текста, и мы думаем о добавлении дерева рендеринга, аналогичного тому, которое браузеры используют для рендеринга HTML.

Браузеры

Функциональность веб-платформы все еще догоняет собственные платформы, и, к сожалению, кое-где все еще есть пробелы. Хотя у нас нет ресурсов, чтобы заполнить некоторые из более серьезных пробелов, я все же пытаюсь исправить то, что могу, когда это имеет смысл.

До того, как я начал работать над Figma, пользовательские курсоры с высоким разрешением в Интернете действительно были сломаны. Мне пришлось вручную исправить Chrome, Firefox и WebKit, потому что все они были сломаны по-разному. До сих пор нет единого универсального способа сделать это (SVG для Firefox, -webkit-image-set для Chrome и WebKit и древний формат .cur для IE), но, по крайней мере, сейчас это возможно.

Я также исправил несколько вопиющих ошибок, связанных с производительностью и удобством использования, чтобы сделать наш продукт лучше. Интернет иногда может расстраивать, но браузеры - это не черный ящик (ну, за исключением этого браузера), и часто все, что нужно, чтобы исправить раздражающие проблемы с Интернетом, - это полдня, когда вы ковыряетесь в браузере. кода, день обсуждения патча и несколько месяцев ожидания выхода релиза.

Веб-платформа может сделать еще больше, чтобы Figma стала еще лучше:

  • Наша самая большая проблема - это отсутствие доступа к контурам глифов и таблицам кернинга, к которым в настоящее время невозможно добраться. Одной из основных проблем является снятие отпечатков пальцев, но эта битва уже проиграна. Мы надеемся, что доступ к данным шрифтов может быть предоставлен за запросом разрешения пользователя, как и другие API, чувствительные к конфиденциальности. Chrome выступил с предложением по исправлению, которое в настоящее время в разработке (они действительно помогли!), Но для других браузеров больше ничего не ожидается.
  • Мы хотели бы добавить поддержку распространенных форматов буфера обмена (.ai, .pdf и т. Д.), Но в Интернете нет возможности сделать это. Единственные форматы в спецификации - это text / plain и text / html (наш формат буфера обмена Figma - это text / html с двоичными данными, закодированными в комментарии HTML).
  • Еще одна проблема для нас - это отсутствие поддержки жестов сжатия сенсорной панели OS X. Chrome добавил малоизвестный прием, при котором жест сжатия отправляет событие колеса с нажатой клавишей ctrlKey, а вызов preventDefault () позволяет странице обрабатывать его. Это потрясающе и делает масштабирование и панорамирование в Figma естественными и легкими. Я попытался добавить его в Firefox, но эта попытка пока не удалась. Сведение пальцев в Safari вызывает поведение масштабирования, которое действительно сбивает пользователей с толку и невозможно отключить.

Заключение

Производительность и качество - одни из наших самых важных характеристик. Они немного отличаются от обычных функций, потому что вы замечаете их только тогда, когда их нет, но они имеют большое значение.

Я очень рад наконец открыть миру Фигму. Продукт еще не открыт для широкой публики, но вы можете подписаться на наш список ожидания и вскоре опробовать его. Сообщите нам свое мнение!